mirror of https://github.com/FreeRDP/FreeRDP
Merge branch 'master' of https://github.com/awakecoding/FreeRDP into awakecoding-staging
This commit is contained in:
commit
b184a7531f
|
@ -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
|
||||
|
|
|
@ -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")
|
||||
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -108,8 +108,6 @@ struct _SMARTCARD_DEVICE
|
|||
{
|
||||
DEVICE device;
|
||||
|
||||
wLog* log;
|
||||
|
||||
char* name;
|
||||
char* path;
|
||||
|
||||
|
|
|
@ -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
|
@ -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;
|
||||
|
|
|
@ -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")
|
|
@ -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")
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 =
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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, ¤t) == 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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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")))
|
||||
{
|
||||
|
|
|
@ -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 */
|
||||
{
|
||||
|
|
|
@ -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})
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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"
|
||||
)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue