Merge branch 'master' of https://github.com/awakecoding/FreeRDP into awakecoding-staging

This commit is contained in:
Mike McDonald 2015-01-20 08:09:00 -05:00
commit b184a7531f
274 changed files with 10689 additions and 6663 deletions

24
.gitignore vendored
View File

@ -27,16 +27,6 @@ include/freerdp/version.h
*_dummy.c
*_dummy.c.base
# Packages
*.zip
*.exe
*.sh
*.deb
*.rpm
*.dmg
*.tar.Z
*.tar.gz
# Eclipse
*.project
*.cproject
@ -89,6 +79,7 @@ RelWithDebInfo
*.resource.txt
*.embed.manifest*
*.intermediate.manifest*
version.rc
# Binaries
*.a
@ -128,3 +119,16 @@ default.log
# etags
TAGS
# generated packages
*.zip
*.exe
*.sh
*.deb
*.rpm
*.dmg
*.tar.Z
*.tar.gz
# packaging related files
!packaging/scripts/prepare_deb_freerdp-nightly.sh

View File

@ -43,6 +43,7 @@ include(CheckCmakeCompat)
# Include cmake modules
include(CheckIncludeFiles)
include(CheckLibraryExists)
include(CheckSymbolExists)
include(CheckStructHasMember)
include(FindPkgConfig)
include(TestBigEndian)
@ -65,7 +66,7 @@ endif()
set(WITH_LIBRARY_VERSIONING "ON")
set(FREERDP_VERSION_MAJOR "1")
set(FREERDP_VERSION_MINOR "2")
set(FREERDP_VERSION_REVISION "0")
set(FREERDP_VERSION_REVISION "1")
set(FREERDP_VERSION_SUFFIX "dev")
set(FREERDP_API_VERSION "${FREERDP_VERSION_MAJOR}.${FREERDP_VERSION_MINOR}")
set(FREERDP_VERSION "${FREERDP_API_VERSION}.${FREERDP_VERSION_REVISION}")
@ -131,7 +132,8 @@ endif()
# Compiler-specific flags
if(CMAKE_COMPILER_IS_GNUCC)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "i686")
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
CHECK_SYMBOL_EXISTS(__x86_64__ "" IS_X86_64)
if(IS_X86_64)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686")
@ -504,9 +506,9 @@ if(APPLE)
set(GSTREAMER_1_0_FEATURE_TYPE "OPTIONAL")
set(X11_FEATURE_TYPE "OPTIONAL")
set(WAYLAND_FEATURE_TYPE "DISABLED")
set(ALSA_FEATURE_TYPE "DISABLED")
if(IOS)
set(X11_FEATURE_TYPE "DISABLED")
set(ALSA_FEATURE_TYPE "DISABLED")
set(PULSE_FEATURE_TYPE "DISABLED")
set(CUPS_FEATURE_TYPE "DISABLED")
set(PCSC_FEATURE_TYPE "DISABLED")
@ -564,6 +566,10 @@ if(TARGET_ARCH MATCHES "x86|x64")
endif()
endif()
if (TARGET_ARCH MATCHES "sparc")
set(HAVE_ALIGNED_REQUIRED 1)
endif()
# Path to put FreeRDP data
set(FREERDP_DATA_PATH "${CMAKE_INSTALL_PREFIX}/share/freerdp")

View File

@ -253,8 +253,8 @@ set(FILENAME "ChannelOptions.cmake")
file(GLOB FILEPATHS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*/${FILENAME}")
foreach(FILEPATH ${FILEPATHS})
if(${FILEPATH} MATCHES "^([^/]*)//${FILENAME}")
string(REGEX REPLACE "^([^/]*)//${FILENAME}" "\\1" DIR ${FILEPATH})
if(${FILEPATH} MATCHES "^([^/]*)/+${FILENAME}")
string(REGEX REPLACE "^([^/]*)/+${FILENAME}" "\\1" DIR ${FILEPATH})
set(CHANNEL_OPTION)
include(${FILEPATH})
if(${CHANNEL_OPTION})

View File

@ -354,17 +354,22 @@ static void audin_alsa_close(IAudinDevice* device)
DEBUG_DVC("");
SetEvent(alsa->stopEvent);
WaitForSingleObject(alsa->thread, INFINITE);
CloseHandle(alsa->stopEvent);
CloseHandle(alsa->thread);
if (alsa->stopEvent)
{
SetEvent(alsa->stopEvent);
WaitForSingleObject(alsa->thread, INFINITE);
CloseHandle(alsa->stopEvent);
alsa->stopEvent = NULL;
CloseHandle(alsa->thread);
alsa->thread = NULL;
}
if (alsa->buffer)
free(alsa->buffer);
alsa->buffer = NULL;
alsa->stopEvent = NULL;
alsa->thread = NULL;
alsa->receive = NULL;
alsa->user_data = NULL;
}

View File

@ -412,11 +412,16 @@ static int audin_plugin_terminated(IWTSPlugin* pPlugin)
if (audin->device)
{
IFCALL(audin->device->Close, audin->device);
IFCALL(audin->device->Free, audin->device);
audin->device = NULL;
}
free(audin->subsystem);
audin->subsystem = NULL;
free(audin->device_name);
audin->device_name = NULL;
free(audin->listener_callback);
free(audin);

View File

@ -387,7 +387,7 @@ static void* audin_server_thread_func(void* arg)
break;
default:
WLog_ERR(TAG, "audin_server_thread_func: unknown MessageId %d\n", MessageId);
WLog_ERR(TAG, "audin_server_thread_func: unknown MessageId %d", MessageId);
break;
}
}

View File

@ -24,7 +24,9 @@ set(${MODULE_PREFIX}_SRCS
${CMAKE_CURRENT_SOURCE_DIR}/addin.c
${CMAKE_CURRENT_SOURCE_DIR}/addin.h)
if(CHANNEL_STATIC_CLIENT_ENTRIES)
list(REMOVE_DUPLICATES CHANNEL_STATIC_CLIENT_ENTRIES)
endif()
foreach(STATIC_ENTRY ${CHANNEL_STATIC_CLIENT_ENTRIES})
foreach(STATIC_MODULE ${CHANNEL_STATIC_CLIENT_MODULES})

View File

@ -57,7 +57,13 @@ void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data
formatList.numFormats = 0;
position = Stream_GetPosition(s);
if (!cliprdr->useLongFormatNames)
if (!formatList.dataLen)
{
/* empty format list */
formatList.formats = NULL;
formatList.numFormats = 0;
}
else if (!cliprdr->useLongFormatNames)
{
formatList.numFormats = (dataLen / 36);
@ -156,7 +162,7 @@ void cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data
if (formatNameLength)
{
formatNameLength = ConvertFromUnicode(CP_UTF8, 0, wszFormatName,
ConvertFromUnicode(CP_UTF8, 0, wszFormatName,
-1, &(formats[index].formatName), 0, NULL, NULL);
}

View File

@ -102,7 +102,8 @@ void cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* s)
if (status != CHANNEL_RC_OK)
{
Stream_Free(s, TRUE);
WLog_ERR(TAG, "cliprdr_packet_send: VirtualChannelWrite failed %d", status);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(status), status);
}
}
@ -409,6 +410,8 @@ static void cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s)
WLog_ERR(TAG, "unknown msgType %d", msgType);
break;
}
Stream_Free(s, TRUE);
}
/**
@ -520,8 +523,10 @@ int cliprdr_client_format_list(CliprdrClientContext* context, CLIPRDR_FORMAT_LIS
if (formatNameSize > 15)
formatNameSize = 15;
Stream_Write(s, wszFormatName, formatNameSize * 2);
if (wszFormatName)
Stream_Write(s, wszFormatName, formatNameSize * 2);
Stream_Zero(s, 32 - (formatNameSize * 2));
free(wszFormatName);
@ -711,8 +716,8 @@ int cliprdr_client_file_contents_response(CliprdrClientContext* context, CLIPRDR
/****************************************************************************************/
static wListDictionary* g_InitHandles;
static wListDictionary* g_OpenHandles;
static wListDictionary* g_InitHandles = NULL;
static wListDictionary* g_OpenHandles = NULL;
void cliprdr_add_init_handle_data(void* pInitHandle, void* pUserData)
{
@ -732,6 +737,11 @@ void* cliprdr_get_init_handle_data(void* pInitHandle)
void cliprdr_remove_init_handle_data(void* pInitHandle)
{
ListDictionary_Remove(g_InitHandles, pInitHandle);
if (ListDictionary_Count(g_InitHandles) < 1)
{
ListDictionary_Free(g_InitHandles);
g_InitHandles = NULL;
}
}
void cliprdr_add_open_handle_data(DWORD openHandle, void* pUserData)
@ -756,6 +766,12 @@ void cliprdr_remove_open_handle_data(DWORD openHandle)
{
void* pOpenHandle = (void*) (size_t) openHandle;
ListDictionary_Remove(g_OpenHandles, pOpenHandle);
if (ListDictionary_Count(g_OpenHandles) < 1)
{
ListDictionary_Free(g_OpenHandles);
g_OpenHandles = NULL;
}
}
static void cliprdr_virtual_channel_event_data_received(cliprdrPlugin* cliprdr,
@ -791,7 +807,7 @@ static void cliprdr_virtual_channel_event_data_received(cliprdrPlugin* cliprdr,
Stream_SealLength(data_in);
Stream_SetPosition(data_in, 0);
MessageQueue_Post(cliprdr->MsgPipe->In, NULL, 0, (void*) data_in, NULL);
MessageQueue_Post(cliprdr->queue, NULL, 0, (void*) data_in, NULL);
}
}
@ -831,10 +847,10 @@ static void* cliprdr_virtual_channel_client_thread(void* arg)
while (1)
{
if (!MessageQueue_Wait(cliprdr->MsgPipe->In))
if (!MessageQueue_Wait(cliprdr->queue))
break;
if (MessageQueue_Peek(cliprdr->MsgPipe->In, &message, TRUE))
if (MessageQueue_Peek(cliprdr->queue, &message, TRUE))
{
if (message.id == WMQ_QUIT)
break;
@ -862,25 +878,33 @@ static void cliprdr_virtual_channel_event_connected(cliprdrPlugin* cliprdr, LPVO
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "cliprdr_virtual_channel_event_connected: open failed: status: %d", status);
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
WTSErrorToString(status), status);
return;
}
cliprdr->MsgPipe = MessagePipe_New();
cliprdr->queue = MessageQueue_New(NULL);
cliprdr->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) cliprdr_virtual_channel_client_thread, (void*) cliprdr, 0, NULL);
}
static void cliprdr_virtual_channel_event_terminated(cliprdrPlugin* cliprdr)
static void cliprdr_virtual_channel_event_disconnected(cliprdrPlugin* cliprdr)
{
MessagePipe_PostQuit(cliprdr->MsgPipe, 0);
UINT rc;
MessageQueue_PostQuit(cliprdr->queue, 0);
WaitForSingleObject(cliprdr->thread, INFINITE);
MessagePipe_Free(cliprdr->MsgPipe);
MessageQueue_Free(cliprdr->queue);
CloseHandle(cliprdr->thread);
cliprdr->channelEntryPoints.pVirtualChannelClose(cliprdr->OpenHandle);
rc = cliprdr->channelEntryPoints.pVirtualChannelClose(cliprdr->OpenHandle);
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
WTSErrorToString(rc), rc);
}
if (cliprdr->data_in)
{
@ -889,7 +913,13 @@ static void cliprdr_virtual_channel_event_terminated(cliprdrPlugin* cliprdr)
}
cliprdr_remove_open_handle_data(cliprdr->OpenHandle);
}
static void cliprdr_virtual_channel_event_terminated(cliprdrPlugin* cliprdr)
{
cliprdr_remove_init_handle_data(cliprdr->InitHandle);
free(cliprdr);
}
static VOID VCAPITYPE cliprdr_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
@ -911,6 +941,7 @@ static VOID VCAPITYPE cliprdr_virtual_channel_init_event(LPVOID pInitHandle, UIN
break;
case CHANNEL_EVENT_DISCONNECTED:
cliprdr_virtual_channel_event_disconnected(cliprdr);
break;
case CHANNEL_EVENT_TERMINATED:
@ -924,6 +955,8 @@ static VOID VCAPITYPE cliprdr_virtual_channel_init_event(LPVOID pInitHandle, UIN
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
UINT rc;
cliprdrPlugin* cliprdr;
CliprdrClientContext* context;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
@ -960,6 +993,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
context->ClientFileContentsResponse = cliprdr_client_file_contents_response;
*(pEntryPointsEx->ppInterface) = (void*) context;
cliprdr->context = context;
}
cliprdr->log = WLog_Get("com.freerdp.channels.cliprdr.client");
@ -973,8 +1007,15 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
CopyMemory(&(cliprdr->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
cliprdr->channelEntryPoints.pVirtualChannelInit(&cliprdr->InitHandle,
rc = cliprdr->channelEntryPoints.pVirtualChannelInit(&cliprdr->InitHandle,
&cliprdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, cliprdr_virtual_channel_init_event);
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
WTSErrorToString(rc), rc);
free(cliprdr);
return -1;
}
cliprdr->channelEntryPoints.pInterface = *(cliprdr->channelEntryPoints.ppInterface);
cliprdr->channelEntryPoints.ppInterface = &(cliprdr->channelEntryPoints.pInterface);

View File

@ -34,12 +34,14 @@ struct cliprdr_plugin
CHANNEL_DEF channelDef;
CHANNEL_ENTRY_POINTS_FREERDP channelEntryPoints;
CliprdrClientContext* context;
wLog* log;
HANDLE thread;
wStream* data_in;
void* InitHandle;
DWORD OpenHandle;
wMessagePipe* MsgPipe;
wMessageQueue* queue;
BOOL capabilitiesReceived;
BOOL useLongFormatNames;

File diff suppressed because it is too large Load Diff

View File

@ -22,29 +22,32 @@
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/stream.h>
#include <winpr/thread.h>
#include <freerdp/server/cliprdr.h>
#include <freerdp/channels/log.h>
#define TAG CHANNELS_TAG("cliprdr.server")
#define CLIPRDR_HEADER_LENGTH 8
struct _cliprdr_server_private
{
HANDLE vcm;
HANDLE Thread;
HANDLE StopEvent;
void* ChannelHandle;
HANDLE ChannelEvent;
BOOL UseLongFormatNames;
BOOL StreamFileClipEnabled;
BOOL FileClipNoFilePaths;
BOOL CanLockClipData;
BOOL useLongFormatNames;
BOOL streamFileClipEnabled;
BOOL fileClipNoFilePaths;
BOOL canLockClipData;
UINT32 ClientFormatNameCount;
CLIPRDR_FORMAT_NAME* ClientFormatNames;
char* ClientTemporaryDirectory;
wStream* s;
char* temporaryDirectory;
};
typedef struct _cliprdr_server_private CliprdrServerPrivate;
#endif /* FREERDP_CHANNEL_SERVER_CLIPRDR_MAIN_H */

View File

@ -101,7 +101,7 @@ int disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback
Stream_Write_UINT32(s, NumMonitors); /* NumMonitors (4 bytes) */
//WLog_ERR(TAG, "NumMonitors: %d\n", NumMonitors);
//WLog_ERR(TAG, "NumMonitors: %d", NumMonitors);
for (index = 0; index < NumMonitors; index++)
{
@ -134,14 +134,14 @@ int disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback
Stream_Write_UINT32(s, Monitors[index].DeviceScaleFactor); /* DeviceScaleFactor (4 bytes) */
#if 0
WLog_DBG(TAG, "\t: Flags: 0x%04X\n", Monitors[index].Flags);
WLog_DBG(TAG, "\t: Left: %d\n", Monitors[index].Left);
WLog_DBG(TAG, "\t: Top: %d\n", Monitors[index].Top);
WLog_DBG(TAG, "\t: Width: %d\n", Monitors[index].Width);
WLog_DBG(TAG, "\t: Height: %d\n", Monitors[index].Height);
WLog_DBG(TAG, "\t: PhysicalWidth: %d\n", Monitors[index].PhysicalWidth);
WLog_DBG(TAG, "\t: PhysicalHeight: %d\n", Monitors[index].PhysicalHeight);
WLog_DBG(TAG, "\t: Orientation: %d\n", Monitors[index].Orientation);
WLog_DBG(TAG, "\t: Flags: 0x%04X", Monitors[index].Flags);
WLog_DBG(TAG, "\t: Left: %d", Monitors[index].Left);
WLog_DBG(TAG, "\t: Top: %d", Monitors[index].Top);
WLog_DBG(TAG, "\t: Width: %d", Monitors[index].Width);
WLog_DBG(TAG, "\t: Height: %d", Monitors[index].Height);
WLog_DBG(TAG, "\t: PhysicalWidth: %d", Monitors[index].PhysicalWidth);
WLog_DBG(TAG, "\t: PhysicalHeight: %d", Monitors[index].PhysicalHeight);
WLog_DBG(TAG, "\t: Orientation: %d", Monitors[index].Orientation);
#endif
}
@ -166,7 +166,7 @@ int disp_recv_display_control_caps_pdu(DISP_CHANNEL_CALLBACK* callback, wStream*
Stream_Read_UINT32(s, disp->MaxNumMonitors); /* MaxNumMonitors (4 bytes) */
Stream_Read_UINT32(s, disp->MaxMonitorAreaFactorA); /* MaxMonitorAreaFactorA (4 bytes) */
Stream_Read_UINT32(s, disp->MaxMonitorAreaFactorB); /* MaxMonitorAreaFactorB (4 bytes) */
//WLog_ERR(TAG, "DisplayControlCapsPdu: MaxNumMonitors: %d MaxMonitorWidth: %d MaxMonitorHeight: %d\n",
//WLog_ERR(TAG, "DisplayControlCapsPdu: MaxNumMonitors: %d MaxMonitorWidth: %d MaxMonitorHeight: %d",
// disp->MaxNumMonitors, disp->MaxMonitorWidth, disp->MaxMonitorHeight);
return 0;
@ -183,7 +183,7 @@ int disp_recv_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s)
Stream_Read_UINT32(s, type); /* Type (4 bytes) */
Stream_Read_UINT32(s, length); /* Length (4 bytes) */
//WLog_ERR(TAG, "Type: %d Length: %d\n", type, length);
//WLog_ERR(TAG, "Type: %d Length: %d", type, length);
switch (type)
{

View File

@ -19,15 +19,10 @@ define_channel_client("drdynvc")
set(${MODULE_PREFIX}_SRCS
drdynvc_main.c
drdynvc_main.h
drdynvc_types.h
dvcman.c
dvcman.h)
drdynvc_main.h)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
install(TARGETS ${MODULE_NAME} DESTINATION ${FREERDP_ADDIN_PATH} EXPORT FreeRDPTargets)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -24,12 +24,495 @@
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <freerdp/constants.h>
#include "dvcman.h"
#include "drdynvc_types.h"
#include "drdynvc_main.h"
#define TAG CHANNELS_TAG("drdynvc.client")
static void dvcman_channel_free(void* channel);
static int dvcman_get_configuration(IWTSListener* pListener, void** ppPropertyBag)
{
*ppPropertyBag = NULL;
return 1;
}
static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
const char* pszChannelName, UINT32 ulFlags,
IWTSListenerCallback* pListenerCallback, IWTSListener** ppListener)
{
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
DVCMAN_LISTENER* listener;
if (dvcman->num_listeners < MAX_PLUGINS)
{
WLog_DBG(TAG, "%d.%s.", dvcman->num_listeners, pszChannelName);
listener = (DVCMAN_LISTENER*) malloc(sizeof(DVCMAN_LISTENER));
ZeroMemory(listener, sizeof(DVCMAN_LISTENER));
listener->iface.GetConfiguration = dvcman_get_configuration;
listener->iface.pInterface = NULL;
listener->dvcman = dvcman;
listener->channel_name = _strdup(pszChannelName);
listener->flags = ulFlags;
listener->listener_callback = pListenerCallback;
if (ppListener)
*ppListener = (IWTSListener*) listener;
dvcman->listeners[dvcman->num_listeners++] = (IWTSListener*) listener;
return 0;
}
else
{
WLog_WARN(TAG, "Maximum DVC listener number reached.");
return 1;
}
}
static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name, IWTSPlugin* pPlugin)
{
DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman;
if (dvcman->num_plugins < MAX_PLUGINS)
{
WLog_DBG(TAG, "num_plugins %d", dvcman->num_plugins);
dvcman->plugin_names[dvcman->num_plugins] = name;
dvcman->plugins[dvcman->num_plugins++] = pPlugin;
return 0;
}
else
{
WLog_WARN(TAG, "Maximum DVC plugin number reached.");
return 1;
}
}
IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name)
{
int i;
DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman;
for (i = 0; i < dvcman->num_plugins; i++)
{
if (dvcman->plugin_names[i] == name ||
strcmp(dvcman->plugin_names[i], name) == 0)
{
return dvcman->plugins[i];
}
}
return NULL;
}
ADDIN_ARGV* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{
return ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->args;
}
void* dvcman_get_rdp_settings(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{
return (void*) ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->settings;
}
UINT32 dvcman_get_channel_id(IWTSVirtualChannel * channel)
{
return ((DVCMAN_CHANNEL*) channel)->channel_id;
}
IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
{
int index;
BOOL found = FALSE;
DVCMAN_CHANNEL* channel;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
ArrayList_Lock(dvcman->channels);
index = 0;
channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, index++);
while (channel)
{
if (channel->channel_id == ChannelId)
{
found = TRUE;
break;
}
channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, index++);
}
ArrayList_Unlock(dvcman->channels);
return (found) ? ((IWTSVirtualChannel*) channel) : NULL;
}
void* dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager* pChannelMgr, const char* ChannelName)
{
int i;
BOOL found = FALSE;
void* pInterface = NULL;
DVCMAN_LISTENER* listener;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
for (i = 0; i < dvcman->num_listeners; i++)
{
listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
if (strcmp(listener->channel_name, ChannelName) == 0)
{
pInterface = listener->iface.pInterface;
found = TRUE;
break;
}
}
return (found) ? pInterface : NULL;
}
IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
{
DVCMAN* dvcman;
dvcman = (DVCMAN*) calloc(1, sizeof(DVCMAN));
dvcman->iface.CreateListener = dvcman_create_listener;
dvcman->iface.FindChannelById = dvcman_find_channel_by_id;
dvcman->iface.GetChannelId = dvcman_get_channel_id;
dvcman->drdynvc = plugin;
dvcman->channels = ArrayList_New(TRUE);
dvcman->channels->object.fnObjectFree = dvcman_channel_free;
dvcman->pool = StreamPool_New(TRUE, 10);
return (IWTSVirtualChannelManager*) dvcman;
}
int dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args, rdpSettings* settings)
{
DVCMAN_ENTRY_POINTS entryPoints;
PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL;
WLog_INFO(TAG, "Loading Dynamic Virtual Channel %s", args->argv[0]);
pDVCPluginEntry = (PDVC_PLUGIN_ENTRY) freerdp_load_channel_addin_entry(args->argv[0],
NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC);
if (pDVCPluginEntry)
{
entryPoints.iface.RegisterPlugin = dvcman_register_plugin;
entryPoints.iface.GetPlugin = dvcman_get_plugin;
entryPoints.iface.GetPluginData = dvcman_get_plugin_data;
entryPoints.iface.GetRdpSettings = dvcman_get_rdp_settings;
entryPoints.dvcman = (DVCMAN*) pChannelMgr;
entryPoints.args = args;
entryPoints.settings = settings;
pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*) &entryPoints);
}
return 0;
}
static DVCMAN_CHANNEL* dvcman_channel_new(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName)
{
DVCMAN_CHANNEL* channel;
if (dvcman_find_channel_by_id(pChannelMgr, ChannelId))
{
WLog_ERR(TAG, "Protocol error: Duplicated ChannelId %d (%s)!", ChannelId, ChannelName);
return NULL;
}
channel = (DVCMAN_CHANNEL*) calloc(1, sizeof(DVCMAN_CHANNEL));
if (!channel)
return NULL;
channel->dvcman = (DVCMAN*) pChannelMgr;
channel->channel_id = ChannelId;
channel->channel_name = _strdup(ChannelName);
InitializeCriticalSection(&(channel->lock));
return channel;
}
void dvcman_channel_free(void* arg)
{
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) arg;
if (channel->channel_callback)
{
channel->channel_callback->OnClose(channel->channel_callback);
channel->channel_callback = NULL;
}
if (channel->dvc_data)
{
Stream_Release(channel->dvc_data);
channel->dvc_data = NULL;
}
DeleteCriticalSection(&(channel->lock));
if (channel->channel_name)
{
free(channel->channel_name);
channel->channel_name = NULL;
}
free(channel);
}
void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
{
int i;
IWTSPlugin* pPlugin;
DVCMAN_LISTENER* listener;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
ArrayList_Free(dvcman->channels);
for (i = 0; i < dvcman->num_listeners; i++)
{
listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
free(listener->channel_name);
free(listener);
}
dvcman->num_listeners = 0;
for (i = 0; i < dvcman->num_plugins; i++)
{
pPlugin = dvcman->plugins[i];
if (pPlugin->Terminated)
pPlugin->Terminated(pPlugin);
}
dvcman->num_plugins = 0;
StreamPool_Free(dvcman->pool);
free(dvcman);
}
int dvcman_init(IWTSVirtualChannelManager* pChannelMgr)
{
int i;
IWTSPlugin* pPlugin;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
for (i = 0; i < dvcman->num_plugins; i++)
{
pPlugin = dvcman->plugins[i];
if (pPlugin->Initialize)
pPlugin->Initialize(pPlugin, pChannelMgr);
}
return 0;
}
static int dvcman_write_channel(IWTSVirtualChannel* pChannel, UINT32 cbSize, BYTE* pBuffer, void* pReserved)
{
int status;
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel;
EnterCriticalSection(&(channel->lock));
status = drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize);
LeaveCriticalSection(&(channel->lock));
return status;
}
static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel)
{
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel;
WLog_DBG(TAG, "id=%d", channel->channel_id);
return 1;
}
int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName)
{
int i;
int bAccept;
DVCMAN_LISTENER* listener;
DVCMAN_CHANNEL* channel;
DrdynvcClientContext* context;
IWTSVirtualChannelCallback* pCallback;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
channel = dvcman_channel_new(pChannelMgr, ChannelId, ChannelName);
if (!channel)
return 1;
channel->status = 1;
ArrayList_Add(dvcman->channels, channel);
for (i = 0; i < dvcman->num_listeners; i++)
{
listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
if (strcmp(listener->channel_name, ChannelName) == 0)
{
channel->iface.Write = dvcman_write_channel;
channel->iface.Close = dvcman_close_channel_iface;
bAccept = 1;
pCallback = NULL;
if (listener->listener_callback->OnNewChannelConnection(listener->listener_callback,
(IWTSVirtualChannel*) channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1)
{
WLog_DBG(TAG, "listener %s created new channel %d",
listener->channel_name, channel->channel_id);
channel->status = 0;
channel->channel_callback = pCallback;
channel->pInterface = listener->iface.pInterface;
context = dvcman->drdynvc->context;
IFCALL(context->OnChannelConnected, context, ChannelName, listener->iface.pInterface);
return 0;
}
}
}
return 1;
}
int dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
{
DVCMAN_CHANNEL* channel;
IWTSVirtualChannelCallback* pCallback;
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
if (!channel)
{
WLog_ERR(TAG, "ChannelId %d not found!", ChannelId);
return 1;
}
if (channel->status == 0)
{
pCallback = channel->channel_callback;
if (pCallback->OnOpen)
pCallback->OnOpen(pCallback);
}
return 0;
}
int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
{
DVCMAN_CHANNEL* channel;
IWTSVirtualChannel* ichannel;
DrdynvcClientContext* context;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
if (!channel)
{
WLog_ERR(TAG, "ChannelId %d not found!", ChannelId);
return 1;
}
if (channel->status == 0)
{
context = dvcman->drdynvc->context;
IFCALL(context->OnChannelDisconnected, context, channel->channel_name, channel->pInterface);
WLog_DBG(TAG, "dvcman_close_channel: channel %d closed", ChannelId);
ichannel = (IWTSVirtualChannel*) channel;
if (ichannel->Close)
ichannel->Close(ichannel);
}
ArrayList_Remove(dvcman->channels, channel);
return 0;
}
int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, UINT32 length)
{
DVCMAN_CHANNEL* channel;
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
if (!channel)
{
WLog_ERR(TAG, "ChannelId %d not found!", ChannelId);
return 1;
}
if (channel->dvc_data)
Stream_Release(channel->dvc_data);
channel->dvc_data = StreamPool_Take(channel->dvcman->pool, length);
channel->dvc_data_length = length;
return 0;
}
int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream* data)
{
int status = 0;
DVCMAN_CHANNEL* channel;
UINT32 dataSize = Stream_GetRemainingLength(data);
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
if (!channel)
{
WLog_ERR(TAG, "ChannelId %d not found!", ChannelId);
return 1;
}
if (channel->dvc_data)
{
/* Fragmented data */
if (Stream_GetPosition(channel->dvc_data) + dataSize > (UINT32) Stream_Capacity(channel->dvc_data))
{
WLog_ERR(TAG, "data exceeding declared length!");
Stream_Release(channel->dvc_data);
channel->dvc_data = NULL;
return 1;
}
Stream_Write(channel->dvc_data, Stream_Pointer(data), dataSize);
if (((size_t) Stream_GetPosition(channel->dvc_data)) >= channel->dvc_data_length)
{
Stream_SealLength(channel->dvc_data);
Stream_SetPosition(channel->dvc_data, 0);
status = channel->channel_callback->OnDataReceived(channel->channel_callback, channel->dvc_data);
Stream_Release(channel->dvc_data);
channel->dvc_data = NULL;
}
}
else
{
status = channel->channel_callback->OnDataReceived(channel->channel_callback, data);
}
return status;
}
static int drdynvc_write_variable_uint(wStream* s, UINT32 val)
{
int cb;
@ -70,7 +553,8 @@ int drdynvc_send(drdynvcPlugin* drdynvc, wStream* s)
if (status != CHANNEL_RC_OK)
{
Stream_Free(s, TRUE);
WLog_ERR(TAG, "drdynvc_send: VirtualChannelWrite failed %d", status);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(status), status);
}
return status;
@ -85,7 +569,7 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN
UINT32 chunkLength;
int status;
DEBUG_DVC("ChannelId=%d size=%d", ChannelId, dataSize);
WLog_DBG(TAG, "ChannelId=%d size=%d", ChannelId, dataSize);
if (drdynvc->channel_error != CHANNEL_RC_OK)
return 1;
@ -159,7 +643,8 @@ int drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, BYTE* data, UIN
if (status != CHANNEL_RC_OK)
{
drdynvc->channel_error = status;
WLog_ERR(TAG, "VirtualChannelWrite failed %d", status);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(status), status);
return 1;
}
@ -179,7 +664,8 @@ static int drdynvc_send_capability_response(drdynvcPlugin* drdynvc)
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "VirtualChannelWrite failed %d", status);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(status), status);
return 1;
}
@ -190,7 +676,7 @@ static int drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, in
{
int status;
DEBUG_DVC("Sp=%d cbChId=%d", Sp, cbChId);
WLog_DBG(TAG, "Sp=%d cbChId=%d", Sp, cbChId);
Stream_Seek(s, 1); /* pad */
Stream_Read_UINT16(s, drdynvc->version);
@ -260,7 +746,7 @@ static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cb
ChannelId = drdynvc_read_variable_uint(s, cbChId);
pos = Stream_GetPosition(s);
DEBUG_DVC("ChannelId=%d ChannelName=%s", ChannelId, Stream_Pointer(s));
WLog_DBG(TAG, "ChannelId=%d ChannelName=%s", ChannelId, Stream_Pointer(s));
channel_status = dvcman_create_channel(drdynvc->channel_mgr, ChannelId, (char*) Stream_Pointer(s));
@ -271,20 +757,22 @@ static int drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cb
if (channel_status == 0)
{
DEBUG_DVC("channel created");
WLog_DBG(TAG, "channel created");
Stream_Write_UINT32(data_out, 0);
}
else
{
DEBUG_DVC("no listener");
WLog_DBG(TAG, "no listener");
Stream_Write_UINT32(data_out, (UINT32)(-1));
dvcman_close_channel(drdynvc->channel_mgr, ChannelId);
}
status = drdynvc_send(drdynvc, data_out);
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "VirtualChannelWrite failed %d", status);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(status), status);
return 1;
}
@ -304,7 +792,7 @@ static int drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp, int cbChId
ChannelId = drdynvc_read_variable_uint(s, cbChId);
Length = drdynvc_read_variable_uint(s, Sp);
DEBUG_DVC("ChannelId=%d Length=%d", ChannelId, Length);
WLog_DBG(TAG, "ChannelId=%d Length=%d", ChannelId, Length);
status = dvcman_receive_channel_data_first(drdynvc->channel_mgr, ChannelId, Length);
@ -319,7 +807,7 @@ static int drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStr
UINT32 ChannelId;
ChannelId = drdynvc_read_variable_uint(s, cbChId);
DEBUG_DVC("ChannelId=%d", ChannelId);
WLog_DBG(TAG, "ChannelId=%d", ChannelId);
return dvcman_receive_channel_data(drdynvc->channel_mgr, ChannelId, s);
}
@ -332,7 +820,9 @@ static int drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbC
wStream* data_out;
ChannelId = drdynvc_read_variable_uint(s, cbChId);
DEBUG_DVC("ChannelId=%d", ChannelId);
WLog_DBG(TAG, "ChannelId=%d", ChannelId);
dvcman_close_channel(drdynvc->channel_mgr, ChannelId);
data_out = Stream_New(NULL, 4);
@ -345,7 +835,8 @@ static int drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbC
if (error != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "VirtualChannelWrite failed %d", error);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(error), error);
return 1;
}
@ -367,7 +858,7 @@ static void drdynvc_order_recv(drdynvcPlugin* drdynvc, wStream* s)
Sp = (value & 0x0c) >> 2;
cbChId = (value & 0x03) >> 0;
DEBUG_DVC("Cmd=0x%x", Cmd);
WLog_DBG(TAG, "Cmd=0x%x", Cmd);
switch (Cmd)
{
@ -399,8 +890,8 @@ static void drdynvc_order_recv(drdynvcPlugin* drdynvc, wStream* s)
/****************************************************************************************/
static wListDictionary* g_InitHandles;
static wListDictionary* g_OpenHandles;
static wListDictionary* g_InitHandles = NULL;
static wListDictionary* g_OpenHandles = NULL;
void drdynvc_add_init_handle_data(void* pInitHandle, void* pUserData)
{
@ -420,6 +911,11 @@ void* drdynvc_get_init_handle_data(void* pInitHandle)
void drdynvc_remove_init_handle_data(void* pInitHandle)
{
ListDictionary_Remove(g_InitHandles, pInitHandle);
if (ListDictionary_Count(g_InitHandles) < 1)
{
ListDictionary_Free(g_InitHandles);
g_InitHandles = NULL;
}
}
void drdynvc_add_open_handle_data(DWORD openHandle, void* pUserData)
@ -444,6 +940,11 @@ void drdynvc_remove_open_handle_data(DWORD openHandle)
{
void* pOpenHandle = (void*) (size_t) openHandle;
ListDictionary_Remove(g_OpenHandles, pOpenHandle);
if (ListDictionary_Count(g_OpenHandles) < 1)
{
ListDictionary_Free(g_OpenHandles);
g_OpenHandles = NULL;
}
}
static void drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc,
@ -472,14 +973,14 @@ static void drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc,
{
if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
{
WLog_ERR(TAG, "drdynvc_plugin_process_received: read error");
WLog_ERR(TAG, "drdynvc_plugin_process_received: read error");
}
drdynvc->data_in = NULL;
Stream_SealLength(data_in);
Stream_SetPosition(data_in, 0);
MessageQueue_Post(drdynvc->MsgPipe->In, NULL, 0, (void*) data_in, NULL);
MessageQueue_Post(drdynvc->queue, NULL, 0, (void*) data_in, NULL);
}
}
@ -492,7 +993,7 @@ static VOID VCAPITYPE drdynvc_virtual_channel_open_event(DWORD openHandle, UINT
if (!drdynvc)
{
WLog_ERR(TAG, "drdynvc_virtual_channel_open_event: error no match");
WLog_ERR(TAG, "drdynvc_virtual_channel_open_event: error no match");
return;
}
@ -519,10 +1020,10 @@ static void* drdynvc_virtual_channel_client_thread(void* arg)
while (1)
{
if (!MessageQueue_Wait(drdynvc->MsgPipe->In))
if (!MessageQueue_Wait(drdynvc->queue))
break;
if (MessageQueue_Peek(drdynvc->MsgPipe->In, &message, TRUE))
if (MessageQueue_Peek(drdynvc->queue, &message, TRUE))
{
if (message.id == WMQ_QUIT)
break;
@ -531,6 +1032,7 @@ static void* drdynvc_virtual_channel_client_thread(void* arg)
{
data = (wStream*) message.wParam;
drdynvc_order_recv(drdynvc, data);
Stream_Free(data, TRUE);
}
}
}
@ -553,11 +1055,12 @@ static void drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "drdynvc_virtual_channel_event_connected: open failed: status: %d", status);
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
WTSErrorToString(status), status);
return;
}
drdynvc->MsgPipe = MessagePipe_New();
drdynvc->queue = MessageQueue_New(NULL);
drdynvc->channel_mgr = dvcman_new(drdynvc);
drdynvc->channel_error = 0;
@ -578,15 +1081,26 @@ static void drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO
(LPTHREAD_START_ROUTINE) drdynvc_virtual_channel_client_thread, (void*) drdynvc, 0, NULL);
}
static void drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc)
static void drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc)
{
MessagePipe_PostQuit(drdynvc->MsgPipe, 0);
UINT status;
MessageQueue_PostQuit(drdynvc->queue, 0);
WaitForSingleObject(drdynvc->thread, INFINITE);
MessagePipe_Free(drdynvc->MsgPipe);
MessageQueue_Free(drdynvc->queue);
CloseHandle(drdynvc->thread);
drdynvc->channelEntryPoints.pVirtualChannelClose(drdynvc->OpenHandle);
drdynvc->queue = NULL;
drdynvc->thread = NULL;
status = drdynvc->channelEntryPoints.pVirtualChannelClose(drdynvc->OpenHandle);
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
WTSErrorToString(status), status);
}
if (drdynvc->data_in)
{
@ -601,7 +1115,12 @@ static void drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc)
}
drdynvc_remove_open_handle_data(drdynvc->OpenHandle);
}
static void drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc)
{
drdynvc_remove_init_handle_data(drdynvc->InitHandle);
free(drdynvc);
}
static VOID VCAPITYPE drdynvc_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
@ -612,7 +1131,7 @@ static VOID VCAPITYPE drdynvc_virtual_channel_init_event(LPVOID pInitHandle, UIN
if (!drdynvc)
{
WLog_ERR(TAG, "drdynvc_virtual_channel_init_event: error no match");
WLog_ERR(TAG, "drdynvc_virtual_channel_init_event: error no match");
return;
}
@ -623,6 +1142,7 @@ static VOID VCAPITYPE drdynvc_virtual_channel_init_event(LPVOID pInitHandle, UIN
break;
case CHANNEL_EVENT_DISCONNECTED:
drdynvc_virtual_channel_event_disconnected(drdynvc);
break;
case CHANNEL_EVENT_TERMINATED:
@ -646,6 +1166,7 @@ int drdynvc_get_version(DrdynvcClientContext* context)
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
UINT rc;
drdynvcPlugin* drdynvc;
DrdynvcClientContext* context;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
@ -693,8 +1214,15 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
CopyMemory(&(drdynvc->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
drdynvc->channelEntryPoints.pVirtualChannelInit(&drdynvc->InitHandle,
rc = drdynvc->channelEntryPoints.pVirtualChannelInit(&drdynvc->InitHandle,
&drdynvc->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, drdynvc_virtual_channel_init_event);
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
WTSErrorToString(rc), rc);
free(drdynvc);
return -1;
}
drdynvc->channelEntryPoints.pInterface = *(drdynvc->channelEntryPoints.ppInterface);
drdynvc->channelEntryPoints.ppInterface = &(drdynvc->channelEntryPoints.pInterface);

View File

@ -21,12 +21,77 @@
#define __DRDYNVC_MAIN_H
#include <winpr/wlog.h>
#include <winpr/synch.h>
#include <freerdp/settings.h>
#include <winpr/collections.h>
#include <freerdp/api.h>
#include <freerdp/svc.h>
#include <freerdp/dvc.h>
#include <freerdp/addin.h>
#include <freerdp/channels/log.h>
#include <freerdp/client/drdynvc.h>
typedef struct drdynvc_plugin drdynvcPlugin;
#define MAX_PLUGINS 32
struct _DVCMAN
{
IWTSVirtualChannelManager iface;
drdynvcPlugin* drdynvc;
int num_plugins;
const char* plugin_names[MAX_PLUGINS];
IWTSPlugin* plugins[MAX_PLUGINS];
int num_listeners;
IWTSListener* listeners[MAX_PLUGINS];
wArrayList* channels;
wStreamPool* pool;
};
typedef struct _DVCMAN DVCMAN;
struct _DVCMAN_LISTENER
{
IWTSListener iface;
DVCMAN* dvcman;
char* channel_name;
UINT32 flags;
IWTSListenerCallback* listener_callback;
};
typedef struct _DVCMAN_LISTENER DVCMAN_LISTENER;
struct _DVCMAN_ENTRY_POINTS
{
IDRDYNVC_ENTRY_POINTS iface;
DVCMAN* dvcman;
ADDIN_ARGV* args;
rdpSettings* settings;
};
typedef struct _DVCMAN_ENTRY_POINTS DVCMAN_ENTRY_POINTS;
struct _DVCMAN_CHANNEL
{
IWTSVirtualChannel iface;
int status;
DVCMAN* dvcman;
void* pInterface;
UINT32 channel_id;
char* channel_name;
IWTSVirtualChannelCallback* channel_callback;
wStream* dvc_data;
UINT32 dvc_data_length;
CRITICAL_SECTION lock;
};
typedef struct _DVCMAN_CHANNEL DVCMAN_CHANNEL;
enum _DRDYNVC_STATE
{
DRDYNVC_STATE_INITIAL,
@ -54,7 +119,7 @@ struct drdynvc_plugin
wStream* data_in;
void* InitHandle;
DWORD OpenHandle;
wMessagePipe* MsgPipe;
wMessageQueue* queue;
DRDYNVC_STATE state;
DrdynvcClientContext* context;
@ -68,7 +133,6 @@ struct drdynvc_plugin
IWTSVirtualChannelManager* channel_mgr;
};
typedef struct drdynvc_plugin drdynvcPlugin;
int drdynvc_write_data(drdynvcPlugin* plugin, UINT32 ChannelId, BYTE* data, UINT32 data_size);

View File

@ -1,38 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Dynamic Virtual Channel
*
* Copyright 2010-2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __DRDYNVC_TYPES_H
#define __DRDYNVC_TYPES_H
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <freerdp/dvc.h>
#include <freerdp/types.h>
#include <freerdp/channels/log.h>
#define TAG CHANNELS_TAG("dvcman.client")
#ifdef WITH_DEBUG_DVC
#define DEBUG_DVC(fmt, ...) WLog_DBG(TAG, fmt, ## __VA_ARGS__)
#else
#define DEBUG_DVC(fmt, ...) do { } while (0)
#endif
#endif

View File

@ -1,504 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Dynamic Virtual Channel Manager
*
* Copyright 2010-2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/stream.h>
#include <freerdp/addin.h>
#include "drdynvc_types.h"
#include "dvcman.h"
static int dvcman_get_configuration(IWTSListener* pListener, void** ppPropertyBag)
{
*ppPropertyBag = NULL;
return 1;
}
static int dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr,
const char* pszChannelName, UINT32 ulFlags,
IWTSListenerCallback* pListenerCallback, IWTSListener** ppListener)
{
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
DVCMAN_LISTENER* listener;
if (dvcman->num_listeners < MAX_PLUGINS)
{
DEBUG_DVC("%d.%s.", dvcman->num_listeners, pszChannelName);
listener = (DVCMAN_LISTENER*) malloc(sizeof(DVCMAN_LISTENER));
ZeroMemory(listener, sizeof(DVCMAN_LISTENER));
listener->iface.GetConfiguration = dvcman_get_configuration;
listener->iface.pInterface = NULL;
listener->dvcman = dvcman;
listener->channel_name = _strdup(pszChannelName);
listener->flags = ulFlags;
listener->listener_callback = pListenerCallback;
if (ppListener)
*ppListener = (IWTSListener*) listener;
dvcman->listeners[dvcman->num_listeners++] = (IWTSListener*) listener;
return 0;
}
else
{
WLog_WARN(TAG, "Maximum DVC listener number reached.");
return 1;
}
}
static int dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name, IWTSPlugin* pPlugin)
{
DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman;
if (dvcman->num_plugins < MAX_PLUGINS)
{
DEBUG_DVC("num_plugins %d", dvcman->num_plugins);
dvcman->plugin_names[dvcman->num_plugins] = name;
dvcman->plugins[dvcman->num_plugins++] = pPlugin;
return 0;
}
else
{
WLog_WARN(TAG, "Maximum DVC plugin number reached.");
return 1;
}
}
IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name)
{
int i;
DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman;
for (i = 0; i < dvcman->num_plugins; i++)
{
if (dvcman->plugin_names[i] == name ||
strcmp(dvcman->plugin_names[i], name) == 0)
{
return dvcman->plugins[i];
}
}
return NULL;
}
ADDIN_ARGV* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{
return ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->args;
}
void* dvcman_get_rdp_settings(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
{
return (void*) ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->settings;
}
UINT32 dvcman_get_channel_id(IWTSVirtualChannel * channel)
{
return ((DVCMAN_CHANNEL*) channel)->channel_id;
}
IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
{
int index;
BOOL found = FALSE;
DVCMAN_CHANNEL* channel;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
ArrayList_Lock(dvcman->channels);
index = 0;
channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, index++);
while (channel)
{
if (channel->channel_id == ChannelId)
{
found = TRUE;
break;
}
channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, index++);
}
ArrayList_Unlock(dvcman->channels);
return (found) ? ((IWTSVirtualChannel*) channel) : NULL;
}
void* dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager* pChannelMgr, const char* ChannelName)
{
int i;
BOOL found = FALSE;
void* pInterface = NULL;
DVCMAN_LISTENER* listener;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
for (i = 0; i < dvcman->num_listeners; i++)
{
listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
if (strcmp(listener->channel_name, ChannelName) == 0)
{
pInterface = listener->iface.pInterface;
found = TRUE;
break;
}
}
return (found) ? pInterface : NULL;
}
IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
{
DVCMAN* dvcman;
dvcman = (DVCMAN*) calloc(1, sizeof(DVCMAN));
dvcman->iface.CreateListener = dvcman_create_listener;
dvcman->iface.FindChannelById = dvcman_find_channel_by_id;
dvcman->iface.GetChannelId = dvcman_get_channel_id;
dvcman->drdynvc = plugin;
dvcman->channels = ArrayList_New(TRUE);
dvcman->pool = StreamPool_New(TRUE, 10);
return (IWTSVirtualChannelManager*) dvcman;
}
int dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args, rdpSettings* settings)
{
DVCMAN_ENTRY_POINTS entryPoints;
PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL;
WLog_INFO(TAG, "Loading Dynamic Virtual Channel %s", args->argv[0]);
pDVCPluginEntry = (PDVC_PLUGIN_ENTRY) freerdp_load_channel_addin_entry(args->argv[0],
NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC);
if (pDVCPluginEntry)
{
entryPoints.iface.RegisterPlugin = dvcman_register_plugin;
entryPoints.iface.GetPlugin = dvcman_get_plugin;
entryPoints.iface.GetPluginData = dvcman_get_plugin_data;
entryPoints.iface.GetRdpSettings = dvcman_get_rdp_settings;
entryPoints.dvcman = (DVCMAN*) pChannelMgr;
entryPoints.args = args;
entryPoints.settings = settings;
pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*) &entryPoints);
}
return 0;
}
static void dvcman_channel_free(DVCMAN_CHANNEL* channel)
{
if (channel->channel_callback)
channel->channel_callback->OnClose(channel->channel_callback);
DeleteCriticalSection(&(channel->lock));
free(channel);
}
void dvcman_free(IWTSVirtualChannelManager* pChannelMgr)
{
int i;
int count;
IWTSPlugin* pPlugin;
DVCMAN_LISTENER* listener;
DVCMAN_CHANNEL* channel;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
ArrayList_Lock(dvcman->channels);
count = ArrayList_Count(dvcman->channels);
for (i = 0; i < count; i++)
{
channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, i);
dvcman_channel_free(channel);
}
ArrayList_Unlock(dvcman->channels);
ArrayList_Free(dvcman->channels);
for (i = 0; i < dvcman->num_listeners; i++)
{
listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
free(listener->channel_name);
free(listener);
}
for (i = 0; i < dvcman->num_plugins; i++)
{
pPlugin = dvcman->plugins[i];
if (pPlugin->Terminated)
pPlugin->Terminated(pPlugin);
}
StreamPool_Free(dvcman->pool);
free(dvcman);
}
int dvcman_init(IWTSVirtualChannelManager* pChannelMgr)
{
int i;
IWTSPlugin* pPlugin;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
for (i = 0; i < dvcman->num_plugins; i++)
{
pPlugin = dvcman->plugins[i];
if (pPlugin->Initialize)
pPlugin->Initialize(pPlugin, pChannelMgr);
}
return 0;
}
static int dvcman_write_channel(IWTSVirtualChannel* pChannel, UINT32 cbSize, BYTE* pBuffer, void* pReserved)
{
int status;
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel;
EnterCriticalSection(&(channel->lock));
status = drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize);
LeaveCriticalSection(&(channel->lock));
return status;
}
static int dvcman_close_channel_iface(IWTSVirtualChannel* pChannel)
{
DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel;
DVCMAN* dvcman = channel->dvcman;
DEBUG_DVC("id=%d", channel->channel_id);
ArrayList_Remove(dvcman->channels, channel);
dvcman_channel_free(channel);
return 1;
}
int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName)
{
int i;
int bAccept;
DVCMAN_LISTENER* listener;
DVCMAN_CHANNEL* channel;
DrdynvcClientContext* context;
IWTSVirtualChannelCallback* pCallback;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
channel = (DVCMAN_CHANNEL*) calloc(1, sizeof(DVCMAN_CHANNEL));
if (!channel)
return -1;
channel->dvcman = dvcman;
channel->channel_id = ChannelId;
channel->channel_name = _strdup(ChannelName);
for (i = 0; i < dvcman->num_listeners; i++)
{
listener = (DVCMAN_LISTENER*) dvcman->listeners[i];
if (strcmp(listener->channel_name, ChannelName) == 0)
{
channel->iface.Write = dvcman_write_channel;
channel->iface.Close = dvcman_close_channel_iface;
InitializeCriticalSection(&(channel->lock));
bAccept = 1;
pCallback = NULL;
if (listener->listener_callback->OnNewChannelConnection(listener->listener_callback,
(IWTSVirtualChannel*) channel, NULL, &bAccept, &pCallback) == 0 && bAccept == 1)
{
DEBUG_DVC("listener %s created new channel %d",
listener->channel_name, channel->channel_id);
channel->status = 0;
channel->channel_callback = pCallback;
channel->pInterface = listener->iface.pInterface;
ArrayList_Add(dvcman->channels, channel);
context = dvcman->drdynvc->context;
IFCALL(context->OnChannelConnected, context, ChannelName, listener->iface.pInterface);
return 0;
}
else
{
WLog_ERR(TAG, "channel rejected by plugin");
free(channel);
return 1;
}
}
}
free(channel);
return 1;
}
int dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
{
DVCMAN_CHANNEL* channel;
IWTSVirtualChannelCallback* pCallback;
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
if (!channel)
{
WLog_ERR(TAG, "ChannelId %d not found!", ChannelId);
return 1;
}
if (channel->status == 0)
{
pCallback = channel->channel_callback;
if (pCallback->OnOpen)
pCallback->OnOpen(pCallback);
}
return 0;
}
int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId)
{
DVCMAN_CHANNEL* channel;
IWTSVirtualChannel* ichannel;
DrdynvcClientContext* context;
DVCMAN* dvcman = (DVCMAN*) pChannelMgr;
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
if (!channel)
{
WLog_ERR(TAG, "ChannelId %d not found!", ChannelId);
return 1;
}
if (channel->dvc_data)
{
Stream_Release(channel->dvc_data);
channel->dvc_data = NULL;
}
if (channel->status == 0)
{
context = dvcman->drdynvc->context;
IFCALL(context->OnChannelDisconnected, context, channel->channel_name, channel->pInterface);
free(channel->channel_name);
DEBUG_DVC("dvcman_close_channel: channel %d closed", ChannelId);
ichannel = (IWTSVirtualChannel*) channel;
ichannel->Close(ichannel);
}
return 0;
}
int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, UINT32 length)
{
DVCMAN_CHANNEL* channel;
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
if (!channel)
{
WLog_ERR(TAG, "ChannelId %d not found!", ChannelId);
return 1;
}
if (channel->dvc_data)
Stream_Release(channel->dvc_data);
channel->dvc_data = StreamPool_Take(channel->dvcman->pool, length);
channel->dvc_data_length = length;
return 0;
}
int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream* data)
{
int status = 0;
DVCMAN_CHANNEL* channel;
UINT32 dataSize = Stream_GetRemainingLength(data);
channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId);
if (!channel)
{
WLog_ERR(TAG, "ChannelId %d not found!", ChannelId);
return 1;
}
if (channel->dvc_data)
{
/* Fragmented data */
if (Stream_GetPosition(channel->dvc_data) + dataSize > (UINT32) Stream_Capacity(channel->dvc_data))
{
WLog_ERR(TAG, "data exceeding declared length!");
Stream_Release(channel->dvc_data);
channel->dvc_data = NULL;
return 1;
}
Stream_Write(channel->dvc_data, Stream_Pointer(data), dataSize);
if (((size_t) Stream_GetPosition(channel->dvc_data)) >= channel->dvc_data_length)
{
Stream_SealLength(channel->dvc_data);
Stream_SetPosition(channel->dvc_data, 0);
status = channel->channel_callback->OnDataReceived(channel->channel_callback, channel->dvc_data);
Stream_Release(channel->dvc_data);
channel->dvc_data = NULL;
}
}
else
{
status = channel->channel_callback->OnDataReceived(channel->channel_callback, data);
}
return status;
}

View File

@ -1,103 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Dynamic Virtual Channel Manager
*
* Copyright 2010-2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __DVCMAN_H
#define __DVCMAN_H
#include <freerdp/dvc.h>
#include <freerdp/addin.h>
#include <freerdp/settings.h>
#include <winpr/synch.h>
#include <winpr/collections.h>
#include "drdynvc_main.h"
#define MAX_PLUGINS 32
struct _DVCMAN
{
IWTSVirtualChannelManager iface;
drdynvcPlugin* drdynvc;
int num_plugins;
const char* plugin_names[MAX_PLUGINS];
IWTSPlugin* plugins[MAX_PLUGINS];
int num_listeners;
IWTSListener* listeners[MAX_PLUGINS];
wArrayList* channels;
wStreamPool* pool;
};
typedef struct _DVCMAN DVCMAN;
struct _DVCMAN_LISTENER
{
IWTSListener iface;
DVCMAN* dvcman;
char* channel_name;
UINT32 flags;
IWTSListenerCallback* listener_callback;
};
typedef struct _DVCMAN_LISTENER DVCMAN_LISTENER;
struct _DVCMAN_ENTRY_POINTS
{
IDRDYNVC_ENTRY_POINTS iface;
DVCMAN* dvcman;
ADDIN_ARGV* args;
rdpSettings* settings;
};
typedef struct _DVCMAN_ENTRY_POINTS DVCMAN_ENTRY_POINTS;
struct _DVCMAN_CHANNEL
{
IWTSVirtualChannel iface;
int status;
DVCMAN* dvcman;
void* pInterface;
UINT32 channel_id;
char* channel_name;
IWTSVirtualChannelCallback* channel_callback;
wStream* dvc_data;
UINT32 dvc_data_length;
CRITICAL_SECTION lock;
};
typedef struct _DVCMAN_CHANNEL DVCMAN_CHANNEL;
IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin);
int dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args, rdpSettings* settings);
void dvcman_free(IWTSVirtualChannelManager* pChannelMgr);
int dvcman_init(IWTSVirtualChannelManager* pChannelMgr);
int dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName);
int dvcman_open_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId);
int dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId);
int dvcman_receive_channel_data_first(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, UINT32 length);
int dvcman_receive_channel_data(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, wStream *data);
void* dvcman_get_channel_interface_by_name(IWTSVirtualChannelManager* pChannelMgr, const char* ChannelName);
#endif

View File

@ -487,7 +487,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
int status;
char* fullpath;
struct STAT st;
#if defined(__linux__) && !defined(ANDROID)
#if defined(__linux__) && !defined(ANDROID) || defined(sun)
struct timespec tv[2];
#else
struct timeval tv[2];
@ -519,7 +519,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
tv[0].tv_usec = 0;
tv[1].tv_usec = 0;
utimes(file->fullpath, tv);
#elif defined (__linux__)
#elif defined (__linux__) || defined (sun)
tv[0].tv_nsec = 0;
tv[1].tv_nsec = 0;
futimens(file->fd, tv);

View File

@ -620,6 +620,9 @@ static void drive_free(DEVICE* device)
CloseHandle(drive->thread);
ListDictionary_Free(drive->files);
MessageQueue_Free(drive->IrpQueue);
Stream_Free(drive->device.data, TRUE);
free(drive);
}

View File

@ -92,7 +92,8 @@ int encomsp_virtual_channel_write(encomspPlugin* encomsp, wStream* s)
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "encomsp_virtual_channel_write: VirtualChannelWrite failed %d", status);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(status), status);
return -1;
}
@ -658,8 +659,8 @@ static void encomsp_process_connect(encomspPlugin* encomsp)
/****************************************************************************************/
static wListDictionary* g_InitHandles;
static wListDictionary* g_OpenHandles;
static wListDictionary* g_InitHandles = NULL;
static wListDictionary* g_OpenHandles = NULL;
void encomsp_add_init_handle_data(void* pInitHandle, void* pUserData)
{
@ -679,6 +680,11 @@ void* encomsp_get_init_handle_data(void* pInitHandle)
void encomsp_remove_init_handle_data(void* pInitHandle)
{
ListDictionary_Remove(g_InitHandles, pInitHandle);
if (ListDictionary_Count(g_InitHandles) < 1)
{
ListDictionary_Free(g_InitHandles);
g_InitHandles = NULL;
}
}
void encomsp_add_open_handle_data(DWORD openHandle, void* pUserData)
@ -703,6 +709,11 @@ void encomsp_remove_open_handle_data(DWORD openHandle)
{
void* pOpenHandle = (void*) (size_t) openHandle;
ListDictionary_Remove(g_OpenHandles, pOpenHandle);
if (ListDictionary_Count(g_OpenHandles) < 1)
{
ListDictionary_Free(g_OpenHandles);
g_OpenHandles = NULL;
}
}
int encomsp_send(encomspPlugin* encomsp, wStream* s)
@ -723,7 +734,8 @@ int encomsp_send(encomspPlugin* encomsp, wStream* s)
if (status != CHANNEL_RC_OK)
{
Stream_Free(s, TRUE);
WLog_ERR(TAG, "encomsp_send: VirtualChannelWrite failed %d", status);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(status), status);
}
return status;
@ -762,7 +774,7 @@ static void encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp,
Stream_SealLength(data_in);
Stream_SetPosition(data_in, 0);
MessageQueue_Post(encomsp->MsgPipe->In, NULL, 0, (void*) data_in, NULL);
MessageQueue_Post(encomsp->queue, NULL, 0, (void*) data_in, NULL);
}
}
@ -804,10 +816,10 @@ static void* encomsp_virtual_channel_client_thread(void* arg)
while (1)
{
if (!MessageQueue_Wait(encomsp->MsgPipe->In))
if (!MessageQueue_Wait(encomsp->queue))
break;
if (MessageQueue_Peek(encomsp->MsgPipe->In, &message, TRUE))
if (MessageQueue_Peek(encomsp->queue, &message, TRUE))
{
if (message.id == WMQ_QUIT)
break;
@ -835,25 +847,35 @@ static void encomsp_virtual_channel_event_connected(encomspPlugin* encomsp, LPVO
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "encomsp_virtual_channel_event_connected: open failed: status: %d", status);
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
WTSErrorToString(status), status);
return;
}
encomsp->MsgPipe = MessagePipe_New();
encomsp->queue = MessageQueue_New(NULL);
encomsp->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) encomsp_virtual_channel_client_thread, (void*) encomsp, 0, NULL);
}
static void encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp)
static void encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp)
{
MessagePipe_PostQuit(encomsp->MsgPipe, 0);
UINT rc;
MessageQueue_PostQuit(encomsp->queue, 0);
WaitForSingleObject(encomsp->thread, INFINITE);
MessagePipe_Free(encomsp->MsgPipe);
MessageQueue_Free(encomsp->queue);
CloseHandle(encomsp->thread);
encomsp->channelEntryPoints.pVirtualChannelClose(encomsp->OpenHandle);
encomsp->queue = NULL;
encomsp->thread = NULL;
rc = encomsp->channelEntryPoints.pVirtualChannelClose(encomsp->OpenHandle);
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
WTSErrorToString(rc), rc);
}
if (encomsp->data_in)
{
@ -862,7 +884,13 @@ static void encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp)
}
encomsp_remove_open_handle_data(encomsp->OpenHandle);
}
static void encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp)
{
encomsp_remove_init_handle_data(encomsp->InitHandle);
free(encomsp);
}
static VOID VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
@ -884,6 +912,7 @@ static VOID VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle, UIN
break;
case CHANNEL_EVENT_DISCONNECTED:
encomsp_virtual_channel_event_disconnected(encomsp);
break;
case CHANNEL_EVENT_TERMINATED:
@ -897,6 +926,7 @@ static VOID VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle, UIN
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
UINT rc;
encomspPlugin* encomsp;
EncomspClientContext* context;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
@ -933,13 +963,20 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
context->GraphicsStreamResumed = NULL;
*(pEntryPointsEx->ppInterface) = (void*) context;
encomsp->context = context;
}
CopyMemory(&(encomsp->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
encomsp->channelEntryPoints.pVirtualChannelInit(&encomsp->InitHandle,
rc = encomsp->channelEntryPoints.pVirtualChannelInit(&encomsp->InitHandle,
&encomsp->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, encomsp_virtual_channel_init_event);
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
WTSErrorToString(rc), rc);
free(encomsp);
return -1;
}
encomsp->channelEntryPoints.pInterface = *(encomsp->channelEntryPoints.ppInterface);
encomsp->channelEntryPoints.ppInterface = &(encomsp->channelEntryPoints.pInterface);

View File

@ -40,11 +40,13 @@ struct encomsp_plugin
CHANNEL_DEF channelDef;
CHANNEL_ENTRY_POINTS_FREERDP channelEntryPoints;
EncomspClientContext* context;
HANDLE thread;
wStream* data_in;
void* InitHandle;
DWORD OpenHandle;
wMessagePipe* MsgPipe;
wMessageQueue* queue;
};
typedef struct encomsp_plugin encomspPlugin;

View File

@ -55,7 +55,8 @@ int rail_send(railPlugin* rail, wStream* s)
if (status != CHANNEL_RC_OK)
{
Stream_Free(s, TRUE);
WLog_ERR(TAG, "rail_send: VirtualChannelWrite failed %d", status);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(status), status);
}
return status;
@ -313,8 +314,8 @@ int rail_server_get_appid_response(RailClientContext* context, RAIL_GET_APPID_RE
/****************************************************************************************/
static wListDictionary* g_InitHandles;
static wListDictionary* g_OpenHandles;
static wListDictionary* g_InitHandles = NULL;
static wListDictionary* g_OpenHandles = NULL;
void rail_add_init_handle_data(void* pInitHandle, void* pUserData)
{
@ -334,6 +335,11 @@ void* rail_get_init_handle_data(void* pInitHandle)
void rail_remove_init_handle_data(void* pInitHandle)
{
ListDictionary_Remove(g_InitHandles, pInitHandle);
if (ListDictionary_Count(g_InitHandles) < 1)
{
ListDictionary_Free(g_InitHandles);
g_InitHandles = NULL;
}
}
void rail_add_open_handle_data(DWORD openHandle, void* pUserData)
@ -358,6 +364,11 @@ void rail_remove_open_handle_data(DWORD openHandle)
{
void* pOpenHandle = (void*) (size_t) openHandle;
ListDictionary_Remove(g_OpenHandles, pOpenHandle);
if (ListDictionary_Count(g_OpenHandles) < 1)
{
ListDictionary_Free(g_OpenHandles);
g_OpenHandles = NULL;
}
}
static void rail_virtual_channel_event_data_received(railPlugin* rail,
@ -393,7 +404,7 @@ static void rail_virtual_channel_event_data_received(railPlugin* rail,
Stream_SealLength(data_in);
Stream_SetPosition(data_in, 0);
MessageQueue_Post(rail->MsgPipe->In, NULL, 0, (void*) data_in, NULL);
MessageQueue_Post(rail->queue, NULL, 0, (void*) data_in, NULL);
}
}
@ -433,10 +444,10 @@ static void* rail_virtual_channel_client_thread(void* arg)
while (1)
{
if (!MessageQueue_Wait(rail->MsgPipe->In))
if (!MessageQueue_Wait(rail->queue))
break;
if (MessageQueue_Peek(rail->MsgPipe->In, &message, TRUE))
if (MessageQueue_Peek(rail->queue, &message, TRUE))
{
if (message.id == WMQ_QUIT)
break;
@ -464,25 +475,35 @@ static void rail_virtual_channel_event_connected(railPlugin* rail, LPVOID pData,
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "rail_virtual_channel_event_connected: open failed: status: %d", status);
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
WTSErrorToString(status), status);
return;
}
rail->MsgPipe = MessagePipe_New();
rail->queue = MessageQueue_New(NULL);
rail->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rail_virtual_channel_client_thread, (void*) rail, 0, NULL);
}
static void rail_virtual_channel_event_terminated(railPlugin* rail)
static void rail_virtual_channel_event_disconnected(railPlugin* rail)
{
MessagePipe_PostQuit(rail->MsgPipe, 0);
UINT rc;
MessageQueue_PostQuit(rail->queue, 0);
WaitForSingleObject(rail->thread, INFINITE);
MessagePipe_Free(rail->MsgPipe);
MessageQueue_Free(rail->queue);
CloseHandle(rail->thread);
rail->channelEntryPoints.pVirtualChannelClose(rail->OpenHandle);
rail->queue = NULL;
rail->thread = NULL;
rc = rail->channelEntryPoints.pVirtualChannelClose(rail->OpenHandle);
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
WTSErrorToString(rc), rc);
}
if (rail->data_in)
{
@ -491,7 +512,12 @@ static void rail_virtual_channel_event_terminated(railPlugin* rail)
}
rail_remove_open_handle_data(rail->OpenHandle);
}
static void rail_virtual_channel_event_terminated(railPlugin* rail)
{
rail_remove_init_handle_data(rail->InitHandle);
free(rail);
}
static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
@ -513,6 +539,7 @@ static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle, UINT e
break;
case CHANNEL_EVENT_DISCONNECTED:
rail_virtual_channel_event_disconnected(rail);
break;
case CHANNEL_EVENT_TERMINATED:
@ -526,6 +553,7 @@ static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle, UINT e
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
UINT rc;
railPlugin* rail;
RailClientContext* context;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
@ -572,6 +600,7 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
context->ServerGetAppIdResponse = rail_server_get_appid_response;
*(pEntryPointsEx->ppInterface) = (void*) context;
rail->context = context;
}
WLog_Init();
@ -581,8 +610,15 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
CopyMemory(&(rail->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
rail->channelEntryPoints.pVirtualChannelInit(&rail->InitHandle,
rc = rail->channelEntryPoints.pVirtualChannelInit(&rail->InitHandle,
&rail->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rail_virtual_channel_init_event);
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
WTSErrorToString(rc), rc);
free(rail);
return -1;
}
rail->channelEntryPoints.pInterface = *(rail->channelEntryPoints.ppInterface);
rail->channelEntryPoints.ppInterface = &(rail->channelEntryPoints.pInterface);

View File

@ -39,12 +39,14 @@ struct rail_plugin
CHANNEL_DEF channelDef;
CHANNEL_ENTRY_POINTS_FREERDP channelEntryPoints;
RailClientContext* context;
wLog* log;
HANDLE thread;
wStream* data_in;
void* InitHandle;
DWORD OpenHandle;
wMessagePipe* MsgPipe;
wMessageQueue* queue;
};
typedef struct rail_plugin railPlugin;

View File

@ -75,6 +75,10 @@ IRP* irp_new(DEVMAN* devman, wStream* s)
return NULL;
irp = (IRP*) _aligned_malloc(sizeof(IRP), MEMORY_ALLOCATION_ALIGNMENT);
if (!irp)
return NULL;
ZeroMemory(irp, sizeof(IRP));
irp->input = s;

View File

@ -452,7 +452,7 @@ static void* drive_hotplug_thread_func(void* arg)
if (mfd < 0)
{
WLog_ERR(TAG, "ERROR: Unable to open /proc/mounts.");
WLog_ERR(TAG, "ERROR: Unable to open /proc/mounts.");
return NULL;
}
@ -506,8 +506,10 @@ static void rdpdr_process_connect(rdpdrPlugin* rdpdr)
rdpdr->devman = devman_new(rdpdr);
settings = (rdpSettings*) rdpdr->channelEntryPoints.pExtendedData;
strncpy(rdpdr->computerName, settings->ComputerName, sizeof(rdpdr->computerName) - 1);
if (settings->ClientHostname)
strncpy(rdpdr->computerName, settings->ClientHostname, sizeof(rdpdr->computerName) - 1);
else
strncpy(rdpdr->computerName, settings->ComputerName, sizeof(rdpdr->computerName) - 1);
for (index = 0; index < settings->DeviceCount; index++)
{
@ -539,8 +541,8 @@ static void rdpdr_send_client_announce_reply(rdpdrPlugin* rdpdr)
s = Stream_New(NULL, 12);
Stream_Write_UINT16(s, RDPDR_CTYP_CORE);
Stream_Write_UINT16(s, PAKID_CORE_CLIENTID_CONFIRM);
Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */
Stream_Write_UINT16(s, PAKID_CORE_CLIENTID_CONFIRM); /* PacketId (2 bytes) */
Stream_Write_UINT16(s, rdpdr->versionMajor);
Stream_Write_UINT16(s, rdpdr->versionMinor);
@ -562,8 +564,8 @@ static void rdpdr_send_client_name_request(rdpdrPlugin* rdpdr)
s = Stream_New(NULL, 16 + computerNameLenW + 2);
Stream_Write_UINT16(s, RDPDR_CTYP_CORE);
Stream_Write_UINT16(s, PAKID_CORE_CLIENT_NAME);
Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */
Stream_Write_UINT16(s, PAKID_CORE_CLIENT_NAME); /* PacketId (2 bytes) */
Stream_Write_UINT32(s, 1); /* unicodeFlag, 0 for ASCII and 1 for Unicode */
Stream_Write_UINT32(s, 0); /* codePage, must be set to zero */
@ -614,8 +616,8 @@ static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL use
s = Stream_New(NULL, 256);
Stream_Write_UINT16(s, RDPDR_CTYP_CORE);
Stream_Write_UINT16(s, PAKID_CORE_DEVICELIST_ANNOUNCE);
Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */
Stream_Write_UINT16(s, PAKID_CORE_DEVICELIST_ANNOUNCE); /* PacketId (2 bytes) */
count_pos = (int) Stream_GetPosition(s);
count = 0;
@ -662,7 +664,7 @@ static void rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL use
Stream_Write(s, Stream_Buffer(device->data), data_len);
count++;
WLog_INFO(TAG, "registered device #%d: %s (type=%d id=%d)\n",
WLog_INFO(TAG, "registered device #%d: %s (type=%d id=%d)",
count, device->name, device->type, device->id);
}
}
@ -716,16 +718,16 @@ static void rdpdr_process_init(rdpdrPlugin* rdpdr)
static void rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s)
{
UINT16 component;
UINT16 packetID;
UINT32 deviceID;
UINT16 packetId;
UINT32 deviceId;
UINT32 status;
Stream_Read_UINT16(s, component);
Stream_Read_UINT16(s, packetID);
Stream_Read_UINT16(s, component); /* Component (2 bytes) */
Stream_Read_UINT16(s, packetId); /* PacketId (2 bytes) */
if (component == RDPDR_CTYP_CORE)
{
switch (packetID)
switch (packetId)
{
case PAKID_CORE_SERVER_ANNOUNCE:
rdpdr_process_server_announce_request(rdpdr, s);
@ -750,7 +752,7 @@ static void rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s)
case PAKID_CORE_DEVICE_REPLY:
/* connect to a specific resource */
Stream_Read_UINT32(s, deviceID);
Stream_Read_UINT32(s, deviceId);
Stream_Read_UINT32(s, status);
break;
@ -760,17 +762,19 @@ static void rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s)
break;
default:
WLog_ERR(TAG, "RDPDR_CTYP_CORE unknown PacketId: 0x%04X", packetId);
break;
}
}
else if (component == RDPDR_CTYP_PRN)
{
WLog_ERR(TAG, "RDPDR_CTYP_PRN unknown PacketId: 0x%04X", packetId);
}
else
{
WLog_ERR(TAG, "unknown message: Component: 0x%04X PacketId: 0x%04X",
component, packetId);
}
Stream_Free(s, TRUE);
@ -780,8 +784,8 @@ static void rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s)
/****************************************************************************************/
static wListDictionary* g_InitHandles;
static wListDictionary* g_OpenHandles;
static wListDictionary* g_InitHandles = NULL;
static wListDictionary* g_OpenHandles = NULL;
void rdpdr_add_init_handle_data(void* pInitHandle, void* pUserData)
{
@ -801,6 +805,11 @@ void* rdpdr_get_init_handle_data(void* pInitHandle)
void rdpdr_remove_init_handle_data(void* pInitHandle)
{
ListDictionary_Remove(g_InitHandles, pInitHandle);
if (ListDictionary_Count(g_InitHandles) < 1)
{
ListDictionary_Free(g_InitHandles);
g_InitHandles = NULL;
}
}
void rdpdr_add_open_handle_data(DWORD openHandle, void* pUserData)
@ -825,6 +834,11 @@ void rdpdr_remove_open_handle_data(DWORD openHandle)
{
void* pOpenHandle = (void*) (size_t) openHandle;
ListDictionary_Remove(g_OpenHandles, pOpenHandle);
if (ListDictionary_Count(g_OpenHandles) < 1)
{
ListDictionary_Free(g_OpenHandles);
g_OpenHandles = NULL;
}
}
int rdpdr_send(rdpdrPlugin* rdpdr, wStream* s)
@ -845,7 +859,8 @@ int rdpdr_send(rdpdrPlugin* rdpdr, wStream* s)
if (status != CHANNEL_RC_OK)
{
Stream_Free(s, TRUE);
WLog_ERR(TAG, "rdpdr_send: VirtualChannelWrite failed %d\n", status);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(status), status);
}
return status;
@ -883,14 +898,14 @@ static void rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr,
{
if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
{
WLog_ERR(TAG, "svc_plugin_process_received: read error\n");
WLog_ERR(TAG, "rdpdr_virtual_channel_event_data_received: read error");
}
rdpdr->data_in = NULL;
Stream_SealLength(data_in);
Stream_SetPosition(data_in, 0);
MessageQueue_Post(rdpdr->MsgPipe->In, NULL, 0, (void*) data_in, NULL);
MessageQueue_Post(rdpdr->queue, NULL, 0, (void*) data_in, NULL);
}
}
@ -903,7 +918,7 @@ static VOID VCAPITYPE rdpdr_virtual_channel_open_event(DWORD openHandle, UINT ev
if (!rdpdr)
{
WLog_ERR(TAG, "rdpdr_virtual_channel_open_event: error no match\n");
WLog_ERR(TAG, "rdpdr_virtual_channel_open_event: error no match");
return;
}
@ -932,10 +947,10 @@ static void* rdpdr_virtual_channel_client_thread(void* arg)
while (1)
{
if (!MessageQueue_Wait(rdpdr->MsgPipe->In))
if (!MessageQueue_Wait(rdpdr->queue))
break;
if (MessageQueue_Peek(rdpdr->MsgPipe->In, &message, TRUE))
if (MessageQueue_Peek(rdpdr->queue, &message, TRUE))
{
if (message.id == WMQ_QUIT)
break;
@ -963,27 +978,38 @@ static void rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, LPVOID pDa
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "rdpdr_virtual_channel_event_connected: open failed: status: %d\n", status);
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
WTSErrorToString(status), status);
return;
}
rdpdr->MsgPipe = MessagePipe_New();
rdpdr->queue = MessageQueue_New(NULL);
rdpdr->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpdr_virtual_channel_client_thread, (void*) rdpdr, 0, NULL);
}
static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr)
static void rdpdr_virtual_channel_event_disconnected(rdpdrPlugin* rdpdr)
{
MessagePipe_PostQuit(rdpdr->MsgPipe, 0);
UINT rc;
MessageQueue_PostQuit(rdpdr->queue, 0);
WaitForSingleObject(rdpdr->thread, INFINITE);
MessagePipe_Free(rdpdr->MsgPipe);
MessageQueue_Free(rdpdr->queue);
CloseHandle(rdpdr->thread);
rdpdr->queue = NULL;
rdpdr->thread = NULL;
drive_hotplug_thread_terminate(rdpdr);
rdpdr->channelEntryPoints.pVirtualChannelClose(rdpdr->OpenHandle);
rc = rdpdr->channelEntryPoints.pVirtualChannelClose(rdpdr->OpenHandle);
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
WTSErrorToString(rc), rc);
}
if (rdpdr->data_in)
{
@ -998,7 +1024,13 @@ static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr)
}
rdpdr_remove_open_handle_data(rdpdr->OpenHandle);
}
static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr)
{
rdpdr_remove_init_handle_data(rdpdr->InitHandle);
free(rdpdr);
}
static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
@ -1009,7 +1041,7 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle, UINT
if (!rdpdr)
{
WLog_ERR(TAG, "rdpdr_virtual_channel_init_event: error no match\n");
WLog_ERR(TAG, "rdpdr_virtual_channel_init_event: error no match");
return;
}
@ -1020,6 +1052,7 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle, UINT
break;
case CHANNEL_EVENT_DISCONNECTED:
rdpdr_virtual_channel_event_disconnected(rdpdr);
break;
case CHANNEL_EVENT_TERMINATED:
@ -1033,6 +1066,7 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle, UINT
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
UINT rc;
rdpdrPlugin* rdpdr;
rdpdr = (rdpdrPlugin*) calloc(1, sizeof(rdpdrPlugin));
@ -1051,8 +1085,15 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
CopyMemory(&(rdpdr->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
rdpdr->channelEntryPoints.pVirtualChannelInit(&rdpdr->InitHandle,
rc = rdpdr->channelEntryPoints.pVirtualChannelInit(&rdpdr->InitHandle,
&rdpdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rdpdr_virtual_channel_init_event);
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
WTSErrorToString(rc), rc);
free(rdpdr);
return -1;
}
rdpdr_add_init_handle_data(rdpdr->InitHandle, (void*) rdpdr);

View File

@ -34,7 +34,7 @@
#include <freerdp/channels/rdpdr.h>
#include <freerdp/channels/log.h>
#define TAG CHANNELS_TAG("rdprd.client")
#define TAG CHANNELS_TAG("rdpdr.client")
typedef struct rdpdr_plugin rdpdrPlugin;
@ -47,7 +47,7 @@ struct rdpdr_plugin
wStream* data_in;
void* InitHandle;
DWORD OpenHandle;
wMessagePipe* MsgPipe;
wMessageQueue* queue;
DEVMAN* devman;

View File

@ -88,6 +88,8 @@ struct _RDPEI_PLUGIN
IWTSListener* listener;
RDPEI_LISTENER_CALLBACK* listener_callback;
RdpeiClientContext* context;
int version;
UINT16 maxTouchContacts;
UINT64 currentFrameTime;
@ -534,6 +536,8 @@ static int rdpei_plugin_terminated(IWTSPlugin* pPlugin)
if (rdpei->listener_callback)
free(rdpei->listener_callback);
free(rdpei->context);
free(rdpei);
return 0;
@ -743,7 +747,7 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
rdpei = (RDPEI_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "rdpei");
if (rdpei == NULL)
if (!rdpei)
{
size_t size;
@ -778,6 +782,7 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
rdpei->iface.pInterface = (void*) context;
error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpei", (IWTSPlugin*) rdpei);
rdpei->context = context;
}
return error;

View File

@ -126,6 +126,7 @@ void rdpei_server_context_reset(RdpeiServerContext *context)
{
RdpeiServerPrivate *priv = context->priv;
priv->channelHandle = INVALID_HANDLE_VALUE;
priv->expectedBytes = RDPINPUT_HEADER_LENGTH;
priv->waitingHeaders = TRUE;
priv->automataState = STATE_INITIAL;
@ -134,8 +135,11 @@ void rdpei_server_context_reset(RdpeiServerContext *context)
void rdpei_server_context_free(RdpeiServerContext* context)
{
Stream_Free(context->priv->inputStream, TRUE);
free(context->priv);
RdpeiServerPrivate *priv = context->priv;
if (priv->channelHandle != INVALID_HANDLE_VALUE)
WTSVirtualChannelClose(priv->channelHandle);
Stream_Free(priv->inputStream, TRUE);
free(priv);
free(context);
}

View File

@ -57,6 +57,9 @@ int rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, RDPGFX_H264_METAB
RDPGFX_RECT16* regionRect;
RDPGFX_H264_QUANT_QUALITY* quantQualityVal;
meta->regionRects = NULL;
meta->quantQualityVals = NULL;
if (Stream_GetRemainingLength(s) < 4)
return -1;

View File

@ -22,9 +22,6 @@
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/wlog.h>
@ -343,7 +340,7 @@ int rdpgfx_recv_start_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
Stream_Read_UINT32(s, pdu.timestamp); /* timestamp (4 bytes) */
Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */
WLog_Print(gfx->log, WLOG_DEBUG, "RecvStartFramePdu: frameId: %d timestamp: 0x%04X\n",
WLog_Print(gfx->log, WLOG_DEBUG, "RecvStartFramePdu: frameId: %d timestamp: 0x%04X",
pdu.frameId, pdu.timestamp);
if (context && context->StartFrame)
@ -368,7 +365,7 @@ int rdpgfx_recv_end_frame_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
Stream_Read_UINT32(s, pdu.frameId); /* frameId (4 bytes) */
WLog_Print(gfx->log, WLOG_DEBUG, "RecvEndFramePdu: frameId: %d\n", pdu.frameId);
WLog_Print(gfx->log, WLOG_DEBUG, "RecvEndFramePdu: frameId: %d", pdu.frameId);
if (context && context->EndFrame)
{
@ -955,9 +952,16 @@ static int rdpgfx_plugin_terminated(IWTSPlugin* pPlugin)
WLog_Print(gfx->log, WLOG_DEBUG, "Terminated");
if (gfx->listener_callback)
{
free(gfx->listener_callback);
gfx->listener_callback = NULL;
}
zgfx_context_free(gfx->zgfx);
if (gfx->zgfx)
{
zgfx_context_free(gfx->zgfx);
gfx->zgfx = NULL;
}
count = HashTable_GetKeys(gfx->SurfaceTable, &pKeys);
@ -994,6 +998,8 @@ static int rdpgfx_plugin_terminated(IWTSPlugin* pPlugin)
}
}
free(context);
free(gfx);
return 0;
@ -1105,7 +1111,7 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
if (!context)
{
free (gfx);
free(gfx);
return -1;
}
@ -1122,8 +1128,8 @@ int DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
if (!gfx->zgfx)
{
free (gfx);
free (context);
free(gfx);
free(context);
return -1;
}

View File

@ -64,6 +64,7 @@ struct rdpsnd_plugin
wMessagePipe* MsgPipe;
wLog* log;
HANDLE stopEvent;
HANDLE ScheduleThread;
BYTE cBlockNo;
@ -104,12 +105,13 @@ static void* rdpsnd_schedule_thread(void* arg)
UINT16 wCurrentTime;
RDPSND_WAVE* wave;
rdpsndPlugin* rdpsnd = (rdpsndPlugin*) arg;
HANDLE events[2];
while (1)
events[0] = MessageQueue_Event(rdpsnd->MsgPipe->Out);
events[1] = rdpsnd->stopEvent;
while (WaitForMultipleObjects(2, events, FALSE, INFINITE) == WAIT_OBJECT_0)
{
if (!MessageQueue_Wait(rdpsnd->MsgPipe->Out))
break;
if (!MessageQueue_Peek(rdpsnd->MsgPipe->Out, &message, TRUE))
break;
@ -132,6 +134,7 @@ static void* rdpsnd_schedule_thread(void* arg)
free(wave);
}
ExitThread(0);
return NULL;
}
@ -151,7 +154,7 @@ void rdpsnd_send_quality_mode_pdu(rdpsndPlugin* rdpsnd)
rdpsnd_virtual_channel_write(rdpsnd, pdu);
}
void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd)
static void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd)
{
int index;
AUDIO_FORMAT* serverFormat;
@ -197,10 +200,10 @@ void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd)
#if 0
WLog_ERR(TAG, "Server ");
rdpsnd_print_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats);
WLog_ERR(TAG, "\n");
WLog_ERR(TAG, "");
WLog_ERR(TAG, "Client ");
rdpsnd_print_audio_formats(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats);
WLog_ERR(TAG, "\n");
WLog_ERR(TAG, "");
#endif
}
@ -543,7 +546,7 @@ static void rdpsnd_recv_pdu(rdpsndPlugin* rdpsnd, wStream* s)
Stream_Seek_UINT8(s); /* bPad */
Stream_Read_UINT16(s, BodySize);
//WLog_ERR(TAG, "msgType %d BodySize %d\n", msgType, BodySize);
//WLog_ERR(TAG, "msgType %d BodySize %d", msgType, BodySize);
switch (msgType)
{
@ -800,18 +803,29 @@ static void rdpsnd_process_connect(rdpsndPlugin* rdpsnd)
if (!rdpsnd->device->DisableConfirmThread)
{
rdpsnd->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
rdpsnd->ScheduleThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_schedule_thread,
(void*) rdpsnd, 0, NULL);
}
}
static void rdpsnd_process_disconnect(rdpsndPlugin* rdpsnd)
{
if (rdpsnd->ScheduleThread)
{
SetEvent(rdpsnd->stopEvent);
WaitForSingleObject(rdpsnd->ScheduleThread, INFINITE);
CloseHandle(rdpsnd->ScheduleThread);
CloseHandle(rdpsnd->stopEvent);
}
}
/****************************************************************************************/
static wListDictionary* g_InitHandles;
static wListDictionary* g_OpenHandles;
static wListDictionary* g_InitHandles = NULL;
static wListDictionary* g_OpenHandles = NULL;
void rdpsnd_add_init_handle_data(void* pInitHandle, void* pUserData)
{
@ -831,6 +845,11 @@ void* rdpsnd_get_init_handle_data(void* pInitHandle)
void rdpsnd_remove_init_handle_data(void* pInitHandle)
{
ListDictionary_Remove(g_InitHandles, pInitHandle);
if (ListDictionary_Count(g_InitHandles) < 1)
{
ListDictionary_Free(g_InitHandles);
g_InitHandles = NULL;
}
}
void rdpsnd_add_open_handle_data(DWORD openHandle, void* pUserData)
@ -855,6 +874,11 @@ void rdpsnd_remove_open_handle_data(DWORD openHandle)
{
void* pOpenHandle = (void*) (size_t) openHandle;
ListDictionary_Remove(g_OpenHandles, pOpenHandle);
if (ListDictionary_Count(g_OpenHandles) < 1)
{
ListDictionary_Free(g_OpenHandles);
g_OpenHandles = NULL;
}
}
int rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s)
@ -874,7 +898,8 @@ int rdpsnd_virtual_channel_write(rdpsndPlugin* rdpsnd, wStream* s)
if (status != CHANNEL_RC_OK)
{
Stream_Free(s, TRUE);
WLog_ERR(TAG, "rdpdr_virtual_channel_write: VirtualChannelWrite failed %d\n", status);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(status), status);
}
return status;
@ -906,7 +931,7 @@ static void rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin,
{
if (Stream_Capacity(s) != Stream_GetPosition(s))
{
WLog_ERR(TAG, "rdpsnd_virtual_channel_event_data_received: read error\n");
WLog_ERR(TAG, "rdpsnd_virtual_channel_event_data_received: read error");
}
plugin->data_in = NULL;
@ -920,20 +945,20 @@ static void rdpsnd_virtual_channel_event_data_received(rdpsndPlugin* plugin,
static VOID VCAPITYPE rdpsnd_virtual_channel_open_event(DWORD openHandle, UINT event,
LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags)
{
rdpsndPlugin* plugin;
rdpsndPlugin* rdpsnd;
plugin = (rdpsndPlugin*) rdpsnd_get_open_handle_data(openHandle);
rdpsnd = (rdpsndPlugin*) rdpsnd_get_open_handle_data(openHandle);
if (!plugin)
if (!rdpsnd)
{
WLog_ERR(TAG, "rdpsnd_virtual_channel_open_event: error no match\n");
WLog_ERR(TAG, "rdpsnd_virtual_channel_open_event: error no match");
return;
}
switch (event)
{
case CHANNEL_EVENT_DATA_RECEIVED:
rdpsnd_virtual_channel_event_data_received(plugin, pData, dataLength, totalLength, dataFlags);
rdpsnd_virtual_channel_event_data_received(rdpsnd, pData, dataLength, totalLength, dataFlags);
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
@ -949,16 +974,16 @@ static void* rdpsnd_virtual_channel_client_thread(void* arg)
{
wStream* data;
wMessage message;
rdpsndPlugin* plugin = (rdpsndPlugin*) arg;
rdpsndPlugin* rdpsnd = (rdpsndPlugin*) arg;
rdpsnd_process_connect(plugin);
rdpsnd_process_connect(rdpsnd);
while (1)
{
if (!MessageQueue_Wait(plugin->MsgPipe->In))
if (!MessageQueue_Wait(rdpsnd->MsgPipe->In))
break;
if (MessageQueue_Peek(plugin->MsgPipe->In, &message, TRUE))
if (MessageQueue_Peek(rdpsnd->MsgPipe->In, &message, TRUE))
{
if (message.id == WMQ_QUIT)
break;
@ -966,11 +991,13 @@ static void* rdpsnd_virtual_channel_client_thread(void* arg)
if (message.id == 0)
{
data = (wStream*) message.wParam;
rdpsnd_recv_pdu(plugin, data);
rdpsnd_recv_pdu(rdpsnd, data);
}
}
}
rdpsnd_process_disconnect(rdpsnd);
ExitThread(0);
return NULL;
}
@ -986,7 +1013,8 @@ static void rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin, LPVOID
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "rdpsnd_virtual_channel_event_connected: open failed: status: %d\n", status);
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
WTSErrorToString(status), status);
return;
}
@ -996,13 +1024,22 @@ static void rdpsnd_virtual_channel_event_connected(rdpsndPlugin* plugin, LPVOID
(LPTHREAD_START_ROUTINE) rdpsnd_virtual_channel_client_thread, (void*) plugin, 0, NULL);
}
static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd)
static void rdpsnd_virtual_channel_event_disconnected(rdpsndPlugin* rdpsnd)
{
UINT rc;
MessagePipe_PostQuit(rdpsnd->MsgPipe, 0);
WaitForSingleObject(rdpsnd->thread, INFINITE);
CloseHandle(rdpsnd->thread);
rdpsnd->channelEntryPoints.pVirtualChannelClose(rdpsnd->OpenHandle);
CloseHandle(rdpsnd->thread);
rdpsnd->thread = NULL;
rc = rdpsnd->channelEntryPoints.pVirtualChannelClose(rdpsnd->OpenHandle);
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
WTSErrorToString(rc), rc);
}
if (rdpsnd->data_in)
{
@ -1010,25 +1047,43 @@ static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd)
rdpsnd->data_in = NULL;
}
if (rdpsnd->device)
IFCALL(rdpsnd->device->Free, rdpsnd->device);
if (rdpsnd->subsystem)
free(rdpsnd->subsystem);
if (rdpsnd->device_name)
free(rdpsnd->device_name);
rdpsnd_free_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats);
rdpsnd->NumberOfServerFormats = 0;
rdpsnd->ServerFormats = NULL;
MessagePipe_Free(rdpsnd->MsgPipe);
rdpsnd->MsgPipe = NULL;
rdpsnd_free_audio_formats(rdpsnd->ClientFormats, rdpsnd->NumberOfClientFormats);
rdpsnd->NumberOfClientFormats = 0;
rdpsnd->ClientFormats = NULL;
rdpsnd_free_audio_formats(rdpsnd->ServerFormats, rdpsnd->NumberOfServerFormats);
rdpsnd->NumberOfServerFormats = 0;
rdpsnd->ServerFormats = NULL;
if (rdpsnd->device)
{
IFCALL(rdpsnd->device->Free, rdpsnd->device);
rdpsnd->device = NULL;
}
if (rdpsnd->subsystem)
{
free(rdpsnd->subsystem);
rdpsnd->subsystem = NULL;
}
if (rdpsnd->device_name)
{
free(rdpsnd->device_name);
rdpsnd->device_name = NULL;
}
rdpsnd_remove_open_handle_data(rdpsnd->OpenHandle);
}
static void rdpsnd_virtual_channel_event_terminated(rdpsndPlugin* rdpsnd)
{
rdpsnd_remove_init_handle_data(rdpsnd->InitHandle);
free(rdpsnd);
}
static VOID VCAPITYPE rdpsnd_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
@ -1039,7 +1094,7 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_init_event(LPVOID pInitHandle, UINT
if (!plugin)
{
WLog_ERR(TAG, "rdpsnd_virtual_channel_init_event: error no match\n");
WLog_ERR(TAG, "rdpsnd_virtual_channel_init_event: error no match");
return;
}
@ -1050,6 +1105,7 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_init_event(LPVOID pInitHandle, UINT
break;
case CHANNEL_EVENT_DISCONNECTED:
rdpsnd_virtual_channel_event_disconnected(plugin);
break;
case CHANNEL_EVENT_TERMINATED:
@ -1063,14 +1119,14 @@ static VOID VCAPITYPE rdpsnd_virtual_channel_init_event(LPVOID pInitHandle, UINT
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
UINT rc;
rdpsndPlugin* rdpsnd;
rdpsnd = (rdpsndPlugin*) malloc(sizeof(rdpsndPlugin));
rdpsnd = (rdpsndPlugin*) calloc(1, sizeof(rdpsndPlugin));
if (rdpsnd)
{
ZeroMemory(rdpsnd, sizeof(rdpsndPlugin));
#if !defined(_WIN32) && !defined(ANDROID)
{
sigset_t mask;
@ -1090,8 +1146,15 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
rdpsnd->log = WLog_Get("com.freerdp.channels.rdpsnd.client");
rdpsnd->channelEntryPoints.pVirtualChannelInit(&rdpsnd->InitHandle,
rc = rdpsnd->channelEntryPoints.pVirtualChannelInit(&rdpsnd->InitHandle,
&rdpsnd->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, rdpsnd_virtual_channel_init_event);
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
WTSErrorToString(rc), rc);
free(rdpsnd);
return -1;
}
rdpsnd_add_init_handle_data(rdpsnd->InitHandle, (void*) rdpsnd);
}

View File

@ -102,11 +102,11 @@ static void CALLBACK rdpsnd_winmm_callback_function(HWAVEOUT hwo, UINT uMsg, DWO
switch (uMsg)
{
case MM_WOM_OPEN:
WLog_ERR(TAG, "MM_WOM_OPEN\n");
WLog_ERR(TAG, "MM_WOM_OPEN");
break;
case MM_WOM_CLOSE:
WLog_ERR(TAG, "MM_WOM_CLOSE\n");
WLog_ERR(TAG, "MM_WOM_CLOSE");
break;
case MM_WOM_DONE:
@ -122,7 +122,7 @@ static void CALLBACK rdpsnd_winmm_callback_function(HWAVEOUT hwo, UINT uMsg, DWO
if (!wave)
return;
WLog_ERR(TAG, "MM_WOM_DONE: dwBufferLength: %d cBlockNo: %d\n",
WLog_ERR(TAG, "MM_WOM_DONE: dwBufferLength: %d cBlockNo: %d",
lpWaveHdr->dwBufferLength, wave->cBlockNo);
wave->wLocalTimeB = GetTickCount();
wTimeDelta = wave->wLocalTimeB - wave->wLocalTimeA;
@ -155,7 +155,7 @@ static void rdpsnd_winmm_open(rdpsndDevicePlugin* device, AUDIO_FORMAT* format,
if (mmResult != MMSYSERR_NOERROR)
{
WLog_ERR(TAG, "waveOutOpen failed: %d\n", mmResult);
WLog_ERR(TAG, "waveOutOpen failed: %d", mmResult);
}
}
@ -172,7 +172,7 @@ static void rdpsnd_winmm_close(rdpsndDevicePlugin* device)
if (mmResult != MMSYSERR_NOERROR)
{
WLog_ERR(TAG, "waveOutClose failure: %d\n", mmResult);
WLog_ERR(TAG, "waveOutClose failure: %d", mmResult);
}
winmm->hWaveOut = NULL;
@ -299,7 +299,7 @@ void rdpsnd_winmm_wave_play(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
if (mmResult != MMSYSERR_NOERROR)
{
WLog_ERR(TAG, "waveOutPrepareHeader failure: %d\n", mmResult);
WLog_ERR(TAG, "waveOutPrepareHeader failure: %d", mmResult);
return;
}
@ -307,7 +307,7 @@ void rdpsnd_winmm_wave_play(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
if (mmResult != MMSYSERR_NOERROR)
{
WLog_ERR(TAG, "waveOutWrite failure: %d\n", mmResult);
WLog_ERR(TAG, "waveOutWrite failure: %d", mmResult);
waveOutUnprepareHeader(winmm->hWaveOut, lpWaveHdr, sizeof(WAVEHDR));
return;
}

View File

@ -109,7 +109,7 @@ static BOOL rdpsnd_server_recv_quality_mode(RdpsndServerContext* context, wStrea
Stream_Read_UINT16(s, quality);
Stream_Seek_UINT16(s); // reserved
WLog_ERR(TAG, "Client requested sound quality: %#0X\n", quality);
WLog_ERR(TAG, "Client requested sound quality: %#0X", quality);
return TRUE;
}
@ -138,7 +138,7 @@ static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
if (!context->num_client_formats)
{
WLog_ERR(TAG, "%s: client doesn't support any format!\n", __FUNCTION__);
WLog_ERR(TAG, "client doesn't support any format!");
return FALSE;
}
@ -175,7 +175,7 @@ static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
if (!context->num_client_formats)
{
WLog_ERR(TAG, "%s: client doesn't support any known format!\n", __FUNCTION__);
WLog_ERR(TAG, "client doesn't support any known format!");
goto out_free;
}
@ -231,7 +231,7 @@ static BOOL rdpsnd_server_select_format(RdpsndServerContext* context, int client
if (client_format_index < 0 || client_format_index >= context->num_client_formats)
{
WLog_ERR(TAG, "%s: index %d is not correct.\n", __FUNCTION__, client_format_index);
WLog_ERR(TAG, "index %d is not correct.", client_format_index);
return FALSE;
}
@ -243,7 +243,7 @@ static BOOL rdpsnd_server_select_format(RdpsndServerContext* context, int client
if (format->nSamplesPerSec == 0)
{
WLog_ERR(TAG, "%s: invalid Client Sound Format!!\n", __FUNCTION__);
WLog_ERR(TAG, "invalid Client Sound Format!!");
return FALSE;
}
@ -476,8 +476,8 @@ static int rdpsnd_server_start(RdpsndServerContext* context)
if (!WTSVirtualChannelQuery(priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &bytesReturned) || (bytesReturned != sizeof(HANDLE)))
{
WLog_ERR(TAG, "%s: error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned size(%d)\n",
__FUNCTION__, bytesReturned);
WLog_ERR(TAG, "error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned size(%d)",
bytesReturned);
if (buffer)
WTSFreeMemory(buffer);
@ -527,9 +527,13 @@ static int rdpsnd_server_stop(RdpsndServerContext* context)
WaitForSingleObject(context->priv->Thread, INFINITE);
CloseHandle(context->priv->Thread);
CloseHandle(context->priv->StopEvent);
}
}
if (context->priv->rdpsnd_pdu)
Stream_Free(context->priv->rdpsnd_pdu, TRUE);
return 0;
}
@ -591,24 +595,18 @@ void rdpsnd_server_context_reset(RdpsndServerContext *context)
void rdpsnd_server_context_free(RdpsndServerContext* context)
{
if (!context->priv->StopEvent)
{
SetEvent(context->priv->StopEvent);
WaitForSingleObject(context->priv->Thread, INFINITE);
}
if (context->priv->ChannelHandle)
WTSVirtualChannelClose(context->priv->ChannelHandle);
if (context->priv->rdpsnd_pdu)
Stream_Free(context->priv->rdpsnd_pdu, TRUE);
if (context->priv->out_buffer)
free(context->priv->out_buffer);
if (context->priv->dsp_context)
freerdp_dsp_context_free(context->priv->dsp_context);
if (context->priv->input_stream)
Stream_Free(context->priv->input_stream, TRUE);
if (context->client_formats)
free(context->client_formats);
@ -642,7 +640,7 @@ int rdpsnd_server_handle_messages(RdpsndServerContext *context)
if (GetLastError() == ERROR_NO_DATA)
return -1;
WLog_ERR(TAG, "%s: channel connection closed\n", __FUNCTION__);
WLog_ERR(TAG, "channel connection closed");
return 0;
}
priv->expectedBytes -= bytesReturned;
@ -699,7 +697,7 @@ int rdpsnd_server_handle_messages(RdpsndServerContext *context)
break;
default:
WLog_ERR(TAG, "%s: UNKOWN MESSAGE TYPE!! (%#0X)\n\n", __FUNCTION__, priv->msgType);
WLog_ERR(TAG, "UNKOWN MESSAGE TYPE!! (%#0X)", priv->msgType);
ret = FALSE;
break;
}

View File

@ -50,7 +50,8 @@ int remdesk_virtual_channel_write(remdeskPlugin* remdesk, wStream* s)
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "VirtualChannelWrite failed %d", status);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(status), status);
return -1;
}
@ -519,8 +520,8 @@ static void remdesk_process_connect(remdeskPlugin* remdesk)
/****************************************************************************************/
static wListDictionary* g_InitHandles;
static wListDictionary* g_OpenHandles;
static wListDictionary* g_InitHandles = NULL;
static wListDictionary* g_OpenHandles = NULL;
void remdesk_add_init_handle_data(void* pInitHandle, void* pUserData)
{
@ -540,6 +541,11 @@ void* remdesk_get_init_handle_data(void* pInitHandle)
void remdesk_remove_init_handle_data(void* pInitHandle)
{
ListDictionary_Remove(g_InitHandles, pInitHandle);
if (ListDictionary_Count(g_InitHandles) < 1)
{
ListDictionary_Free(g_InitHandles);
g_InitHandles = NULL;
}
}
void remdesk_add_open_handle_data(DWORD openHandle, void* pUserData)
@ -564,6 +570,11 @@ void remdesk_remove_open_handle_data(DWORD openHandle)
{
void* pOpenHandle = (void*) (size_t) openHandle;
ListDictionary_Remove(g_OpenHandles, pOpenHandle);
if (ListDictionary_Count(g_OpenHandles) < 1)
{
ListDictionary_Free(g_OpenHandles);
g_OpenHandles = NULL;
}
}
int remdesk_send(remdeskPlugin* remdesk, wStream* s)
@ -584,7 +595,8 @@ int remdesk_send(remdeskPlugin* remdesk, wStream* s)
if (status != CHANNEL_RC_OK)
{
Stream_Free(s, TRUE);
WLog_ERR(TAG, "VirtualChannelWrite failed %d", status);
WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08X]",
WTSErrorToString(status), status);
}
return status;
@ -623,7 +635,7 @@ static void remdesk_virtual_channel_event_data_received(remdeskPlugin* remdesk,
Stream_SealLength(data_in);
Stream_SetPosition(data_in, 0);
MessageQueue_Post(remdesk->MsgPipe->In, NULL, 0, (void*) data_in, NULL);
MessageQueue_Post(remdesk->queue, NULL, 0, (void*) data_in, NULL);
}
}
@ -665,10 +677,10 @@ static void* remdesk_virtual_channel_client_thread(void* arg)
while (1)
{
if (!MessageQueue_Wait(remdesk->MsgPipe->In))
if (!MessageQueue_Wait(remdesk->queue))
break;
if (MessageQueue_Peek(remdesk->MsgPipe->In, &message, TRUE))
if (MessageQueue_Peek(remdesk->queue, &message, TRUE))
{
if (message.id == WMQ_QUIT)
break;
@ -696,25 +708,36 @@ static void remdesk_virtual_channel_event_connected(remdeskPlugin* remdesk, LPVO
if (status != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "open failed: status: %d", status);
WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08X]",
WTSErrorToString(status), status);
return;
}
remdesk->MsgPipe = MessagePipe_New();
remdesk->queue = MessageQueue_New(NULL);
remdesk->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) remdesk_virtual_channel_client_thread, (void*) remdesk, 0, NULL);
}
static void remdesk_virtual_channel_event_terminated(remdeskPlugin* remdesk)
static void remdesk_virtual_channel_event_disconnected(remdeskPlugin* remdesk)
{
MessagePipe_PostQuit(remdesk->MsgPipe, 0);
UINT rc;
MessageQueue_PostQuit(remdesk->queue, 0);
WaitForSingleObject(remdesk->thread, INFINITE);
MessagePipe_Free(remdesk->MsgPipe);
MessageQueue_Free(remdesk->queue);
CloseHandle(remdesk->thread);
remdesk->channelEntryPoints.pVirtualChannelClose(remdesk->OpenHandle);
remdesk->queue = NULL;
remdesk->thread = NULL;
rc = remdesk->channelEntryPoints.pVirtualChannelClose(remdesk->OpenHandle);
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
WTSErrorToString(rc), rc);
}
if (remdesk->data_in)
{
@ -723,7 +746,13 @@ static void remdesk_virtual_channel_event_terminated(remdeskPlugin* remdesk)
}
remdesk_remove_open_handle_data(remdesk->OpenHandle);
}
static void remdesk_virtual_channel_event_terminated(remdeskPlugin* remdesk)
{
remdesk_remove_init_handle_data(remdesk->InitHandle);
free(remdesk);
}
static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
@ -745,6 +774,7 @@ static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle, UIN
break;
case CHANNEL_EVENT_DISCONNECTED:
remdesk_virtual_channel_event_disconnected(remdesk);
break;
case CHANNEL_EVENT_TERMINATED:
@ -758,6 +788,8 @@ static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle, UIN
BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
{
UINT rc;
remdeskPlugin* remdesk;
RemdeskClientContext* context;
CHANNEL_ENTRY_POINTS_FREERDP* pEntryPointsEx;
@ -787,12 +819,20 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
context->handle = (void*) remdesk;
*(pEntryPointsEx->ppInterface) = (void*) context;
remdesk->context = context;
}
CopyMemory(&(remdesk->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
remdesk->channelEntryPoints.pVirtualChannelInit(&remdesk->InitHandle,
rc = remdesk->channelEntryPoints.pVirtualChannelInit(&remdesk->InitHandle,
&remdesk->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, remdesk_virtual_channel_init_event);
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",
WTSErrorToString(rc), rc);
free(remdesk);
return -1;
}
remdesk->channelEntryPoints.pInterface = *(remdesk->channelEntryPoints.ppInterface);
remdesk->channelEntryPoints.ppInterface = &(remdesk->channelEntryPoints.pInterface);

View File

@ -41,12 +41,14 @@ struct remdesk_plugin
CHANNEL_DEF channelDef;
CHANNEL_ENTRY_POINTS_FREERDP channelEntryPoints;
RemdeskClientContext* context;
HANDLE thread;
wStream* data_in;
void* InitHandle;
DWORD OpenHandle;
wMessagePipe* MsgPipe;
rdpSettings* settings;
wMessageQueue* queue;
UINT32 Version;
char* ExpertBlob;

View File

@ -805,13 +805,13 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
assert(FALSE);
WLog_Print(serial->log, WLOG_DEBUG, "Unknown server's serial driver: %s. SerCx2 will be used", driver);
serial->ServerSerialDriverId = SerialDriverSerCx2Sys;
serial->ServerSerialDriverId = SerialDriverSerialSys;
}
}
else
{
/* default driver */
serial->ServerSerialDriverId = SerialDriverSerCx2Sys;
serial->ServerSerialDriverId = SerialDriverSerialSys;
}

View File

@ -23,10 +23,6 @@
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/smartcard.h>
#include <winpr/environment.h>
@ -105,6 +101,9 @@ void smartcard_context_free(SMARTCARD_CONTEXT* pContext)
if (!pContext)
return;
/* cancel blocking calls like SCardGetStatusChange */
SCardCancel(pContext->hContext);
MessageQueue_PostQuit(pContext->IrpQueue, 0);
WaitForSingleObject(pContext->thread, INFINITE);
CloseHandle(pContext->thread);
@ -118,14 +117,24 @@ static void smartcard_free(DEVICE* device)
{
SMARTCARD_DEVICE* smartcard = (SMARTCARD_DEVICE*) device;
MessageQueue_PostQuit(smartcard->IrpQueue, 0);
WaitForSingleObject(smartcard->thread, INFINITE);
if (smartcard->IrpQueue)
{
MessageQueue_PostQuit(smartcard->IrpQueue, 0);
WaitForSingleObject(smartcard->thread, INFINITE);
CloseHandle(smartcard->thread);
MessageQueue_Free(smartcard->IrpQueue);
smartcard->IrpQueue = NULL;
Stream_Free(smartcard->device.data, TRUE);
CloseHandle(smartcard->thread);
smartcard->thread = NULL;
}
if (smartcard->device.data)
{
Stream_Free(smartcard->device.data, TRUE);
smartcard->device.data = NULL;
}
MessageQueue_Free(smartcard->IrpQueue);
ListDictionary_Free(smartcard->rgSCardContextList);
ListDictionary_Free(smartcard->rgOutstandingMessages);
Queue_Free(smartcard->CompletedIrpQueue);
@ -372,7 +381,7 @@ void smartcard_process_irp(SMARTCARD_DEVICE* smartcard, IRP* irp)
}
else
{
WLog_ERR(TAG, "Unexpected SmartCard IRP: MajorFunction 0x%08X MinorFunction: 0x%08X",
WLog_ERR(TAG, "Unexpected SmartCard IRP: MajorFunction 0x%08X MinorFunction: 0x%08X",
irp->MajorFunction, irp->MinorFunction);
irp->IoStatus = STATUS_NOT_SUPPORTED;
@ -414,6 +423,7 @@ static void* smartcard_thread_func(void* arg)
{
WaitForSingleObject(irp->thread, INFINITE);
CloseHandle(irp->thread);
irp->thread = NULL;
}
smartcard_complete_irp(smartcard, irp);
@ -441,6 +451,7 @@ static void* smartcard_thread_func(void* arg)
{
WaitForSingleObject(irp->thread, INFINITE);
CloseHandle(irp->thread);
irp->thread = NULL;
}
smartcard_complete_irp(smartcard, irp);
@ -506,15 +517,17 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
smartcard->name = name;
}
smartcard->log = WLog_Get("com.freerdp.channel.smartcard.client");
//WLog_SetLogLevel(smartcard->log, WLOG_DEBUG);
smartcard->IrpQueue = MessageQueue_New(NULL);
smartcard->rgSCardContextList = ListDictionary_New(TRUE);
smartcard->rgOutstandingMessages = ListDictionary_New(TRUE);
smartcard->CompletedIrpQueue = Queue_New(TRUE, -1, -1);
smartcard->rgSCardContextList = ListDictionary_New(TRUE);
ListDictionary_ValueObject(smartcard->rgSCardContextList)->fnObjectFree =
(OBJECT_FREE_FN) smartcard_context_free;
smartcard->rgOutstandingMessages = ListDictionary_New(TRUE);
smartcard->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) smartcard_thread_func,
smartcard, CREATE_SUSPENDED, NULL);

View File

@ -108,8 +108,6 @@ struct _SMARTCARD_DEVICE
{
DEVICE device;
wLog* log;
char* name;
char* path;

View File

@ -23,9 +23,6 @@
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <winpr/crt.h>
@ -308,26 +305,32 @@ static UINT32 smartcard_ListReadersA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD
LPSTR mszReaders = NULL;
DWORD cchReaders = 0;
IRP* irp = operation->irp;
cchReaders = SCARD_AUTOALLOCATE;
status = ret.ReturnCode = SCardListReadersA(operation->hContext, (LPCSTR) call->mszGroups, (LPSTR) &mszReaders, &cchReaders);
ret.msz = (BYTE*) mszReaders;
ret.cBytes = cchReaders;
if (status)
if (call->mszGroups)
{
free(call->mszGroups);
call->mszGroups = NULL;
}
if (status != SCARD_S_SUCCESS)
return status;
smartcard_trace_list_readers_return(smartcard, &ret, FALSE);
status = smartcard_pack_list_readers_return(smartcard, irp->output, &ret);
if (status)
if (status != SCARD_S_SUCCESS)
return status;
if (mszReaders)
SCardFreeMemory(operation->hContext, mszReaders);
if (call->mszGroups)
free(call->mszGroups);
return ret.ReturnCode;
}
@ -340,8 +343,10 @@ static UINT32 smartcard_ListReadersW_Decode(SMARTCARD_DEVICE* smartcard, SMARTCA
return STATUS_NO_MEMORY;
status = smartcard_unpack_list_readers_call(smartcard, irp->input, call);
smartcard_trace_list_readers_call(smartcard, call, TRUE);
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
return status;
}
@ -352,15 +357,26 @@ static UINT32 smartcard_ListReadersW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD
LPWSTR mszReaders = NULL;
DWORD cchReaders = 0;
IRP* irp = operation->irp;
cchReaders = SCARD_AUTOALLOCATE;
status = ret.ReturnCode = SCardListReadersW(operation->hContext, (LPCWSTR) call->mszGroups, (LPWSTR) &mszReaders, &cchReaders);
status = ret.ReturnCode = SCardListReadersW(operation->hContext,
(LPCWSTR) call->mszGroups, (LPWSTR) &mszReaders, &cchReaders);
ret.msz = (BYTE*) mszReaders;
ret.cBytes = cchReaders * 2;
if (call->mszGroups)
{
free(call->mszGroups);
call->mszGroups = NULL;
}
if (status != SCARD_S_SUCCESS)
return status;
smartcard_trace_list_readers_return(smartcard, &ret, TRUE);
status = smartcard_pack_list_readers_return(smartcard, irp->output, &ret);
if (status != SCARD_S_SUCCESS)
@ -369,9 +385,6 @@ static UINT32 smartcard_ListReadersW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD
if (mszReaders)
SCardFreeMemory(operation->hContext, mszReaders);
if (call->mszGroups)
free(call->mszGroups);
return ret.ReturnCode;
}
@ -396,16 +409,21 @@ static UINT32 smartcard_GetStatusChangeA_Call(SMARTCARD_DEVICE* smartcard, SMART
GetStatusChange_Return ret;
LPSCARD_READERSTATEA rgReaderState = NULL;
IRP* irp = operation->irp;
status = ret.ReturnCode = SCardGetStatusChangeA(operation->hContext, call->dwTimeOut, call->rgReaderStates, call->cReaders);
status = ret.ReturnCode = SCardGetStatusChangeA(operation->hContext,
call->dwTimeOut, call->rgReaderStates, call->cReaders);
if (status && (status != SCARD_E_TIMEOUT) && (status != SCARD_E_CANCELLED))
{
call->cReaders=0;
call->cReaders = 0;
}
ret.cReaders = call->cReaders;
ret.rgReaderStates = (ReaderState_Return*) calloc(ret.cReaders, sizeof(ReaderState_Return));
if (!ret.rgReaderStates)
return STATUS_NO_MEMORY;
for (index = 0; index < ret.cReaders; index++)
{
ret.rgReaderStates[index].dwCurrentState = call->rgReaderStates[index].dwCurrentState;
@ -468,6 +486,9 @@ static UINT32 smartcard_GetStatusChangeW_Call(SMARTCARD_DEVICE* smartcard, SMART
ret.cReaders = call->cReaders;
ret.rgReaderStates = (ReaderState_Return*) calloc(ret.cReaders, sizeof(ReaderState_Return));
if (!ret.rgReaderStates)
return STATUS_NO_MEMORY;
for (index = 0; index < ret.cReaders; index++)
{
ret.rgReaderStates[index].dwCurrentState = call->rgReaderStates[index].dwCurrentState;
@ -539,8 +560,8 @@ static UINT32 smartcard_ConnectA_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_O
static UINT32 smartcard_ConnectA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation, ConnectA_Call* call)
{
LONG status;
SCARDHANDLE hCard;
Connect_Return ret;
SCARDHANDLE hCard = 0;
Connect_Return ret = { 0 };
IRP* irp = operation->irp;
if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
@ -550,7 +571,8 @@ static UINT32 smartcard_ConnectA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPE
}
status = ret.ReturnCode = SCardConnectA(operation->hContext, (char*) call->szReader, call->Common.dwShareMode,
call->Common.dwPreferredProtocols, &hCard, &ret.dwActiveProtocol);
call->Common.dwPreferredProtocols, &hCard, &ret.dwActiveProtocol);
smartcard_scard_context_native_to_redir(smartcard, &(ret.hContext), operation->hContext);
smartcard_scard_handle_native_to_redir(smartcard, &(ret.hCard), hCard);
smartcard_trace_connect_return(smartcard, &ret);
@ -580,14 +602,15 @@ static UINT32 smartcard_ConnectW_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_O
status = smartcard_unpack_connect_w_call(smartcard, irp->input, call);
smartcard_trace_connect_w_call(smartcard, call);
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->Common.hContext));
return status;
}
static UINT32 smartcard_ConnectW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation, ConnectW_Call* call)
{
LONG status;
SCARDHANDLE hCard;
Connect_Return ret;
SCARDHANDLE hCard = 0;
Connect_Return ret = { 0 };
IRP* irp = operation->irp;
if ((call->Common.dwPreferredProtocols == SCARD_PROTOCOL_UNDEFINED) &&
@ -597,7 +620,8 @@ static UINT32 smartcard_ConnectW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPE
}
status = ret.ReturnCode = SCardConnectW(operation->hContext, (WCHAR*) call->szReader, call->Common.dwShareMode,
call->Common.dwPreferredProtocols, &hCard, &ret.dwActiveProtocol);
call->Common.dwPreferredProtocols, &hCard, &ret.dwActiveProtocol);
smartcard_scard_context_native_to_redir(smartcard, &(ret.hContext), operation->hContext);
smartcard_scard_handle_native_to_redir(smartcard, &(ret.hCard), hCard);
smartcard_trace_connect_return(smartcard, &ret);
@ -781,8 +805,9 @@ static DWORD smartcard_StatusA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERA
ret.cbAtrLen = call->cbAtrLen;
ZeroMemory(ret.pbAtr, 32);
cchReaderLen = SCARD_AUTOALLOCATE;
status = ret.ReturnCode = SCardStatusA(operation->hCard, (LPSTR) &mszReaderNames, &cchReaderLen,
&ret.dwState, &ret.dwProtocol, (BYTE*) &ret.pbAtr, &ret.cbAtrLen);
&ret.dwState, &ret.dwProtocol, (BYTE*) &ret.pbAtr, &ret.cbAtrLen);
if (status == SCARD_S_SUCCESS)
{
@ -831,8 +856,10 @@ static DWORD smartcard_StatusW_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERA
ret.cbAtrLen = call->cbAtrLen;
ZeroMemory(ret.pbAtr, 32);
cchReaderLen = SCARD_AUTOALLOCATE;
status = ret.ReturnCode = SCardStatusW(operation->hCard, (LPWSTR) &mszReaderNames, &cchReaderLen,
&ret.dwState, &ret.dwProtocol, (BYTE*) &ret.pbAtr, &ret.cbAtrLen);
&ret.dwState, &ret.dwProtocol, (BYTE*) &ret.pbAtr, &ret.cbAtrLen);
ret.mszReaderNames = (BYTE*) mszReaderNames;
ret.cBytes = cchReaderLen * 2;
smartcard_trace_status_return(smartcard, &ret, TRUE);
@ -856,9 +883,12 @@ static UINT32 smartcard_Transmit_Decode(SMARTCARD_DEVICE* smartcard, SMARTCARD_O
return STATUS_NO_MEMORY;
status = smartcard_unpack_transmit_call(smartcard, irp->input, call);
smartcard_trace_transmit_call(smartcard, call);
operation->hContext = smartcard_scard_context_native_from_redir(smartcard, &(call->hContext));
operation->hCard = smartcard_scard_handle_native_from_redir(smartcard, &(call->hCard));
return status;
}
@ -877,11 +907,14 @@ static UINT32 smartcard_Transmit_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPE
ret.cbRecvLength = call->cbRecvLength;
ret.pbRecvBuffer = (BYTE*) malloc(ret.cbRecvLength);
if (!ret.pbRecvBuffer)
return STATUS_NO_MEMORY;
}
ret.pioRecvPci = call->pioRecvPci;
status = ret.ReturnCode = SCardTransmit(operation->hCard, call->pioSendPci, call->pbSendBuffer,
call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
call->cbSendLength, ret.pioRecvPci, ret.pbRecvBuffer, &(ret.cbRecvLength));
smartcard_trace_transmit_return(smartcard, &ret);
status = smartcard_pack_transmit_return(smartcard, irp->output, &ret);
@ -930,8 +963,9 @@ static UINT32 smartcard_Control_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPER
return SCARD_E_NO_MEMORY;
status = ret.ReturnCode = SCardControl(operation->hCard,
call->dwControlCode, call->pvInBuffer, call->cbInBufferSize,
ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
call->dwControlCode, call->pvInBuffer, call->cbInBufferSize,
ret.pvOutBuffer, call->cbOutBufferSize, &ret.cbOutBufferSize);
smartcard_trace_control_return(smartcard, &ret);
status = smartcard_pack_control_return(smartcard, irp->output, &ret);
@ -966,27 +1000,41 @@ static UINT32 smartcard_GetAttrib_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OP
{
LONG status;
DWORD cbAttrLen;
BOOL autoAllocate;
GetAttrib_Return ret;
IRP* irp = operation->irp;
ret.pbAttr = NULL;
if (call->fpbAttrIsNULL)
call->cbAttrLen = 0;
if (call->cbAttrLen)
autoAllocate = (call->cbAttrLen == SCARD_AUTOALLOCATE) ? TRUE : FALSE;
if (call->cbAttrLen && !autoAllocate)
{
ret.pbAttr = (BYTE*) malloc(call->cbAttrLen);
if (!ret.pbAttr)
return SCARD_E_NO_MEMORY;
}
cbAttrLen = call->cbAttrLen;
status = ret.ReturnCode = SCardGetAttrib(operation->hCard, call->dwAttrId, ret.pbAttr, &cbAttrLen);
status = ret.ReturnCode = SCardGetAttrib(operation->hCard, call->dwAttrId,
autoAllocate ? (LPBYTE) &(ret.pbAttr) : ret.pbAttr, &cbAttrLen);
ret.cbAttrLen = cbAttrLen;
smartcard_trace_get_attrib_return(smartcard, &ret, call->dwAttrId);
if (ret.ReturnCode)
{
WLog_Print(smartcard->log, WLOG_WARN,
"SCardGetAttrib: %s (0x%08X) cbAttrLen: %d\n",
SCardGetAttributeString(call->dwAttrId), call->dwAttrId, call->cbAttrLen);
WLog_WARN(TAG, "SCardGetAttrib: %s (0x%08X) cbAttrLen: %d",
SCardGetAttributeString(call->dwAttrId), call->dwAttrId, call->cbAttrLen);
Stream_Zero(irp->output, 256);
free(ret.pbAttr);
return ret.ReturnCode;
}
@ -1008,7 +1056,7 @@ static UINT32 smartcard_AccessStartedEvent_Decode(SMARTCARD_DEVICE* smartcard, S
if (Stream_GetRemainingLength(irp->input) < 4)
{
WLog_Print(smartcard->log, WLOG_WARN, "AccessStartedEvent is too short: %d",
WLog_WARN(TAG, "AccessStartedEvent is too short: %d",
(int) Stream_GetRemainingLength(irp->input));
return SCARD_F_INTERNAL_ERROR;
}
@ -1049,47 +1097,51 @@ static UINT32 smartcard_LocateCardsByATRA_Decode(SMARTCARD_DEVICE* smartcard, SM
static UINT32 smartcard_LocateCardsByATRA_Call(SMARTCARD_DEVICE* smartcard, SMARTCARD_OPERATION* operation, LocateCardsByATRA_Call* call)
{
LONG status;
DWORD index, index2, index3;
BOOL equal;
DWORD i, j, k;
GetStatusChange_Return ret;
LPSCARD_READERSTATEA rgReaderState2 = NULL;
LPSCARD_READERSTATEA state = NULL;
LPSCARD_READERSTATEA states = NULL;
IRP* irp = operation->irp;
states = calloc(call->cReaders, sizeof(SCARD_READERSTATEA));
for (index = 0; index < call->cReaders; index++)
{
states[index].szReader = (LPCSTR) call->rgReaderStates[index].szReader;
states[index].dwCurrentState = call->rgReaderStates[index].Common.dwCurrentState;
states[index].dwEventState = call->rgReaderStates[index].Common.dwEventState;
states[index].cbAtr = call->rgReaderStates[index].Common.cbAtr;
CopyMemory(&(states[index].rgbAtr), &(call->rgReaderStates[index].Common.rgbAtr), 36);
}
states = (LPSCARD_READERSTATEA) calloc(call->cReaders, sizeof(SCARD_READERSTATEA));
if (!states)
return STATUS_NO_MEMORY;
for (i = 0; i < call->cReaders; i++)
{
states[i].szReader = (LPCSTR) call->rgReaderStates[i].szReader;
states[i].dwCurrentState = call->rgReaderStates[i].Common.dwCurrentState;
states[i].dwEventState = call->rgReaderStates[i].Common.dwEventState;
states[i].cbAtr = call->rgReaderStates[i].Common.cbAtr;
CopyMemory(&(states[i].rgbAtr), &(call->rgReaderStates[i].Common.rgbAtr), 36);
}
status = ret.ReturnCode = SCardGetStatusChangeA(operation->hContext, 0x000001F4, states, call->cReaders);
if (status && (status != SCARD_E_TIMEOUT) && (status != SCARD_E_CANCELLED))
{
call->cReaders=0;
call->cReaders = 0;
}
for (index = 0; index < call->cAtrs; index++)
for (i = 0; i < call->cAtrs; i++)
{
for (index2 = 0; index2 < call->cReaders; index2++)
for (j = 0; j < call->cReaders; j++)
{
equal = TRUE;
for (index3 = 0; index3 < call->rgAtrMasks[index].cbAtr; index3++)
for (k = 0; k < call->rgAtrMasks[i].cbAtr; k++)
{
if ((call->rgAtrMasks[index].rgbAtr[index3] & call->rgAtrMasks[index].rgbMask[index3]) !=
(states[index2].rgbAtr[index3] & call->rgAtrMasks[index].rgbMask[index3]))
if ((call->rgAtrMasks[i].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]) !=
(states[j].rgbAtr[k] & call->rgAtrMasks[i].rgbMask[k]))
{
equal = FALSE;
break;
}
if (equal)
{
states[index2].dwEventState |= SCARD_STATE_ATRMATCH;
states[j].dwEventState |= SCARD_STATE_ATRMATCH;
}
}
}
@ -1098,13 +1150,16 @@ static UINT32 smartcard_LocateCardsByATRA_Call(SMARTCARD_DEVICE* smartcard, SMAR
ret.cReaders = call->cReaders;
ret.rgReaderStates = (ReaderState_Return*) calloc(ret.cReaders, sizeof(ReaderState_Return));
for (index = 0; index < ret.cReaders; index++)
if (!ret.rgReaderStates)
return STATUS_NO_MEMORY;
for (i = 0; i < ret.cReaders; i++)
{
rgReaderState2 = &states[index];
ret.rgReaderStates[index].dwCurrentState = rgReaderState2->dwCurrentState;
ret.rgReaderStates[index].dwEventState = rgReaderState2->dwEventState;
ret.rgReaderStates[index].cbAtr = rgReaderState2->cbAtr;
CopyMemory(&(ret.rgReaderStates[index].rgbAtr), &(rgReaderState2->rgbAtr), 32);
state = &states[i];
ret.rgReaderStates[i].dwCurrentState = state->dwCurrentState;
ret.rgReaderStates[i].dwEventState = state->dwEventState;
ret.rgReaderStates[i].cbAtr = state->cbAtr;
CopyMemory(&(ret.rgReaderStates[i].rgbAtr), &(state->rgbAtr), 32);
}
free(states);
@ -1116,13 +1171,13 @@ static UINT32 smartcard_LocateCardsByATRA_Call(SMARTCARD_DEVICE* smartcard, SMAR
if (call->rgReaderStates)
{
for (index = 0; index < call->cReaders; index++)
for (i = 0; i < call->cReaders; i++)
{
rgReaderState2 = (LPSCARD_READERSTATEA) &call->rgReaderStates[index];
state = (LPSCARD_READERSTATEA) &call->rgReaderStates[i];
if (rgReaderState2->szReader) {
free((void*) rgReaderState2->szReader);
rgReaderState2->szReader = NULL;
if (state->szReader) {
free((void*) state->szReader);
state->szReader = NULL;
}
}
@ -1148,7 +1203,7 @@ UINT32 smartcard_irp_device_control_decode(SMARTCARD_DEVICE* smartcard, SMARTCAR
if (Stream_GetRemainingLength(irp->input) < 32)
{
WLog_Print(smartcard->log, WLOG_WARN, "Device Control Request is too short: %d",
WLog_WARN(TAG, "Device Control Request is too short: %d",
(int) Stream_GetRemainingLength(irp->input));
return SCARD_F_INTERNAL_ERROR;
}
@ -1161,18 +1216,14 @@ UINT32 smartcard_irp_device_control_decode(SMARTCARD_DEVICE* smartcard, SMARTCAR
if (Stream_Length(irp->input) != (Stream_GetPosition(irp->input) + inputBufferLength))
{
WLog_Print(smartcard->log, WLOG_WARN,
"InputBufferLength mismatch: Actual: %d Expected: %d\n",
Stream_Length(irp->input), Stream_GetPosition(irp->input) + inputBufferLength);
WLog_WARN(TAG, "InputBufferLength mismatch: Actual: %d Expected: %d",
Stream_Length(irp->input), Stream_GetPosition(irp->input) + inputBufferLength);
return SCARD_F_INTERNAL_ERROR;
}
WLog_Print(smartcard->log, WLOG_DEBUG, "%s (0x%08X) FileId: %d CompletionId: %d",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, irp->FileId, irp->CompletionId);
#if 0
WLog_DBG(TAG, "%s (0x%08X) FileId: %d CompletionId: %d\n",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, irp->FileId, irp->CompletionId);
#endif
WLog_DBG(TAG, "%s (0x%08X) FileId: %d CompletionId: %d",
smartcard_get_ioctl_string(ioControlCode, TRUE),
ioControlCode, irp->FileId, irp->CompletionId);
if ((ioControlCode != SCARD_IOCTL_ACCESSSTARTEDEVENT) &&
(ioControlCode != SCARD_IOCTL_RELEASESTARTEDEVENT))
@ -1416,17 +1467,16 @@ UINT32 smartcard_irp_device_control_decode(SMARTCARD_DEVICE* smartcard, SMARTCAR
{
offset = (RDPDR_DEVICE_IO_REQUEST_LENGTH + RDPDR_DEVICE_IO_CONTROL_REQ_HDR_LENGTH);
smartcard_unpack_read_size_align(smartcard, irp->input,
Stream_GetPosition(irp->input) - offset, 8);
Stream_GetPosition(irp->input) - offset, 8);
}
if (((size_t) Stream_GetPosition(irp->input)) < Stream_Length(irp->input))
{
UINT32 difference;
difference = (int)(Stream_Length(irp->input) - Stream_GetPosition(irp->input));
WLog_Print(smartcard->log, WLOG_WARN,
"IRP was not fully parsed %s (0x%08X): Actual: %d, Expected: %d, Difference: %d",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
(int) Stream_GetPosition(irp->input), (int) Stream_Length(irp->input), difference);
WLog_WARN(TAG, "IRP was not fully parsed %s (0x%08X): Actual: %d, Expected: %d, Difference: %d",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
(int) Stream_GetPosition(irp->input), (int) Stream_Length(irp->input), difference);
winpr_HexDump(TAG, WLOG_WARN, Stream_Pointer(irp->input), difference);
}
@ -1434,10 +1484,9 @@ UINT32 smartcard_irp_device_control_decode(SMARTCARD_DEVICE* smartcard, SMARTCAR
{
UINT32 difference;
difference = (int)(Stream_GetPosition(irp->input) - Stream_Length(irp->input));
WLog_Print(smartcard->log, WLOG_WARN,
"IRP was parsed beyond its end %s (0x%08X): Actual: %d, Expected: %d, Difference: %d",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
(int) Stream_GetPosition(irp->input), (int) Stream_Length(irp->input), difference);
WLog_WARN(TAG, "IRP was parsed beyond its end %s (0x%08X): Actual: %d, Expected: %d, Difference: %d",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
(int) Stream_GetPosition(irp->input), (int) Stream_Length(irp->input), difference);
}
if (status != SCARD_S_SUCCESS)
@ -1462,6 +1511,7 @@ UINT32 smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_
irp = operation->irp;
call = operation->call;
ioControlCode = operation->ioControlCode;
/**
* [MS-RDPESC] 3.2.5.1: Sending Outgoing Messages:
* the output buffer length SHOULD be set to 2048
@ -1470,6 +1520,7 @@ UINT32 smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_
* about it, but we still reserve at least 2048 bytes.
*/
Stream_EnsureRemainingCapacity(irp->output, 2048);
/* Device Control Response */
Stream_Seek_UINT32(irp->output); /* OutputBufferLength (4 bytes) */
Stream_Seek(irp->output, SMARTCARD_COMMON_TYPE_HEADER_LENGTH); /* CommonTypeHeader (8 bytes) */
@ -1689,17 +1740,15 @@ UINT32 smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_
(ioControlCode != SCARD_IOCTL_RELEASESTARTEDEVENT))
{
offset = (RDPDR_DEVICE_IO_RESPONSE_LENGTH + RDPDR_DEVICE_IO_CONTROL_RSP_HDR_LENGTH);
smartcard_pack_write_size_align(smartcard, irp->output,
Stream_GetPosition(irp->output) - offset, 8);
smartcard_pack_write_size_align(smartcard, irp->output, Stream_GetPosition(irp->output) - offset, 8);
}
if ((result != SCARD_S_SUCCESS) && (result != SCARD_E_TIMEOUT) &&
(result != SCARD_E_NO_READERS_AVAILABLE) && (result != SCARD_E_NO_SERVICE))
{
WLog_Print(smartcard->log, WLOG_WARN,
"IRP failure: %s (0x%08X), status: %s (0x%08X)",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
SCardGetErrorString(result), result);
WLog_WARN(TAG, "IRP failure: %s (0x%08X), status: %s (0x%08X)",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode,
SCardGetErrorString(result), result);
}
irp->IoStatus = 0;
@ -1709,21 +1758,22 @@ UINT32 smartcard_irp_device_control_call(SMARTCARD_DEVICE* smartcard, SMARTCARD_
/* NTSTATUS error */
irp->IoStatus = result;
Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH);
WLog_Print(smartcard->log, WLOG_WARN,
"IRP failure: %s (0x%08X), ntstatus: 0x%08X",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, result);
WLog_WARN(TAG, "IRP failure: %s (0x%08X), ntstatus: 0x%08X",
smartcard_get_ioctl_string(ioControlCode, TRUE), ioControlCode, result);
}
Stream_SealLength(irp->output);
outputBufferLength = Stream_Length(irp->output) - RDPDR_DEVICE_IO_RESPONSE_LENGTH - 4;
objectBufferLength = outputBufferLength - RDPDR_DEVICE_IO_RESPONSE_LENGTH;
Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH);
/* Device Control Response */
Stream_Write_UINT32(irp->output, outputBufferLength); /* OutputBufferLength (4 bytes) */
smartcard_pack_common_type_header(smartcard, irp->output); /* CommonTypeHeader (8 bytes) */
smartcard_pack_private_type_header(smartcard, irp->output, objectBufferLength); /* PrivateTypeHeader (8 bytes) */
Stream_Write_UINT32(irp->output, result); /* Result (4 bytes) */
Stream_SetPosition(irp->output, Stream_Length(irp->output));
return SCARD_S_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@ -908,6 +908,8 @@ static int urbdrc_on_new_channel_connection(IWTSListenerCallback* pListenerCallb
URBDRC_CHANNEL_CALLBACK* callback;
WLog_VRB(TAG, "");
callback = (URBDRC_CHANNEL_CALLBACK*) malloc(sizeof(URBDRC_CHANNEL_CALLBACK));
memset(callback, 0, sizeof(URBDRC_CHANNEL_CALLBACK));
callback->iface.OnDataReceived = urbdrc_on_data_received;
callback->iface.OnClose = urbdrc_on_close;
callback->plugin = listener_callback->plugin;

View File

@ -0,0 +1,47 @@
message("PRELOADING cache")
set (BUILD_TESTING ON CACHE BOOL "testing")
set (WITH_MANPAGES OFF CACHE BOOL "man pages")
set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
set (BUILD_TESTING ON CACHE BOOL "build testing")
set (WITH_PULSE ON CACHE BOOL "pulse")
set (WITH_CHANNELS ON CACHE BOOL "channels")
set (STATIC_CHANNELS ON CACHE BOOL "static channels")
set (WITH_CUPS ON CACHE BOOL "cups")
set (WITH_PCSC ON CACHE BOOL "PCSC")
set (WITH_JPEG ON CACHE BOOL "jepg")
set (WITH_GSTREAMER_0_10 ON CACHE BOOL "gstreamer")
set (WITH_GSM ON CACHE BOOL "gsm")
set (CHANNEL_URBDRC ON CACHE BOOL "urbdrc")
set (CHANNEL_URBDRC_CLIENT ON CACHE BOOL "urbdrc client")
set (WITH_SERVER ON CACHE BOOL "server side")
set (WITH_DEBUG_ALL OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_CAPABILITIES OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_CERTIFICATE OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_CHANNELS OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_CLIPRDR OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_DVC OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_GDI OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_KBD OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_LICENSE OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_NEGO OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_NLA OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_NTLM OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_ORDERS OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_RAIL OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_RDP OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_REDIR OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_RFX OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_SCARD OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_SND OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_SVC OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_THREADS OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_TIMEZONE OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_TRANSPORT OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_TSG OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_TSMF OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_WND OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_X11 OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_X11_CLIPRDR OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_X11_LOCAL_MOVESIZE OFF CACHE BOOL "enable debug")
set (WITH_DEBUG_XV OFF CACHE BOOL "enable debug")
set (WITH_SAMPLE ON CACHE BOOL "samples")

View File

@ -1,5 +1,6 @@
message("PRELOADING mac cache")
set (WITH_MANPAGES OFF CACHE BOOL "man pages")
set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
set (WITH_CUPS OFF CACHE BOOL "CUPS printing")
set (BUILD_TESTING OFF CACHE BOOL "build testing")
set (WITH_CUPS ON CACHE BOOL "CUPS printing")
set (WITH_X11 ON CACHE BOOL "Enable X11")
set (BUILD_TESTING ON CACHE BOOL "build testing")

View File

@ -57,6 +57,7 @@ int android_context_new(freerdp* instance, rdpContext* context)
void android_context_free(freerdp* instance, rdpContext* context)
{
freerdp_channels_close(instance->context->channels, instance);
freerdp_channels_free(context->channels);
android_event_queue_uninit(instance);
}
@ -541,7 +542,7 @@ static int android_freerdp_run(freerdp* instance)
freerdp_callback("OnDisconnecting", "(I)V", instance);
DEBUG_ANDROID("Close channels...");
freerdp_channels_close(instance->context->channels, instance);
freerdp_channels_disconnect(instance->context->channels, instance);
DEBUG_ANDROID("Cleanup threads...");
@ -745,9 +746,7 @@ JNIEXPORT void JNICALL jni_freerdp_set_connection_info(JNIEnv *env, jclass cls,
settings->TlsSecurity = FALSE;
settings->NlaSecurity = FALSE;
settings->ExtSecurity = FALSE;
settings->DisableEncryption = TRUE;
settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
settings->UseRdpSecurityLayer = TRUE;
break;
case 2:

View File

@ -63,8 +63,8 @@ set(FILENAME "ModuleOptions.cmake")
file(GLOB FILEPATHS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*/${FILENAME}")
foreach(FILEPATH ${FILEPATHS})
if(${FILEPATH} MATCHES "^([^/]*)//${FILENAME}")
string(REGEX REPLACE "^([^/]*)//${FILENAME}" "\\1" FREERDP_CLIENT ${FILEPATH})
if(${FILEPATH} MATCHES "^([^/]*)/+${FILENAME}")
string(REGEX REPLACE "^([^/]*)/+${FILENAME}" "\\1" FREERDP_CLIENT ${FILEPATH})
set(FREERDP_CLIENT_ENABLED 0)
include(${FILEPATH})
if(FREERDP_CLIENT_ENABLED)

View File

@ -404,6 +404,9 @@ int dfreerdp_run(freerdp* instance)
df_process_channel_event(channels, instance);
}
freerdp_channels_disconnect(channels, instance);
freerdp_disconnect(instance);
freerdp_channels_close(channels, instance);
freerdp_channels_free(channels);
df_free(dfi);

View File

@ -1,6 +1,12 @@
project(MacFreeRDP-library)
if(${CMAKE_VERSION} GREATER 2.8.12)
cmake_policy(SET CMP0026 OLD)
cmake_policy(SET CMP0045 OLD)
endif()
set(MODULE_NAME "MacFreeRDP-library")
set(MODULE_OUTPUT_NAME "MacFreeRDP")
set(MODULE_PREFIX "FREERDP_CLIENT_MAC_LIBRARY")

View File

@ -201,6 +201,11 @@ int mac_cliprdr_server_format_list(CliprdrClientContext* cliprdr, CLIPRDR_FORMAT
mac_cliprdr_send_client_format_data_request(cliprdr, CF_UNICODETEXT);
break;
}
else if (format->formatId == CF_OEMTEXT)
{
mac_cliprdr_send_client_format_data_request(cliprdr, CF_OEMTEXT);
break;
}
else if (format->formatId == CF_TEXT)
{
mac_cliprdr_send_client_format_data_request(cliprdr, CF_TEXT);
@ -305,11 +310,15 @@ int mac_cliprdr_server_format_data_response(CliprdrClientContext* cliprdr, CLIPR
SetEvent(mfc->clipboardRequestEvent);
if ((formatId == CF_TEXT) || (formatId == CF_UNICODETEXT))
if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) || (formatId == CF_UNICODETEXT))
{
formatId = ClipboardRegisterFormat(mfc->clipboard, "UTF8_STRING");
data = (void*) ClipboardGetData(mfc->clipboard, formatId, &size);
if (size > 1)
size--; /* we need the size without the null terminator */
NSString* str = [[NSString alloc] initWithBytes: (void*) data length:size encoding:NSUTF8StringEncoding];
free(data);

View File

@ -755,10 +755,13 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
formatData = [item dataForType:type];
formatId = ClipboardRegisterFormat(mfc->clipboard, "UTF8_STRING");
size = (UINT32) [formatData length];
/* length does not include null terminator */
data = (BYTE*) malloc(size);
size = (UINT32) [formatData length];
data = (BYTE*) malloc(size + 1);
[formatData getBytes:data length:size];
data[size] = '\0';
size++;
ClipboardSetData(mfc->clipboard, formatId, (void*) data, size);
formatMatch = TRUE;

View File

@ -63,6 +63,7 @@ set_target_properties(${MODULE_NAME} PROPERTIES RESOURCE "${${MODULE_PREFIX}_RES
# Tell the compiler where to look for the FreeRDP framework
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -F../")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -F../")
# Tell XCode where to look for the MacFreeRDP framework
set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS

View File

@ -212,6 +212,9 @@ int tfreerdp_run(freerdp* instance)
}
}
freerdp_channels_disconnect(channels, instance);
freerdp_disconnect(instance);
freerdp_channels_close(channels, instance);
freerdp_channels_free(channels);
freerdp_free(instance);

View File

@ -43,22 +43,29 @@ static void wl_pointer_motion(void* data, struct wl_pointer* pointer, uint32_t t
input = input_w->input;
x = wl_fixed_to_int(sx_w);
y = wl_fixed_to_int(sy_w);
x = (UINT16) wl_fixed_to_int(sx_w);
y = (UINT16) wl_fixed_to_int(sy_w);
input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
input_w->last_x = x;
input_w->last_y = y;
}
static void wl_pointer_button(void* data, struct wl_pointer* pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
{
wlfInput* input_w = data;
rdpInput* input;
int flags;
UINT16 x;
UINT16 y;
UINT16 flags;
input = input_w->input;
if (state == WL_POINTER_BUTTON_STATE_PRESSED)
flags = PTR_FLAGS_DOWN;
else
flags = 0;
switch (button)
{
@ -72,7 +79,33 @@ static void wl_pointer_button(void* data, struct wl_pointer* pointer, uint32_t s
flags |= PTR_FLAGS_BUTTON3;
break;
default:
break;
return;
}
x = input_w->last_x;
y = input_w->last_y;
input->MouseEvent(input, flags, x, y);
}
static void wl_pointer_axis(void* data, struct wl_pointer* pointer, uint32_t time, uint32_t axis, wl_fixed_t value)
{
wlfInput* input_w = data;
rdpInput* input;
UINT16 flags;
int direction;
input = input_w->input;
flags = PTR_FLAGS_WHEEL;
if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
{
direction = wl_fixed_to_int(value);
if (direction < 0)
flags |= 0x0078;
else
flags |= PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
}
input->MouseEvent(input, flags, 0, 0);
@ -84,7 +117,7 @@ static const struct wl_pointer_listener wl_pointer_listener =
wl_pointer_leave,
wl_pointer_motion,
wl_pointer_button,
NULL
wl_pointer_axis
};
static void wl_keyboard_keymap(void* data, struct wl_keyboard* keyboard, uint32_t format, int fd, uint32_t size)
@ -94,7 +127,18 @@ static void wl_keyboard_keymap(void* data, struct wl_keyboard* keyboard, uint32_
static void wl_keyboard_enter(void* data, struct wl_keyboard* keyboard, uint32_t serial, struct wl_surface* surface, struct wl_array* keys)
{
wlfInput* input_w = data;
rdpInput* input;
UINT16 x;
UINT16 y;
input = input_w->input;
x = input_w->last_x;
y = input_w->last_y;
input->FocusInEvent(input, 0);
input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
}
static void wl_keyboard_leave(void* data, struct wl_keyboard* keyboard, uint32_t serial, struct wl_surface* surface)
@ -116,7 +160,7 @@ static void wl_keyboard_key(void* data, struct wl_keyboard* keyboard, uint32_t s
else
key_down = FALSE;
rdp_scancode = freerdp_keyboard_get_rdp_scancode_from_x11_keycode(key);
rdp_scancode = (DWORD) key;
if (rdp_scancode == RDP_SCANCODE_UNKNOWN)
return;
@ -183,6 +227,8 @@ wlfInput* wlf_CreateInput(wlfContext* wlfc)
if (input)
{
input->input = wlfc->context.input;
input->last_x = 0;
input->last_y = 0;
wl_seat_add_listener(seat, &wl_seat_listener, input);
}

View File

@ -28,10 +28,12 @@ typedef struct wlf_input wlfInput;
struct wlf_input
{
rdpInput *input;
rdpInput* input;
UINT16 last_x;
UINT16 last_y;
struct wl_pointer *pointer;
struct wl_keyboard *keyboard;
struct wl_pointer* pointer;
struct wl_keyboard* keyboard;
};
wlfInput* wlf_CreateInput(wlfContext* wlfc);

View File

@ -64,6 +64,8 @@ static void wl_callback_done(void* data, struct wl_callback* callback, uint32_t
wlfWindow* window = data;
wlfBuffer* buffer;
struct wl_shm_pool* shm_pool;
void* shm_data;
void* free_data;
int fd;
int fdt;
@ -74,29 +76,35 @@ static void wl_callback_done(void* data, struct wl_callback* callback, uint32_t
else
return;
fd = shm_open("wlfreerdp_shm", O_CREAT | O_TRUNC | O_RDWR, 0666);
fdt = ftruncate(fd, window->width * window->height * 4);
if (fdt != 0)
{
WLog_ERR(TAG, "window_redraw: could not allocate memory");
close(fd);
return;
}
if (!buffer->buffer) {
fd = shm_open("/wlfreerdp_shm", O_CREAT | O_RDWR, 0666);
fdt = ftruncate(fd, window->width * window->height * 4);
if (fdt != 0)
{
WLog_ERR(TAG, "window_redraw: could not allocate memory");
close(fd);
return;
}
buffer->shm_data = mmap(0, window->width * window->height * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (buffer->shm_data == MAP_FAILED)
{
WLog_ERR(TAG, "window_redraw: failed to memory map buffer");
close(fd);
return;
}
shm_data = mmap(NULL, window->width * window->height * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (shm_data == MAP_FAILED)
{
WLog_ERR(TAG, "window_redraw: failed to memory map buffer");
close(fd);
return;
}
shm_pool = wl_shm_create_pool(window->display->shm, fd, window->width * window->height * 4);
buffer->buffer = wl_shm_pool_create_buffer(shm_pool, 0, window->width, window->height, window->width* 4, WL_SHM_FORMAT_XRGB8888);
wl_buffer_add_listener(buffer->buffer, &wl_buffer_listener, buffer);
wl_shm_pool_destroy(shm_pool);
shm_unlink("wlfreerdp_shm");
close(fd);
shm_pool = wl_shm_create_pool(window->display->shm, fd, window->width * window->height * 4);
buffer->buffer = wl_shm_pool_create_buffer(shm_pool, 0, window->width, window->height, window->width* 4, WL_SHM_FORMAT_XRGB8888);
wl_buffer_add_listener(buffer->buffer, &wl_buffer_listener, buffer);
wl_shm_pool_destroy(shm_pool);
shm_unlink("/wlfreerdp_shm");
close(fd);
free_data = buffer->shm_data;
buffer->shm_data = shm_data;
munmap(free_data, window->width * window->height * 4);
}
/* this is the real surface data */
memcpy(buffer->shm_data, (void*) window->data, window->width * window->height * 4);
@ -109,7 +117,6 @@ static void wl_callback_done(void* data, struct wl_callback* callback, uint32_t
wl_surface_commit(window->surface);
buffer->busy = TRUE;
munmap(buffer->shm_data, window->width * window->height * 4);
}
static const struct wl_callback_listener wl_callback_listener =

View File

@ -48,33 +48,31 @@ void wl_begin_paint(rdpContext* context)
void wl_end_paint(rdpContext* context)
{
char *data;
rdpGdi* gdi;
wlfDisplay* display;
wlfWindow* window;
wlfContext* context_w;
INT32 x, y;
UINT32 w, h;
int i;
gdi = context->gdi;
if (gdi->primary->hdc->hwnd->invalid->null)
return;
x = gdi->primary->hdc->hwnd->invalid->x;
y = gdi->primary->hdc->hwnd->invalid->y;
w = gdi->primary->hdc->hwnd->invalid->w;
h = gdi->primary->hdc->hwnd->invalid->h;
context_w = (wlfContext*) context;
display = context_w->display;
window = context_w->window;
data = realloc(window->data, gdi->width * gdi->height * 4);
if (!data)
{
if (window->data)
free(window->data);
window->data = NULL;
}
else
{
window->data = data;
memcpy(window->data, (void*) gdi->primary_buffer, gdi->width * gdi->height * 4);
}
for (i = 0; i < h; i++)
memcpy(window->data + ((i+y)*(gdi->width*4)) + x*4,
gdi->primary_buffer + ((i+y)*(gdi->width*4)) + x*4,
w*4);
wlf_RefreshDisplay(display);
}
@ -246,6 +244,9 @@ int wlfreerdp_run(freerdp* instance)
wlf_DestroyInput(context, context->input);
wlf_DestroyDisplay(context, context->display);
freerdp_channels_disconnect(instance->context->channels, instance);
freerdp_disconnect(instance);
freerdp_channels_close(instance->context->channels, instance);
freerdp_channels_free(instance->context->channels);
freerdp_free(instance);

View File

@ -40,7 +40,7 @@ set(${MODULE_PREFIX}_SRCS
# On windows create dll version information.
# Vendor, product and year are already set in top level CMakeLists.txt
if (WIN32)
if (WIN32 AND BUILD_SHARED_LIBS)
set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR})
set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION})

View File

@ -506,7 +506,7 @@ BOOL wf_authenticate(freerdp* instance, char** username, char** password, char**
if (status != NO_ERROR)
{
WLog_ERR(TAG, "CredUIPromptForCredentials unexpected status: 0x%08X", status);
WLog_ERR(TAG, "CredUIPromptForCredentials unexpected status: 0x%08X", status);
return FALSE;
}
@ -514,7 +514,7 @@ BOOL wf_authenticate(freerdp* instance, char** username, char** password, char**
ZeroMemory(Domain, sizeof(Domain));
status = CredUIParseUserNameA(UserName, User, sizeof(User), Domain, sizeof(Domain));
//WLog_ERR(TAG, "User: %s Domain: %s Password: %s", User, Domain, Password);
//WLog_ERR(TAG, "User: %s Domain: %s Password: %s", User, Domain, Password);
*username = _strdup(User);
if (strlen(Domain) > 0)
@ -554,21 +554,6 @@ BOOL wf_verify_certificate(freerdp* instance, char* subject, char* issuer, char*
return TRUE;
}
int wf_receive_channel_data(freerdp* instance, UINT16 channelId, BYTE* data, int size, int flags, int total_size)
{
return freerdp_channels_data(instance, channelId, data, size, flags, total_size);
}
BOOL wf_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds, int* wcount)
{
return TRUE;
}
BOOL wf_check_fds(freerdp* instance)
{
return TRUE;
}
static BOOL wf_auto_reconnect(freerdp* instance)
{
wfContext* wfc = (wfContext *)instance->context;
@ -581,7 +566,7 @@ static BOOL wf_auto_reconnect(freerdp* instance)
return FALSE;
/* A network disconnect was detected */
WLog_ERR(TAG, "Network disconnect!");
WLog_ERR(TAG, "Network disconnect!");
if (!instance->settings->AutoReconnectionEnabled)
{
@ -607,7 +592,7 @@ static BOOL wf_auto_reconnect(freerdp* instance)
Sleep(5000);
}
WLog_ERR(TAG, "Maximum reconnect retries exceeded");
WLog_ERR(TAG, "Maximum reconnect retries exceeded");
return FALSE;
}
@ -621,8 +606,7 @@ void* wf_input_thread(void* arg)
assert( NULL != instance);
status = 1;
queue = freerdp_get_message_queue(instance,
FREERDP_INPUT_MESSAGE_QUEUE);
queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
while (MessageQueue_Wait(queue))
{
@ -644,70 +628,36 @@ void* wf_input_thread(void* arg)
return NULL;
}
void* wf_channels_thread(void* arg)
{
int status;
HANDLE event;
rdpChannels* channels;
freerdp* instance = (freerdp*) arg;
channels = instance->context->channels;
event = freerdp_channels_get_event_handle(instance);
while (WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0)
{
status = freerdp_channels_process_pending_messages(instance);
if (!status)
break;
}
ExitThread(0);
return NULL;
}
DWORD WINAPI wf_client_thread(LPVOID lpParam)
{
MSG msg;
int index;
int rcount;
int wcount;
int width;
int height;
BOOL msg_ret;
int quit_msg;
void* rfds[32];
void* wfds[32];
int fds_count;
HANDLE fds[64];
DWORD nCount;
HANDLE handles[64];
wfContext* wfc;
freerdp* instance;
rdpContext* context;
rdpChannels* channels;
rdpSettings* settings;
BOOL async_input;
BOOL async_channels;
BOOL async_transport;
HANDLE input_thread;
HANDLE channels_thread;
instance = (freerdp*) lpParam;
assert(NULL != instance);
context = instance->context;
wfc = (wfContext*) instance->context;
assert(NULL != wfc);
ZeroMemory(rfds, sizeof(rfds));
ZeroMemory(wfds, sizeof(wfds));
if (freerdp_connect(instance) != TRUE)
if (!freerdp_connect(instance))
return 0;
channels = instance->context->channels;
settings = instance->context->settings;
async_input = settings->AsyncInput;
async_channels = settings->AsyncChannels;
async_transport = settings->AsyncTransport;
if (async_input)
@ -717,15 +667,9 @@ DWORD WINAPI wf_client_thread(LPVOID lpParam)
instance, 0, NULL);
}
if (async_channels)
{
channels_thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) wf_channels_thread, instance, 0, NULL);
}
while (1)
{
rcount = 0;
wcount = 0;
nCount = 0;
if (freerdp_focus_required(instance))
{
@ -735,80 +679,29 @@ DWORD WINAPI wf_client_thread(LPVOID lpParam)
if (!async_transport)
{
if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
{
WLog_ERR(TAG, "Failed to get FreeRDP file descriptor");
break;
}
}
if (wf_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
{
WLog_ERR(TAG, "Failed to get wfreerdp file descriptor");
break;
nCount += freerdp_get_event_handles(context, &handles[nCount]);
}
if (!async_channels)
if (MsgWaitForMultipleObjects(nCount, handles, FALSE, 1000, QS_ALLINPUT) == WAIT_FAILED)
{
if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds, &wcount) != TRUE)
{
WLog_ERR(TAG, "Failed to get channel manager file descriptor");
break;
}
}
fds_count = 0;
/* setup read fds */
for (index = 0; index < rcount; index++)
{
fds[fds_count++] = rfds[index];
}
/* setup write fds */
for (index = 0; index < wcount; index++)
{
fds[fds_count++] = wfds[index];
}
/* exit if nothing to do */
if (fds_count == 0)
{
WLog_ERR(TAG, "wfreerdp_run: fds_count is zero");
//break;
}
/* do the wait */
if (MsgWaitForMultipleObjects(fds_count, fds, FALSE, 1000, QS_ALLINPUT) == WAIT_FAILED)
{
WLog_ERR(TAG, "wfreerdp_run: WaitForMultipleObjects failed: 0x%04X", GetLastError());
WLog_ERR(TAG, "wfreerdp_run: WaitForMultipleObjects failed: 0x%04X", GetLastError());
break;
}
if (!async_transport)
{
if (freerdp_check_fds(instance) != TRUE)
if (!freerdp_check_event_handles(context))
{
if (wf_auto_reconnect(instance))
continue;
WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
break;
}
}
if (freerdp_shall_disconnect(instance))
{
break;
}
if (wf_check_fds(instance) != TRUE)
{
WLog_ERR(TAG, "Failed to check wfreerdp file descriptor");
break;
}
if (!async_channels)
{
if (freerdp_channels_check_fds(channels, instance) != TRUE)
{
WLog_ERR(TAG, "Failed to check channel manager file descriptor");
break;
}
}
if (freerdp_shall_disconnect(instance))
break;
quit_msg = FALSE;
@ -833,9 +726,6 @@ DWORD WINAPI wf_client_thread(LPVOID lpParam)
width = LOWORD(msg.lParam);
height = HIWORD(msg.lParam);
//wfc->client_width = width;
//wfc->client_height = height;
SetWindowPos(wfc->hwnd, HWND_TOP, 0, 0, width, height, SWP_FRAMECHANGED);
}
@ -851,32 +741,26 @@ DWORD WINAPI wf_client_thread(LPVOID lpParam)
if (quit_msg)
break;
Sleep(100);
}
/* cleanup */
freerdp_channels_close(channels, instance);
freerdp_channels_disconnect(channels, instance);
if (async_input)
{
wMessageQueue* input_queue;
input_queue = freerdp_get_message_queue(instance,
FREERDP_INPUT_MESSAGE_QUEUE);
input_queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
MessageQueue_PostQuit(input_queue, 0);
WaitForSingleObject(input_thread, INFINITE);
CloseHandle(input_thread);
}
if (async_channels)
{
WaitForSingleObject(channels_thread, INFINITE);
CloseHandle(channels_thread);
}
freerdp_disconnect(instance);
WLog_DBG(TAG, "Main thread exited.");
ExitThread(0);
return 0;
}
@ -898,7 +782,7 @@ DWORD WINAPI wf_keyboard_thread(LPVOID lpParam)
{
if (status == -1)
{
WLog_ERR(TAG, "keyboard thread error getting message");
WLog_ERR(TAG, "keyboard thread error getting message");
break;
}
else
@ -912,7 +796,7 @@ DWORD WINAPI wf_keyboard_thread(LPVOID lpParam)
}
else
{
WLog_ERR(TAG, "failed to install keyboard hook");
WLog_ERR(TAG, "failed to install keyboard hook");
}
WLog_DBG(TAG, "Keyboard thread exited.");
@ -1123,7 +1007,6 @@ int wfreerdp_client_new(freerdp* instance, rdpContext* context)
instance->PostConnect = wf_post_connect;
instance->Authenticate = wf_authenticate;
instance->VerifyCertificate = wf_verify_certificate;
instance->ReceiveChannelData = wf_receive_channel_data;
wfc->instance = instance;
wfc->settings = instance->settings;
@ -1134,9 +1017,12 @@ int wfreerdp_client_new(freerdp* instance, rdpContext* context)
void wfreerdp_client_free(freerdp* instance, rdpContext* context)
{
rdpChannels* channels = context->channels;
if (context->cache)
cache_free(context->cache);
freerdp_channels_close(channels, instance);
freerdp_channels_free(context->channels);
}

View File

@ -1073,7 +1073,7 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
switch (Msg)
{
case WM_CREATE:
DEBUG_CLIPRDR("info: %s - WM_CREATE", __FUNCTION__);
DEBUG_CLIPRDR("info: WM_CREATE");
clipboard = (wfClipboard*)((CREATESTRUCT*) lParam)->lpCreateParams;
if (!AddClipboardFormatListener(hWnd)) {
DEBUG_CLIPRDR("error: AddClipboardFormatListener failed with %#x.", GetLastError());
@ -1082,12 +1082,12 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
break;
case WM_CLOSE:
DEBUG_CLIPRDR("info: %s - WM_CLOSE", __FUNCTION__);
DEBUG_CLIPRDR("info: WM_CLOSE");
RemoveClipboardFormatListener(hWnd);
break;
case WM_CLIPBOARDUPDATE:
DEBUG_CLIPRDR("info: %s - WM_CLIPBOARDUPDATE", __FUNCTION__);
DEBUG_CLIPRDR("info: WM_CLIPBOARDUPDATE");
if (clipboard->sync)
{
if ((GetClipboardOwner() != clipboard->hwnd) &&
@ -1105,7 +1105,7 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
break;
case WM_RENDERALLFORMATS:
DEBUG_CLIPRDR("info: %s - WM_RENDERALLFORMATS", __FUNCTION__);
DEBUG_CLIPRDR("info: WM_RENDERALLFORMATS");
/* discard all contexts in clipboard */
if (!OpenClipboard(clipboard->hwnd))
{
@ -1117,7 +1117,7 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
break;
case WM_RENDERFORMAT:
DEBUG_CLIPRDR("info: %s - WM_RENDERFORMAT", __FUNCTION__);
DEBUG_CLIPRDR("info: WM_RENDERFORMAT");
if (cliprdr_send_data_request(clipboard, (UINT32) wParam) != 0)
{
DEBUG_CLIPRDR("error: cliprdr_send_data_request failed.");
@ -1138,11 +1138,11 @@ static LRESULT CALLBACK cliprdr_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM
break;
case WM_CLIPRDR_MESSAGE:
DEBUG_CLIPRDR("info: %s - WM_CLIPRDR_MESSAGE", __FUNCTION__);
DEBUG_CLIPRDR("info: WM_CLIPRDR_MESSAGE");
switch (wParam)
{
case OLE_SETCLIPBOARD:
DEBUG_CLIPRDR("info: %s - OLE_SETCLIPBOARD", __FUNCTION__);
DEBUG_CLIPRDR("info: OLE_SETCLIPBOARD");
if (wf_create_file_obj(clipboard, &clipboard->data_obj))
{
if (OleSetClipboard(clipboard->data_obj) != S_OK)

View File

@ -157,7 +157,8 @@ void wf_event_focus_in(wfContext* wfc)
{
UINT16 syncFlags;
rdpInput* input;
UINT16 mouseX, mouseY;
POINT pt;
RECT rc;
input = wfc->instance->input;
@ -175,10 +176,15 @@ void wf_event_focus_in(wfContext* wfc)
if (GetKeyState(VK_KANA))
syncFlags |= KBD_SYNC_KANA_LOCK;
mouseX = 0;
mouseY = 0;
input->FocusInEvent(input, syncFlags);
input->FocusInEvent(input, syncFlags, mouseX, mouseY);
/* send pointer position if the cursor is currently inside our client area */
GetCursorPos(&pt);
ScreenToClient(wfc->hwnd, &pt);
GetClientRect(wfc->hwnd, &rc);
if (pt.x >= rc.left && pt.x < rc.right && pt.y >= rc.top && pt.y < rc.bottom)
input->MouseEvent(input, PTR_FLAGS_MOVE, (UINT16)pt.x, (UINT16)pt.y);
}
static int wf_event_process_WM_MOUSEWHEEL(wfContext* wfc, HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)

View File

@ -71,7 +71,6 @@ int main(int argc, char* argv[])
thread = freerdp_client_get_thread(context);
WaitForSingleObject(thread, INFINITE);
GetExitCodeThread(thread, &dwExitCode);
freerdp_client_stop(context);

File diff suppressed because it is too large Load Diff

View File

@ -265,15 +265,11 @@ static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard)
static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasData, BYTE* data, int size)
{
UINT32 index;
UINT32 count;
BOOL bSuccess;
UINT32 SrcSize;
UINT32 DstSize;
UINT32 formatId;
UINT32 altFormatId;
UINT32* pFormatIds;
const char* formatName;
BYTE* pSrcData = NULL;
BYTE* pDstData = NULL;
xfCliprdrFormat* format;
@ -295,7 +291,9 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
switch (format->formatId)
{
case CF_TEXT:
case CF_OEMTEXT:
case CF_UNICODETEXT:
size = strlen((char*) data) + 1;
formatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
break;
@ -304,6 +302,7 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
break;
case CB_FORMAT_HTML:
size = strlen((char*) data) + 1;
formatId = ClipboardGetFormatId(clipboard->system, "text/html");
break;
}
@ -317,42 +316,11 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
CopyMemory(pSrcData, data, SrcSize);
bSuccess = ClipboardSetData(clipboard->system, formatId, (void*) pSrcData, SrcSize);
if (!bSuccess)
free (pSrcData);
free(pSrcData);
pFormatIds = NULL;
count = ClipboardGetFormatIds(clipboard->system, &pFormatIds);
for (index = 0; index < count; index++)
{
formatId = pFormatIds[index];
formatName = ClipboardGetFormatName(clipboard->system, formatId);
if (formatId < CF_MAX)
{
switch (formatId)
{
case CF_TEXT:
altFormatId = CF_TEXT;
break;
case CF_UNICODETEXT:
altFormatId = CF_UNICODETEXT;
break;
case CF_DIB:
altFormatId = CF_DIB;
break;
}
}
else if (strcmp(formatName, "HTML Format") == 0)
{
altFormatId = formatId;
break;
}
}
free(pFormatIds);
altFormatId = clipboard->requestedFormatId;
if (bSuccess && altFormatId)
{
@ -367,6 +335,7 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
}
xf_cliprdr_send_data_response(clipboard, pDstData, (int) DstSize);
free(pDstData);
}
static BOOL xf_cliprdr_get_requested_data(xfClipboard* clipboard, Atom target)
@ -398,6 +367,7 @@ static BOOL xf_cliprdr_get_requested_data(xfClipboard* clipboard, Atom target)
XFree(data);
data = NULL;
}
if (bytes_left <= 0 && !clipboard->incr_starts)
{
@ -770,7 +740,7 @@ int xf_cliprdr_send_client_format_list(xfClipboard* clipboard)
free(formats);
if (clipboard->owner != xfc->drawable)
if (clipboard->owner && clipboard->owner != xfc->drawable)
{
/* Request the owner for TARGETS, and wait for SelectionNotify event */
XConvertSelection(xfc->display, clipboard->clipboard_atom,
@ -941,6 +911,7 @@ static int xf_cliprdr_server_format_data_response(CliprdrClientContext* context,
UINT32 formatId;
UINT32 altFormatId;
xfCliprdrFormat* format;
BOOL nullTerminated = FALSE;
UINT32 size = formatDataResponse->dataLen;
BYTE* data = formatDataResponse->requestedFormatData;
xfClipboard* clipboard = (xfClipboard*) context->custom;
@ -958,6 +929,7 @@ static int xf_cliprdr_server_format_data_response(CliprdrClientContext* context,
}
pDstData = NULL;
DstSize = 0;
formatId = 0;
altFormatId = 0;
@ -967,11 +939,19 @@ static int xf_cliprdr_server_format_data_response(CliprdrClientContext* context,
case CF_TEXT:
formatId = CF_TEXT;
altFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
nullTerminated = TRUE;
break;
case CF_OEMTEXT:
formatId = CF_OEMTEXT;
altFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
nullTerminated = TRUE;
break;
case CF_UNICODETEXT:
formatId = CF_UNICODETEXT;
altFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
nullTerminated = TRUE;
break;
case CF_DIB:
@ -982,6 +962,7 @@ static int xf_cliprdr_server_format_data_response(CliprdrClientContext* context,
case CB_FORMAT_HTML:
formatId = ClipboardGetFormatId(clipboard->system, "HTML Format");
altFormatId = ClipboardGetFormatId(clipboard->system, "text/html");
nullTerminated = TRUE;
break;
}
@ -994,6 +975,7 @@ static int xf_cliprdr_server_format_data_response(CliprdrClientContext* context,
CopyMemory(pSrcData, data, SrcSize);
bSuccess = ClipboardSetData(clipboard->system, formatId, (void*) pSrcData, SrcSize);
if (!bSuccess)
free (pSrcData);
@ -1001,6 +983,9 @@ static int xf_cliprdr_server_format_data_response(CliprdrClientContext* context,
{
DstSize = 0;
pDstData = (BYTE*) ClipboardGetData(clipboard->system, altFormatId, &DstSize);
if ((DstSize > 1) && nullTerminated)
DstSize--;
}
clipboard->data = pDstData;
@ -1142,6 +1127,12 @@ void xf_clipboard_free(xfClipboard* clipboard)
clipboard->serverFormats = NULL;
}
if (clipboard->numClientFormats)
{
for (i = 0; i < clipboard->numClientFormats; i++)
free(clipboard->clientFormats[i].formatName);
}
ClipboardDestroy(clipboard->system);
free(clipboard->data);

View File

@ -178,15 +178,42 @@ int xf_event_execute_action_script(xfContext* xfc, XEvent* event)
return 1;
}
void xf_event_adjust_coordinates(xfContext* xfc, int* x, int *y)
{
if (!xfc->remote_app)
{
#ifdef WITH_XRENDER
if (xf_picture_transform_required(xfc))
{
double xScalingFactor = xfc->width / (double)xfc->scaledWidth;
double yScalingFactor = xfc->height / (double)xfc->scaledHeight;
*x = (int)((*x - xfc->offset_x) * xScalingFactor);
*y = (int)((*y - xfc->offset_y) * yScalingFactor);
}
#endif
}
CLAMP_COORDINATES(*x, *y);
}
static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app)
{
int x, y;
int w, h;
x = event->xexpose.x;
y = event->xexpose.y;
w = event->xexpose.width;
h = event->xexpose.height;
if (!app && (xfc->settings->SmartSizing || xfc->settings->MultiTouchGestures))
{
x = 0;
y = 0;
w = xfc->width;
h = xfc->height;
}
else
{
x = event->xexpose.x;
y = event->xexpose.y;
w = event->xexpose.width;
h = event->xexpose.height;
}
if (xfc->gfx)
{
@ -196,28 +223,20 @@ static BOOL xf_event_Expose(xfContext* xfc, XEvent* event, BOOL app)
if (!app)
{
if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y))
{
xf_draw_screen_scaled(xfc, x - xfc->offset_x,
y - xfc->offset_y, w, h, FALSE);
}
else
{
XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc, x, y, w, h, x, y);
}
xf_draw_screen(xfc, x, y, w, h);
}
else
{
xfAppWindow* appWindow;
appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window);
if (appWindow)
{
xf_UpdateWindowArea(xfc, appWindow, x, y, w, h);
}
}
return TRUE;
}
@ -251,14 +270,8 @@ BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window win
RootWindowOfScreen(xfc->screen),
x, y, &x, &y, &childWindow);
}
/* Take scaling in to consideration */
if ( (xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y) )
{
x = (int)((x - xfc->offset_x) * (1.0 / xfc->settings->ScalingFactor) );
y = (int)((y - xfc->offset_y) * (1.0 / xfc->settings->ScalingFactor) );
}
CLAMP_COORDINATES(x,y);
xf_event_adjust_coordinates(xfc, &x, &y);
input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
@ -358,16 +371,8 @@ BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button, Window win
}
if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x)
|| (xfc->offset_y))
{
x = (int) ((x - xfc->offset_x)
* (1.0 / xfc->settings->ScalingFactor));
y = (int) ((y - xfc->offset_y)
* (1.0 / xfc->settings->ScalingFactor));
}
xf_event_adjust_coordinates(xfc, &x, &y);
CLAMP_COORDINATES(x,y);
if (extended)
input->ExtendedMouseEvent(input, flags, x, y);
else
@ -447,14 +452,7 @@ BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, Window w
x, y, &x, &y, &childWindow);
}
if ((xfc->settings->ScalingFactor != 1.0) || (xfc->offset_x) || (xfc->offset_y))
{
x = (int) ((x - xfc->offset_x) * (1.0 / xfc->settings->ScalingFactor));
y = (int) ((y - xfc->offset_y) * (1.0 / xfc->settings->ScalingFactor));
}
CLAMP_COORDINATES(x,y);
xf_event_adjust_coordinates(xfc, &x, &y);
if (extended)
input->ExtendedMouseEvent(input, flags, x, y);
@ -642,7 +640,33 @@ static BOOL xf_event_ConfigureNotify(xfContext* xfc, XEvent* event, BOOL app)
xfAppWindow* appWindow;
if (!app)
{
if (xfc->window->width != event->xconfigure.width ||
xfc->window->height != event->xconfigure.height)
{
xfc->window->width = event->xconfigure.width;
xfc->window->height = event->xconfigure.height;
#ifdef WITH_XRENDER
xfc->offset_x = 0;
xfc->offset_y = 0;
if (xfc->settings->SmartSizing || xfc->settings->MultiTouchGestures)
{
if (!xfc->fullscreen)
{
xfc->scaledWidth = xfc->window->width;
xfc->scaledHeight = xfc->window->height;
}
xf_draw_screen(xfc, 0, 0, xfc->width, xfc->height);
}
else
{
xfc->scaledWidth = xfc->width;
xfc->scaledHeight = xfc->height;
}
#endif
}
return TRUE;
}
appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window);
@ -754,12 +778,12 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app)
if (app)
{
xfAppWindow* appWindow;
appWindow = xf_AppWindowFromX11Window(xfc, event->xany.window);
if (!appWindow)
return TRUE;
if ((((Atom) event->xproperty.atom == xfc->_NET_WM_STATE) && (event->xproperty.state != PropertyDelete)) ||
(((Atom) event->xproperty.atom == xfc->WM_STATE) && (event->xproperty.state != PropertyDelete)))
{
@ -771,7 +795,7 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app)
unsigned long nitems;
unsigned long bytes;
unsigned char* prop;
if ((Atom) event->xproperty.atom == xfc->_NET_WM_STATE)
{
status = xf_GetWindowProperty(xfc, event->xproperty.window,
@ -795,7 +819,7 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app)
XFree(prop);
}
}
if ((Atom) event->xproperty.atom == xfc->WM_STATE)
{
status = xf_GetWindowProperty(xfc, event->xproperty.window,
@ -828,7 +852,7 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app)
appWindow->rail_state = WINDOW_SHOW;
xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_RESTORE);
}
}
}
}
return TRUE;
@ -907,7 +931,7 @@ static BOOL xf_event_suppress_events(xfContext* xfc, xfAppWindow* appWindow, XEv
case LMS_TERMINATING:
/* Already sent RDP end move to server. Allow events to pass. */
break;
}
}
return FALSE;
}

View File

@ -31,6 +31,8 @@ void xf_event_action_script_free(xfContext* xfc);
BOOL xf_event_process(freerdp* instance, XEvent* event);
void xf_event_SendClientEvent(xfContext* xfc, xfWindow* window, Atom atom, unsigned int numArgs, ...);
void xf_event_adjust_coordinates(xfContext* xfc, int* x, int *y);
BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window window, BOOL app);
BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button, Window window, BOOL app);
BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, Window window, BOOL app);

View File

@ -3,6 +3,8 @@
* X11 GDI
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2014 Thincast Technologies GmbH
* Copyright 2014 Norbert Federa <norbert.federa@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -217,6 +219,58 @@ BOOL xf_set_rop3(xfContext* xfc, int rop3)
return TRUE;
}
UINT32 xf_convert_rdp_order_color(xfContext* xfc, UINT32 color)
{
UINT32 r, g, b;
switch (xfc->srcBpp)
{
case 32:
case 24:
if (xfc->visual->red_mask == 0xFF0000 &&
xfc->visual->green_mask == 0xFF00 &&
xfc->visual->blue_mask == 0xFF)
{
return color;
}
GetRGB32(r, g, b, color);
break;
case 16:
color = (color & 0xFF00) | ((color >> 16) & 0xFF);
if (xfc->visual->red_mask == 0xF800 &&
xfc->visual->green_mask == 0x07E0 &&
xfc->visual->blue_mask == 0x001F)
{
return color;
}
GetRGB16(r, g, b, color);
break;
case 15:
color = (color & 0xFF00) | ((color >> 16) & 0xFF);
GetRGB15(r, g, b, color);
break;
case 8:
color = (color >> 16) & (UINT32) 0xFF;
if (xfc->palette)
{
r = xfc->palette[(color * 4) + 2];
g = xfc->palette[(color * 4) + 1];
b = xfc->palette[(color * 4) + 0];
}
break;
default:
return color;
}
return ( ((r >> xfc->red_shift_r) << xfc->red_shift_l) |
((g >> xfc->green_shift_r) << xfc->green_shift_l) |
((b >> xfc->blue_shift_r) << xfc->blue_shift_l) );
}
Pixmap xf_brush_new(xfContext* xfc, int width, int height, int bpp, BYTE* data)
{
GC gc;
@ -440,10 +494,6 @@ void xf_gdi_dstblt(rdpContext* context, DSTBLT_ORDER* dstblt)
if (xfc->drawing == xfc->primary)
{
if (!xfc->remote_app)
{
XFillRectangle(xfc->display, xfc->drawable, xfc->gc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight);
}
gdi_InvalidateRegion(xfc->hdc, dstblt->nLeftRect, dstblt->nTopRect, dstblt->nWidth, dstblt->nHeight);
}
@ -465,8 +515,8 @@ void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
brush = &patblt->brush;
xf_set_rop3(xfc, gdi_rop3_code(patblt->bRop));
foreColor = freerdp_convert_gdi_order_color(patblt->foreColor, context->settings->ColorDepth, xfc->format, xfc->palette);
backColor = freerdp_convert_gdi_order_color(patblt->backColor, context->settings->ColorDepth, xfc->format, xfc->palette);
foreColor = xf_convert_rdp_order_color(xfc, patblt->foreColor);
backColor = xf_convert_rdp_order_color(xfc, patblt->backColor);
if (brush->style == GDI_BS_SOLID)
{
@ -531,11 +581,6 @@ void xf_gdi_patblt(rdpContext* context, PATBLT_ORDER* patblt)
if (xfc->drawing == xfc->primary)
{
XSetFunction(xfc->display, xfc->gc, GXcopy);
if (!xfc->remote_app)
{
XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight, patblt->nLeftRect, patblt->nTopRect);
}
gdi_InvalidateRegion(xfc->hdc, patblt->nLeftRect, patblt->nTopRect, patblt->nWidth, patblt->nHeight);
}
@ -557,19 +602,6 @@ void xf_gdi_scrblt(rdpContext* context, SCRBLT_ORDER* scrblt)
if (xfc->drawing == xfc->primary)
{
if (!xfc->remote_app)
{
if (xfc->unobscured)
{
XCopyArea(xfc->display, xfc->drawable, xfc->drawable, xfc->gc, scrblt->nXSrc, scrblt->nYSrc,
scrblt->nWidth, scrblt->nHeight, scrblt->nLeftRect, scrblt->nTopRect);
}
}
else
{
XSetFunction(xfc->display, xfc->gc, GXcopy);
XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc, scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth, scrblt->nHeight, scrblt->nLeftRect, scrblt->nTopRect);
}
gdi_InvalidateRegion(xfc->hdc, scrblt->nLeftRect, scrblt->nTopRect, scrblt->nWidth, scrblt->nHeight);
}
@ -585,7 +617,7 @@ void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect)
xf_lock_x11(xfc, FALSE);
color = freerdp_convert_gdi_order_color(opaque_rect->color, context->settings->ColorDepth, xfc->format, xfc->palette);
color = xf_convert_rdp_order_color(xfc, opaque_rect->color);
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
@ -597,13 +629,6 @@ void xf_gdi_opaque_rect(rdpContext* context, OPAQUE_RECT_ORDER* opaque_rect)
if (xfc->drawing == xfc->primary)
{
if (!xfc->remote_app)
{
XFillRectangle(xfc->display, xfc->drawable, xfc->gc,
opaque_rect->nLeftRect, opaque_rect->nTopRect,
opaque_rect->nWidth, opaque_rect->nHeight);
}
gdi_InvalidateRegion(xfc->hdc, opaque_rect->nLeftRect, opaque_rect->nTopRect,
opaque_rect->nWidth, opaque_rect->nHeight);
}
@ -620,7 +645,7 @@ void xf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* mult
xf_lock_x11(xfc, FALSE);
color = freerdp_convert_gdi_order_color(multi_opaque_rect->color, context->settings->ColorDepth, xfc->format, xfc->palette);
color = xf_convert_rdp_order_color(xfc, multi_opaque_rect->color);
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
@ -636,12 +661,6 @@ void xf_gdi_multi_opaque_rect(rdpContext* context, MULTI_OPAQUE_RECT_ORDER* mult
if (xfc->drawing == xfc->primary)
{
if (!xfc->remote_app)
{
XFillRectangle(xfc->display, xfc->drawable, xfc->gc,
rectangle->left, rectangle->top,
rectangle->width, rectangle->height);
}
gdi_InvalidateRegion(xfc->hdc, rectangle->left, rectangle->top, rectangle->width, rectangle->height);
}
}
@ -662,7 +681,7 @@ void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to)
xf_lock_x11(xfc, FALSE);
xf_set_rop2(xfc, line_to->bRop2);
color = freerdp_convert_gdi_order_color(line_to->penColor, context->settings->ColorDepth, xfc->format, xfc->palette);
color = xf_convert_rdp_order_color(xfc, line_to->penColor);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
XSetForeground(xfc->display, xfc->gc, color);
@ -672,24 +691,15 @@ void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to)
if (xfc->drawing == xfc->primary)
{
if (!xfc->remote_app)
{
XDrawLine(xfc->display, xfc->drawable, xfc->gc,
line_to->nXStart, line_to->nYStart, line_to->nXEnd, line_to->nYEnd);
}
int width, height;
int x, y, w, h;
width = line_to->nXStart - line_to->nXEnd;
height = line_to->nYStart - line_to->nYEnd;
x = MIN(line_to->nXStart, line_to->nXEnd);
y = MIN(line_to->nYStart, line_to->nYEnd);
if (width < 0)
width *= (-1);
if (height < 0)
height *= (-1);
gdi_InvalidateRegion(xfc->hdc, line_to->nXStart, line_to->nYStart, width, height);
w = abs(line_to->nXEnd - line_to->nXStart) + 1;
h = abs(line_to->nYEnd - line_to->nYStart) + 1;
gdi_InvalidateRegion(xfc->hdc, x, y, w, h);
}
XSetFunction(xfc->display, xfc->gc, GXcopy);
@ -697,22 +707,57 @@ void xf_gdi_line_to(rdpContext* context, LINE_TO_ORDER* line_to)
xf_unlock_x11(xfc, FALSE);
}
static void xf_gdi_invalidate_poly_region(xfContext* xfc, XPoint* points, int npoints, BOOL autoclose)
{
int i, x, y, x1, y1, x2, y2, w, h;
x1 = points[0].x;
y1 = points[0].y;
for (i = 1; i <= npoints; i++)
{
if (i == npoints)
{
if (!autoclose)
break;
x2 = points[0].x;
y2 = points[0].y;
if (x2 == points[0].x && y2 == points[0].y)
break;
}
else
{
x2 = points[i].x + x1;
y2 = points[i].y + y1;
}
x = MIN(x1, x2);
y = MIN(y1, y2);
w = abs(x2 - x1) + 1;
h = abs(y2 - y1) + 1;
x1 = x2;
y1 = y2;
gdi_InvalidateRegion(xfc->hdc, x, y, w, h);
}
}
void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline)
{
int i;
int x, y;
int x1, y1;
int x2, y2;
int npoints;
UINT32 color;
XPoint* points;
int width, height;
xfContext* xfc = (xfContext*) context;
xf_lock_x11(xfc, FALSE);
xf_set_rop2(xfc, polyline->bRop2);
color = freerdp_convert_gdi_order_color(polyline->penColor, context->settings->ColorDepth, xfc->format, xfc->palette);
color = xf_convert_rdp_order_color(xfc, polyline->penColor);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
XSetForeground(xfc->display, xfc->gc, color);
@ -733,29 +778,7 @@ void xf_gdi_polyline(rdpContext* context, POLYLINE_ORDER* polyline)
if (xfc->drawing == xfc->primary)
{
if (!xfc->remote_app)
{
XDrawLines(xfc->display, xfc->drawable, xfc->gc, points, npoints, CoordModePrevious);
}
x1 = points[0].x;
y1 = points[0].y;
for (i = 1; i < npoints; i++)
{
x2 = points[i].x + x1;
y2 = points[i].y + y1;
x = (x2 < x1) ? x2 : x1;
width = (x2 > x1) ? x2 - x1 : x1 - x2;
y = (y2 < y1) ? y2 : y1;
height = (y2 > y1) ? y2 - y1 : y1 - y2;
x1 = x2;
y1 = y2;
gdi_InvalidateRegion(xfc->hdc, x, y, width, height);
}
xf_gdi_invalidate_poly_region(xfc, points, npoints, FALSE);
}
XSetFunction(xfc->display, xfc->gc, GXcopy);
@ -780,13 +803,6 @@ void xf_gdi_memblt(rdpContext* context, MEMBLT_ORDER* memblt)
if (xfc->drawing == xfc->primary)
{
if (!xfc->remote_app)
{
XCopyArea(xfc->display, bitmap->pixmap, xfc->drawable, xfc->gc,
memblt->nXSrc, memblt->nYSrc, memblt->nWidth, memblt->nHeight,
memblt->nLeftRect, memblt->nTopRect);
}
gdi_InvalidateRegion(xfc->hdc, memblt->nLeftRect, memblt->nTopRect, memblt->nWidth, memblt->nHeight);
}
@ -809,8 +825,8 @@ void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
brush = &mem3blt->brush;
bitmap = (xfBitmap*) mem3blt->bitmap;
xf_set_rop3(xfc, gdi_rop3_code(mem3blt->bRop));
foreColor = freerdp_convert_gdi_order_color(mem3blt->foreColor, context->settings->ColorDepth, xfc->format, xfc->palette);
backColor = freerdp_convert_gdi_order_color(mem3blt->backColor, context->settings->ColorDepth, xfc->format, xfc->palette);
foreColor = xf_convert_rdp_order_color(xfc, mem3blt->foreColor);
backColor = xf_convert_rdp_order_color(xfc, mem3blt->backColor);
if (brush->style == GDI_BS_PATTERN)
{
@ -852,12 +868,6 @@ void xf_gdi_mem3blt(rdpContext* context, MEM3BLT_ORDER* mem3blt)
if (xfc->drawing == xfc->primary)
{
if (!xfc->remote_app)
{
XCopyArea(xfc->display, bitmap->pixmap, xfc->drawable, xfc->gc,
mem3blt->nXSrc, mem3blt->nYSrc, mem3blt->nWidth, mem3blt->nHeight,
mem3blt->nLeftRect, mem3blt->nTopRect);
}
gdi_InvalidateRegion(xfc->hdc, mem3blt->nLeftRect, mem3blt->nTopRect, mem3blt->nWidth, mem3blt->nHeight);
}
@ -882,7 +892,7 @@ void xf_gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc)
xf_lock_x11(xfc, FALSE);
xf_set_rop2(xfc, polygon_sc->bRop2);
brush_color = freerdp_convert_gdi_order_color(polygon_sc->brushColor, context->settings->ColorDepth, xfc->format, xfc->palette);
brush_color = xf_convert_rdp_order_color(xfc, polygon_sc->brushColor);
npoints = polygon_sc->numPoints + 1;
points = malloc(sizeof(XPoint) * npoints);
@ -919,8 +929,7 @@ void xf_gdi_polygon_sc(rdpContext* context, POLYGON_SC_ORDER* polygon_sc)
if (xfc->drawing == xfc->primary)
{
XFillPolygon(xfc->display, xfc->drawable, xfc->gc,
points, npoints, Complex, CoordModePrevious);
xf_gdi_invalidate_poly_region(xfc, points, npoints, TRUE);
}
XSetFunction(xfc->display, xfc->gc, GXcopy);
@ -943,8 +952,8 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
brush = &(polygon_cb->brush);
xf_set_rop2(xfc, polygon_cb->bRop2);
foreColor = freerdp_convert_gdi_order_color(polygon_cb->foreColor, context->settings->ColorDepth, xfc->format, xfc->palette);
backColor = freerdp_convert_gdi_order_color(polygon_cb->backColor, context->settings->ColorDepth, xfc->format, xfc->palette);
foreColor = xf_convert_rdp_order_color(xfc, polygon_cb->foreColor);
backColor = xf_convert_rdp_order_color(xfc, polygon_cb->backColor);
npoints = polygon_cb->numPoints + 1;
points = malloc(sizeof(XPoint) * npoints);
@ -981,20 +990,6 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
XSetFillStyle(xfc->display, xfc->gc, FillTiled);
XSetTile(xfc->display, xfc->gc, pattern);
XSetTSOrigin(xfc->display, xfc->gc, brush->x, brush->y);
XFillPolygon(xfc->display, xfc->drawing, xfc->gc,
points, npoints, Complex, CoordModePrevious);
if (xfc->drawing == xfc->primary)
{
XFillPolygon(xfc->display, xfc->drawable, xfc->gc,
points, npoints, Complex, CoordModePrevious);
}
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
XSetTSOrigin(xfc->display, xfc->gc, 0, 0);
XFreePixmap(xfc->display, pattern);
}
else
{
@ -1009,20 +1004,20 @@ void xf_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
XSetFillStyle(xfc->display, xfc->gc, FillOpaqueStippled);
XSetStipple(xfc->display, xfc->gc, pattern);
XSetTSOrigin(xfc->display, xfc->gc, brush->x, brush->y);
}
XFillPolygon(xfc->display, xfc->drawing, xfc->gc,
points, npoints, Complex, CoordModePrevious);
XSetTSOrigin(xfc->display, xfc->gc, brush->x, brush->y);
if (xfc->drawing == xfc->primary)
{
XFillPolygon(xfc->display, xfc->drawable, xfc->gc,
points, npoints, Complex, CoordModePrevious);
}
XFillPolygon(xfc->display, xfc->drawing, xfc->gc,
points, npoints, Complex, CoordModePrevious);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
XSetTSOrigin(xfc->display, xfc->gc, 0, 0);
XFreePixmap(xfc->display, pattern);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
XSetTSOrigin(xfc->display, xfc->gc, 0, 0);
XFreePixmap(xfc->display, pattern);
if (xfc->drawing == xfc->primary)
{
xf_gdi_invalidate_poly_region(xfc, points, npoints, TRUE);
}
}
else
@ -1174,18 +1169,12 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
XFree(image);
}
/* Copy the updated region from backstore to the window. */
/* Invalidate the updated region */
for (i = 0; i < message->numRects; i++)
{
tx = message->rects[i].x + cmd->destLeft;
ty = message->rects[i].y + cmd->destTop;
if (!xfc->remote_app)
{
XCopyArea(xfc->display, xfc->primary, xfc->drawable, xfc->gc,
tx, ty, message->rects[i].width, message->rects[i].height, tx, ty);
}
xf_gdi_surface_update_frame(xfc, tx, ty, message->rects[i].width, message->rects[i].height);
}
@ -1224,13 +1213,6 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
XFree(image);
if (!xfc->remote_app)
{
XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc,
cmd->destLeft, cmd->destTop, cmd->width, cmd->height,
cmd->destLeft, cmd->destTop);
}
xf_gdi_surface_update_frame(xfc, cmd->destLeft, cmd->destTop, cmd->width, cmd->height);
XSetClipMask(xfc->display, xfc->gc, None);
@ -1263,13 +1245,6 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* cmd)
cmd->width, cmd->height);
XFree(image);
if (!xfc->remote_app)
{
XCopyArea(xfc->display, xfc->primary, xfc->window->handle, xfc->gc,
cmd->destLeft, cmd->destTop,
cmd->width, cmd->height, cmd->destLeft, cmd->destTop);
}
xf_gdi_surface_update_frame(xfc, cmd->destLeft, cmd->destTop, cmd->width, cmd->height);
XSetClipMask(xfc->display, xfc->gc, None);

View File

@ -27,5 +27,6 @@
void xf_gdi_register_update_callbacks(rdpUpdate* update);
void xf_gdi_bitmap_update(rdpContext* context, BITMAP_UPDATE* bitmapUpdate);
UINT32 xf_convert_rdp_order_color(xfContext* xfc, UINT32 color);
#endif /* __XF_GDI_H */

View File

@ -26,57 +26,87 @@
#define TAG CLIENT_TAG("x11")
static int xf_call_for_each_surface(xfContext* xfc, wArrayList* surfaceList, int (*processSurface)(xfContext*, xfGfxSurface*, void*), void* param)
{
int status = 1;
int surfaceIndex;
RdpgfxClientContext* context = xfc->gfx;
/* Iterating backwards to be able to remove surfaces from the list */
surfaceIndex = ArrayList_Count(surfaceList) - 1;
for (; surfaceIndex >= 0; surfaceIndex--)
{
UINT32 surfaceId;
xfGfxSurface* surface;
surfaceId = (UINT32) (ULONG_PTR) ArrayList_GetItem(xfc->gfxMappedSurfaceIds, surfaceIndex);
surface = (xfGfxSurface*) context->GetSurfaceData(context, surfaceId);
if (!surface)
{
ArrayList_RemoveAt(surfaceList, surfaceIndex);
continue;
}
if (processSurface(xfc, surface, param) < 0)
status = -1;
}
return status;
}
static int do_clearInvalidRegion(xfContext* xfc, xfGfxSurface* surface, void* param)
{
region16_clear(&surface->invalidRegion);
return 1;
}
int xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics)
{
xfContext* xfc = (xfContext*) context->custom;
freerdp_client_codecs_reset(xfc->codecs, FREERDP_CODEC_ALL);
region16_init(&(xfc->invalidRegion));
xf_call_for_each_surface(xfc, xfc->gfxMappedSurfaceIds, do_clearInvalidRegion, NULL);
xfc->graphicsReset = TRUE;
return 1;
}
int xf_OutputUpdate(xfContext* xfc)
int xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface)
{
UINT16 width, height;
xfGfxSurface* surface;
UINT32 surfaceX, surfaceY;
RECTANGLE_16 surfaceRect;
const RECTANGLE_16* extents;
if (!xfc->graphicsReset)
return 1;
surfaceX = surface->mapping.output.originX;
surfaceY = surface->mapping.output.originY;
surface = (xfGfxSurface*) xfc->gfx->GetSurfaceData(xfc->gfx, xfc->outputSurfaceId);
if (!surface)
return -1;
surfaceRect.left = 0;
surfaceRect.top = 0;
surfaceRect.right = xfc->width;
surfaceRect.bottom = xfc->height;
region16_intersect_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &surfaceRect);
surfaceRect.left = surfaceX;
surfaceRect.top = surfaceY;
surfaceRect.right = surfaceX + surface->width;
surfaceRect.bottom = surfaceY + surface->height;
XSetClipMask(xfc->display, xfc->gc, None);
XSetFunction(xfc->display, xfc->gc, GXcopy);
XSetFillStyle(xfc->display, xfc->gc, FillSolid);
if (!region16_is_empty(&(xfc->invalidRegion)))
if (!region16_is_empty(&surface->invalidRegion))
{
extents = region16_extents(&(xfc->invalidRegion));
extents = region16_extents(&surface->invalidRegion);
width = extents->right - extents->left;
height = extents->bottom - extents->top;
if (width > xfc->width)
width = xfc->width;
if (width > surface->width)
width = surface->width;
if (height > xfc->height)
height = xfc->height;
if (height > surface->height)
height = surface->height;
if (surface->stage)
{
@ -84,11 +114,23 @@ int xf_OutputUpdate(xfContext* xfc)
surface->width, surface->height, surface->data, surface->format, surface->scanline, 0, 0, NULL);
}
XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image,
extents->left, extents->top, extents->left, extents->top, width, height);
#ifdef WITH_XRENDER
if (xfc->settings->SmartSizing || xfc->settings->MultiTouchGestures)
{
XPutImage(xfc->display, xfc->primary, xfc->gc, surface->image,
extents->left, extents->top, extents->left + surfaceX, extents->top + surfaceY, width, height);
xf_draw_screen(xfc, extents->left, extents->top, width, height);
}
else
#endif
{
XPutImage(xfc->display, xfc->drawable, xfc->gc, surface->image,
extents->left, extents->top, extents->left + surfaceX, extents->top + surfaceY, width, height);
}
}
region16_clear(&(xfc->invalidRegion));
region16_clear(&surface->invalidRegion);
XSetClipMask(xfc->display, xfc->gc, None);
XSync(xfc->display, True);
@ -96,8 +138,78 @@ int xf_OutputUpdate(xfContext* xfc)
return 1;
}
static int xf_UpdateSurface(xfContext* xfc, xfGfxSurface* surface, void* param)
{
int status = 1;
switch (surface->mapping.mode)
{
case GFX_MAP_OUTPUT:
status = xf_OutputUpdate(xfc, surface);
break;
case GFX_MAP_NONE:
break;
}
return status;
}
int xf_UpdateSurfaces(xfContext* xfc)
{
if (!xfc->graphicsReset)
return 1;
return xf_call_for_each_surface(xfc, xfc->gfxMappedSurfaceIds, xf_UpdateSurface, NULL);
}
BOOL xf_MappedSurfaceRect(xfContext* xfc, xfGfxSurface* surface, RECTANGLE_16* rect)
{
BOOL mapped = FALSE;
switch (surface->mapping.mode)
{
case GFX_MAP_OUTPUT:
mapped = TRUE;
rect->left = surface->mapping.output.originX;
rect->top = surface->mapping.output.originY;
rect->right = surface->mapping.output.originX + surface->width;
rect->bottom = surface->mapping.output.originY + surface->height;
break;
case GFX_MAP_NONE:
break;
}
return mapped;
}
static int do_OutputExpose(xfContext* xfc, xfGfxSurface* surface, void* param)
{
RECTANGLE_16 surfaceRect;
RECTANGLE_16 intersection;
RECTANGLE_16* invalidRect = param;
if (!xf_MappedSurfaceRect(xfc, surface, &surfaceRect))
return -1;
if (rectangles_intersection(invalidRect, &surfaceRect, &intersection))
{
/* Invalid rects are specified relative to surface origin */
intersection.left -= surfaceRect.left;
intersection.top -= surfaceRect.top;
intersection.right -= surfaceRect.left;
intersection.bottom -= surfaceRect.top;
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &intersection);
}
return 1;
}
int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height)
{
int status = 1;
RECTANGLE_16 invalidRect;
invalidRect.left = x;
@ -105,11 +217,13 @@ int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height)
invalidRect.right = x + width;
invalidRect.bottom = y + height;
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
if (xf_call_for_each_surface(xfc, xfc->gfxMappedSurfaceIds, do_OutputExpose, &invalidRect) < 0)
status = -1;
xf_OutputUpdate(xfc);
if (xf_UpdateSurfaces(xfc) < 0)
status = -1;
return 1;
return status;
}
int xf_StartFrame(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFrame)
@ -125,7 +239,7 @@ int xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame)
{
xfContext* xfc = (xfContext*) context->custom;
xf_OutputUpdate(xfc);
xf_UpdateSurfaces(xfc);
xfc->inGfxFrame = FALSE;
@ -150,10 +264,10 @@ int xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context,
invalidRect.right = cmd->right;
invalidRect.bottom = cmd->bottom;
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect);
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
xf_UpdateSurfaces(xfc);
return 1;
}
@ -225,7 +339,7 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP
nXDst, nYDst, nWidth, nHeight,
tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, 0, 0, NULL);
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &updateRects[j]);
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &updateRects[j]);
}
region16_uninit(&updateRegion);
@ -233,8 +347,10 @@ int xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDP
rfx_message_free(xfc->codecs->rfx, message);
region16_uninit(&clippingRects);
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
xf_UpdateSurfaces(xfc);
return 1;
}
@ -269,10 +385,10 @@ int xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, R
invalidRect.right = cmd->right;
invalidRect.bottom = cmd->bottom;
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect);
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
xf_UpdateSurfaces(xfc);
return 1;
}
@ -301,10 +417,10 @@ int xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGF
invalidRect.right = cmd->right;
invalidRect.bottom = cmd->bottom;
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect);
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
xf_UpdateSurfaces(xfc);
return 1;
}
@ -338,7 +454,8 @@ int xf_SurfaceCommand_H264(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_
DstData = surface->data;
status = h264_decompress(xfc->codecs->h264, bs->data, bs->length, &DstData,
surface->format, surface->scanline , surface->height, meta->regionRects, meta->numRegionRects);
surface->format, surface->scanline , surface->width,
surface->height, meta->regionRects, meta->numRegionRects);
if (status < 0)
{
@ -348,11 +465,11 @@ int xf_SurfaceCommand_H264(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_
for (i = 0; i < meta->numRegionRects; i++)
{
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), (RECTANGLE_16*) &(meta->regionRects[i]));
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, (RECTANGLE_16*) &(meta->regionRects[i]));
}
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
xf_UpdateSurfaces(xfc);
return 1;
}
@ -381,10 +498,10 @@ int xf_SurfaceCommand_Alpha(xfContext* xfc, RdpgfxClientContext* context, RDPGFX
invalidRect.right = cmd->right;
invalidRect.bottom = cmd->bottom;
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect);
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
xf_UpdateSurfaces(xfc);
return 1;
}
@ -471,14 +588,16 @@ int xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context,
surface->scanline, nXDst, nYDst, nWidth, nHeight,
tile->data, PIXEL_FORMAT_XRGB32, 64 * 4, nXSrc, nYSrc, NULL);
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &updateRects[j]);
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &updateRects[j]);
}
region16_uninit(&updateRegion);
}
region16_uninit(&clippingRects);
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
xf_UpdateSurfaces(xfc);
return 1;
}
@ -589,6 +708,10 @@ int xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* cr
(char*) surface->stage, surface->width, surface->height, xfc->scanline_pad, surface->stageStep);
}
surface->mapping.mode = GFX_MAP_NONE;
region16_init(&surface->invalidRegion);
context->SetSurfaceData(context, surface->surfaceId, (void*) surface);
return 1;
@ -606,9 +729,11 @@ int xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* de
XFree(surface->image);
_aligned_free(surface->data);
_aligned_free(surface->stage);
region16_uninit(&surface->invalidRegion);
free(surface);
}
ArrayList_Remove(xfc->gfxMappedSurfaceIds, (void*) (ULONG_PTR) deleteSurface->surfaceId);
context->SetSurfaceData(context, deleteSurface->surfaceId, NULL);
if (xfc->codecs->progressive)
@ -655,11 +780,11 @@ int xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill)
freerdp_image_fill(surface->data, surface->format, surface->scanline,
rect->left, rect->top, nWidth, nHeight, color);
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect);
}
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
xf_UpdateSurfaces(xfc);
return 1;
}
@ -715,11 +840,11 @@ int xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_
invalidRect.right = destPt->x + rectSrc->right;
invalidRect.bottom = destPt->y + rectSrc->bottom;
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
region16_union_rect(&surfaceDst->invalidRegion, &surfaceDst->invalidRegion, &invalidRect);
}
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
xf_UpdateSurfaces(xfc);
return 1;
}
@ -800,11 +925,11 @@ int xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU*
invalidRect.right = destPt->x + cacheEntry->width - 1;
invalidRect.bottom = destPt->y + cacheEntry->height - 1;
region16_union_rect(&(xfc->invalidRegion), &(xfc->invalidRegion), &invalidRect);
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, &invalidRect);
}
if (!xfc->inGfxFrame)
xf_OutputUpdate(xfc);
xf_UpdateSurfaces(xfc);
return 1;
}
@ -833,9 +958,18 @@ int xf_EvictCacheEntry(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PD
int xf_MapSurfaceToOutput(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput)
{
xfGfxSurface* surface;
xfContext* xfc = (xfContext*) context->custom;
xfc->outputSurfaceId = surfaceToOutput->surfaceId;
surface = (xfGfxSurface*) context->GetSurfaceData(context, surfaceToOutput->surfaceId);
surface->mapping.mode = GFX_MAP_OUTPUT;
surface->mapping.output.originX = surfaceToOutput->outputOriginX;
surface->mapping.output.originY = surfaceToOutput->outputOriginY;
region16_clear(&surface->invalidRegion);
ArrayList_Add(xfc->gfxMappedSurfaceIds, (void*) (ULONG_PTR) surfaceToOutput->surfaceId);
return 1;
}
@ -866,13 +1000,14 @@ void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx)
gfx->MapSurfaceToOutput = xf_MapSurfaceToOutput;
gfx->MapSurfaceToWindow = xf_MapSurfaceToWindow;
region16_init(&(xfc->invalidRegion));
xfc->gfxMappedSurfaceIds = ArrayList_New(FALSE);
}
void xf_graphics_pipeline_uninit(xfContext* xfc, RdpgfxClientContext* gfx)
{
region16_uninit(&(xfc->invalidRegion));
gfx->custom = NULL;
xfc->gfx = NULL;
if (xfc->gfxMappedSurfaceIds)
{
ArrayList_Free(xfc->gfxMappedSurfaceIds);
xfc->gfxMappedSurfaceIds = NULL;
}
}

View File

@ -25,6 +25,13 @@
#include <freerdp/gdi/gfx.h>
enum xf_gfx_mapping_mode
{
GFX_MAP_NONE,
GFX_MAP_OUTPUT
};
typedef enum xf_gfx_mapping_mode xfGfxMappingMode;
struct xf_gfx_surface
{
UINT16 surfaceId;
@ -37,6 +44,19 @@ struct xf_gfx_surface
int scanline;
int stageStep;
UINT32 format;
struct
{
xfGfxMappingMode mode;
union
{
struct
{
UINT32 originX;
UINT32 originY;
} output;
};
} mapping;
REGION16 invalidRegion;
};
typedef struct xf_gfx_surface xfGfxSurface;

View File

@ -35,6 +35,7 @@
#include <freerdp/codec/jpeg.h>
#include "xf_graphics.h"
#include "xf_gdi.h"
#include <freerdp/log.h>
#define TAG CLIENT_TAG("x11")
@ -318,6 +319,35 @@ void xf_Pointer_SetDefault(rdpContext* context)
#endif
}
void xf_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y)
{
xfContext* xfc = (xfContext*) context;
XWindowAttributes current;
XSetWindowAttributes tmp;
if (!xfc->focused || !xfc->window)
return;
xf_lock_x11(xfc, FALSE);
if (XGetWindowAttributes(xfc->display, xfc->window->handle, &current) == 0)
goto out;
tmp.event_mask = (current.your_event_mask & ~(PointerMotionMask));
if (XChangeWindowAttributes(xfc->display, xfc->window->handle, CWEventMask, &tmp) == 0)
goto out;
XWarpPointer(xfc->display, None, xfc->window->handle, 0, 0, 0, 0, x, y);
tmp.event_mask = current.your_event_mask;
XChangeWindowAttributes(xfc->display, xfc->window->handle, CWEventMask, &tmp);
out:
xf_unlock_x11(xfc, FALSE);
return;
}
/* Glyph Class */
void xf_Glyph_New(rdpContext* context, rdpGlyph* glyph)
@ -381,8 +411,8 @@ void xf_Glyph_BeginDraw(rdpContext* context, int x, int y, int width, int height
{
xfContext* xfc = (xfContext*) context;
bgcolor = freerdp_convert_gdi_order_color(bgcolor, context->settings->ColorDepth, xfc->format, xfc->palette);
fgcolor = freerdp_convert_gdi_order_color(fgcolor, context->settings->ColorDepth, xfc->format, xfc->palette);
bgcolor = xf_convert_rdp_order_color(xfc, bgcolor);
fgcolor = xf_convert_rdp_order_color(xfc, fgcolor);
xf_lock_x11(xfc, FALSE);
@ -453,6 +483,7 @@ void xf_register_graphics(rdpGraphics* graphics)
pointer->Set = xf_Pointer_Set;
pointer->SetNull = xf_Pointer_SetNull;
pointer->SetDefault = xf_Pointer_SetDefault;
pointer->SetPosition = xf_Pointer_SetPosition;
graphics_register_pointer(graphics, pointer);
free(pointer);

View File

@ -57,7 +57,7 @@ typedef struct touch_contact
double pos_y;
double last_x;
double last_y;
} touchContact;
touchContact contacts[MAX_CONTACTS];
@ -87,7 +87,7 @@ const char* xf_input_get_class_string(int class)
return "XIScrollClass";
else if (class == XITouchClass)
return "XITouchClass";
return "XIUnknownClass";
}
@ -104,71 +104,71 @@ int xf_input_init(xfContext* xfc, Window window)
XIEventMask evmasks[64];
int opcode, event, error;
BYTE masks[8][XIMaskLen(XI_LASTEVENT)];
z_vector = 0;
px_vector = 0;
py_vector = 0;
nmasks = 0;
ndevices = 0;
active_contacts = 0;
ZeroMemory(contacts, sizeof(touchContact) * MAX_CONTACTS);
if (!XQueryExtension(xfc->display, "XInputExtension", &opcode, &event, &error))
{
WLog_WARN(TAG, "XInput extension not available.");
return -1;
}
xfc->XInputOpcode = opcode;
XIQueryVersion(xfc->display, &major, &minor);
if (major * 1000 + minor < 2002)
{
WLog_WARN(TAG, "Server does not support XI 2.2");
return -1;
}
if (xfc->settings->MultiTouchInput)
xfc->use_xinput = TRUE;
info = XIQueryDevice(xfc->display, XIAllDevices, &ndevices);
for (i = 0; i < ndevices; i++)
{
BOOL touch = FALSE;
XIDeviceInfo* dev = &info[i];
for (j = 0; j < dev->num_classes; j++)
{
XIAnyClassInfo* class = dev->classes[j];
XITouchClassInfo* t = (XITouchClassInfo*) class;
if ((class->type == XITouchClass) && (t->mode == XIDirectTouch) &&
(strcmp(dev->name, "Virtual core pointer") != 0))
{
touch = TRUE;
}
}
for (j = 0; j < dev->num_classes; j++)
{
XIAnyClassInfo* class = dev->classes[j];
XITouchClassInfo* t = (XITouchClassInfo*) class;
if (xfc->settings->MultiTouchInput)
{
WLog_INFO(TAG, "%s (%d) \"%s\" id: %d",
xf_input_get_class_string(class->type),
class->type, dev->name, dev->deviceid);
}
evmasks[nmasks].mask = masks[nmasks];
evmasks[nmasks].mask_len = sizeof(masks[0]);
ZeroMemory(masks[nmasks], sizeof(masks[0]));
evmasks[nmasks].deviceid = dev->deviceid;
if ((class->type == XITouchClass) && (t->mode == XIDirectTouch) &&
(strcmp(dev->name, "Virtual core pointer") != 0))
{
@ -178,13 +178,13 @@ int xf_input_init(xfContext* xfc, Window window)
dev->name, (t->mode == XIDirectTouch) ? "direct" : "dependent",
dev->deviceid, t->mode, t->num_touches);
}
XISetMask(masks[nmasks], XI_TouchBegin);
XISetMask(masks[nmasks], XI_TouchUpdate);
XISetMask(masks[nmasks], XI_TouchEnd);
nmasks++;
}
if (xfc->use_xinput)
{
if (!touch && (class->type == XIButtonClass) && strcmp(dev->name, "Virtual core pointer"))
@ -204,17 +204,17 @@ int xf_input_init(xfContext* xfc, Window window)
if (nmasks > 0)
xstatus = XISelectEvents(xfc->display, window, evmasks, nmasks);
return 0;
}
BOOL xf_input_is_duplicate(XGenericEventCookie* cookie)
{
XIDeviceEvent* event;
event = cookie->data;
if ( (lastEvent.time == event->time) &&
(lastEvType == cookie->evtype) &&
(lastEvent.detail == event->detail) &&
@ -223,18 +223,18 @@ BOOL xf_input_is_duplicate(XGenericEventCookie* cookie)
{
return TRUE;
}
return FALSE;
}
void xf_input_save_last_event(XGenericEventCookie* cookie)
{
XIDeviceEvent* event;
event = cookie->data;
lastEvType = cookie->evtype;
lastEvent.time = event->time;
lastEvent.detail = event->detail;
lastEvent.event_x = event->event_x;
@ -245,30 +245,30 @@ void xf_input_detect_pan(xfContext* xfc)
{
double dx[2];
double dy[2];
double px;
double py;
double dist_x;
double dist_y;
if (active_contacts != 2)
{
return;
}
dx[0] = contacts[0].pos_x - contacts[0].last_x;
dx[1] = contacts[1].pos_x - contacts[1].last_x;
dy[0] = contacts[0].pos_y - contacts[0].last_y;
dy[1] = contacts[1].pos_y - contacts[1].last_y;
px = fabs(dx[0]) < fabs(dx[1]) ? dx[0] : dx[1];
py = fabs(dy[0]) < fabs(dy[1]) ? dy[0] : dy[1];
px_vector += px;
py_vector += py;
dist_x = fabs(contacts[0].pos_x - contacts[1].pos_x);
dist_y = fabs(contacts[0].pos_y - contacts[1].pos_y);
@ -276,18 +276,17 @@ void xf_input_detect_pan(xfContext* xfc)
{
if (px_vector > PAN_THRESHOLD)
{
{
PanningChangeEventArgs e;
EventArgsInit(&e, "xfreerdp");
e.XPan = 5;
e.YPan = 0;
e.dx = 5;
e.dy = 0;
PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e);
}
px_vector = 0;
px_vector = 0;
py_vector = 0;
z_vector = 0;
@ -296,38 +295,38 @@ void xf_input_detect_pan(xfContext* xfc)
{
{
PanningChangeEventArgs e;
EventArgsInit(&e, "xfreerdp");
e.XPan = -5;
e.YPan = 0;
e.dx = -5;
e.dy = 0;
PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e);
}
px_vector = 0;
px_vector = 0;
py_vector = 0;
z_vector = 0;
}
}
if (dist_x > MIN_FINGER_DIST)
{
if (py_vector > PAN_THRESHOLD)
{
{
PanningChangeEventArgs e;
EventArgsInit(&e, "xfreerdp");
e.XPan = 0;
e.YPan = 5;
e.dx = 0;
e.dy = 5;
PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e);
}
py_vector = 0;
px_vector = 0;
py_vector = 0;
z_vector = 0;
@ -336,15 +335,15 @@ void xf_input_detect_pan(xfContext* xfc)
{
{
PanningChangeEventArgs e;
EventArgsInit(&e, "xfreerdp");
e.XPan = 0;
e.YPan = -5;
e.dx = 0;
e.dy = -5;
PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e);
}
py_vector = 0;
px_vector = 0;
py_vector = 0;
z_vector = 0;
@ -356,20 +355,20 @@ void xf_input_detect_pinch(xfContext* xfc)
{
double dist;
double zoom;
double delta;
ResizeWindowEventArgs e;
ZoomingChangeEventArgs e;
if (active_contacts != 2)
{
firstDist = -1.0;
return;
}
/* first calculate the distance */
dist = sqrt(pow(contacts[1].pos_x - contacts[0].last_x, 2.0) +
pow(contacts[1].pos_y - contacts[0].last_y, 2.0));
/* if this is the first 2pt touch */
if (firstDist <= 0)
{
@ -377,7 +376,7 @@ void xf_input_detect_pinch(xfContext* xfc)
lastDist = firstDist;
scale_cnt = 0;
z_vector = 0;
px_vector = 0;
py_vector = 0;
z_vector = 0;
@ -385,58 +384,38 @@ void xf_input_detect_pinch(xfContext* xfc)
else
{
delta = lastDist - dist;
if(delta > 1.0)
delta = 1.0;
if(delta < -1.0)
delta = -1.0;
/* compare the current distance to the first one */
zoom = (dist / firstDist);
z_vector += delta;
lastDist = dist;
if (z_vector > ZOOM_THRESHOLD)
{
xfc->settings->ScalingFactor -= 0.05;
if (xfc->settings->ScalingFactor < 0.8)
xfc->settings->ScalingFactor = 0.8;
EventArgsInit(&e, "xfreerdp");
e.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor;
e.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor;
xf_transform_window(xfc);
PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e);
xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE);
e.dx = e.dy = -10;
PubSub_OnZoomingChange(((rdpContext*) xfc)->pubSub, xfc, &e);
z_vector = 0;
px_vector = 0;
py_vector = 0;
z_vector = 0;
}
if (z_vector < -ZOOM_THRESHOLD)
{
xfc->settings->ScalingFactor += 0.05;
if (xfc->settings->ScalingFactor > 1.2)
xfc->settings->ScalingFactor = 1.2;
EventArgsInit(&e, "xfreerdp");
e.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor;
e.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor;
xf_transform_window(xfc);
PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e);
xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE);
e.dx = e.dy = 10;
PubSub_OnZoomingChange(((rdpContext*) xfc)->pubSub, xfc, &e);
z_vector = 0;
px_vector = 0;
py_vector = 0;
z_vector = 0;
@ -447,7 +426,7 @@ void xf_input_detect_pinch(xfContext* xfc)
void xf_input_touch_begin(xfContext* xfc, XIDeviceEvent* event)
{
int i;
for (i = 0; i < MAX_CONTACTS; i++)
{
if (contacts[i].id == 0)
@ -456,7 +435,7 @@ void xf_input_touch_begin(xfContext* xfc, XIDeviceEvent* event)
contacts[i].count = 1;
contacts[i].pos_x = event->event_x;
contacts[i].pos_y = event->event_y;
active_contacts++;
break;
}
@ -476,10 +455,10 @@ void xf_input_touch_update(xfContext* xfc, XIDeviceEvent* event)
contacts[i].last_y = contacts[i].pos_y;
contacts[i].pos_x = event->event_x;
contacts[i].pos_y = event->event_y;
xf_input_detect_pinch(xfc);
xf_input_detect_pan(xfc);
break;
}
}
@ -495,7 +474,7 @@ void xf_input_touch_end(xfContext* xfc, XIDeviceEvent* event)
{
contacts[i].id = 0;
contacts[i].count = 0;
active_contacts--;
break;
}
@ -505,9 +484,9 @@ void xf_input_touch_end(xfContext* xfc, XIDeviceEvent* event)
int xf_input_handle_event_local(xfContext* xfc, XEvent* event)
{
XGenericEventCookie* cookie = &event->xcookie;
XGetEventData(xfc->display, cookie);
if ((cookie->type == GenericEvent) && (cookie->extension == xfc->XInputOpcode))
{
switch (cookie->evtype)
@ -517,27 +496,27 @@ int xf_input_handle_event_local(xfContext* xfc, XEvent* event)
xf_input_touch_begin(xfc, cookie->data);
xf_input_save_last_event(cookie);
break;
case XI_TouchUpdate:
if (xf_input_is_duplicate(cookie) == FALSE)
xf_input_touch_update(xfc, cookie->data);
xf_input_save_last_event(cookie);
break;
case XI_TouchEnd:
if (xf_input_is_duplicate(cookie) == FALSE)
xf_input_touch_end(xfc, cookie->data);
xf_input_save_last_event(cookie);
break;
default:
WLog_ERR(TAG, "unhandled xi type= %d", cookie->evtype);
break;
}
}
XFreeEventData(xfc->display,cookie);
return 0;
}
@ -610,16 +589,18 @@ int xf_input_touch_remote(xfContext* xfc, XIDeviceEvent* event, int evtype)
int touchId;
int contactId;
RdpeiClientContext* rdpei = xfc->rdpei;
if (!rdpei)
return 0;
xf_input_hide_cursor(xfc);
touchId = event->detail;
x = (int) event->event_x;
y = (int) event->event_y;
xf_event_adjust_coordinates(xfc, &x, &y);
if (evtype == XI_TouchBegin)
{
WLog_DBG(TAG, "TouchBegin: %d", touchId);
@ -635,7 +616,7 @@ int xf_input_touch_remote(xfContext* xfc, XIDeviceEvent* event, int evtype)
WLog_DBG(TAG, "TouchEnd: %d", touchId);
contactId = rdpei->TouchEnd(rdpei, touchId, x, y);
}
return 0;
}
@ -646,33 +627,33 @@ int xf_input_event(xfContext* xfc, XIDeviceEvent* event, int evtype)
switch (evtype)
{
case XI_ButtonPress:
xf_generic_ButtonPress(xfc, (int) event->event_x, (int) event->event_y,
event->detail, event->event, xfc->remote_app);
break;
case XI_ButtonRelease:
xf_generic_ButtonRelease(xfc, (int) event->event_x, (int) event->event_y,
event->detail, event->event, xfc->remote_app);
break;
case XI_Motion:
xf_generic_MotionNotify(xfc, (int) event->event_x, (int) event->event_y,
event->detail, event->event, xfc->remote_app);
break;
}
return 0;
}
int xf_input_handle_event_remote(xfContext* xfc, XEvent* event)
{
XGenericEventCookie* cookie = &event->xcookie;
XGetEventData(xfc->display, cookie);
if ((cookie->type == GenericEvent) && (cookie->extension == xfc->XInputOpcode))
{
switch (cookie->evtype)
@ -680,23 +661,23 @@ int xf_input_handle_event_remote(xfContext* xfc, XEvent* event)
case XI_TouchBegin:
xf_input_touch_remote(xfc, cookie->data, XI_TouchBegin);
break;
case XI_TouchUpdate:
xf_input_touch_remote(xfc, cookie->data, XI_TouchUpdate);
break;
case XI_TouchEnd:
xf_input_touch_remote(xfc, cookie->data, XI_TouchEnd);
break;
default:
xf_input_event(xfc, cookie->data, cookie->evtype);
break;
}
}
XFreeEventData(xfc->display,cookie);
return 0;
}
@ -716,7 +697,7 @@ int xf_input_handle_event(xfContext* xfc, XEvent* event)
{
return xf_input_handle_event_remote(xfc, event);
}
if (xfc->settings->MultiTouchGestures)
{
return xf_input_handle_event_local(xfc, event);

View File

@ -314,28 +314,30 @@ UINT32 xf_keyboard_get_toggle_keys_state(xfContext* xfc)
void xf_keyboard_focus_in(xfContext* xfc)
{
rdpInput* input;
UINT32 syncFlags = 0;
int dummy, mouseX = 0, mouseY = 0;
Window wdummy;
UINT32 state = 0;
UINT32 syncFlags, state;
Window w;
int d, x, y;
if (xfc->display && xfc->window)
if (!xfc->display || !xfc->window)
return;
input = xfc->instance->input;
syncFlags = xf_keyboard_get_toggle_keys_state(xfc);
input->FocusInEvent(input, syncFlags);
/* finish with a mouse pointer position like mstsc.exe if required */
if (xfc->remote_app)
return;
if (XQueryPointer(xfc->display, xfc->window->handle, &w, &w, &d, &d, &x, &y, &state))
{
input = xfc->instance->input;
syncFlags = xf_keyboard_get_toggle_keys_state(xfc);
if (!xfc->remote_app)
if (x >= 0 && x < xfc->window->width && y >= 0 && y < xfc->window->height)
{
XQueryPointer(xfc->display, xfc->window->handle, &wdummy, &wdummy,
&mouseX, &mouseY, &dummy, &dummy, &state);
xf_event_adjust_coordinates(xfc, &x, &y);
input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
}
else
{
XQueryPointer(xfc->display, DefaultRootWindow(xfc->display),
&wdummy, &wdummy, &dummy, &dummy, &dummy, &dummy, &state);
}
input->FocusInEvent(input, syncFlags, mouseX, mouseY);
}
}
@ -447,15 +449,15 @@ BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym)
if(xfc->fullscreen_toggle)
{
if (keysym == XK_Return)
{
if (mod.Ctrl && mod.Alt)
{
/* Ctrl-Alt-Enter: toggle full screen */
xf_toggle_fullscreen(xfc);
return TRUE;
}
}
if (keysym == XK_Return)
{
if (mod.Ctrl && mod.Alt)
{
/* Ctrl-Alt-Enter: toggle full screen */
xf_toggle_fullscreen(xfc);
return TRUE;
}
}
}
if ((keysym == XK_c) || (keysym == XK_C))
@ -468,140 +470,81 @@ BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym)
}
}
if (keysym == XK_period)
#if 0 /* set to 1 to enable multi touch gesture simulation via keyboard */
#ifdef WITH_XRENDER
if (!xfc->remote_app && xfc->settings->MultiTouchGestures)
{
if (mod.Ctrl && mod.Alt)
{
/* Zoom In (scale larger) */
int pdx = 0;
int pdy = 0;
int zdx = 0;
int zdy = 0;
double s = xfc->settings->ScalingFactor;
s += 0.1;
if (s > 2.0)
s = 2.0;
xfc->settings->ScalingFactor = s;
xfc->currentWidth = xfc->originalWidth * s;
xfc->currentHeight = xfc->originalHeight * s;
xf_transform_window(xfc);
switch(keysym)
{
ResizeWindowEventArgs e;
EventArgsInit(&e, "xfreerdp");
e.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor;
e.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor;
PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e);
case XK_0: /* Ctrl-Alt-0: Reset scaling and panning */
xfc->scaledWidth = xfc->width;
xfc->scaledHeight = xfc->height;
xfc->offset_x = 0;
xfc->offset_y = 0;
if (!xfc->fullscreen && (xfc->width != xfc->window->width ||
xfc->height != xfc->window->height))
{
xf_ResizeDesktopWindow(xfc, xfc->window, xfc->width, xfc->height);
}
xf_draw_screen(xfc, 0, 0, xfc->width, xfc->height);
return TRUE;
case XK_1: /* Ctrl-Alt-1: Zoom in */
zdx = zdy = 10;
break;
case XK_2: /* Ctrl-Alt-2: Zoom out */
zdx = zdy = -10;
break;
case XK_3: /* Ctrl-Alt-3: Pan left */
pdx = -10;
break;
case XK_4: /* Ctrl-Alt-4: Pan right */
pdx = 10;
break;
case XK_5: /* Ctrl-Alt-5: Pan up */
pdy = -10;
break;
case XK_6: /* Ctrl-Alt-6: Pan up */
pdy = 10;
break;
}
xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE);
return TRUE;
}
}
if (keysym == XK_comma)
{
if (mod.Ctrl && mod.Alt)
{
/* Zoom Out (scale smaller) */
double s = xfc->settings->ScalingFactor;
s -= 0.1;
if (s < 0.5)
s = 0.5;
xfc->settings->ScalingFactor = s;
xfc->currentWidth = xfc->originalWidth * s;
xfc->currentHeight = xfc->originalHeight * s;
xf_transform_window(xfc);
{
ResizeWindowEventArgs e;
EventArgsInit(&e, "xfreerdp");
e.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor;
e.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor;
PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &e);
}
xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE);
return TRUE;
}
}
if (keysym == XK_KP_4)
{
if (mod.Ctrl && mod.Alt)
{
if (pdx != 0 || pdy != 0)
{
PanningChangeEventArgs e;
EventArgsInit(&e, "xfreerdp");
e.XPan = -5;
e.YPan = 0;
e.dx = pdx;
e.dy = pdy;
PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e);
return TRUE;
}
return TRUE;
}
}
if (keysym == XK_KP_6)
{
if (mod.Ctrl && mod.Alt)
{
if (zdx != 0 || zdy != 0)
{
PanningChangeEventArgs e;
ZoomingChangeEventArgs e;
EventArgsInit(&e, "xfreerdp");
e.XPan = 5;
e.YPan = 0;
PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e);
e.dx = zdx;
e.dy = zdy;
PubSub_OnZoomingChange(((rdpContext*) xfc)->pubSub, xfc, &e);
return TRUE;
}
return TRUE;
}
}
if (keysym == XK_KP_8)
{
if (mod.Ctrl && mod.Alt)
{
{
PanningChangeEventArgs e;
EventArgsInit(&e, "xfreerdp");
e.XPan = 0;
e.YPan = -5;
PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e);
}
return TRUE;
}
}
if (keysym == XK_KP_2)
{
if (mod.Ctrl && mod.Alt)
{
{
PanningChangeEventArgs e;
EventArgsInit(&e, "xfreerdp");
e.XPan = 0;
e.YPan = 5;
PubSub_OnPanningChange(((rdpContext*) xfc)->pubSub, xfc, &e);
}
return TRUE;
}
}
#endif /* WITH_XRENDER defined */
#endif /* pinch/zoom/pan simulation */
return FALSE;
}

View File

@ -50,6 +50,11 @@ int xf_list_monitors(xfContext* xfc)
XineramaScreenInfo* screen = NULL;
display = XOpenDisplay(NULL);
if (!display)
{
WLog_ERR(TAG, "failed to open X display");
return -1;
}
if (XineramaQueryExtension(display, &ignored, &ignored2))
{
@ -76,6 +81,11 @@ int xf_list_monitors(xfContext* xfc)
display = XOpenDisplay(NULL);
if(!display)
{
WLog_ERR(TAG, "failed to open X display");
return -1;
}
screen = ScreenOfDisplay(display, DefaultScreen(display));
WLog_DBG(TAG, " * [0] %dx%d\t+%d+%d", WidthOfScreen(screen), HeightOfScreen(screen), 0, 0);
XCloseDisplay(display);

View File

@ -397,7 +397,7 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char *name, int width, int heig
{
XMoveWindow(xfc->display, window->handle, settings->DesktopPosX, settings->DesktopPosY);
}
XStoreName(xfc->display, window->handle, name);
}
@ -412,11 +412,20 @@ void xf_ResizeDesktopWindow(xfContext* xfc, xfWindow* window, int width, int hei
if (size_hints)
{
size_hints->flags = PMinSize | PMaxSize;
size_hints->min_width = size_hints->max_width = xfc->width;
size_hints->min_height = size_hints->max_height = xfc->height;
size_hints->min_width = size_hints->max_width = width;
size_hints->min_height = size_hints->max_height = height;
#ifdef WITH_XRENDER
if (xfc->settings->SmartSizing)
{
size_hints->min_width = size_hints->min_height = 1;
size_hints->max_width = size_hints->max_height = 16384;
}
#endif
XSetWMNormalHints(xfc->display, window->handle, size_hints);
XResizeWindow(xfc->display, window->handle, xfc->width, xfc->height);
XResizeWindow(xfc->display, window->handle, width, height);
XFree(size_hints);
}
}
@ -500,6 +509,14 @@ void xf_SetWindowStyle(xfContext* xfc, xfAppWindow* appWindow, UINT32 style, UIN
void xf_SetWindowText(xfContext* xfc, xfAppWindow* appWindow, char* name)
{
XStoreName(xfc->display, appWindow->handle, name);
const size_t i = strlen(name);
XStoreName(xfc->display, appWindow->handle, name);
Atom wm_Name = XInternAtom(xfc->display, "_NET_WM_NAME", FALSE);
Atom utf8Str = XInternAtom(xfc->display, "UTF8_STRING", FALSE);
XChangeProperty(xfc->display, appWindow->handle, wm_Name, utf8Str, 8,
PropModeReplace, (unsigned char *)name, i);
}
void xf_FixWindowCoordinates(xfContext* xfc, int* x, int* y, int* width, int* height)

View File

@ -105,6 +105,7 @@ struct xf_context
BOOL grab_keyboard;
BOOL unobscured;
BOOL debug;
HANDLE x11event;
xfWindow* window;
xfAppWindow* appWindow;
xfPointer* pointer;
@ -121,10 +122,9 @@ struct xf_context
UINT32 bitmap_size;
BYTE* bitmap_buffer;
BYTE* primary_buffer;
REGION16 invalidRegion;
BOOL inGfxFrame;
BOOL graphicsReset;
UINT16 outputSurfaceId;
wArrayList* gfxMappedSurfaceIds;
BOOL frame_begin;
UINT16 frame_x1;
@ -132,15 +132,21 @@ struct xf_context
UINT16 frame_x2;
UINT16 frame_y2;
int originalWidth;
int originalHeight;
int currentWidth;
int currentHeight;
int XInputOpcode;
BOOL enableScaling;
UINT8 red_shift_l;
UINT8 red_shift_r;
UINT8 green_shift_l;
UINT8 green_shift_r;
UINT8 blue_shift_l;
UINT8 blue_shift_r;
int XInputOpcode;
#ifdef WITH_XRENDER
int scaledWidth;
int scaledHeight;
int offset_x;
int offset_y;
#endif
BOOL focused;
BOOL use_xinput;
@ -196,6 +202,7 @@ struct xf_context
wHashTable* railWindows;
BOOL xkbAvailable;
BOOL xrenderAvailable;
};
void xf_create_window(xfContext* xfc);
@ -250,8 +257,8 @@ enum XF_EXIT_CODE
void xf_lock_x11(xfContext* xfc, BOOL display);
void xf_unlock_x11(xfContext* xfc, BOOL display);
void xf_draw_screen_scaled(xfContext* xfc, int x, int y, int w, int h, BOOL scale);
void xf_transform_window(xfContext* xfc);
BOOL xf_picture_transform_required(xfContext* xfc);
void xf_draw_screen(xfContext* xfc, int x, int y, int w, int h);
FREERDP_API DWORD xf_exit_code_from_disconnect_reason(DWORD reason);

View File

@ -44,7 +44,7 @@ endif()
# On windows create dll version information.
# Vendor, product and year are already set in top level CMakeLists.txt
if (WIN32)
if (WIN32 AND BUILD_SHARED_LIBS)
set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR})
set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION})

View File

@ -112,19 +112,25 @@ static BOOL freerdp_client_settings_post_process(rdpSettings* settings)
{
if (settings->Username)
{
free(settings->GatewayUsername);
settings->GatewayUsername = _strdup(settings->Username);
if (!settings->GatewayUsername)
goto out_error;
}
if (settings->Domain)
{
free(settings->GatewayDomain);
settings->GatewayDomain = _strdup(settings->Domain);
if (!settings->GatewayDomain)
goto out_error;
}
if (settings->Password)
{
free(settings->GatewayPassword);
settings->GatewayPassword = _strdup(settings->Password);
if (!settings->GatewayPassword)
goto out_error;
}

View File

@ -3,6 +3,7 @@
* FreeRDP Client Command-Line Interface
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2014 Norbert Federa <norbert.federa@thincast.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -66,7 +67,7 @@ COMMAND_LINE_ARGUMENT_A args[] =
{ "monitor-list", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT, NULL, NULL, NULL, -1, NULL, "List detected monitors" },
{ "t", COMMAND_LINE_VALUE_REQUIRED, "<title>", NULL, NULL, -1, "title", "Window title" },
{ "decorations", COMMAND_LINE_VALUE_BOOL, NULL, NULL, BoolValueTrue, -1, NULL, "Window decorations" },
{ "smart-sizing", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Scale remote desktop to window size" },
{ "smart-sizing", COMMAND_LINE_VALUE_OPTIONAL, "<width>x<height>", NULL, NULL, -1, NULL, "Scale remote desktop to window size" },
{ "a", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, "addin", "Addin" },
{ "vc", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Static virtual channel" },
{ "dvc", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Dynamic virtual channel" },
@ -77,7 +78,7 @@ COMMAND_LINE_ARGUMENT_A args[] =
{ "gu", COMMAND_LINE_VALUE_REQUIRED, "[<domain>\\]<user> or <user>[@<domain>]", NULL, NULL, -1, NULL, "Gateway username" },
{ "gp", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Gateway password" },
{ "gd", COMMAND_LINE_VALUE_REQUIRED, "<domain>", NULL, NULL, -1, NULL, "Gateway domain" },
{ "gateway-usage-method", COMMAND_LINE_VALUE_REQUIRED, "<direct|detect>", NULL, NULL, -1, NULL, "Gateway usage method" },
{ "gateway-usage-method", COMMAND_LINE_VALUE_REQUIRED, "<direct|detect>", NULL, NULL, -1, "gum", "Gateway usage method" },
{ "load-balance-info", COMMAND_LINE_VALUE_REQUIRED, "<info string>", NULL, NULL, -1, NULL, "Load balance info" },
{ "app", COMMAND_LINE_VALUE_REQUIRED, "<executable path> or <||alias>", NULL, NULL, -1, NULL, "Remote application program" },
{ "app-name", COMMAND_LINE_VALUE_REQUIRED, "<app name>", NULL, NULL, -1, NULL, "Remote application name for user interface" },
@ -131,8 +132,7 @@ COMMAND_LINE_ARGUMENT_A args[] =
{ "sec-tls", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "tls protocol security" },
{ "sec-nla", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "nla protocol security" },
{ "sec-ext", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "nla extended protocol security" },
{ "tls-ciphers", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "List of permitted openssl ciphers - see ciphers(1)" },
{ "tls-ciphers-netmon", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Use tls ciphers that netmon can parse" },
{ "tls-ciphers", COMMAND_LINE_VALUE_REQUIRED, "<netmon|ma|ciphers>", NULL, NULL, -1, NULL, "Allowed TLS ciphers" },
{ "cert-name", COMMAND_LINE_VALUE_REQUIRED, "<name>", NULL, NULL, -1, NULL, "certificate name" },
{ "cert-ignore", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "ignore certificate" },
{ "pcb", COMMAND_LINE_VALUE_REQUIRED, "<blob>", NULL, NULL, -1, NULL, "Preconnection Blob" },
@ -167,6 +167,7 @@ COMMAND_LINE_ARGUMENT_A args[] =
{ "heartbeat", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support heartbeat PDUs" },
{ "multitransport", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support multitransport protocol" },
{ "assistance", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Remote assistance password" },
{ "encryption-methods", COMMAND_LINE_VALUE_REQUIRED, "<40,56,128,FIPS>", NULL, NULL, -1, NULL, "RDP standard security encryption methods" },
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
};
@ -507,7 +508,7 @@ static char** freerdp_command_line_parse_comma_separated_values(char* list, int*
int index;
int nCommas;
nArgs = nCommas = 0;
nCommas = 0;
assert(NULL != count);
@ -1078,8 +1079,10 @@ BOOL freerdp_client_detect_command_line(int argc, char** argv, DWORD* flags)
if (posix_cli_status <= COMMAND_LINE_STATUS_PRINT)
return compatibility;
if (windows_cli_count >= posix_cli_count)
/* Check, if this may be windows style syntax... */
if ((windows_cli_count && (windows_cli_count >= posix_cli_count)) || (windows_cli_status <= COMMAND_LINE_STATUS_PRINT))
{
windows_cli_count = 1;
*flags = COMMAND_LINE_SEPARATOR_COLON;
*flags |= COMMAND_LINE_SIGIL_SLASH | COMMAND_LINE_SIGIL_PLUS_MINUS;
}
@ -1187,7 +1190,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
return status;
}
arg = CommandLineFindArgumentA(args, "v");
CommandLineFindArgumentA(args, "v");
arg = args;
@ -1226,7 +1229,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
continue;
length = p2 - p;
settings->ServerHostname = (char*) malloc(length);
settings->ServerHostname = (char*) calloc(length, sizeof(char));
strncpy(settings->ServerHostname, p+1, length-1);
if (*(p2 + 1) == ':')
{
@ -1344,7 +1347,19 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
CommandLineSwitchCase(arg, "smart-sizing")
{
settings->SmartSizing = arg->Value ? TRUE : FALSE;
settings->SmartSizing = TRUE;
if (arg->Value)
{
str = _strdup(arg->Value);
if ((p = strchr(str, 'x')))
{
*p = '\0';
settings->SmartSizingWidth = atoi(str);
settings->SmartSizingHeight = atoi(&p[1]);
}
free(str);
}
}
CommandLineSwitchCase(arg, "bpp")
{
@ -1448,7 +1463,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
settings->GatewayEnabled = TRUE;
settings->GatewayUseSameCredentials = TRUE;
freerdp_set_gateway_usage_method(settings, TSC_PROXY_MODE_DETECT);
freerdp_set_gateway_usage_method(settings, TSC_PROXY_MODE_DIRECT);
}
CommandLineSwitchCase(arg, "gu")
{
@ -1721,9 +1736,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
settings->TlsSecurity = FALSE;
settings->NlaSecurity = FALSE;
settings->ExtSecurity = FALSE;
settings->DisableEncryption = TRUE;
settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT| ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
settings->UseRdpSecurityLayer = TRUE;
}
else if (strcmp("tls", arg->Value) == 0) /* TLS */
{
@ -1751,6 +1764,33 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
WLog_ERR(TAG, "unknown protocol security: %s", arg->Value);
}
}
CommandLineSwitchCase(arg, "encryption-methods")
{
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
{
UINT32 i;
char** p;
int count = 0;
p = freerdp_command_line_parse_comma_separated_values(arg->Value, &count);
for (i = 0; i < count; i++)
{
if (!strcmp(p[i], "40"))
settings->EncryptionMethods |= ENCRYPTION_METHOD_40BIT;
else if (!strcmp(p[i], "56"))
settings->EncryptionMethods |= ENCRYPTION_METHOD_56BIT;
else if (!strcmp(p[i], "128"))
settings->EncryptionMethods |= ENCRYPTION_METHOD_128BIT;
else if (!strcmp(p[i], "FIPS"))
settings->EncryptionMethods |= ENCRYPTION_METHOD_FIPS;
else
WLog_ERR(TAG, "unknown encryption method '%s'", p[i]);
}
free(p);
}
}
CommandLineSwitchCase(arg, "sec-rdp")
{
settings->RdpSecurity = arg->Value ? TRUE : FALSE;
@ -1769,11 +1809,18 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
CommandLineSwitchCase(arg, "tls-ciphers")
{
settings->PermittedTLSCiphers = _strdup(arg->Value);
}
CommandLineSwitchCase(arg, "tls-ciphers-netmon")
{
settings->PermittedTLSCiphers = arg->Value ? _strdup("ALL:!ECDH") : NULL;
if (strcmp(arg->Value, "netmon") == 0)
{
settings->AllowedTlsCiphers = _strdup("ALL:!ECDH");
}
else if (strcmp(arg->Value, "ma") == 0)
{
settings->AllowedTlsCiphers = _strdup("AES128-SHA");
}
else
{
settings->AllowedTlsCiphers = _strdup(arg->Value);
}
}
CommandLineSwitchCase(arg, "cert-name")
{
@ -1789,7 +1836,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
CommandLineSwitchCase(arg, "encryption")
{
settings->DisableEncryption = arg->Value ? FALSE : TRUE;
settings->UseRdpSecurityLayer = arg->Value ? FALSE : TRUE;
}
CommandLineSwitchCase(arg, "grab-keyboard")
{
@ -1971,6 +2018,7 @@ int freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings)
UINT32 index;
ADDIN_ARGV* args;
settings->DynamicChannelCount = 0;
if ((freerdp_static_channel_collection_find(settings, "rdpsnd")) ||
(freerdp_dynamic_channel_collection_find(settings, "tsmf")))
{

View File

@ -122,16 +122,20 @@ void freerdp_client_old_parse_hostname(char* str, char** ServerHostname, UINT32*
int freerdp_client_old_process_plugin(rdpSettings* settings, ADDIN_ARGV* args)
{
int args_handled = 0;
if (strcmp(args->argv[0], "cliprdr") == 0)
{
args_handled++;
settings->RedirectClipboard = TRUE;
WLog_WARN(TAG, "--plugin cliprdr -> +clipboard");
}
else if (strcmp(args->argv[0], "rdpdr") == 0)
{
args_handled++;
if (args->argc < 2)
return -1;
return 1;
args_handled++;
if ((strcmp(args->argv[1], "disk") == 0) ||
(strcmp(args->argv[1], "drive") == 0))
{
@ -159,21 +163,26 @@ int freerdp_client_old_process_plugin(rdpSettings* settings, ADDIN_ARGV* args)
}
else if (strcmp(args->argv[0], "drdynvc") == 0)
{
args_handled++;
freerdp_client_add_dynamic_channel(settings, args->argc - 1, &args->argv[1]);
}
else if (strcmp(args->argv[0], "rdpsnd") == 0)
{
args_handled++;
if (args->argc < 2)
return -1;
return 1;
args_handled++;
freerdp_addin_replace_argument_value(args, args->argv[1], "sys", args->argv[1]);
freerdp_client_add_static_channel(settings, args->argc, args->argv);
}
else if (strcmp(args->argv[0], "rail") == 0)
{
args_handled++;
if (args->argc < 2)
return -1;
return 1;
args_handled++;
settings->RemoteApplicationProgram = _strdup(args->argv[1]);
}
else
@ -181,14 +190,12 @@ int freerdp_client_old_process_plugin(rdpSettings* settings, ADDIN_ARGV* args)
freerdp_client_add_static_channel(settings, args->argc, args->argv);
}
return 1;
return args_handled;
}
int freerdp_client_old_command_line_pre_filter(void* context, int index, int argc, LPCSTR* argv)
{
rdpSettings* settings;
settings = (rdpSettings*) context;
rdpSettings* settings = (rdpSettings*) context;
if (index == (argc - 1))
{
@ -204,11 +211,10 @@ int freerdp_client_old_command_line_pre_filter(void* context, int index, int arg
return -1;
}
if (settings)
{
freerdp_client_old_parse_hostname((char*) argv[index],
&settings->ServerHostname, &settings->ServerPort);
}
freerdp_client_old_parse_hostname((char*) argv[index],
&settings->ServerHostname, &settings->ServerPort);
return 2;
}
else
{
@ -218,6 +224,7 @@ int freerdp_client_old_command_line_pre_filter(void* context, int index, int arg
if (strcmp("--plugin", argv[index]) == 0)
{
int args_handled = 0;
int length;
char *a, *p;
int i, j, t;
@ -233,20 +240,19 @@ int freerdp_client_old_command_line_pre_filter(void* context, int index, int arg
return -1;
args = (ADDIN_ARGV*) malloc(sizeof(ADDIN_ARGV));
args->argv = (char**) malloc(sizeof(char*) * 5);
args->argv = (char**) calloc(argc, sizeof(char*));
args->argc = 1;
args->argv[0] = _strdup(argv[t]);
if ((index < argc - 1) && strcmp("--data", argv[index + 1]) == 0)
{
i = 0;
index += 2;
args->argc = 1;
while ((index < argc) && (strcmp("--", argv[index]) != 0))
{
args_handled ++;
args->argc = 1;
args->argv[0] = _strdup(argv[t]);
for (j = 0, p = (char*) argv[index]; (j < 4) && (p != NULL); j++)
{
@ -267,6 +273,9 @@ int freerdp_client_old_command_line_pre_filter(void* context, int index, int arg
if (p != NULL)
{
p = strchr(p, ':');
}
if (p != NULL)
{
length = (int) (p - a);
args->argv[j + 1] = (char*) malloc(length + 1);
CopyMemory(args->argv[j + 1], a, length);
@ -281,11 +290,14 @@ int freerdp_client_old_command_line_pre_filter(void* context, int index, int arg
args->argc++;
}
if (settings && settings->instance)
if (settings)
{
freerdp_client_old_process_plugin(settings, args);
}
for (i = 0; i < args->argc; i++)
free(args->argv[i]);
memset(args->argv, 0, argc * sizeof(char*));
index++;
i++;
}
@ -294,19 +306,16 @@ int freerdp_client_old_command_line_pre_filter(void* context, int index, int arg
{
if (settings)
{
if (settings->instance)
{
freerdp_client_old_process_plugin(settings, args);
}
args->argv[0] = _strdup(argv[t]);
args_handled = freerdp_client_old_process_plugin(settings, args);
free (args->argv[0]);
}
}
for (i = 0; i < args->argc; i++)
free(args->argv[i]);
free(args->argv);
free(args);
return (index - old_index);
return (index - old_index) + args_handled;
}
return 0;
@ -695,9 +704,7 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
settings->RdpSecurity = TRUE;
settings->TlsSecurity = FALSE;
settings->NlaSecurity = FALSE;
settings->DisableEncryption = FALSE;
settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_56BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
settings->UseRdpSecurityLayer = FALSE;
}
else if (strncmp("tls", arg->Value, 1) == 0) /* TLS */
{

View File

@ -6,7 +6,8 @@ set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
set(${MODULE_PREFIX}_TESTS
TestClientRdpFile.c
TestClientChannels.c)
TestClientChannels.c
TestClientCmdLine.c)
create_test_sourcelist(${MODULE_PREFIX}_SRCS
${${MODULE_PREFIX}_DRIVER}
@ -14,7 +15,7 @@ create_test_sourcelist(${MODULE_PREFIX}_SRCS
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-client)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-client freerdp)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})

View File

@ -0,0 +1,93 @@
#include <freerdp/client.h>
#include <freerdp/client/cmdline.h>
#include <freerdp/settings.h>
#include <winpr/cmdline.h>
#include <winpr/spec.h>
#define TESTCASE(cmd, expected_return) status = freerdp_client_settings_parse_command_line(settings, ARRAYSIZE(cmd), cmd); \
if (status != expected_return) { \
printf("Test argument %s failed\n", #cmd); \
return -1; \
}
#define TESTCASE_SUCCESS(cmd) status = freerdp_client_settings_parse_command_line(settings, ARRAYSIZE(cmd), cmd); \
if (status < 0) { \
printf("Test argument %s failed\n", #cmd); \
return -1; \
}
int TestClientCmdLine(int argc, char* argv[])
{
int status;
rdpSettings* settings = freerdp_settings_new(0);
char* cmd1[] = {"xfreerdp", "--help"};
TESTCASE(cmd1, COMMAND_LINE_STATUS_PRINT_HELP);
char* cmd2[] = {"xfreerdp", "/help"};
TESTCASE(cmd2, COMMAND_LINE_STATUS_PRINT_HELP);
char* cmd3[] = {"xfreerdp", "-help"};
TESTCASE(cmd3, COMMAND_LINE_STATUS_PRINT_HELP);
char* cmd4[] = {"xfreerdp", "--version"};
TESTCASE(cmd4, COMMAND_LINE_STATUS_PRINT_VERSION);
char* cmd5[] = {"xfreerdp", "/version"};
TESTCASE(cmd5, COMMAND_LINE_STATUS_PRINT_VERSION);
char* cmd6[] = {"xfreerdp", "-version"};
TESTCASE(cmd6, COMMAND_LINE_STATUS_PRINT_VERSION);
char* cmd7[] = {"xfreerdp", "test.freerdp.com"};
TESTCASE_SUCCESS(cmd7);
char* cmd8[] = {"xfreerdp", "-v", "test.freerdp.com"};
TESTCASE_SUCCESS(cmd8);
char* cmd9[] = {"xfreerdp", "--v", "test.freerdp.com"};
TESTCASE_SUCCESS(cmd9);
char* cmd10[] = {"xfreerdp", "/v:test.freerdp.com"};
TESTCASE_SUCCESS(cmd10);
char* cmd11[] = {"xfreerdp", "--plugin", "rdpsnd", "--plugin", "rdpdr", "--data", "disk:media:/tmp", "--", "test.freerdp.com" };
TESTCASE_SUCCESS(cmd11);
char* cmd12[] = {"xfreerdp", "/sound", "/drive:media:/tmp", "/v:test.freerdp.com" };
TESTCASE_SUCCESS(cmd12);
// password gets overwritten therefore it need to be writeable
char* cmd13[6] = {"xfreerdp", "-u", "test", "-p", "test", "test.freerdp.com"};
cmd13[4] = malloc(5);
strncpy(cmd13[4], "test", 4);
TESTCASE_SUCCESS(cmd13);
free(cmd13[4]);
char* cmd14[] = {"xfreerdp", "-u", "test", "-p", "test", "-v", "test.freerdp.com"};
cmd14[4] = malloc(5);
strncpy(cmd14[4], "test", 4);
TESTCASE_SUCCESS(cmd14);
free(cmd14[4]);
char* cmd15[] = {"xfreerdp", "/u:test", "/p:test", "/v:test.freerdp.com"};
cmd15[2] = malloc(7);
strncpy(cmd15[2], "/p:test", 6);
TESTCASE_SUCCESS(cmd15);
free(cmd15[2]);
char* cmd16[] = {"xfreerdp", "-invalid"};
TESTCASE(cmd16, COMMAND_LINE_ERROR_NO_KEYWORD);
char* cmd17[] = {"xfreerdp", "--invalid"};
TESTCASE(cmd17, COMMAND_LINE_ERROR_NO_KEYWORD);
char* cmd18[] = {"xfreerdp", "/kbd-list"};
TESTCASE(cmd18, COMMAND_LINE_STATUS_PRINT);
char* cmd19[] = {"xfreerdp", "/monitor-list"};
TESTCASE(cmd19, COMMAND_LINE_STATUS_PRINT);
return 0;
}

View File

@ -223,7 +223,7 @@ int ios_run_freerdp(freerdp* instance)
mfi->connection_state = TSXConnectionDisconnected;
// Cleanup
freerdp_channels_close(channels, instance);
freerdp_channels_disconnect(channels, instance);
freerdp_disconnect(instance);
gdi_free(instance);
cache_free(instance->context->cache);
@ -252,6 +252,7 @@ int ios_context_new(freerdp* instance, rdpContext* context)
void ios_context_free(freerdp* instance, rdpContext* context)
{
mfInfo* mfi = ((mfContext*) context)->mfi;
freerdp_channels_close(context->channels, instance);
freerdp_channels_free(context->channels);
ios_events_free_pipe(mfi);
free(mfi);

View File

@ -158,9 +158,7 @@ NSString* TSXSessionDidFailToConnectNotification = @"TSXSessionDidFailToConnect"
settings->TlsSecurity = FALSE;
settings->NlaSecurity = FALSE;
settings->ExtSecurity = FALSE;
settings->DisableEncryption = TRUE;
settings->EncryptionMethods = ENCRYPTION_METHOD_40BIT | ENCRYPTION_METHOD_128BIT | ENCRYPTION_METHOD_FIPS;
settings->EncryptionLevel = ENCRYPTION_LEVEL_CLIENT_COMPATIBLE;
settings->UseRdpSecurityLayer = TRUE;
break;
default:

View File

@ -6,8 +6,10 @@ elseif((CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64") AND (CMAKE_SIZEOF_VOID_P
elseif((CMAKE_SYSTEM_PROCESSOR MATCHES "i386") AND (CMAKE_SIZEOF_VOID_P EQUAL 8) AND (APPLE))
# Mac is weird like that.
set(TARGET_ARCH "x64")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "arm*")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^arm*")
set(TARGET_ARCH "ARM")
elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "sparc")
set(TARGET_ARCH "sparc")
endif()
option(WITH_MANPAGES "Generate manpages." ON)
@ -116,6 +118,7 @@ option(WITH_DEBUG_X11_CLIPRDR "Print X11 clipboard redirection debug messages" $
option(WITH_DEBUG_X11_LOCAL_MOVESIZE "Print X11 Client local movesize debug messages" ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_X11 "Print X11 Client debug messages" ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_XV "Print XVideo debug messages" ${DEFAULT_DEBUG_OPTION})
option(WITH_DEBUG_RINGBUFFER "Enable Ringbuffer debug messages" ${DEFAULT_DEBUG_OPTION})
if(ANDROID)
include(ConfigOptionsAndroid)

View File

@ -1,6 +1,8 @@
# - Try to find the OpenH264 library
# Once done this will define
#
# OPENH264_ROOT - A list of search hints
#
# OPENH264_FOUND - system has OpenH264
# OPENH264_INCLUDE_DIR - the OpenH264 include directory
# OPENH264_LIBRARIES - libopenh264 library
@ -9,8 +11,15 @@ if (OPENH264_INCLUDE_DIR AND OPENH264_LIBRARY)
set(OPENH264_FIND_QUIETLY TRUE)
endif (OPENH264_INCLUDE_DIR AND OPENH264_LIBRARY)
find_path(OPENH264_INCLUDE_DIR NAMES wels/codec_api.h wels/codec_app_def.h wels/codec_def.h)
find_library(OPENH264_LIBRARY openh264)
find_path(OPENH264_INCLUDE_DIR NAMES wels/codec_api.h wels/codec_app_def.h wels/codec_def.h
PATH_SUFFIXES include
HINTS ${OPENH264_ROOT})
find_library(OPENH264_LIBRARY NAMES openh264 welsdec
PATH_SUFFIXES lib
HINTS ${OPENH264_ROOT})
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenH264 DEFAULT_MSG OPENH264_LIBRARY OPENH264_INCLUDE_DIR)
if (OPENH264_INCLUDE_DIR AND OPENH264_LIBRARY)
set(OPENH264_FOUND TRUE)

View File

@ -268,7 +268,7 @@ if (OPENSSL_INCLUDE_DIR)
set(OPENSSL_VERSION "${_OPENSSL_VERSION}")
elseif(OPENSSL_INCLUDE_DIR AND EXISTS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h")
file(STRINGS "${OPENSSL_INCLUDE_DIR}/openssl/opensslv.h" openssl_version_str
REGEX "^#define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])+.*")
REGEX "^#.?define[\t ]+OPENSSL_VERSION_NUMBER[\t ]+0x([0-9a-fA-F])+.*")
# The version number is encoded as 0xMNNFFPPS: major minor fix patch status
# The status gives if this is a developer or prerelease and is ignored here.

View File

@ -11,14 +11,14 @@ find_library(PULSE_LIBRARY pulse PATHS ${PULSE_LIBRARY_DIRS})
FIND_PACKAGE_HANDLE_STANDARD_ARGS(Pulse DEFAULT_MSG PULSE_INCLUDE_DIR PULSE_LIBRARY)
if(PULSE_LIBRARY)
execute_process(COMMAND "pactl" "--version" OUTPUT_VARIABLE PULSE_VERSION_OUTPUT)
STRING(REGEX MATCH "[0-9]+\\.[0-9]+\\.[0-9]+" PULSE_VERSION "${PULSE_VERSION_OUTPUT}")
if(NOT PULSE_VERSION)
message(FATAL_ERROR "PulseAudio is not installed")
endif()
STRING(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" PULSE_VERSION_MAJOR "${PULSE_VERSION}")
STRING(REGEX REPLACE "^[0-9]+\\.([0-9])+\\.[0-9]+" "\\1" PULSE_VERSION_MINOR "${PULSE_VERSION}")
STRING(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" PULSE_VERSION_PATCH "${PULSE_VERSION}")
file(STRINGS "${PULSE_INCLUDE_DIR}/pulse/version.h" STR1 REGEX "PA_MAJOR")
file(STRINGS "${PULSE_INCLUDE_DIR}/pulse/version.h" STR2 REGEX "PA_MINOR")
file(STRINGS "${PULSE_INCLUDE_DIR}/pulse/version.h" STR3 REGEX "PA_MICRO")
string(REGEX MATCHALL "[0-9]+" PULSE_VERSION_MAJOR ${STR1})
string(REGEX MATCHALL "[0-9]+" PULSE_VERSION_MINOR ${STR2})
string(REGEX MATCHALL "[0-9]+" PULSE_VERSION_PATCH ${STR3})
if(PULSE_VERSION_PATCH EQUAL 0)
set(PULSE_VERSION "${PULSE_VERSION_MAJOR}.${PULSE_VERSION_MINOR}")
else()

View File

@ -8,10 +8,12 @@
#
# WAYLAND_INCLUDE_DIR - where to find wayland-client.h, etc.
# WAYLAND_LIBRARY - the Wayland client library
# WAYLAND_VERSION - wayland client version if found and pkg-config was used
#
#=============================================================================
# Copyright 2014 Manuel Bachmann <tarnyko@tarnyko.net>
# Copyright 2015 Bernhard Miklautz <bernhard.miklautz@shacknet.at>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -26,21 +28,38 @@
# limitations under the License.
#=============================================================================
set(REQUIRED_WAYLAND_CLIENT_VERSION 1.3.0)
include(FindPkgConfig)
if(PKG_CONFIG_FOUND)
pkg_check_modules(WAYLAND wayland-client)
endif()
find_path(WAYLAND_INCLUDE_DIR NAMES wayland-client.h
PATHS ${WAYLAND_INCLUDE_DIRS}
DOC "The Wayland include directory"
)
find_library(WAYLAND_LIBRARY NAMES wayland-client
PATHS ${WAYLAND_LIBRARY_DIRS}
DOC "The Wayland client library"
)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_LIBRARY WAYLAND_INCLUDE_DIR)
if(WAYLAND_FOUND)
set( WAYLAND_LIBRARIES ${WAYLAND_LIBRARY} )
set( WAYLAND_INCLUDE_DIRS ${WAYLAND_INCLUDE_DIR} )
if(WAYLAND_VERSION)
if (${WAYLAND_VERSION} VERSION_LESS ${REQUIRED_WAYLAND_CLIENT_VERSION})
message(WARNING "Installed wayland version ${WAYLAND_VERSION} is too old - minimum required version ${REQUIRED_WAYLAND_CLIENT_VERSION}")
set(WAYLAND_FOUND FALSE)
endif()
else()
message(WARNING "Couldn't detect wayland version - no version check is done")
endif()
mark_as_advanced(WAYLAND_INCLUDE_DIR WAYLAND_LIBRARY)
if(WAYLAND_FOUND)
set(WAYLAND_LIBRARIES ${WAYLAND_LIBRARY})
set(WAYLAND_INCLUDE_DIRS ${WAYLAND_INCLUDE_DIR})
endif()
mark_as_advanced(WAYLAND_INCLUDE_DIR WAYLAND_LIBRARY WAYLAND_VERSION)

View File

@ -28,15 +28,26 @@
# limitations under the License.
#=============================================================================
if (APPLE)
set(CMAKE_FIND_FRAMEWORK_OLD ${CMAKE_FIND_FRAMEWORK})
set(CMAKE_FIND_FRAMEWORK LAST)
endif ()
find_path(X11_INCLUDE_DIR NAMES X11/Xlib.h
PATH_SUFFIXES X11
PATHS /opt/X11/include
DOC "The X11 include directory"
)
find_library(X11_LIBRARY NAMES X11
PATHS /opt/X11/lib
DOC "The X11 library"
)
if(APPLE)
set(CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK_OLD})
endif()
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(X11 DEFAULT_MSG X11_LIBRARY X11_INCLUDE_DIR)

View File

@ -30,10 +30,12 @@
find_path(XKBFILE_INCLUDE_DIR NAMES X11/extensions/XKBfile.h
PATH_SUFFIXES X11/extensions
PATHS /opt/X11/include
DOC "The XKBFile include directory"
)
find_library(XKBFILE_LIBRARY NAMES xkbfile
PATHS /opt/X11/lib
DOC "The XKBFile library"
)

View File

@ -28,10 +28,12 @@
find_path(XRANDR_INCLUDE_DIR NAMES X11/extensions/Xrandr.h
PATH_SUFFIXES X11/extensions
PATHS /opt/X11/include
DOC "The XRANDR include directory"
)
find_library(XRANDR_LIBRARY NAMES Xrandr
PATHS /opt/X11/lib
DOC "The XRANDR library"
)

View File

@ -30,10 +30,12 @@
find_path(XSHM_INCLUDE_DIR NAMES X11/extensions/XShm.h
PATH_SUFFIXES X11/extensions
PATHS /opt/X11/include
DOC "The XShm include directory"
)
find_library(XSHM_LIBRARY NAMES Xext
PATHS /opt/X11/lib
DOC "The XShm library"
)

View File

@ -30,10 +30,12 @@
find_path(XTEST_INCLUDE_DIR NAMES X11/extensions/XTest.h
PATH_SUFFIXES X11/extensions
PATHS /opt/X11/include
DOC "The XTest include directory"
)
find_library(XTEST_LIBRARY NAMES Xtst
PATHS /opt/X11/lib
DOC "The XTest library"
)

View File

@ -30,10 +30,12 @@
find_path(XCURSOR_INCLUDE_DIR NAMES X11/Xcursor/Xcursor.h
PATH_SUFFIXES X11/Xcursor
PATHS /opt/X11/include
DOC "The Xcursor include directory"
)
find_library(XCURSOR_LIBRARY NAMES Xcursor
PATHS /opt/X11/lib
DOC "The Xcursor library"
)

View File

@ -30,10 +30,12 @@
find_path(XDAMAGE_INCLUDE_DIR NAMES X11/extensions/Xdamage.h
PATH_SUFFIXES X11/extensions
PATHS /opt/X11/include
DOC "The Xdamage include directory"
)
find_library(XDAMAGE_LIBRARY NAMES Xdamage
PATHS /opt/X11/lib
DOC "The Xdamage library"
)

View File

@ -30,10 +30,12 @@
find_path(XEXT_INCLUDE_DIR NAMES X11/extensions/Xext.h
PATH_SUFFIXES X11/extensions
PATHS /opt/X11/include
DOC "The Xext include directory"
)
find_library(XEXT_LIBRARY NAMES Xext
PATHS /opt/X11/lib
DOC "The Xext library"
)

View File

@ -30,10 +30,12 @@
find_path(XFIXES_INCLUDE_DIR NAMES X11/extensions/Xfixes.h
PATH_SUFFIXES X11/extensions
PATHS /opt/X11/include
DOC "The Xfixes include directory"
)
find_library(XFIXES_LIBRARY NAMES Xfixes
PATHS /opt/X11/lib
DOC "The Xfixes library"
)

View File

@ -32,9 +32,11 @@
include(CheckSymbolExists)
find_path(XI_INCLUDE_DIR NAMES X11/extensions/XInput2.h
PATHS /opt/X11/include
DOC "The Xi include directory")
find_library(XI_LIBRARY NAMES Xi
PATHS /opt/X11/lib
DOC "The Xi library")
include(FindPackageHandleStandardArgs)

View File

@ -29,11 +29,13 @@
#=============================================================================
find_path(XINERAMA_INCLUDE_DIR NAMES X11/extensions/Xinerama.h
PATHS /opt/X11/include
PATH_SUFFIXES X11/extensions
DOC "The Xinerama include directory"
)
find_library(XINERAMA_LIBRARY NAMES Xinerama
PATHS /opt/X11/lib
DOC "The Xinerama library"
)

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