Merged changes from FreeRDP branch, notably support for fullscreen on mac os x.

This commit is contained in:
Benoît LeBlanc 2013-09-30 11:31:01 -04:00
commit 7198ee2def
273 changed files with 13726 additions and 1551 deletions

View File

@ -123,7 +123,14 @@ if(CMAKE_COMPILER_IS_GNUCC)
else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=i686")
endif()
else()
if(CMAKE_POSITION_INDEPENDENT_CODE)
if(${CMAKE_VERSION} VERSION_LESS 2.8.9)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
endif()
endif()
endif()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
CHECK_C_COMPILER_FLAG (-Wno-unused-result Wno-unused-result)
if(Wno-unused-result)
@ -158,7 +165,10 @@ if(CMAKE_COMPILER_IS_GNUCC)
endif()
endif()
if(CMAKE_COMPILER_IS_CLANG)
if("${CMAKE_C_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Weverything -Wno-unused-parameter")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-unused-macros -Wno-padded")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-c11-extensions -Wno-gnu")
if(WITH_SSE2)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mssse3")
endif()
@ -194,7 +204,7 @@ if(WIN32)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUNICODE -D_UNICODE")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_WIN32_WINNT=0x0501")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWIN32_LEAN_AND_MEAN")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWIN32_LEAN_AND_MEAN")
endif()
if(IOS)
@ -230,22 +240,22 @@ endif()
# Mac OS X
if(APPLE)
if(IOS)
if (NOT FREERDP_IOS_EXTERNAL_SSL_PATH)
message(STATUS "FREERDP_IOS_EXTERNAL_SSL_PATH not set! Required if openssl is not found in the iOS SDK (which usually isn't")
endif()
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${FREERDP_IOS_EXTERNAL_SSL_PATH})
set_property(GLOBAL PROPERTY XCODE_ATTRIBUTE_SKIP_INSTALL YES)
else()
if(IOS)
if (NOT FREERDP_IOS_EXTERNAL_SSL_PATH)
message(STATUS "FREERDP_IOS_EXTERNAL_SSL_PATH not set! Required if openssl is not found in the iOS SDK (which usually isn't")
endif()
set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${FREERDP_IOS_EXTERNAL_SSL_PATH})
set_property(GLOBAL PROPERTY XCODE_ATTRIBUTE_SKIP_INSTALL YES)
else(IOS)
if(NOT DEFINED CMAKE_OSX_ARCHITECTURES)
set(CMAKE_OSX_ARCHITECTURES i386 x86_64)
endif()
if(IS_DIRECTORY /opt/local/include)
include_directories(/opt/local/include)
link_directories(/opt/local/lib)
endif()
endif()
if(IS_DIRECTORY /opt/local/include)
include_directories(/opt/local/include)
link_directories(/opt/local/lib)
endif()
endif(IOS)
# Temporarily disabled, causes the cmake script to be reexecuted, causing the compilation to fail.
# Workaround: specify the parameter in the command-line
@ -253,11 +263,11 @@ if(APPLE)
# set(CMAKE_C_COMPILER "clang")
# endif()
if (WITH_VERBOSE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -v")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -v")
endif()
endif()
if (WITH_VERBOSE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -v")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -v")
endif()
endif(APPLE)
# Android
if(ANDROID)
@ -280,6 +290,7 @@ if(NOT IOS AND NOT ANDROID)
endif()
if(UNIX OR CYGWIN)
check_include_files(sys/eventfd.h HAVE_AIO_H)
check_include_files(sys/eventfd.h HAVE_EVENTFD_H)
check_include_files(sys/timerfd.h HAVE_TIMERFD_H)
set(X11_FEATURE_TYPE "RECOMMENDED")

View File

@ -163,14 +163,9 @@ static BOOL audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size
}
if (WaitForSingleObject(alsa->stopEvent, 0) == WAIT_OBJECT_0)
{
ret = 0;
frames = 0;
}
break;
else
{
ret = alsa->receive(encoded_data, encoded_size, alsa->user_data);
}
alsa->buffer_frames = 0;
@ -182,7 +177,7 @@ static BOOL audin_alsa_thread_receive(AudinALSADevice* alsa, BYTE* src, int size
frames -= cframes;
}
return ret;
return (ret) ? TRUE : FALSE;
}
static void* audin_alsa_thread_func(void* arg)
@ -198,9 +193,6 @@ static void* audin_alsa_thread_func(void* arg)
rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel;
tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel;
alsa->buffer = (BYTE*) malloc(tbytes_per_frame * alsa->frames_per_packet);
ZeroMemory(alsa->buffer, tbytes_per_frame * alsa->frames_per_packet);
alsa->buffer_frames = 0;
buffer = (BYTE*) malloc(rbytes_per_frame * alsa->frames_per_packet);
ZeroMemory(buffer, rbytes_per_frame * alsa->frames_per_packet);
freerdp_dsp_context_reset_adpcm(alsa->dsp_context);
@ -241,15 +233,11 @@ static void* audin_alsa_thread_func(void* arg)
free(buffer);
free(alsa->buffer);
alsa->buffer = NULL;
if (capture_handle)
snd_pcm_close(capture_handle);
SetEvent(alsa->stopEvent);
DEBUG_DVC("out");
ExitThread(0);
return NULL;
}
@ -258,8 +246,6 @@ static void audin_alsa_free(IAudinDevice* device)
{
AudinALSADevice* alsa = (AudinALSADevice*) device;
SetEvent(alsa->stopEvent);
freerdp_dsp_context_free(alsa->dsp_context);
free(alsa->device_name);
@ -337,6 +323,8 @@ static void audin_alsa_set_format(IAudinDevice* device, audinFormat* format, UIN
static void audin_alsa_open(IAudinDevice* device, AudinReceive receive, void* user_data)
{
int rbytes_per_frame;
int tbytes_per_frame;
AudinALSADevice* alsa = (AudinALSADevice*) device;
DEBUG_DVC("");
@ -344,8 +332,15 @@ static void audin_alsa_open(IAudinDevice* device, AudinReceive receive, void* us
alsa->receive = receive;
alsa->user_data = user_data;
rbytes_per_frame = alsa->actual_channels * alsa->bytes_per_channel;
tbytes_per_frame = alsa->target_channels * alsa->bytes_per_channel;
alsa->buffer = (BYTE*) malloc(tbytes_per_frame * alsa->frames_per_packet);
ZeroMemory(alsa->buffer, tbytes_per_frame * alsa->frames_per_packet);
alsa->buffer_frames = 0;
alsa->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
alsa->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) audin_alsa_thread_func, alsa, 0, NULL);
alsa->thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) audin_alsa_thread_func, alsa, 0, NULL);
}
static void audin_alsa_close(IAudinDevice* device)
@ -355,7 +350,16 @@ static void audin_alsa_close(IAudinDevice* device)
DEBUG_DVC("");
SetEvent(alsa->stopEvent);
WaitForSingleObject(alsa->thread, INFINITE);
CloseHandle(alsa->stopEvent);
CloseHandle(alsa->thread);
if (alsa->buffer)
free(alsa->buffer);
alsa->buffer = NULL;
alsa->stopEvent = NULL;
alsa->thread = NULL;
alsa->receive = NULL;
alsa->user_data = NULL;
}

View File

@ -540,3 +540,4 @@ int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEnt
return 0;
}

View File

@ -78,7 +78,7 @@ static void audin_server_send_version(audin_server* audin, wStream* s)
{
Stream_Write_UINT8(s, MSG_SNDIN_VERSION);
Stream_Write_UINT32(s, 1); /* Version (4 bytes) */
WTSVirtualChannelWrite(audin->audin_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
}
static BOOL audin_server_recv_version(audin_server* audin, wStream* s, UINT32 length)
@ -130,7 +130,7 @@ static void audin_server_send_formats(audin_server* audin, wStream* s)
}
}
WTSVirtualChannelWrite(audin->audin_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
}
static BOOL audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 length)
@ -166,6 +166,7 @@ static BOOL audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 le
Stream_Read_UINT16(s, audin->context.client_formats[i].nBlockAlign);
Stream_Read_UINT16(s, audin->context.client_formats[i].wBitsPerSample);
Stream_Read_UINT16(s, audin->context.client_formats[i].cbSize);
if (audin->context.client_formats[i].cbSize > 0)
{
Stream_Seek(s, audin->context.client_formats[i].cbSize);
@ -201,7 +202,7 @@ static void audin_server_send_open(audin_server* audin, wStream* s)
Stream_Write_UINT16(s, 16); /* wBitsPerSample */
Stream_Write_UINT16(s, 0); /* cbSize */
WTSVirtualChannelWrite(audin->audin_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
}
static BOOL audin_server_recv_open_reply(audin_server* audin, wStream* s, UINT32 length)
@ -283,10 +284,10 @@ static void* audin_server_thread_func(void* arg)
void* buffer;
BYTE MessageId;
BOOL ready = FALSE;
UINT32 bytes_returned = 0;
DWORD BytesReturned = 0;
audin_server* audin = (audin_server*) arg;
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualFileHandle, &buffer, &bytes_returned) == TRUE)
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualFileHandle, &buffer, &BytesReturned) == TRUE)
{
fd = *((void**) buffer);
WTSFreeMemory(buffer);
@ -303,7 +304,7 @@ static void* audin_server_thread_func(void* arg)
if (WaitForSingleObject(audin->stopEvent, 0) == WAIT_OBJECT_0)
break;
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, &buffer, &bytes_returned) == FALSE)
if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, &buffer, &BytesReturned) == FALSE)
break;
ready = *((BOOL*) buffer);
@ -330,46 +331,48 @@ static void* audin_server_thread_func(void* arg)
Stream_SetPosition(s, 0);
if (WTSVirtualChannelRead(audin->audin_channel, 0, Stream_Buffer(s),
Stream_Capacity(s), &bytes_returned) == FALSE)
if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s),
Stream_Capacity(s), &BytesReturned) == FALSE)
{
if (bytes_returned == 0)
if (BytesReturned == 0)
break;
Stream_EnsureRemainingCapacity(s, (int) bytes_returned);
Stream_EnsureRemainingCapacity(s, BytesReturned);
if (WTSVirtualChannelRead(audin->audin_channel, 0, Stream_Buffer(s),
Stream_Capacity(s), &bytes_returned) == FALSE)
if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s),
Stream_Capacity(s), &BytesReturned) == FALSE)
{
break;
}
}
if (bytes_returned < 1)
if (BytesReturned < 1)
continue;
Stream_Read_UINT8(s, MessageId);
bytes_returned--;
BytesReturned--;
switch (MessageId)
{
case MSG_SNDIN_VERSION:
if (audin_server_recv_version(audin, s, bytes_returned))
if (audin_server_recv_version(audin, s, BytesReturned))
audin_server_send_formats(audin, s);
break;
case MSG_SNDIN_FORMATS:
if (audin_server_recv_formats(audin, s, bytes_returned))
if (audin_server_recv_formats(audin, s, BytesReturned))
audin_server_send_open(audin, s);
break;
case MSG_SNDIN_OPEN_REPLY:
audin_server_recv_open_reply(audin, s, bytes_returned);
audin_server_recv_open_reply(audin, s, BytesReturned);
break;
case MSG_SNDIN_DATA_INCOMING:
break;
case MSG_SNDIN_DATA:
audin_server_recv_data(audin, s, bytes_returned);
audin_server_recv_data(audin, s, BytesReturned);
break;
case MSG_SNDIN_FORMATCHANGE:
@ -394,7 +397,7 @@ static BOOL audin_server_open(audin_server_context* context)
if (!audin->thread)
{
audin->audin_channel = WTSVirtualChannelOpenEx(context->vcm, "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC);
audin->audin_channel = WTSVirtualChannelManagerOpenEx(context->vcm, "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC);
if (!audin->audin_channel)
return FALSE;
@ -419,7 +422,9 @@ static BOOL audin_server_close(audin_server_context* context)
SetEvent(audin->stopEvent);
WaitForSingleObject(audin->thread, INFINITE);
CloseHandle(audin->thread);
CloseHandle(audin->stopEvent);
audin->thread = NULL;
audin->stopEvent = NULL;
}
if (audin->audin_channel)

View File

@ -182,10 +182,14 @@ FREERDP_ADDIN** freerdp_channels_list_dynamic_addins(LPSTR pszName, LPSTR pszSub
NativePathCchAppendA(pszSearchPath, cchSearchPath + 1, pszAddinPath);
NativePathCchAppendA(pszSearchPath, cchSearchPath + 1, pszPattern);
free(pszPattern);
cchSearchPath = strlen(pszSearchPath);
hFind = FindFirstFileA(pszSearchPath, &FindData);
free(pszSearchPath);
nAddins = 0;
ppAddins = (FREERDP_ADDIN**) malloc(sizeof(FREERDP_ADDIN*) * 128);
ppAddins[nAddins] = NULL;

View File

@ -631,8 +631,9 @@ FREERDP_API int freerdp_channels_send_event(rdpChannels* channels, wMessage* eve
/**
* called only from main thread
*/
static void freerdp_channels_process_sync(rdpChannels* channels, freerdp* instance)
static int freerdp_channels_process_sync(rdpChannels* channels, freerdp* instance)
{
int rc = TRUE;
wMessage message;
wMessage* event;
rdpChannel* channel;
@ -642,7 +643,10 @@ static void freerdp_channels_process_sync(rdpChannels* channels, freerdp* instan
while (MessageQueue_Peek(channels->MsgPipe->Out, &message, TRUE))
{
if (message.id == WMQ_QUIT)
{
rc = FALSE;
break;
}
if (message.id == 0)
{
@ -677,6 +681,8 @@ static void freerdp_channels_process_sync(rdpChannels* channels, freerdp* instan
*/
}
}
return rc;
}
/**
@ -730,7 +736,7 @@ int freerdp_channels_process_pending_messages(freerdp* instance)
if (WaitForSingleObject(MessageQueue_Event(channels->MsgPipe->Out), 0) == WAIT_OBJECT_0)
{
freerdp_channels_process_sync(channels, instance);
return freerdp_channels_process_sync(channels, instance);
}
return TRUE;
@ -782,4 +788,7 @@ void freerdp_channels_close(rdpChannels* channels, freerdp* instance)
if (pChannelClientData->pChannelInitEventProc)
pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle, CHANNEL_EVENT_TERMINATED, 0, 0);
}
/* Emit a quit signal to the internal message pipe. */
MessagePipe_PostQuit(channels->MsgPipe, 0);
}

View File

@ -21,3 +21,6 @@ if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()
if(WITH_SERVER_CHANNELS)
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()

View File

@ -1,7 +1,7 @@
set(OPTION_DEFAULT OFF)
set(OPTION_CLIENT_DEFAULT ON)
set(OPTION_SERVER_DEFAULT OFF)
set(OPTION_SERVER_DEFAULT ON)
define_channel_options(NAME "cliprdr" TYPE "static"
DESCRIPTION "Clipboard Virtual Channel Extension"

View File

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

View File

@ -1,58 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Clipboard Virtual Channel
*
* Copyright 2009-2011 Jay Sorg
* Copyright 2010-2011 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef __CLIPRDR_CONSTANTS
#define __CLIPRDR_CONSTANTS
/* CLIPRDR_HEADER.msgType */
#define CB_MONITOR_READY 0x0001
#define CB_FORMAT_LIST 0x0002
#define CB_FORMAT_LIST_RESPONSE 0x0003
#define CB_FORMAT_DATA_REQUEST 0x0004
#define CB_FORMAT_DATA_RESPONSE 0x0005
#define CB_TEMP_DIRECTORY 0x0006
#define CB_CLIP_CAPS 0x0007
#define CB_FILECONTENTS_REQUEST 0x0008
#define CB_FILECONTENTS_RESPONSE 0x0009
#define CB_LOCK_CLIPDATA 0x000A
#define CB_UNLOCK_CLIPDATA 0x000B
/* CLIPRDR_HEADER.msgFlags */
#define CB_RESPONSE_OK 0x0001
#define CB_RESPONSE_FAIL 0x0002
#define CB_ASCII_NAMES 0x0004
/* CLIPRDR_CAPS_SET.capabilitySetType */
#define CB_CAPSTYPE_GENERAL 0x0001
/* CLIPRDR_GENERAL_CAPABILITY.lengthCapability */
#define CB_CAPSTYPE_GENERAL_LEN 12
/* CLIPRDR_GENERAL_CAPABILITY.version */
#define CB_CAPS_VERSION_1 0x00000001
#define CB_CAPS_VERSION_2 0x00000002
/* CLIPRDR_GENERAL_CAPABILITY.generalFlags */
#define CB_USE_LONG_FORMAT_NAMES 0x00000002
#define CB_STREAM_FILECLIP_ENABLED 0x00000004
#define CB_FILECLIP_NO_FILE_PATHS 0x00000008
#define CB_CAN_LOCK_CLIPDATA 0x00000010
#endif /* __CLIPRDR_CONSTANTS */

View File

@ -34,7 +34,6 @@
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/client/cliprdr.h>
#include "cliprdr_constants.h"
#include "cliprdr_main.h"
#include "cliprdr_format.h"
@ -62,21 +61,25 @@ void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, RDP_CB_FORMAT_LIS
for (i = 0; i < cb_event->num_formats; i++)
{
const char* name;
int name_length;
int name_length, short_name_length = 32, x;
switch (cb_event->formats[i])
{
case CB_FORMAT_HTML:
name = CFSTR_HTML; name_length = sizeof(CFSTR_HTML);
name = CFSTR_HTML;
name_length = sizeof(CFSTR_HTML);
break;
case CB_FORMAT_PNG:
name = CFSTR_PNG; name_length = sizeof(CFSTR_PNG);
name = CFSTR_PNG;
name_length = sizeof(CFSTR_PNG);
break;
case CB_FORMAT_JPEG:
name = CFSTR_JPEG; name_length = sizeof(CFSTR_JPEG);
name = CFSTR_JPEG;
name_length = sizeof(CFSTR_JPEG);
break;
case CB_FORMAT_GIF:
name = CFSTR_GIF; name_length = sizeof(CFSTR_GIF);
name = CFSTR_GIF;
name_length = sizeof(CFSTR_GIF);
break;
default:
name = "\0\0";
@ -85,12 +88,23 @@ void cliprdr_process_format_list_event(cliprdrPlugin* cliprdr, RDP_CB_FORMAT_LIS
}
if (!cliprdr->use_long_format_names)
name_length = 32;
Stream_EnsureRemainingCapacity(body, 4 + name_length);
{
x = (name_length > short_name_length) ?
name_length : short_name_length;
Stream_Write_UINT32(body, cb_event->formats[i]);
Stream_Write(body, name, name_length);
Stream_EnsureRemainingCapacity(body, 4 + short_name_length);
Stream_Write_UINT32(body, cb_event->formats[i]);
Stream_Write(body, name, x);
while (x++ < short_name_length)
Stream_Write(body, "\0", 1);
}
else
{
Stream_EnsureRemainingCapacity(body, 4 + name_length);
Stream_Write_UINT32(body, cb_event->formats[i]);
Stream_Write(body, name, name_length);
}
}
Stream_SealLength(body);

View File

@ -27,13 +27,13 @@
#include <string.h>
#include <winpr/crt.h>
#include <winpr/print.h>
#include <freerdp/types.h>
#include <freerdp/constants.h>
#include <freerdp/utils/svc_plugin.h>
#include <freerdp/client/cliprdr.h>
#include "cliprdr_constants.h"
#include "cliprdr_main.h"
#include "cliprdr_format.h"
@ -77,6 +77,11 @@ void cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* s)
Stream_Write_UINT32(s, dataLen);
Stream_SetPosition(s, pos);
#ifdef WITH_DEBUG_CLIPRDR
printf("Cliprdr Sending (%d bytes)\n", dataLen + 8);
winpr_HexDump(Stream_Buffer(s), dataLen + 8);
#endif
svc_plugin_send((rdpSvcPlugin*) cliprdr, s);
}
@ -207,6 +212,10 @@ static void cliprdr_process_receive(rdpSvcPlugin* plugin, wStream* s)
DEBUG_CLIPRDR("msgType: %s (%d), msgFlags: %d dataLen: %d",
CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen);
#ifdef WITH_DEBUG_CLIPRDR
winpr_HexDump(Stream_Buffer(s), dataLen + 8);
#endif
switch (msgType)
{
case CB_CLIP_CAPS:

View File

@ -25,14 +25,6 @@
#include <freerdp/utils/debug.h>
struct _CLIPRDR_FORMAT_NAME
{
UINT32 id;
char* name;
int length;
};
typedef struct _CLIPRDR_FORMAT_NAME CLIPRDR_FORMAT_NAME;
struct cliprdr_plugin
{
rdpSvcPlugin plugin;

View File

@ -0,0 +1,35 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
define_channel_server("cliprdr")
set(${MODULE_PREFIX}_SRCS
cliprdr_main.c
cliprdr_main.h)
add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE freerdp
MODULES freerdp-utils)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")

View File

@ -0,0 +1,536 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Clipboard Virtual Channel Extension
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/stream.h>
#include "cliprdr_main.h"
/**
* Initialization Sequence\n
* Client Server\n
* | |\n
* |<----------------------Server Clipboard Capabilities PDU-----------------|\n
* |<-----------------------------Monitor Ready PDU--------------------------|\n
* |-----------------------Client Clipboard Capabilities PDU---------------->|\n
* |---------------------------Temporary Directory PDU---------------------->|\n
* |-------------------------------Format List PDU-------------------------->|\n
* |<--------------------------Format List Response PDU----------------------|\n
*
*/
/**
* Data Transfer Sequences\n
* Shared Local\n
* Clipboard Owner Clipboard Owner\n
* | |\n
* |-------------------------------------------------------------------------|\n _
* |-------------------------------Format List PDU-------------------------->|\n |
* |<--------------------------Format List Response PDU----------------------|\n _| Copy Sequence
* |<---------------------Lock Clipboard Data PDU (Optional)-----------------|\n
* |-------------------------------------------------------------------------|\n
* |-------------------------------------------------------------------------|\n _
* |<--------------------------Format Data Request PDU-----------------------|\n | Paste Sequence Palette,
* |---------------------------Format Data Response PDU--------------------->|\n _| Metafile, File List Data
* |-------------------------------------------------------------------------|\n
* |-------------------------------------------------------------------------|\n _
* |<------------------------Format Contents Request PDU---------------------|\n | Paste Sequence
* |-------------------------Format Contents Response PDU------------------->|\n _| File Stream Data
* |<---------------------Lock Clipboard Data PDU (Optional)-----------------|\n
* |-------------------------------------------------------------------------|\n
*
*/
static int cliprdr_server_send_capabilities(CliprdrServerContext* context)
{
wStream* s;
BOOL status;
UINT32 generalFlags;
CLIPRDR_HEADER header;
printf("CliprdrServerSendCapabilities\n");
header.msgType = CB_CLIP_CAPS;
header.msgFlags = 0;
header.dataLen = 16;
generalFlags = 0;
if (context->priv->UseLongFormatNames)
generalFlags |= CB_USE_LONG_FORMAT_NAMES;
s = Stream_New(NULL, header.dataLen + CLIPRDR_HEADER_LENGTH);
Stream_Write_UINT16(s, header.msgType); /* msgType (2 bytes) */
Stream_Write_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */
Stream_Write_UINT32(s, header.dataLen); /* dataLen (4 bytes) */
Stream_Write_UINT16(s, 1); /* cCapabilitiesSets (2 bytes) */
Stream_Write_UINT16(s, 0); /* pad1 (2 bytes) */
Stream_Write_UINT16(s, CB_CAPSTYPE_GENERAL); /* capabilitySetType (2 bytes) */
Stream_Write_UINT16(s, CB_CAPSTYPE_GENERAL_LEN); /* lengthCapability (2 bytes) */
Stream_Write_UINT32(s, CB_CAPS_VERSION_2); /* version (4 bytes) */
Stream_Write_UINT32(s, generalFlags); /* generalFlags (4 bytes) */
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
Stream_Free(s, TRUE);
return 0;
}
static int cliprdr_server_send_monitor_ready(CliprdrServerContext* context)
{
wStream* s;
BOOL status;
CLIPRDR_HEADER header;
printf("CliprdrServerSendMonitorReady\n");
header.msgType = CB_MONITOR_READY;
header.msgFlags = 0;
header.dataLen = 0;
s = Stream_New(NULL, header.dataLen + CLIPRDR_HEADER_LENGTH);
Stream_Write_UINT16(s, header.msgType); /* msgType (2 bytes) */
Stream_Write_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */
Stream_Write_UINT32(s, header.dataLen); /* dataLen (4 bytes) */
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
Stream_Free(s, TRUE);
return 0;
}
static int cliprdr_server_send_format_list_response(CliprdrServerContext* context)
{
wStream* s;
BOOL status;
CLIPRDR_HEADER header;
printf("CliprdrServerSendFormatListResponse\n");
header.msgType = CB_FORMAT_LIST_RESPONSE;
header.msgFlags = CB_RESPONSE_OK;
header.dataLen = 0;
s = Stream_New(NULL, header.dataLen + CLIPRDR_HEADER_LENGTH);
Stream_Write_UINT16(s, header.msgType); /* msgType (2 bytes) */
Stream_Write_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */
Stream_Write_UINT32(s, header.dataLen); /* dataLen (4 bytes) */
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
Stream_Free(s, TRUE);
return 0;
}
static int cliprdr_server_receive_capabilities(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
{
UINT32 version;
UINT32 generalFlags;
UINT16 cCapabilitiesSets;
UINT16 capabilitySetType;
UINT16 lengthCapability;
Stream_Read_UINT16(s, cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */
Stream_Seek_UINT16(s); /* pad1 (2 bytes) */
Stream_Read_UINT16(s, capabilitySetType); /* capabilitySetType (2 bytes) */
Stream_Read_UINT16(s, lengthCapability); /* lengthCapability (2 bytes) */
Stream_Read_UINT32(s, version); /* version (4 bytes) */
Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */
if (generalFlags & CB_USE_LONG_FORMAT_NAMES)
context->priv->UseLongFormatNames = TRUE;
if (generalFlags & CB_STREAM_FILECLIP_ENABLED)
context->priv->StreamFileClipEnabled = TRUE;
if (generalFlags & CB_FILECLIP_NO_FILE_PATHS)
context->priv->FileClipNoFilePaths = TRUE;
if (generalFlags & CB_CAN_LOCK_CLIPDATA)
context->priv->CanLockClipData = TRUE;
return 0;
}
static int cliprdr_server_receive_temporary_directory(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
{
WCHAR* wszTempDir;
if (Stream_GetRemainingLength(s) < 520)
return -1;
wszTempDir = (WCHAR*) Stream_Pointer(s);
if (wszTempDir[260] != 0)
return -1;
ConvertFromUnicode(CP_UTF8, 0, wszTempDir, -1,
&(context->priv->ClientTemporaryDirectory), 0, NULL, NULL);
printf("ClientTemporaryDirectory: %s\n", context->priv->ClientTemporaryDirectory);
return 0;
}
int cliprdr_wcslen(const WCHAR* str, const WCHAR* end)
{
WCHAR* p = (WCHAR*) str;
if (!p)
return -1;
while (*p)
{
if (p == end)
return -1;
p++;
}
return (p - str);
}
static void cliprdr_free_format_list(UINT32 count, CLIPRDR_FORMAT_NAME* formatNames)
{
int i;
if (formatNames)
{
for (i = 0; i < count; i++)
{
free(formatNames[i].name);
}
free(formatNames);
}
}
static int cliprdr_server_receive_long_format_list(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
{
int i;
WCHAR* end;
int length;
int position;
printf("%s\n", __FUNCTION__);
position = Stream_GetPosition(s);
Stream_SetPosition(s, Stream_Length(s));
end = (WCHAR*) Stream_Pointer(s);
Stream_SetPosition(s, position);
cliprdr_free_format_list(context->priv->ClientFormatNameCount, context->priv->ClientFormatNames);
context->priv->ClientFormatNameCount = 0;
context->priv->ClientFormatNames = NULL;
while (Stream_GetRemainingLength(s) >= 6)
{
Stream_Seek(s, 4); /* formatId (4 bytes) */
length = cliprdr_wcslen((WCHAR*) Stream_Pointer(s), end);
if (length < 0)
return -1;
Stream_Seek(s, (length + 1) * 2); /* wszFormatName */
context->priv->ClientFormatNameCount++;
}
context->priv->ClientFormatNames = (CLIPRDR_FORMAT_NAME*)
malloc(sizeof(CLIPRDR_FORMAT_NAME) * context->priv->ClientFormatNameCount);
Stream_SetPosition(s, position);
for (i = 0; i < context->priv->ClientFormatNameCount; i++)
{
Stream_Read_UINT32(s, context->priv->ClientFormatNames[i].id); /* formatId (4 bytes) */
length = cliprdr_wcslen((WCHAR*) Stream_Pointer(s), end);
context->priv->ClientFormatNames[i].name = NULL;
if (length)
{
context->priv->ClientFormatNames[i].length = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s),
-1, &(context->priv->ClientFormatNames[i].name), 0, NULL, NULL) - 1;
}
else
{
context->priv->ClientFormatNames[i].length = 0;
}
Stream_Seek(s, (length + 1) * 2); /* wszFormatName */
}
for (i = 0; i < context->priv->ClientFormatNameCount; i++)
{
printf("Format %d: Id: 0x%04X Name: %s Length: %d\n", i,
context->priv->ClientFormatNames[i].id,
context->priv->ClientFormatNames[i].name,
context->priv->ClientFormatNames[i].length);
}
return 0;
}
static int cliprdr_server_receive_short_format_list(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
{
printf("%s: unimplemented\n", __FUNCTION__);
return 0;
}
static int cliprdr_server_receive_format_list(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
{
int status;
if (context->priv->UseLongFormatNames)
{
status = cliprdr_server_receive_long_format_list(context, s, header);
}
else
{
status = cliprdr_server_receive_short_format_list(context, s, header);
}
cliprdr_server_send_format_list_response(context);
return status;
}
static int cliprdr_server_receive_pdu(CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header)
{
printf("CliprdrServerReceivePdu: msgType: %d msgFlags: 0x%08X dataLen: %d\n",
header->msgType, header->msgFlags, header->dataLen);
switch (header->msgType)
{
case CB_CLIP_CAPS:
cliprdr_server_receive_capabilities(context, s, header);
break;
case CB_TEMP_DIRECTORY:
cliprdr_server_receive_temporary_directory(context, s, header);
break;
case CB_FORMAT_LIST:
cliprdr_server_receive_format_list(context, s, header);
break;
case CB_FORMAT_LIST_RESPONSE:
break;
case CB_LOCK_CLIPDATA:
break;
case CB_UNLOCK_CLIPDATA:
break;
case CB_FORMAT_DATA_REQUEST:
break;
case CB_FORMAT_DATA_RESPONSE:
break;
case CB_FILECONTENTS_REQUEST:
break;
case CB_FILECONTENTS_RESPONSE:
break;
default:
printf("Unexpected clipboard PDU type: %d\n", header->msgType);
break;
}
return 0;
}
static void* cliprdr_server_thread(void* arg)
{
wStream* s;
DWORD status;
DWORD nCount;
void* buffer;
int position;
HANDLE events[8];
HANDLE ChannelEvent;
DWORD BytesReturned;
CLIPRDR_HEADER header;
CliprdrServerContext* context;
context = (CliprdrServerContext*) arg;
buffer = NULL;
BytesReturned = 0;
ChannelEvent = NULL;
s = Stream_New(NULL, 4096);
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
{
if (BytesReturned == sizeof(HANDLE))
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
WTSFreeMemory(buffer);
}
nCount = 0;
events[nCount++] = ChannelEvent;
events[nCount++] = context->priv->StopEvent;
cliprdr_server_send_capabilities(context);
cliprdr_server_send_monitor_ready(context);
while (1)
{
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
{
break;
}
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
{
if (BytesReturned)
Stream_Seek(s, BytesReturned);
}
else
{
Stream_EnsureRemainingCapacity(s, BytesReturned);
}
if (Stream_GetPosition(s) >= CLIPRDR_HEADER_LENGTH)
{
position = Stream_GetPosition(s);
Stream_SetPosition(s, 0);
Stream_Read_UINT16(s, header.msgType); /* msgType (2 bytes) */
Stream_Read_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */
Stream_Read_UINT32(s, header.dataLen); /* dataLen (4 bytes) */
Stream_SetPosition(s, position);
if (Stream_GetPosition(s) >= (header.dataLen + CLIPRDR_HEADER_LENGTH))
{
Stream_SealLength(s);
Stream_SetPosition(s, CLIPRDR_HEADER_LENGTH);
cliprdr_server_receive_pdu(context, s, &header);
Stream_SetPosition(s, 0);
}
}
}
Stream_Free(s, TRUE);
return NULL;
}
static int cliprdr_server_start(CliprdrServerContext* context)
{
context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "cliprdr", 0);
if (!context->priv->ChannelHandle)
return -1;
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) cliprdr_server_thread, (void*) context, 0, NULL);
return 0;
}
static int cliprdr_server_stop(CliprdrServerContext* context)
{
SetEvent(context->priv->StopEvent);
WaitForSingleObject(context->priv->Thread, INFINITE);
CloseHandle(context->priv->Thread);
return 0;
}
CliprdrServerContext* cliprdr_server_context_new(WTSVirtualChannelManager* vcm)
{
CliprdrServerContext* context;
context = (CliprdrServerContext*) malloc(sizeof(CliprdrServerContext));
if (context)
{
ZeroMemory(context, sizeof(CliprdrServerContext));
context->vcm = vcm;
context->Start = cliprdr_server_start;
context->Stop = cliprdr_server_stop;
context->priv = (CliprdrServerPrivate*) malloc(sizeof(CliprdrServerPrivate));
if (context->priv)
{
ZeroMemory(context->priv, sizeof(CliprdrServerPrivate));
context->priv->UseLongFormatNames = TRUE;
context->priv->StreamFileClipEnabled = TRUE;
context->priv->FileClipNoFilePaths = TRUE;
context->priv->CanLockClipData = TRUE;
}
}
return context;
}
void cliprdr_server_context_free(CliprdrServerContext* context)
{
if (context)
{
if (context->priv)
{
free(context->priv);
}
free(context);
}
}

View File

@ -0,0 +1,56 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Clipboard Virtual Channel Extension
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CHANNEL_SERVER_CLIPRDR_MAIN_H
#define FREERDP_CHANNEL_SERVER_CLIPRDR_MAIN_H
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <freerdp/server/cliprdr.h>
#define CLIPRDR_HEADER_LENGTH 8
struct _CLIPRDR_HEADER
{
UINT16 msgType;
UINT16 msgFlags;
UINT32 dataLen;
};
typedef struct _CLIPRDR_HEADER CLIPRDR_HEADER;
struct _cliprdr_server_private
{
HANDLE Thread;
HANDLE StopEvent;
void* ChannelHandle;
BOOL UseLongFormatNames;
BOOL StreamFileClipEnabled;
BOOL FileClipNoFilePaths;
BOOL CanLockClipData;
UINT32 ClientFormatNameCount;
CLIPRDR_FORMAT_NAME* ClientFormatNames;
char* ClientTemporaryDirectory;
};
#endif /* FREERDP_CHANNEL_SERVER_CLIPRDR_MAIN_H */

View File

@ -21,3 +21,6 @@ if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()
if(WITH_SERVER_CHANNELS)
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()

View File

@ -1,7 +1,7 @@
set(OPTION_DEFAULT OFF)
set(OPTION_CLIENT_DEFAULT ON)
set(OPTION_SERVER_DEFAULT OFF)
set(OPTION_SERVER_DEFAULT ON)
define_channel_options(NAME "drdynvc" TYPE "static"
DESCRIPTION "Dynamic Virtual Channel Extension"

View File

@ -284,10 +284,27 @@ static int drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStr
static int drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s)
{
UINT32 ChannelId;
wStream* data_out;
int value;
int error;
ChannelId = drdynvc_read_variable_uint(s, cbChId);
DEBUG_DVC("ChannelId=%d", ChannelId);
dvcman_close_channel(drdynvc->channel_mgr, ChannelId);
data_out = Stream_New(NULL, 4);
value = (CLOSE_REQUEST_PDU << 4) | (cbChId & 0x03);
Stream_Write_UINT8(data_out, value);
drdynvc_write_variable_uint(data_out, ChannelId);
error = svc_plugin_send((rdpSvcPlugin*) drdynvc, data_out);
if (error != CHANNEL_RC_OK)
{
DEBUG_WARN("VirtualChannelWrite failed %d", error);
return 1;
}
drdynvc->channel_error = error;
return 0;
}

View File

@ -0,0 +1,35 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
define_channel_server("drdynvc")
set(${MODULE_PREFIX}_SRCS
drdynvc_main.c
drdynvc_main.h)
add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE freerdp
MODULES freerdp-utils)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")

View File

@ -0,0 +1,149 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Dynamic Virtual Channel Extension
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/stream.h>
#include "drdynvc_main.h"
static void* drdynvc_server_thread(void* arg)
{
wStream* s;
DWORD status;
DWORD nCount;
void* buffer;
HANDLE events[8];
HANDLE ChannelEvent;
DWORD BytesReturned;
DrdynvcServerContext* context;
context = (DrdynvcServerContext*) arg;
buffer = NULL;
BytesReturned = 0;
ChannelEvent = NULL;
s = Stream_New(NULL, 4096);
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
{
if (BytesReturned == sizeof(HANDLE))
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
WTSFreeMemory(buffer);
}
nCount = 0;
events[nCount++] = ChannelEvent;
events[nCount++] = context->priv->StopEvent;
while (1)
{
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
{
break;
}
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
{
if (BytesReturned)
Stream_Seek(s, BytesReturned);
}
else
{
Stream_EnsureRemainingCapacity(s, BytesReturned);
}
}
Stream_Free(s, TRUE);
return NULL;
}
static int drdynvc_server_start(DrdynvcServerContext* context)
{
context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpdr", 0);
if (!context->priv->ChannelHandle)
return -1;
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) drdynvc_server_thread, (void*) context, 0, NULL);
return 0;
}
static int drdynvc_server_stop(DrdynvcServerContext* context)
{
SetEvent(context->priv->StopEvent);
WaitForSingleObject(context->priv->Thread, INFINITE);
CloseHandle(context->priv->Thread);
return 0;
}
DrdynvcServerContext* drdynvc_server_context_new(WTSVirtualChannelManager* vcm)
{
DrdynvcServerContext* context;
context = (DrdynvcServerContext*) malloc(sizeof(DrdynvcServerContext));
if (context)
{
ZeroMemory(context, sizeof(DrdynvcServerContext));
context->vcm = vcm;
context->Start = drdynvc_server_start;
context->Stop = drdynvc_server_stop;
context->priv = (DrdynvcServerPrivate*) malloc(sizeof(DrdynvcServerPrivate));
if (context->priv)
{
ZeroMemory(context->priv, sizeof(DrdynvcServerPrivate));
}
}
return context;
}
void drdynvc_server_context_free(DrdynvcServerContext* context)
{
if (context)
{
if (context->priv)
{
free(context->priv);
}
free(context);
}
}

View File

@ -0,0 +1,37 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Dynamic Virtual Channel Extension
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CHANNEL_SERVER_DRDYNVC_MAIN_H
#define FREERDP_CHANNEL_SERVER_DRDYNVC_MAIN_H
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <freerdp/settings.h>
#include <freerdp/server/drdynvc.h>
struct _drdynvc_server_private
{
HANDLE Thread;
HANDLE StopEvent;
void* ChannelHandle;
};
#endif /* FREERDP_CHANNEL_SERVER_DRDYNVC_MAIN_H */

View File

@ -117,7 +117,7 @@ static DRIVE_FILE* drive_get_file_by_id(DRIVE_DEVICE* disk, UINT32 id)
static void drive_process_irp_create(DRIVE_DEVICE* disk, IRP* irp)
{
char* path;
char* path = NULL;
int status;
UINT32 FileId;
DRIVE_FILE* file;
@ -633,17 +633,18 @@ static void drive_process_irp_list(DRIVE_DEVICE* disk)
static void* drive_thread_func(void* arg)
{
DRIVE_DEVICE* disk = (DRIVE_DEVICE*) arg;
HANDLE hdl[] = {disk->irpEvent, disk->stopEvent};
while (1)
{
WaitForSingleObject(disk->irpEvent, INFINITE);
if (WaitForSingleObject(disk->stopEvent, 0) == WAIT_OBJECT_0)
DWORD rc = WaitForMultipleObjects(2, hdl, FALSE, INFINITE);
if (rc == WAIT_OBJECT_0 + 1)
break;
ResetEvent(disk->irpEvent);
drive_process_irp_list(disk);
}
ExitThread(0);
return NULL;
}
@ -664,8 +665,10 @@ static void drive_free(DEVICE* device)
DRIVE_DEVICE* disk = (DRIVE_DEVICE*) device;
SetEvent(disk->stopEvent);
WaitForSingleObject(disk->thread, INFINITE);
CloseHandle(disk->thread);
CloseHandle(disk->irpEvent);
CloseHandle(disk->stopEvent);
while ((irp = (IRP*) InterlockedPopEntrySList(disk->pIrpList)) != NULL)
irp->Discard(irp);
@ -727,7 +730,7 @@ void drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, char*
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) disk);
ResumeThread(disk->thread);
ResumeThread(disk->thread);
}
}

View File

@ -137,7 +137,7 @@ static void parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
buffer = (BYTE*) malloc(Length);
status = read(parallel->file, irp->output->pointer, Length);
status = read(parallel->file, buffer, Length);
if (status < 0)
{

View File

@ -200,6 +200,8 @@ static void* printer_thread_func(void* arg)
printer_process_irp(printer_dev, irp);
}
ExitThread(0);
return NULL;
}
@ -219,11 +221,14 @@ static void printer_free(DEVICE* device)
SetEvent(printer_dev->stopEvent);
WaitForSingleObject(printer_dev->thread, INFINITE);
CloseHandle(printer_dev->thread);
while ((irp = (IRP*) InterlockedPopEntrySList(printer_dev->pIrpList)) != NULL)
irp->Discard(irp);
CloseHandle(printer_dev->thread);
CloseHandle(printer_dev->stopEvent);
CloseHandle(printer_dev->event);
_aligned_free(printer_dev->pIrpList);
if (printer_dev->printer)

View File

@ -20,3 +20,7 @@ define_channel("rdpdr")
if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()
if(WITH_SERVER_CHANNELS)
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()

View File

@ -1,7 +1,7 @@
set(OPTION_DEFAULT OFF)
set(OPTION_CLIENT_DEFAULT ON)
set(OPTION_SERVER_DEFAULT OFF)
set(OPTION_SERVER_DEFAULT ON)
define_channel_options(NAME "rdpdr" TYPE "static"
DESCRIPTION "Device Redirection Virtual Channel Extension"

View File

@ -33,132 +33,132 @@
#include "rdpdr_capabilities.h"
/* Output device redirection capability set header */
static void rdpdr_write_capset_header(wStream* data_out, UINT16 capabilityType, UINT16 capabilityLength, UINT32 version)
static void rdpdr_write_capset_header(wStream* s, UINT16 capabilityType, UINT16 capabilityLength, UINT32 version)
{
Stream_Write_UINT16(data_out, capabilityType);
Stream_Write_UINT16(data_out, capabilityLength);
Stream_Write_UINT32(data_out, version);
Stream_Write_UINT16(s, capabilityType);
Stream_Write_UINT16(s, capabilityLength);
Stream_Write_UINT32(s, version);
}
/* Output device direction general capability set */
static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, wStream* data_out)
static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, wStream* s)
{
rdpdr_write_capset_header(data_out, CAP_GENERAL_TYPE, 44, GENERAL_CAPABILITY_VERSION_02);
rdpdr_write_capset_header(s, CAP_GENERAL_TYPE, 44, GENERAL_CAPABILITY_VERSION_02);
Stream_Write_UINT32(data_out, 0); /* osType, ignored on receipt */
Stream_Write_UINT32(data_out, 0); /* osVersion, unused and must be set to zero */
Stream_Write_UINT16(data_out, 1); /* protocolMajorVersion, must be set to 1 */
Stream_Write_UINT16(data_out, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinorVersion */
Stream_Write_UINT32(data_out, 0x0000FFFF); /* ioCode1 */
Stream_Write_UINT32(data_out, 0); /* ioCode2, must be set to zero, reserved for future use */
Stream_Write_UINT32(data_out, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */
Stream_Write_UINT32(data_out, ENABLE_ASYNCIO); /* extraFlags1 */
Stream_Write_UINT32(data_out, 0); /* extraFlags2, must be set to zero, reserved for future use */
Stream_Write_UINT32(data_out, 0); /* SpecialTypeDeviceCap, number of special devices to be redirected before logon */
Stream_Write_UINT32(s, 0); /* osType, ignored on receipt */
Stream_Write_UINT32(s, 0); /* osVersion, unused and must be set to zero */
Stream_Write_UINT16(s, 1); /* protocolMajorVersion, must be set to 1 */
Stream_Write_UINT16(s, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinorVersion */
Stream_Write_UINT32(s, 0x0000FFFF); /* ioCode1 */
Stream_Write_UINT32(s, 0); /* ioCode2, must be set to zero, reserved for future use */
Stream_Write_UINT32(s, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */
Stream_Write_UINT32(s, ENABLE_ASYNCIO); /* extraFlags1 */
Stream_Write_UINT32(s, 0); /* extraFlags2, must be set to zero, reserved for future use */
Stream_Write_UINT32(s, 0); /* SpecialTypeDeviceCap, number of special devices to be redirected before logon */
}
/* Process device direction general capability set */
static void rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* data_in)
static void rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* s)
{
UINT16 capabilityLength;
Stream_Read_UINT16(data_in, capabilityLength);
Stream_Seek(data_in, capabilityLength - 4);
Stream_Read_UINT16(s, capabilityLength);
Stream_Seek(s, capabilityLength - 4);
}
/* Output printer direction capability set */
static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, wStream* data_out)
static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, wStream* s)
{
rdpdr_write_capset_header(data_out, CAP_PRINTER_TYPE, 8, PRINT_CAPABILITY_VERSION_01);
rdpdr_write_capset_header(s, CAP_PRINTER_TYPE, 8, PRINT_CAPABILITY_VERSION_01);
}
/* Process printer direction capability set */
static void rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* data_in)
static void rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* s)
{
UINT16 capabilityLength;
Stream_Read_UINT16(data_in, capabilityLength);
Stream_Seek(data_in, capabilityLength - 4);
Stream_Read_UINT16(s, capabilityLength);
Stream_Seek(s, capabilityLength - 4);
}
/* Output port redirection capability set */
static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, wStream* data_out)
static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, wStream* s)
{
rdpdr_write_capset_header(data_out, CAP_PORT_TYPE, 8, PORT_CAPABILITY_VERSION_01);
rdpdr_write_capset_header(s, CAP_PORT_TYPE, 8, PORT_CAPABILITY_VERSION_01);
}
/* Process port redirection capability set */
static void rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* data_in)
static void rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* s)
{
UINT16 capabilityLength;
Stream_Read_UINT16(data_in, capabilityLength);
Stream_Seek(data_in, capabilityLength - 4);
Stream_Read_UINT16(s, capabilityLength);
Stream_Seek(s, capabilityLength - 4);
}
/* Output drive redirection capability set */
static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, wStream* data_out)
static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, wStream* s)
{
rdpdr_write_capset_header(data_out, CAP_DRIVE_TYPE, 8, DRIVE_CAPABILITY_VERSION_02);
rdpdr_write_capset_header(s, CAP_DRIVE_TYPE, 8, DRIVE_CAPABILITY_VERSION_02);
}
/* Process drive redirection capability set */
static void rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* data_in)
static void rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* s)
{
UINT16 capabilityLength;
Stream_Read_UINT16(data_in, capabilityLength);
Stream_Seek(data_in, capabilityLength - 4);
Stream_Read_UINT16(s, capabilityLength);
Stream_Seek(s, capabilityLength - 4);
}
/* Output smart card redirection capability set */
static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, wStream* data_out)
static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s)
{
rdpdr_write_capset_header(data_out, CAP_SMARTCARD_TYPE, 8, SMARTCARD_CAPABILITY_VERSION_01);
rdpdr_write_capset_header(s, CAP_SMARTCARD_TYPE, 8, SMARTCARD_CAPABILITY_VERSION_01);
}
/* Process smartcard redirection capability set */
static void rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* data_in)
static void rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s)
{
UINT16 capabilityLength;
Stream_Read_UINT16(data_in, capabilityLength);
Stream_Seek(data_in, capabilityLength - 4);
Stream_Read_UINT16(s, capabilityLength);
Stream_Seek(s, capabilityLength - 4);
}
void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* data_in)
void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s)
{
UINT16 i;
UINT16 numCapabilities;
UINT16 capabilityType;
Stream_Read_UINT16(data_in, numCapabilities);
Stream_Seek(data_in, 2); /* pad (2 bytes) */
Stream_Read_UINT16(s, numCapabilities);
Stream_Seek(s, 2); /* pad (2 bytes) */
for(i = 0; i < numCapabilities; i++)
for (i = 0; i < numCapabilities; i++)
{
Stream_Read_UINT16(data_in, capabilityType);
Stream_Read_UINT16(s, capabilityType);
switch (capabilityType)
{
case CAP_GENERAL_TYPE:
rdpdr_process_general_capset(rdpdr, data_in);
rdpdr_process_general_capset(rdpdr, s);
break;
case CAP_PRINTER_TYPE:
rdpdr_process_printer_capset(rdpdr, data_in);
rdpdr_process_printer_capset(rdpdr, s);
break;
case CAP_PORT_TYPE:
rdpdr_process_port_capset(rdpdr, data_in);
rdpdr_process_port_capset(rdpdr, s);
break;
case CAP_DRIVE_TYPE:
rdpdr_process_drive_capset(rdpdr, data_in);
rdpdr_process_drive_capset(rdpdr, s);
break;
case CAP_SMARTCARD_TYPE:
rdpdr_process_smartcard_capset(rdpdr, data_in);
rdpdr_process_smartcard_capset(rdpdr, s);
break;
default:
@ -170,21 +170,21 @@ void rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* data_in)
void rdpdr_send_capability_response(rdpdrPlugin* rdpdr)
{
wStream* data_out;
wStream* s;
data_out = Stream_New(NULL, 256);
s = Stream_New(NULL, 256);
Stream_Write_UINT16(data_out, RDPDR_CTYP_CORE);
Stream_Write_UINT16(data_out, PAKID_CORE_CLIENT_CAPABILITY);
Stream_Write_UINT16(s, RDPDR_CTYP_CORE);
Stream_Write_UINT16(s, PAKID_CORE_CLIENT_CAPABILITY);
Stream_Write_UINT16(data_out, 5); /* numCapabilities */
Stream_Write_UINT16(data_out, 0); /* pad */
Stream_Write_UINT16(s, 5); /* numCapabilities */
Stream_Write_UINT16(s, 0); /* pad */
rdpdr_write_general_capset(rdpdr, data_out);
rdpdr_write_printer_capset(rdpdr, data_out);
rdpdr_write_port_capset(rdpdr, data_out);
rdpdr_write_drive_capset(rdpdr, data_out);
rdpdr_write_smartcard_capset(rdpdr, data_out);
rdpdr_write_general_capset(rdpdr, s);
rdpdr_write_printer_capset(rdpdr, s);
rdpdr_write_port_capset(rdpdr, s);
rdpdr_write_drive_capset(rdpdr, s);
rdpdr_write_smartcard_capset(rdpdr, s);
svc_plugin_send((rdpSvcPlugin*)rdpdr, data_out);
svc_plugin_send((rdpSvcPlugin*)rdpdr, s);
}

View File

@ -0,0 +1,35 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
define_channel_server("rdpdr")
set(${MODULE_PREFIX}_SRCS
rdpdr_main.c
rdpdr_main.h)
add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")
set_target_properties(${MODULE_NAME} PROPERTIES PREFIX "")
set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS
MONOLITHIC ${MONOLITHIC_BUILD}
MODULE freerdp
MODULES freerdp-utils)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")

View File

@ -0,0 +1,699 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Device Redirection Virtual Channel Extension
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/stream.h>
#include "rdpdr_main.h"
static UINT32 g_ClientId = 0;
static int rdpdr_server_send_announce_request(RdpdrServerContext* context)
{
wStream* s;
BOOL status;
RDPDR_HEADER header;
printf("RdpdrServerSendAnnounceRequest\n");
header.Component = RDPDR_CTYP_CORE;
header.PacketId = PAKID_CORE_SERVER_ANNOUNCE;
s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8);
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
Stream_Write_UINT16(s, context->priv->VersionMajor); /* VersionMajor (2 bytes) */
Stream_Write_UINT16(s, context->priv->VersionMinor); /* VersionMinor (2 bytes) */
Stream_Write_UINT32(s, context->priv->ClientId); /* ClientId (4 bytes) */
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
Stream_Free(s, TRUE);
return 0;
}
static int rdpdr_server_receive_announce_response(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header)
{
UINT32 ClientId;
UINT16 VersionMajor;
UINT16 VersionMinor;
Stream_Read_UINT16(s, VersionMajor); /* VersionMajor (2 bytes) */
Stream_Read_UINT16(s, VersionMinor); /* VersionMinor (2 bytes) */
Stream_Read_UINT32(s, ClientId); /* ClientId (4 bytes) */
printf("Client Announce Response: VersionMajor: 0x%04X VersionMinor: 0x%04X ClientId: 0x%04X\n",
VersionMajor, VersionMinor, ClientId);
context->priv->ClientId = ClientId;
return 0;
}
static int rdpdr_server_receive_client_name_request(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header)
{
UINT32 UnicodeFlag;
UINT32 ComputerNameLen;
Stream_Read_UINT32(s, UnicodeFlag); /* UnicodeFlag (4 bytes) */
Stream_Seek_UINT32(s); /* CodePage (4 bytes), MUST be set to zero */
Stream_Read_UINT32(s, ComputerNameLen); /* ComputerNameLen (4 bytes) */
/**
* Caution: ComputerNameLen is given *bytes*,
* not in characters, including the NULL terminator!
*/
if (context->priv->ClientComputerName)
{
free(context->priv->ClientComputerName);
context->priv->ClientComputerName = NULL;
}
if (UnicodeFlag)
{
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s),
-1, &(context->priv->ClientComputerName), 0, NULL, NULL);
}
else
{
context->priv->ClientComputerName = _strdup((char*) Stream_Pointer(s));
}
Stream_Seek(s, ComputerNameLen);
printf("ClientComputerName: %s\n", context->priv->ClientComputerName);
return 0;
}
static int rdpdr_server_read_capability_set_header(wStream* s, RDPDR_CAPABILITY_HEADER* header)
{
Stream_Read_UINT16(s, header->CapabilityType); /* CapabilityType (2 bytes) */
Stream_Read_UINT16(s, header->CapabilityLength); /* CapabilityLength (2 bytes) */
Stream_Read_UINT32(s, header->Version); /* Version (4 bytes) */
return 0;
}
static int rdpdr_server_write_capability_set_header(wStream* s, RDPDR_CAPABILITY_HEADER* header)
{
Stream_Write_UINT16(s, header->CapabilityType); /* CapabilityType (2 bytes) */
Stream_Write_UINT16(s, header->CapabilityLength); /* CapabilityLength (2 bytes) */
Stream_Write_UINT32(s, header->Version); /* Version (4 bytes) */
return 0;
}
static int rdpdr_server_read_general_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header)
{
UINT32 ioCode1;
UINT32 extraFlags1;
UINT32 extendedPdu;
UINT16 VersionMajor;
UINT16 VersionMinor;
UINT32 SpecialTypeDeviceCap;
Stream_Seek_UINT32(s); /* osType (4 bytes), ignored on receipt */
Stream_Seek_UINT32(s); /* osVersion (4 bytes), unused and must be set to zero */
Stream_Read_UINT16(s, VersionMajor); /* protocolMajorVersion (2 bytes) */
Stream_Read_UINT16(s, VersionMinor); /* protocolMinorVersion (2 bytes) */
Stream_Read_UINT32(s, ioCode1); /* ioCode1 (4 bytes) */
Stream_Seek_UINT32(s); /* ioCode2 (4 bytes), must be set to zero, reserved for future use */
Stream_Read_UINT32(s, extendedPdu); /* extendedPdu (4 bytes) */
Stream_Read_UINT32(s, extraFlags1); /* extraFlags1 (4 bytes) */
Stream_Seek_UINT32(s); /* extraFlags2 (4 bytes), must be set to zero, reserved for future use */
Stream_Read_UINT32(s, SpecialTypeDeviceCap); /* SpecialTypeDeviceCap (4 bytes) */
context->priv->UserLoggedOnPdu = (extendedPdu & RDPDR_USER_LOGGEDON_PDU) ? TRUE : FALSE;
return 0;
}
static int rdpdr_server_write_general_capability_set(RdpdrServerContext* context, wStream* s)
{
UINT32 ioCode1;
UINT32 extendedPdu;
UINT32 extraFlags1;
UINT32 SpecialTypeDeviceCap;
RDPDR_CAPABILITY_HEADER header;
header.CapabilityType = CAP_GENERAL_TYPE;
header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH + 36;
header.Version = GENERAL_CAPABILITY_VERSION_02;
ioCode1 = 0;
ioCode1 |= RDPDR_IRP_MJ_CREATE; /* always set */
ioCode1 |= RDPDR_IRP_MJ_CLEANUP; /* always set */
ioCode1 |= RDPDR_IRP_MJ_CLOSE; /* always set */
ioCode1 |= RDPDR_IRP_MJ_READ; /* always set */
ioCode1 |= RDPDR_IRP_MJ_WRITE; /* always set */
ioCode1 |= RDPDR_IRP_MJ_FLUSH_BUFFERS; /* always set */
ioCode1 |= RDPDR_IRP_MJ_SHUTDOWN; /* always set */
ioCode1 |= RDPDR_IRP_MJ_DEVICE_CONTROL; /* always set */
ioCode1 |= RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION; /* always set */
ioCode1 |= RDPDR_IRP_MJ_SET_VOLUME_INFORMATION; /* always set */
ioCode1 |= RDPDR_IRP_MJ_QUERY_INFORMATION; /* always set */
ioCode1 |= RDPDR_IRP_MJ_SET_INFORMATION; /* always set */
ioCode1 |= RDPDR_IRP_MJ_DIRECTORY_CONTROL; /* always set */
ioCode1 |= RDPDR_IRP_MJ_LOCK_CONTROL; /* always set */
ioCode1 |= RDPDR_IRP_MJ_QUERY_SECURITY; /* optional */
ioCode1 |= RDPDR_IRP_MJ_SET_SECURITY; /* optional */
extendedPdu = 0;
extendedPdu |= RDPDR_CLIENT_DISPLAY_NAME_PDU; /* always set */
extendedPdu |= RDPDR_DEVICE_REMOVE_PDUS; /* optional */
if (context->priv->UserLoggedOnPdu)
extendedPdu |= RDPDR_USER_LOGGEDON_PDU; /* optional */
extraFlags1 = 0;
extraFlags1 |= ENABLE_ASYNCIO; /* optional */
SpecialTypeDeviceCap = 0;
Stream_EnsureRemainingCapacity(s, header.CapabilityLength);
rdpdr_server_write_capability_set_header(s, &header);
Stream_Write_UINT32(s, 0); /* osType (4 bytes), ignored on receipt */
Stream_Write_UINT32(s, 0); /* osVersion (4 bytes), unused and must be set to zero */
Stream_Write_UINT16(s, context->priv->VersionMajor); /* protocolMajorVersion (2 bytes) */
Stream_Write_UINT16(s, context->priv->VersionMinor); /* protocolMinorVersion (2 bytes) */
Stream_Write_UINT32(s, ioCode1); /* ioCode1 (4 bytes) */
Stream_Write_UINT32(s, 0); /* ioCode2 (4 bytes), must be set to zero, reserved for future use */
Stream_Write_UINT32(s, extendedPdu); /* extendedPdu (4 bytes) */
Stream_Write_UINT32(s, extraFlags1); /* extraFlags1 (4 bytes) */
Stream_Write_UINT32(s, 0); /* extraFlags2 (4 bytes), must be set to zero, reserved for future use */
Stream_Write_UINT32(s, SpecialTypeDeviceCap); /* SpecialTypeDeviceCap (4 bytes) */
return 0;
}
static int rdpdr_server_read_printer_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header)
{
return 0;
}
static int rdpdr_server_write_printer_capability_set(RdpdrServerContext* context, wStream* s)
{
RDPDR_CAPABILITY_HEADER header;
header.CapabilityType = CAP_PRINTER_TYPE;
header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH;
header.Version = PRINT_CAPABILITY_VERSION_01;
Stream_EnsureRemainingCapacity(s, header.CapabilityLength);
rdpdr_server_write_capability_set_header(s, &header);
return 0;
}
static int rdpdr_server_read_port_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header)
{
return 0;
}
static int rdpdr_server_write_port_capability_set(RdpdrServerContext* context, wStream* s)
{
RDPDR_CAPABILITY_HEADER header;
header.CapabilityType = CAP_PORT_TYPE;
header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH;
header.Version = PORT_CAPABILITY_VERSION_01;
Stream_EnsureRemainingCapacity(s, header.CapabilityLength);
rdpdr_server_write_capability_set_header(s, &header);
return 0;
}
static int rdpdr_server_read_drive_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header)
{
return 0;
}
static int rdpdr_server_write_drive_capability_set(RdpdrServerContext* context, wStream* s)
{
RDPDR_CAPABILITY_HEADER header;
header.CapabilityType = CAP_DRIVE_TYPE;
header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH;
header.Version = DRIVE_CAPABILITY_VERSION_02;
Stream_EnsureRemainingCapacity(s, header.CapabilityLength);
rdpdr_server_write_capability_set_header(s, &header);
return 0;
}
static int rdpdr_server_read_smartcard_capability_set(RdpdrServerContext* context, wStream* s, RDPDR_CAPABILITY_HEADER* header)
{
return 0;
}
static int rdpdr_server_write_smartcard_capability_set(RdpdrServerContext* context, wStream* s)
{
RDPDR_CAPABILITY_HEADER header;
header.CapabilityType = CAP_SMARTCARD_TYPE;
header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH;
header.Version = SMARTCARD_CAPABILITY_VERSION_01;
Stream_EnsureRemainingCapacity(s, header.CapabilityLength);
rdpdr_server_write_capability_set_header(s, &header);
return 0;
}
static int rdpdr_server_send_core_capability_request(RdpdrServerContext* context)
{
wStream* s;
BOOL status;
RDPDR_HEADER header;
UINT16 numCapabilities;
printf("RdpdrServerSendCoreCapabilityRequest\n");
header.Component = RDPDR_CTYP_CORE;
header.PacketId = PAKID_CORE_SERVER_CAPABILITY;
numCapabilities = 5;
s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 512);
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
Stream_Write_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */
Stream_Write_UINT16(s, 0); /* Padding (2 bytes) */
rdpdr_server_write_general_capability_set(context, s);
rdpdr_server_write_printer_capability_set(context, s);
rdpdr_server_write_port_capability_set(context, s);
rdpdr_server_write_drive_capability_set(context, s);
rdpdr_server_write_smartcard_capability_set(context, s);
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
Stream_Free(s, TRUE);
return 0;
}
static int rdpdr_server_receive_core_capability_response(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header)
{
int i;
UINT16 numCapabilities;
RDPDR_CAPABILITY_HEADER capabilityHeader;
Stream_Read_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */
Stream_Seek_UINT16(s); /* Padding (2 bytes) */
for (i = 0; i < numCapabilities; i++)
{
rdpdr_server_read_capability_set_header(s, &capabilityHeader);
switch (capabilityHeader.CapabilityType)
{
case CAP_GENERAL_TYPE:
rdpdr_server_read_general_capability_set(context, s, &capabilityHeader);
break;
case CAP_PRINTER_TYPE:
rdpdr_server_read_printer_capability_set(context, s, &capabilityHeader);
break;
case CAP_PORT_TYPE:
rdpdr_server_read_port_capability_set(context, s, &capabilityHeader);
break;
case CAP_DRIVE_TYPE:
rdpdr_server_read_drive_capability_set(context, s, &capabilityHeader);
break;
case CAP_SMARTCARD_TYPE:
rdpdr_server_read_smartcard_capability_set(context, s, &capabilityHeader);
break;
default:
printf("Unknown capabilityType %d\n", capabilityHeader.CapabilityType);
Stream_Seek(s, capabilityHeader.CapabilityLength - RDPDR_CAPABILITY_HEADER_LENGTH);
break;
}
}
return 0;
}
static int rdpdr_server_send_client_id_confirm(RdpdrServerContext* context)
{
wStream* s;
BOOL status;
RDPDR_HEADER header;
printf("RdpdrServerSendClientIdConfirm\n");
header.Component = RDPDR_CTYP_CORE;
header.PacketId = PAKID_CORE_CLIENTID_CONFIRM;
s = Stream_New(NULL, RDPDR_HEADER_LENGTH + 8);
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
Stream_Write_UINT16(s, context->priv->VersionMajor); /* VersionMajor (2 bytes) */
Stream_Write_UINT16(s, context->priv->VersionMinor); /* VersionMinor (2 bytes) */
Stream_Write_UINT32(s, context->priv->ClientId); /* ClientId (4 bytes) */
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
Stream_Free(s, TRUE);
return 0;
}
static int rdpdr_server_receive_device_list_announce_request(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header)
{
int i;
UINT32 DeviceCount;
UINT32 DeviceType;
UINT32 DeviceId;
char PreferredDosName[9];
UINT32 DeviceDataLength;
PreferredDosName[8] = 0;
Stream_Read_UINT32(s, DeviceCount); /* DeviceCount (4 bytes) */
printf("%s: DeviceCount: %d\n", __FUNCTION__, DeviceCount);
for (i = 0; i < DeviceCount; i++)
{
Stream_Read_UINT32(s, DeviceType); /* DeviceType (4 bytes) */
Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */
Stream_Read(s, PreferredDosName, 8); /* PreferredDosName (8 bytes) */
Stream_Read_UINT32(s, DeviceDataLength); /* DeviceDataLength (4 bytes) */
printf("Device %d Name: %s Id: 0x%04X DataLength: %d\n",
i, PreferredDosName, DeviceId, DeviceDataLength);
switch (DeviceId)
{
case RDPDR_DTYP_FILESYSTEM:
break;
case RDPDR_DTYP_PRINT:
break;
case RDPDR_DTYP_SERIAL:
break;
case RDPDR_DTYP_PARALLEL:
break;
case RDPDR_DTYP_SMARTCARD:
break;
default:
break;
}
Stream_Seek(s, DeviceDataLength);
}
return 0;
}
static int rdpdr_server_send_user_logged_on(RdpdrServerContext* context)
{
wStream* s;
BOOL status;
RDPDR_HEADER header;
printf("%s\n", __FUNCTION__);
header.Component = RDPDR_CTYP_CORE;
header.PacketId = PAKID_CORE_USER_LOGGEDON;
s = Stream_New(NULL, RDPDR_HEADER_LENGTH);
Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */
Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
Stream_SealLength(s);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_Length(s), NULL);
Stream_Free(s, TRUE);
return 0;
}
static int rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header)
{
printf("RdpdrServerReceivePdu: Component: 0x%04X PacketId: 0x%04X\n",
header->Component, header->PacketId);
winpr_HexDump(Stream_Buffer(s), Stream_Length(s));
if (header->Component == RDPDR_CTYP_CORE)
{
switch (header->PacketId)
{
case PAKID_CORE_CLIENTID_CONFIRM:
rdpdr_server_receive_announce_response(context, s, header);
break;
case PAKID_CORE_CLIENT_NAME:
rdpdr_server_receive_client_name_request(context, s, header);
rdpdr_server_send_core_capability_request(context);
break;
case PAKID_CORE_CLIENT_CAPABILITY:
rdpdr_server_receive_core_capability_response(context, s, header);
rdpdr_server_send_client_id_confirm(context);
if (context->priv->UserLoggedOnPdu)
rdpdr_server_send_user_logged_on(context);
break;
case PAKID_CORE_DEVICELIST_ANNOUNCE:
rdpdr_server_receive_device_list_announce_request(context, s, header);
break;
case PAKID_CORE_DEVICE_REPLY:
break;
case PAKID_CORE_DEVICE_IOREQUEST:
break;
case PAKID_CORE_DEVICE_IOCOMPLETION:
break;
case PAKID_CORE_DEVICELIST_REMOVE:
break;
default:
break;
}
}
else if (header->Component == RDPDR_CTYP_PRN)
{
switch (header->PacketId)
{
case PAKID_PRN_CACHE_DATA:
break;
case PAKID_PRN_USING_XPS:
break;
default:
break;
}
}
else
{
printf("Unknown RDPDR_HEADER.Component: 0x%04X\n", header->Component);
return -1;
}
return 0;
}
static void* rdpdr_server_thread(void* arg)
{
wStream* s;
DWORD status;
DWORD nCount;
void* buffer;
int position;
HANDLE events[8];
RDPDR_HEADER header;
HANDLE ChannelEvent;
DWORD BytesReturned;
RdpdrServerContext* context;
context = (RdpdrServerContext*) arg;
buffer = NULL;
BytesReturned = 0;
ChannelEvent = NULL;
s = Stream_New(NULL, 4096);
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
{
if (BytesReturned == sizeof(HANDLE))
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
WTSFreeMemory(buffer);
}
nCount = 0;
events[nCount++] = ChannelEvent;
events[nCount++] = context->priv->StopEvent;
rdpdr_server_send_announce_request(context);
while (1)
{
BytesReturned = 0;
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
{
break;
}
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR) Stream_Pointer(s),
Stream_Capacity(s) - Stream_GetPosition(s), &BytesReturned))
{
if (BytesReturned)
Stream_Seek(s, BytesReturned);
}
else
{
Stream_EnsureRemainingCapacity(s, BytesReturned);
}
if (Stream_GetPosition(s) >= RDPDR_HEADER_LENGTH)
{
position = Stream_GetPosition(s);
Stream_SetPosition(s, 0);
Stream_Read_UINT16(s, header.Component); /* Component (2 bytes) */
Stream_Read_UINT16(s, header.PacketId); /* PacketId (2 bytes) */
Stream_SetPosition(s, position);
Stream_SealLength(s);
Stream_SetPosition(s, RDPDR_HEADER_LENGTH);
rdpdr_server_receive_pdu(context, s, &header);
Stream_SetPosition(s, 0);
}
}
Stream_Free(s, TRUE);
return NULL;
}
static int rdpdr_server_start(RdpdrServerContext* context)
{
context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpdr", 0);
if (!context->priv->ChannelHandle)
return -1;
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpdr_server_thread, (void*) context, 0, NULL);
return 0;
}
static int rdpdr_server_stop(RdpdrServerContext* context)
{
SetEvent(context->priv->StopEvent);
WaitForSingleObject(context->priv->Thread, INFINITE);
CloseHandle(context->priv->Thread);
return 0;
}
RdpdrServerContext* rdpdr_server_context_new(WTSVirtualChannelManager* vcm)
{
RdpdrServerContext* context;
context = (RdpdrServerContext*) malloc(sizeof(RdpdrServerContext));
if (context)
{
ZeroMemory(context, sizeof(RdpdrServerContext));
context->vcm = vcm;
context->Start = rdpdr_server_start;
context->Stop = rdpdr_server_stop;
context->priv = (RdpdrServerPrivate*) malloc(sizeof(RdpdrServerPrivate));
if (context->priv)
{
ZeroMemory(context->priv, sizeof(RdpdrServerPrivate));
context->priv->VersionMajor = RDPDR_VERSION_MAJOR;
context->priv->VersionMinor = RDPDR_VERSION_MINOR_RDP6X;
context->priv->ClientId = g_ClientId++;
context->priv->UserLoggedOnPdu = TRUE;
}
}
return context;
}
void rdpdr_server_context_free(RdpdrServerContext* context)
{
if (context)
{
if (context->priv)
{
free(context->priv);
}
free(context);
}
}

View File

@ -0,0 +1,70 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Device Redirection Virtual Channel Extension
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CHANNEL_SERVER_RDPDR_MAIN_H
#define FREERDP_CHANNEL_SERVER_RDPDR_MAIN_H
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <freerdp/settings.h>
#include <freerdp/server/rdpdr.h>
struct _rdpdr_server_private
{
HANDLE Thread;
HANDLE StopEvent;
void* ChannelHandle;
UINT32 ClientId;
UINT16 VersionMajor;
UINT16 VersionMinor;
char* ClientComputerName;
BOOL UserLoggedOnPdu;
};
#define RDPDR_HEADER_LENGTH 4
struct _RDPDR_HEADER
{
UINT16 Component;
UINT16 PacketId;
};
typedef struct _RDPDR_HEADER RDPDR_HEADER;
#define RDPDR_VERSION_MAJOR 0x0001
#define RDPDR_VERSION_MINOR_RDP50 0x0002
#define RDPDR_VERSION_MINOR_RDP51 0x0005
#define RDPDR_VERSION_MINOR_RDP52 0x000A
#define RDPDR_VERSION_MINOR_RDP6X 0x000C
#define RDPDR_CAPABILITY_HEADER_LENGTH 8
struct _RDPDR_CAPABILITY_HEADER
{
UINT16 CapabilityType;
UINT16 CapabilityLength;
UINT32 Version;
};
typedef struct _RDPDR_CAPABILITY_HEADER RDPDR_CAPABILITY_HEADER;
#endif /* FREERDP_CHANNEL_SERVER_RDPDR_MAIN_H */

View File

@ -21,6 +21,7 @@
#include "config.h"
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -97,6 +98,7 @@ struct _RDPEI_PLUGIN
RDPINPUT_CONTACT_POINT* contactPoints;
HANDLE event;
HANDLE stopEvent;
HANDLE thread;
CRITICAL_SECTION lock;
@ -156,10 +158,16 @@ static void* rdpei_schedule_thread(void* arg)
DWORD status;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) arg;
RdpeiClientContext* context = (RdpeiClientContext*) rdpei->iface.pInterface;
HANDLE hdl[] = {rdpei->event, rdpei->stopEvent};
assert(NULL != rdpei);
assert(NULL != context);
while (1)
{
status = WaitForSingleObject(rdpei->event, 20);
status = WaitForMultipleObjects(2, hdl, FALSE, 20);
if (status == WAIT_OBJECT_0 + 1)
break;
EnterCriticalSection(&rdpei->lock);
@ -174,6 +182,8 @@ static void* rdpei_schedule_thread(void* arg)
LeaveCriticalSection(&rdpei->lock);
}
ExitThread(0);
return NULL;
}
@ -218,13 +228,6 @@ int rdpei_send_cs_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback)
Stream_SealLength(s);
if (!rdpei->thread)
{
InitializeCriticalSection(&rdpei->lock);
rdpei->event = CreateEvent(NULL, TRUE, FALSE, NULL);
rdpei->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) rdpei_schedule_thread, (void*) rdpei, 0, NULL);
}
status = rdpei_send_pdu(callback, s, EVENTID_CS_READY, pduLength);
Stream_Free(s, TRUE);
@ -487,6 +490,12 @@ static int rdpei_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage
(IWTSListenerCallback*) rdpei->listener_callback, &(rdpei->listener));
rdpei->listener->pInterface = rdpei->iface.pInterface;
InitializeCriticalSection(&rdpei->lock);
rdpei->event = CreateEvent(NULL, TRUE, FALSE, NULL);
rdpei->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
rdpei->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
rdpei_schedule_thread, (void*) rdpei, 0, NULL);
return status;
}
@ -497,6 +506,22 @@ static int rdpei_plugin_terminated(IWTSPlugin* pPlugin)
DEBUG_DVC("");
assert(NULL != pPlugin);
SetEvent(rdpei->stopEvent);
EnterCriticalSection(&rdpei->lock);
WaitForSingleObject(rdpei->thread, INFINITE);
CloseHandle(rdpei->stopEvent);
CloseHandle(rdpei->event);
CloseHandle(rdpei->thread);
DeleteCriticalSection(&rdpei->lock);
if (rdpei->listener_callback)
free(rdpei->listener_callback);
free(rdpei);
return 0;

View File

@ -72,7 +72,7 @@ struct rdpsnd_alsa_plugin
return -1; \
}
int rdpsnd_alsa_set_hw_params(rdpsndAlsaPlugin* alsa)
static int rdpsnd_alsa_set_hw_params(rdpsndAlsaPlugin* alsa)
{
int status;
snd_pcm_hw_params_t* hw_params;
@ -131,7 +131,7 @@ int rdpsnd_alsa_set_hw_params(rdpsndAlsaPlugin* alsa)
return 0;
}
int rdpsnd_alsa_set_sw_params(rdpsndAlsaPlugin* alsa)
static int rdpsnd_alsa_set_sw_params(rdpsndAlsaPlugin* alsa)
{
int status;
snd_pcm_sw_params_t* sw_params;
@ -158,7 +158,7 @@ int rdpsnd_alsa_set_sw_params(rdpsndAlsaPlugin* alsa)
return 0;
}
int rdpsnd_alsa_validate_params(rdpsndAlsaPlugin* alsa)
static int rdpsnd_alsa_validate_params(rdpsndAlsaPlugin* alsa)
{
int status;
snd_pcm_uframes_t buffer_size;
@ -413,8 +413,6 @@ static UINT32 rdpsnd_alsa_get_volume(rdpsndDevicePlugin* device)
long volume_max;
long volume_left;
long volume_right;
int percent_left;
int percent_right;
UINT32 dwVolume;
UINT16 dwVolumeLeft;
UINT16 dwVolumeRight;
@ -438,9 +436,6 @@ static UINT32 rdpsnd_alsa_get_volume(rdpsndDevicePlugin* device)
dwVolumeLeft = (UINT16) (((volume_left * 0xFFFF) - volume_min) / (volume_max - volume_min));
dwVolumeRight = (UINT16) (((volume_right * 0xFFFF) - volume_min) / (volume_max - volume_min));
percent_left = (dwVolumeLeft * 100) / 0xFFFF;
percent_right = (dwVolumeRight * 100) / 0xFFFF;
break;
}
}
@ -458,8 +453,6 @@ static void rdpsnd_alsa_set_volume(rdpsndDevicePlugin* device, UINT32 value)
long volume_max;
long volume_left;
long volume_right;
int percent_left;
int percent_right;
snd_mixer_elem_t* elem;
rdpsndAlsaPlugin* alsa = (rdpsndAlsaPlugin*) device;
@ -469,9 +462,6 @@ static void rdpsnd_alsa_set_volume(rdpsndDevicePlugin* device, UINT32 value)
left = (value & 0xFFFF);
right = ((value >> 16) & 0xFFFF);
percent_left = (left * 100) / 0xFFFF;
percent_right = (right * 100) / 0xFFFF;
for (elem = snd_mixer_first_elem(alsa->mixer_handle); elem; elem = snd_mixer_elem_next(elem))
{
if (snd_mixer_selem_has_playback_volume(elem))
@ -485,7 +475,7 @@ static void rdpsnd_alsa_set_volume(rdpsndDevicePlugin* device, UINT32 value)
}
}
BYTE* rdpsnd_alsa_process_audio_sample(rdpsndDevicePlugin* device, BYTE* data, int* size)
static BYTE* rdpsnd_alsa_process_audio_sample(rdpsndDevicePlugin* device, BYTE* data, int* size)
{
int frames;
BYTE* srcData;
@ -618,17 +608,15 @@ static void rdpsnd_alsa_wave_play(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
wave->wTimeStampB = wave->wTimeStampA + wave->wLatency;
//fprintf(stderr, "wTimeStampA: %d wTimeStampB: %d wLatency: %d\n", wave->wTimeStampA, wave->wTimeStampB, wave->wLatency);
device->WaveConfirm(device, wave);
}
COMMAND_LINE_ARGUMENT_A rdpsnd_alsa_args[] =
static COMMAND_LINE_ARGUMENT_A rdpsnd_alsa_args[] =
{
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "device" },
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
};
static void rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* args)
static int rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* args)
{
int status;
DWORD flags;
@ -638,6 +626,8 @@ static void rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV*
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv, rdpsnd_alsa_args, flags, alsa, NULL, NULL);
if (status < 0)
return status;
arg = rdpsnd_alsa_args;
@ -656,6 +646,8 @@ static void rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV*
CommandLineSwitchEnd(arg)
}
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
return status;
}
#ifdef STATIC_CHANNELS

View File

@ -548,9 +548,10 @@ static void rdpsnd_pulse_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
rdpsnd_pulse_args, flags, pulse, NULL, NULL);
if (status < 0)
return;
arg = rdpsnd_pulse_args;
do
{
if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT))

View File

@ -146,8 +146,10 @@ void rdpsnd_select_supported_audio_formats(rdpsndPlugin* rdpsnd)
rdpsnd->NumberOfClientFormats = 0;
rdpsnd->ClientFormats = NULL;
rdpsnd->ClientFormats = (AUDIO_FORMAT*) malloc(sizeof(AUDIO_FORMAT) * rdpsnd->NumberOfServerFormats);
if (!rdpsnd->NumberOfServerFormats)
return;
rdpsnd->ClientFormats = (AUDIO_FORMAT*) malloc(sizeof(AUDIO_FORMAT) * rdpsnd->NumberOfServerFormats);
for (index = 0; index < (int) rdpsnd->NumberOfServerFormats; index++)
{
serverFormat = &rdpsnd->ServerFormats[index];
@ -417,7 +419,10 @@ static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s)
wave->wAudioLength = rdpsnd_compute_audio_time_length(format, size);
if (!rdpsnd->device)
{
free(wave);
return;
}
if (rdpsnd->device->WaveDecode)
{
@ -437,8 +442,8 @@ static void rdpsnd_recv_wave_pdu(rdpsndPlugin* rdpsnd, wStream* s)
{
wave->wTimeStampB = rdpsnd->wTimeStamp + wave->wAudioLength + TIME_DELAY_MS;
wave->wLocalTimeB = wave->wLocalTimeA + wave->wAudioLength + TIME_DELAY_MS;
rdpsnd->device->WaveConfirm(rdpsnd->device, wave);
}
rdpsnd->device->WaveConfirm(rdpsnd->device, wave);
}
static void rdpsnd_recv_close_pdu(rdpsndPlugin* rdpsnd)
@ -589,6 +594,8 @@ static void rdpsnd_process_addin_args(rdpsndPlugin* rdpsnd, ADDIN_ARGV* args)
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
rdpsnd_args, flags, rdpsnd, NULL, NULL);
if (status < 0)
return;
arg = rdpsnd_args;

View File

@ -18,7 +18,8 @@
define_channel_server("rdpsnd")
set(${MODULE_PREFIX}_SRCS
rdpsnd.c)
rdpsnd_main.c
rdpsnd_main.h)
add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry")

View File

@ -541,6 +541,9 @@ void rdpsnd_server_context_free(rdpsnd_server_context* context)
SetEvent(rdpsnd->StopEvent);
WaitForSingleObject(rdpsnd->thread, INFINITE);
CloseHandle(rdpsnd->StopEvent);
CloseHandle(rdpsnd->thread);
if (rdpsnd->rdpsnd_channel)
WTSVirtualChannelClose(rdpsnd->rdpsnd_channel);

View File

@ -0,0 +1,572 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Server Audio Virtual Channel
*
* Copyright 2012 Vic Lee
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/print.h>
#include <winpr/stream.h>
#include "rdpsnd_main.h"
static BOOL rdpsnd_server_send_formats(RdpsndServerContext* context, wStream* s)
{
int pos;
UINT16 i;
BOOL status;
Stream_Write_UINT8(s, SNDC_FORMATS);
Stream_Write_UINT8(s, 0);
Stream_Seek_UINT16(s);
Stream_Write_UINT32(s, 0); /* dwFlags */
Stream_Write_UINT32(s, 0); /* dwVolume */
Stream_Write_UINT32(s, 0); /* dwPitch */
Stream_Write_UINT16(s, 0); /* wDGramPort */
Stream_Write_UINT16(s, context->num_server_formats); /* wNumberOfFormats */
Stream_Write_UINT8(s, context->block_no); /* cLastBlockConfirmed */
Stream_Write_UINT16(s, 0x06); /* wVersion */
Stream_Write_UINT8(s, 0); /* bPad */
for (i = 0; i < context->num_server_formats; i++)
{
Stream_Write_UINT16(s, context->server_formats[i].wFormatTag); /* wFormatTag (WAVE_FORMAT_PCM) */
Stream_Write_UINT16(s, context->server_formats[i].nChannels); /* nChannels */
Stream_Write_UINT32(s, context->server_formats[i].nSamplesPerSec); /* nSamplesPerSec */
Stream_Write_UINT32(s, context->server_formats[i].nSamplesPerSec *
context->server_formats[i].nChannels *
context->server_formats[i].wBitsPerSample / 8); /* nAvgBytesPerSec */
Stream_Write_UINT16(s, context->server_formats[i].nBlockAlign); /* nBlockAlign */
Stream_Write_UINT16(s, context->server_formats[i].wBitsPerSample); /* wBitsPerSample */
Stream_Write_UINT16(s, context->server_formats[i].cbSize); /* cbSize */
if (context->server_formats[i].cbSize > 0)
{
Stream_Write(s, context->server_formats[i].data, context->server_formats[i].cbSize);
}
}
pos = Stream_GetPosition(s);
Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_SetPosition(s, 0);
return status;
}
static void rdpsnd_server_recv_waveconfirm(RdpsndServerContext* context, wStream* s)
{
UINT16 timestamp = 0;
BYTE confirmBlockNum = 0;
Stream_Read_UINT16(s, timestamp);
Stream_Read_UINT8(s, confirmBlockNum);
Stream_Seek_UINT8(s);
}
static void rdpsnd_server_recv_quality_mode(RdpsndServerContext* context, wStream* s)
{
UINT16 quality;
Stream_Read_UINT16(s, quality);
Stream_Seek_UINT16(s); // reserved
fprintf(stderr, "Client requested sound quality: %#0X\n", quality);
}
static BOOL rdpsnd_server_recv_formats(RdpsndServerContext* context, wStream* s)
{
int i, num_known_format = 0;
UINT32 flags, vol, pitch;
UINT16 udpPort, version;
BYTE lastblock;
Stream_Read_UINT32(s, flags); /* dwFlags */
Stream_Read_UINT32(s, vol); /* dwVolume */
Stream_Read_UINT32(s, pitch); /* dwPitch */
Stream_Read_UINT16(s, udpPort); /* wDGramPort */
Stream_Read_UINT16(s, context->num_client_formats); /* wNumberOfFormats */
Stream_Read_UINT8(s, lastblock); /* cLastBlockConfirmed */
Stream_Read_UINT16(s, version); /* wVersion */
Stream_Seek_UINT8(s); /* bPad */
if (context->num_client_formats > 0)
{
context->client_formats = (AUDIO_FORMAT*) malloc(context->num_client_formats * sizeof(AUDIO_FORMAT));
ZeroMemory(context->client_formats, sizeof(AUDIO_FORMAT));
for (i = 0; i < context->num_client_formats; i++)
{
Stream_Read_UINT16(s, context->client_formats[i].wFormatTag);
Stream_Read_UINT16(s, context->client_formats[i].nChannels);
Stream_Read_UINT32(s, context->client_formats[i].nSamplesPerSec);
Stream_Read_UINT32(s, context->client_formats[i].nAvgBytesPerSec);
Stream_Read_UINT16(s, context->client_formats[i].nBlockAlign);
Stream_Read_UINT16(s, context->client_formats[i].wBitsPerSample);
Stream_Read_UINT16(s, context->client_formats[i].cbSize);
if (context->client_formats[i].cbSize > 0)
{
Stream_Seek(s, context->client_formats[i].cbSize);
}
if (context->client_formats[i].wFormatTag != 0)
{
//lets call this a known format
//TODO: actually look through our own list of known formats
num_known_format++;
}
}
}
if (num_known_format == 0)
{
fprintf(stderr, "Client doesn't support any known formats!\n");
return FALSE;
}
return TRUE;
}
static void* rdpsnd_server_thread(void* arg)
{
wStream* s;
DWORD status;
DWORD nCount;
void* buffer;
BYTE msgType;
UINT16 BodySize;
HANDLE events[8];
HANDLE ChannelEvent;
DWORD BytesReturned;
RdpsndServerContext* context;
context = (RdpsndServerContext*) arg;
buffer = NULL;
BytesReturned = 0;
ChannelEvent = NULL;
s = Stream_New(NULL, 4096);
if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, &BytesReturned) == TRUE)
{
if (BytesReturned == sizeof(HANDLE))
CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE));
WTSFreeMemory(buffer);
}
nCount = 0;
events[nCount++] = ChannelEvent;
events[nCount++] = context->priv->StopEvent;
s = Stream_New(NULL, 4096);
rdpsnd_server_send_formats(context, s);
while (1)
{
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
if (WaitForSingleObject(context->priv->StopEvent, 0) == WAIT_OBJECT_0)
{
break;
}
Stream_SetPosition(s, 0);
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
{
if (BytesReturned)
Stream_Seek(s, BytesReturned);
}
else
{
if (!BytesReturned)
break;
Stream_EnsureRemainingCapacity(s, BytesReturned);
if (WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE)
{
break;
}
}
Stream_Read_UINT8(s, msgType);
Stream_Seek_UINT8(s); /* bPad */
Stream_Read_UINT16(s, BodySize);
switch (msgType)
{
case SNDC_WAVECONFIRM:
rdpsnd_server_recv_waveconfirm(context, s);
break;
case SNDC_QUALITYMODE:
rdpsnd_server_recv_quality_mode(context, s);
break;
case SNDC_FORMATS:
if (rdpsnd_server_recv_formats(context, s))
{
IFCALL(context->Activated, context);
}
break;
default:
fprintf(stderr, "UNKOWN MESSAGE TYPE!! (%#0X)\n\n", msgType);
break;
}
}
Stream_Free(s, TRUE);
return NULL;
}
static BOOL rdpsnd_server_initialize(RdpsndServerContext* context)
{
context->Start(context);
return TRUE;
}
static void rdpsnd_server_select_format(RdpsndServerContext* context, int client_format_index)
{
int bs;
int out_buffer_size;
AUDIO_FORMAT *format;
if (client_format_index < 0 || client_format_index >= context->num_client_formats)
{
fprintf(stderr, "rdpsnd_server_select_format: index %d is not correct.\n", client_format_index);
return;
}
context->priv->src_bytes_per_sample = context->src_format.wBitsPerSample / 8;
context->priv->src_bytes_per_frame = context->priv->src_bytes_per_sample * context->src_format.nChannels;
context->selected_client_format = client_format_index;
format = &context->client_formats[client_format_index];
if (format->nSamplesPerSec == 0)
{
fprintf(stderr, "Invalid Client Sound Format!!\n\n");
return;
}
if (format->wFormatTag == WAVE_FORMAT_DVI_ADPCM)
{
bs = (format->nBlockAlign - 4 * format->nChannels) * 4;
context->priv->out_frames = (format->nBlockAlign * 4 * format->nChannels * 2 / bs + 1) * bs / (format->nChannels * 2);
}
else if (format->wFormatTag == WAVE_FORMAT_ADPCM)
{
bs = (format->nBlockAlign - 7 * format->nChannels) * 2 / format->nChannels + 2;
context->priv->out_frames = bs * 4;
}
else
{
context->priv->out_frames = 0x4000 / context->priv->src_bytes_per_frame;
}
if (format->nSamplesPerSec != context->src_format.nSamplesPerSec)
{
context->priv->out_frames = (context->priv->out_frames * context->src_format.nSamplesPerSec + format->nSamplesPerSec - 100) / format->nSamplesPerSec;
}
context->priv->out_pending_frames = 0;
out_buffer_size = context->priv->out_frames * context->priv->src_bytes_per_frame;
if (context->priv->out_buffer_size < out_buffer_size)
{
context->priv->out_buffer = (BYTE*) realloc(context->priv->out_buffer, out_buffer_size);
context->priv->out_buffer_size = out_buffer_size;
}
freerdp_dsp_context_reset_adpcm(context->priv->dsp_context);
}
static BOOL rdpsnd_server_send_audio_pdu(RdpsndServerContext* context)
{
int size;
BYTE* src;
int frames;
int fill_size;
BOOL status;
AUDIO_FORMAT* format;
int tbytes_per_frame;
wStream* s = context->priv->rdpsnd_pdu;
format = &context->client_formats[context->selected_client_format];
tbytes_per_frame = format->nChannels * context->priv->src_bytes_per_sample;
if ((format->nSamplesPerSec == context->src_format.nSamplesPerSec) &&
(format->nChannels == context->src_format.nChannels))
{
src = context->priv->out_buffer;
frames = context->priv->out_pending_frames;
}
else
{
context->priv->dsp_context->resample(context->priv->dsp_context, context->priv->out_buffer,
context->priv->src_bytes_per_sample, context->src_format.nChannels,
context->src_format.nSamplesPerSec, context->priv->out_pending_frames,
format->nChannels, format->nSamplesPerSec);
frames = context->priv->dsp_context->resampled_frames;
src = context->priv->dsp_context->resampled_buffer;
}
size = frames * tbytes_per_frame;
if (format->wFormatTag == WAVE_FORMAT_DVI_ADPCM)
{
context->priv->dsp_context->encode_ima_adpcm(context->priv->dsp_context,
src, size, format->nChannels, format->nBlockAlign);
src = context->priv->dsp_context->adpcm_buffer;
size = context->priv->dsp_context->adpcm_size;
}
else if (format->wFormatTag == WAVE_FORMAT_ADPCM)
{
context->priv->dsp_context->encode_ms_adpcm(context->priv->dsp_context,
src, size, format->nChannels, format->nBlockAlign);
src = context->priv->dsp_context->adpcm_buffer;
size = context->priv->dsp_context->adpcm_size;
}
context->block_no = (context->block_no + 1) % 256;
/* Fill to nBlockAlign for the last audio packet */
fill_size = 0;
if ((format->wFormatTag == WAVE_FORMAT_DVI_ADPCM || format->wFormatTag == WAVE_FORMAT_ADPCM) &&
(context->priv->out_pending_frames < context->priv->out_frames) && ((size % format->nBlockAlign) != 0))
{
fill_size = format->nBlockAlign - (size % format->nBlockAlign);
}
/* WaveInfo PDU */
Stream_SetPosition(s, 0);
Stream_Write_UINT8(s, SNDC_WAVE); /* msgType */
Stream_Write_UINT8(s, 0); /* bPad */
Stream_Write_UINT16(s, size + fill_size + 8); /* BodySize */
Stream_Write_UINT16(s, 0); /* wTimeStamp */
Stream_Write_UINT16(s, context->selected_client_format); /* wFormatNo */
Stream_Write_UINT8(s, context->block_no); /* cBlockNo */
Stream_Seek(s, 3); /* bPad */
Stream_Write(s, src, 4);
WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_SetPosition(s, 0);
/* Wave PDU */
Stream_EnsureRemainingCapacity(s, size + fill_size);
Stream_Write_UINT32(s, 0); /* bPad */
Stream_Write(s, src + 4, size - 4);
if (fill_size > 0)
Stream_Zero(s, fill_size);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_SetPosition(s, 0);
context->priv->out_pending_frames = 0;
return status;
}
static BOOL rdpsnd_server_send_samples(RdpsndServerContext* context, const void* buf, int nframes)
{
int cframes;
int cframesize;
if (context->selected_client_format < 0)
return FALSE;
while (nframes > 0)
{
cframes = MIN(nframes, context->priv->out_frames - context->priv->out_pending_frames);
cframesize = cframes * context->priv->src_bytes_per_frame;
CopyMemory(context->priv->out_buffer +
(context->priv->out_pending_frames * context->priv->src_bytes_per_frame), buf, cframesize);
buf = (BYTE*) buf + cframesize;
nframes -= cframes;
context->priv->out_pending_frames += cframes;
if (context->priv->out_pending_frames >= context->priv->out_frames)
{
if (!rdpsnd_server_send_audio_pdu(context))
return FALSE;
}
}
return TRUE;
}
static BOOL rdpsnd_server_set_volume(RdpsndServerContext* context, int left, int right)
{
int pos;
BOOL status;
wStream* s = context->priv->rdpsnd_pdu;
Stream_Write_UINT8(s, SNDC_SETVOLUME);
Stream_Write_UINT8(s, 0);
Stream_Seek_UINT16(s);
Stream_Write_UINT16(s, left);
Stream_Write_UINT16(s, right);
pos = Stream_GetPosition(s);
Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_SetPosition(s, 0);
return status;
}
static BOOL rdpsnd_server_close(RdpsndServerContext* context)
{
int pos;
BOOL status;
wStream* s = context->priv->rdpsnd_pdu;
if (context->selected_client_format < 0)
return FALSE;
if (context->priv->out_pending_frames > 0)
{
if (!rdpsnd_server_send_audio_pdu(context))
return FALSE;
}
context->selected_client_format = -1;
Stream_Write_UINT8(s, SNDC_CLOSE);
Stream_Write_UINT8(s, 0);
Stream_Seek_UINT16(s);
pos = Stream_GetPosition(s);
Stream_SetPosition(s, 2);
Stream_Write_UINT16(s, pos - 4);
Stream_SetPosition(s, pos);
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_SetPosition(s, 0);
return status;
}
static int rdpsnd_server_start(RdpsndServerContext* context)
{
context->priv->ChannelHandle = WTSVirtualChannelManagerOpenEx(context->vcm, "rdpsnd", 0);
if (!context->priv->ChannelHandle)
return -1;
context->priv->rdpsnd_pdu = Stream_New(NULL, 4096);
context->priv->StopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
context->priv->Thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) rdpsnd_server_thread, (void*) context, 0, NULL);
return 0;
}
static int rdpsnd_server_stop(RdpsndServerContext* context)
{
SetEvent(context->priv->StopEvent);
WaitForSingleObject(context->priv->Thread, INFINITE);
CloseHandle(context->priv->Thread);
return 0;
}
RdpsndServerContext* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm)
{
RdpsndServerContext* context;
context = (RdpsndServerContext*) malloc(sizeof(RdpsndServerContext));
if (context)
{
ZeroMemory(context, sizeof(RdpsndServerContext));
context->vcm = vcm;
context->Start = rdpsnd_server_start;
context->Stop = rdpsnd_server_stop;
context->selected_client_format = -1;
context->Initialize = rdpsnd_server_initialize;
context->SelectFormat = rdpsnd_server_select_format;
context->SendSamples = rdpsnd_server_send_samples;
context->SetVolume = rdpsnd_server_set_volume;
context->Close = rdpsnd_server_close;
context->priv = (RdpsndServerPrivate*) malloc(sizeof(RdpsndServerPrivate));
if (context->priv)
{
ZeroMemory(context->priv, sizeof(RdpsndServerPrivate));
context->priv->dsp_context = freerdp_dsp_context_new();
}
}
return context;
}
void rdpsnd_server_context_free(RdpsndServerContext* context)
{
SetEvent(context->priv->StopEvent);
WaitForSingleObject(context->priv->Thread, INFINITE);
if (context->priv->ChannelHandle)
WTSVirtualChannelClose(context->priv->ChannelHandle);
if (context->priv->rdpsnd_pdu)
Stream_Free(context->priv->rdpsnd_pdu, TRUE);
if (context->priv->out_buffer)
free(context->priv->out_buffer);
if (context->priv->dsp_context)
freerdp_dsp_context_free(context->priv->dsp_context);
if (context->client_formats)
free(context->client_formats);
free(context);
}

View File

@ -0,0 +1,48 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Server Audio Virtual Channel
*
* Copyright 2012 Vic Lee
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CHANNEL_SERVER_RDPSND_MAIN_H
#define FREERDP_CHANNEL_SERVER_RDPSND_MAIN_H
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <freerdp/codec/dsp.h>
#include <freerdp/channels/wtsvc.h>
#include <freerdp/server/rdpsnd.h>
struct _rdpsnd_server_private
{
HANDLE Thread;
HANDLE StopEvent;
void* ChannelHandle;
wStream* rdpsnd_pdu;
BYTE* out_buffer;
int out_buffer_size;
int out_frames;
int out_pending_frames;
UINT32 src_bytes_per_sample;
UINT32 src_bytes_per_frame;
FREERDP_DSP_CONTEXT* dsp_context;
};
#endif /* FREERDP_CHANNEL_SERVER_RDPSND_MAIN_H */

View File

@ -22,6 +22,7 @@
#include "config.h"
#endif
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -346,6 +347,7 @@ void* serial_thread_mfunc(void* arg)
{
SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg;
assert(NULL != serial);
while(1)
{
int sl;
@ -366,6 +368,7 @@ void* serial_thread_mfunc(void* arg)
}
}
ExitThread(0);
return NULL;
}
@ -376,6 +379,7 @@ static void* serial_thread_func(void* arg)
SERIAL_DEVICE* serial = (SERIAL_DEVICE*)arg;
HANDLE ev[] = {serial->stopEvent, Queue_Event(serial->queue), serial->newEvent};
assert(NULL != serial);
while (1)
{
status = WaitForMultipleObjects(3, ev, FALSE, INFINITE);
@ -401,6 +405,7 @@ static void* serial_thread_func(void* arg)
serial_check_fds(serial);
}
ExitThread(0);
return NULL;
}

View File

@ -42,6 +42,9 @@
#include <freerdp/server/audin.h>
#include <freerdp/server/rdpsnd.h>
#include <freerdp/server/cliprdr.h>
#include <freerdp/server/rdpdr.h>
#include <freerdp/server/drdynvc.h>
void freerdp_channels_dummy()
{
@ -50,6 +53,15 @@ void freerdp_channels_dummy()
rdpsnd_server_context_new(NULL);
rdpsnd_server_context_free(NULL);
cliprdr_server_context_new(NULL);
cliprdr_server_context_free(NULL);
rdpdr_server_context_new(NULL);
rdpdr_server_context_free(NULL);
drdynvc_server_context_new(NULL);
drdynvc_server_context_free(NULL);
}
/**
@ -420,7 +432,7 @@ WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client)
vcm = (WTSVirtualChannelManager*) malloc(sizeof(WTSVirtualChannelManager));
if (vcm != NULL)
if (vcm)
{
ZeroMemory(vcm, sizeof(WTSVirtualChannelManager));
@ -470,8 +482,7 @@ void WTSDestroyVirtualChannelManager(WTSVirtualChannelManager* vcm)
}
}
void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm,
void** fds, int* fds_count)
void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm, void** fds, int* fds_count)
{
void* fd;
@ -507,13 +518,13 @@ BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm)
/* Initialize drdynvc channel once and only once. */
vcm->drdynvc_state = DRDYNVC_STATE_INITIALIZED;
channel = WTSVirtualChannelOpenEx(vcm, "drdynvc", 0);
channel = WTSVirtualChannelManagerOpenEx(vcm, "drdynvc", 0);
if (channel)
{
vcm->drdynvc_channel = channel;
dynvc_caps = 0x00010050; /* DYNVC_CAPS_VERSION1 (4 bytes) */
WTSVirtualChannelWrite(channel, (BYTE*) &dynvc_caps, sizeof(dynvc_caps), NULL);
WTSVirtualChannelWrite(channel, (PCHAR) &dynvc_caps, sizeof(dynvc_caps), NULL);
}
}
@ -539,10 +550,12 @@ BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm)
return result;
}
void* WTSVirtualChannelOpenEx(
/* __in */ WTSVirtualChannelManager* vcm,
/* __in */ const char* pVirtualName,
/* __in */ UINT32 flags)
HANDLE WTSVirtualChannelManagerGetEventHandle(WTSVirtualChannelManager* vcm)
{
return vcm->send_event;
}
HANDLE WTSVirtualChannelManagerOpenEx(WTSVirtualChannelManager* vcm, LPSTR pVirtualName, DWORD flags)
{
int i;
int len;
@ -592,7 +605,7 @@ void* WTSVirtualChannelOpenEx(
s = Stream_New(NULL, 64);
wts_write_drdynvc_create_request(s, channel->channel_id, pVirtualName);
WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_Free(s, TRUE);
DEBUG_DVC("ChannelId %d.%s (total %d)", channel->channel_id, pVirtualName, list_size(vcm->dvc_channel_list));
@ -646,11 +659,7 @@ void* WTSVirtualChannelOpenEx(
return channel;
}
BOOL WTSVirtualChannelQuery(
/* __in */ void* hChannelHandle,
/* __in */ WTS_VIRTUAL_CLASS WtsVirtualClass,
/* __out */ void** ppBuffer,
/* __out */ UINT32* pBytesReturned)
BOOL WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned)
{
void* pfd;
BOOL bval;
@ -659,6 +668,7 @@ BOOL WTSVirtualChannelQuery(
BOOL result = FALSE;
rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
ZeroMemory(fds, sizeof(fds));
switch (WtsVirtualClass)
{
case WTSVirtualFileHandle:
@ -677,6 +687,13 @@ BOOL WTSVirtualChannelQuery(
result = TRUE;
break;
case WTSVirtualEventHandle:
*ppBuffer = malloc(sizeof(HANDLE));
CopyMemory(*ppBuffer, &(channel->receive_event), sizeof(HANDLE));
*pBytesReturned = sizeof(void*);
result = TRUE;
break;
case WTSVirtualChannelReady:
if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC)
{
@ -715,25 +732,19 @@ BOOL WTSVirtualChannelQuery(
return result;
}
void WTSFreeMemory(
/* __in */ void* pMemory)
VOID WTSFreeMemory(PVOID pMemory)
{
free(pMemory);
}
BOOL WTSVirtualChannelRead(
/* __in */ void* hChannelHandle,
/* __in */ UINT32 TimeOut,
/* __out */ BYTE* Buffer,
/* __in */ UINT32 BufferSize,
/* __out */ UINT32* pBytesRead)
BOOL WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead)
{
wts_data_item* item;
rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
item = (wts_data_item*) list_peek(channel->receive_queue);
if (item == NULL)
if (!item)
{
ResetEvent(channel->receive_event);
*pBytesRead = 0;
@ -755,16 +766,12 @@ BOOL WTSVirtualChannelRead(
ReleaseMutex(channel->mutex);
CopyMemory(Buffer, item->buffer, item->length);
wts_data_item_free(item) ;
wts_data_item_free(item);
return TRUE;
}
BOOL WTSVirtualChannelWrite(
/* __in */ void* hChannelHandle,
/* __in */ BYTE* Buffer,
/* __in */ UINT32 Length,
/* __out */ UINT32* pBytesWritten)
BOOL WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten)
{
rdpPeerChannel* channel = (rdpPeerChannel*) hChannelHandle;
wts_data_item* item;
@ -774,7 +781,7 @@ BOOL WTSVirtualChannelWrite(
int first;
UINT32 written;
if (channel == NULL)
if (!channel)
return FALSE;
if (channel->channel_type == RDP_PEER_CHANNEL_TYPE_SVC)
@ -841,8 +848,7 @@ BOOL WTSVirtualChannelWrite(
return TRUE;
}
BOOL WTSVirtualChannelClose(
/* __in */ void* hChannelHandle)
BOOL WTSVirtualChannelClose(HANDLE hChannelHandle)
{
wStream* s;
wts_data_item* item;
@ -868,7 +874,7 @@ BOOL WTSVirtualChannelClose(
{
s = Stream_New(NULL, 8);
wts_write_drdynvc_header(s, CLOSE_REQUEST_PDU, channel->channel_id);
WTSVirtualChannelWrite(vcm->drdynvc_channel, Stream_Buffer(s), Stream_GetPosition(s), NULL);
WTSVirtualChannelWrite(vcm->drdynvc_channel, (PCHAR) Stream_Buffer(s), Stream_GetPosition(s), NULL);
Stream_Free(s, TRUE);
}
}

View File

@ -112,13 +112,16 @@ struct _SMARTCARD_IRP_WORKER
};
typedef struct _SMARTCARD_IRP_WORKER SMARTCARD_IRP_WORKER;
static void smartcard_process_irp_thread_func(SMARTCARD_IRP_WORKER* irpWorker)
static void *smartcard_process_irp_thread_func(SMARTCARD_IRP_WORKER* irpWorker)
{
smartcard_process_irp(irpWorker->smartcard, irpWorker->irp);
CloseHandle(irpWorker->thread);
free(irpWorker);
ExitThread(0);
return NULL;
}
static void* smartcard_thread_func(void* arg)
@ -312,7 +315,7 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
{
char* name;
char* path;
int i, length;
int i, length, ck;
RDPDR_SMARTCARD* device;
SMARTCARD_DEVICE* smartcard;
@ -320,41 +323,49 @@ int DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
name = device->Name;
path = device->Path;
if (name)
/* TODO: check if server supports sc redirect (version 5.1) */
smartcard = (SMARTCARD_DEVICE*) malloc(sizeof(SMARTCARD_DEVICE));
ZeroMemory(smartcard, sizeof(SMARTCARD_DEVICE));
smartcard->device.type = RDPDR_DTYP_SMARTCARD;
smartcard->device.name = "SCARD";
smartcard->device.IRPRequest = smartcard_irp_request;
smartcard->device.Free = smartcard_free;
length = strlen(smartcard->device.name);
smartcard->device.data = Stream_New(NULL, length + 1);
Stream_Write(smartcard->device.data, "SCARD", 6);
smartcard->name = NULL;
smartcard->path = NULL;
if (path)
{
/* TODO: check if server supports sc redirect (version 5.1) */
smartcard = (SMARTCARD_DEVICE*) malloc(sizeof(SMARTCARD_DEVICE));
ZeroMemory(smartcard, sizeof(SMARTCARD_DEVICE));
smartcard->device.type = RDPDR_DTYP_SMARTCARD;
smartcard->device.name = "SCARD";
smartcard->device.IRPRequest = smartcard_irp_request;
smartcard->device.Free = smartcard_free;
length = strlen(smartcard->device.name);
smartcard->device.data = Stream_New(NULL, length + 1);
for (i = 0; i <= length; i++)
Stream_Write_UINT8(smartcard->device.data, name[i] < 0 ? '_' : name[i]);
smartcard->path = path;
smartcard->pIrpList = (PSLIST_HEADER) _aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
InitializeSListHead(smartcard->pIrpList);
smartcard->irpEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
smartcard->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
smartcard->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) smartcard_thread_func,
smartcard, CREATE_SUSPENDED, NULL);
smartcard->CompletionIds = list_new();
smartcard->CompletionIdsMutex = CreateMutex(NULL, FALSE, NULL);
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) smartcard);
ResumeThread(smartcard->thread);
smartcard->name = name;
}
else if (name)
{
if (1 == sscanf(name, "%d", &ck))
smartcard->path = name;
else
smartcard->name = name;
}
smartcard->pIrpList = (PSLIST_HEADER) _aligned_malloc(sizeof(SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
InitializeSListHead(smartcard->pIrpList);
smartcard->irpEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
smartcard->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
smartcard->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) smartcard_thread_func,
smartcard, CREATE_SUSPENDED, NULL);
smartcard->CompletionIds = list_new();
smartcard->CompletionIdsMutex = CreateMutex(NULL, FALSE, NULL);
pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*) smartcard);
ResumeThread(smartcard->thread);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -74,11 +74,11 @@ static BOOL tsmf_alsa_open(ITSMFAudioDevice* audio, const char* device)
if (!device)
{
if (!alsa->device[0])
strcpy(alsa->device, "default");
strncpy(alsa->device, "default", sizeof(alsa->device));
}
else
{
strcpy(alsa->device, device);
strncpy(alsa->device, device, sizeof(alsa->device));
}
return tsmf_alsa_open_device(alsa);

View File

@ -279,6 +279,7 @@ static int urbdrc_process_io_control(URBDRC_CHANNEL_CALLBACK* callback, BYTE* da
default:
LLOGLN(urbdrc_debug, ("urbdrc_process_io_control: unknown IoControlCode 0x%X", IoControlCode));
zfree(OutputBuffer);
return -1;
break;
}
@ -1718,6 +1719,7 @@ static int urb_control_feature_request(URBDRC_CHANNEL_CALLBACK * callback, BYTE
break;
default:
fprintf(stderr, "urb_control_feature_request: Error Command %x\n", command);
zfree(out_data);
return -1;
}

View File

@ -485,6 +485,7 @@ static LIBUSB_DEVICE_DESCRIPTOR* udev_new_descript(LIBUSB_DEVICE* libusb_dev)
if (ret < 0)
{
fprintf(stderr, "libusb_get_device_descriptor: ERROR!!\n");
free(descriptor);
return NULL;
}
@ -1543,6 +1544,9 @@ static int func_cancel_xact_request(TRANSFER_REQUEST *request)
{
int status;
if (!request)
return -1;
if ((!request->transfer) || (request->endpoint != request->transfer->endpoint) ||
(request->transfer->endpoint == 0) || (request->submit != 1))
{
@ -1583,6 +1587,8 @@ cancel_retry:
while (request_queue->has_next(request_queue))
{
request = request_queue->get_next(request_queue);
if (!request)
continue;
LLOGLN(libusb_debug, ("%s: CancelId:0x%x RequestId:0x%x endpoint 0x%x!!",
__func__, RequestId, request->RequestId, request->endpoint));

View File

@ -18,6 +18,7 @@
* limitations under the License.
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -287,6 +288,9 @@ static int urdbrc_send_virtual_channel_add(IWTSVirtualChannel* channel, UINT32 M
LLOGLN(10, ("urdbrc_send_virtual_channel_add"));
assert(NULL != channel);
assert(NULL != channel->Write);
InterfaceId = ((STREAM_ID_PROXY<<30) | CLIENT_DEVICE_SINK);
out_size = 12;
@ -830,7 +834,10 @@ static int urbdrc_on_data_received(IWTSVirtualChannelCallback* pChannelCallback,
transfer_data = (TRANSFER_DATA*) malloc(sizeof(TRANSFER_DATA));
if (transfer_data == NULL)
{
fprintf(stderr, "transfer_data is NULL!!");
return 0;
}
transfer_data->callback = callback;
transfer_data->urbdrc = urbdrc;

View File

@ -3,10 +3,10 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="auto"
package="com.freerdp.freerdpcore"
android:versionCode="1"
android:versionCode="2"
android:versionName="@GIT_REVISION@" >
<uses-sdk android:targetSdkVersion="8" android:minSdkVersion="8"/>
<uses-sdk android:targetSdkVersion="@ANDROID_APP_TARGET_SDK@" android:minSdkVersion="@ANDROID_APP_MIN_SDK@"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>

View File

@ -16,28 +16,39 @@
# See the License for the specific language governing permissions and
# limitations under the License.
set(ANDROID_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(ANDROID_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
set(ANDROID_PACKAGE_NAME "aFreeRDPCore")
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml.cmake ${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml.cmake
${CMAKE_CURRENT_BINARY_DIR}/AndroidManifest.xml @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build.xml.cmake
${CMAKE_CURRENT_BINARY_DIR}/build.xml @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/project.properties.cmake
${CMAKE_CURRENT_BINARY_DIR}/project.properties @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/ant.properties.cmake
${CMAKE_CURRENT_BINARY_DIR}/ant.properties @ONLY)
file(COPY res DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
if (ANDROID_SDK)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/local.properties.cmake ${CMAKE_CURRENT_SOURCE_DIR}/local.properties @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/local.properties.cmake
${CMAKE_CURRENT_BINARY_DIR}/local.properties @ONLY)
endif()
add_subdirectory(jni)
if(ANDROID_BUILD_JAVA)
set(ANDROIDLIB "${ANDROID_SOURCE_DIR}/bin/classes.jar")
set(ANDROIDLIB "${ANDROID_BINARY_DIR}/bin/classes.jar")
# command to create the android package
add_custom_command(
OUTPUT "${ANDROIDLIB}"
COMMAND ${ANT_COMMAND} ${ANDROID_BUILD_TYPE}
WORKING_DIRECTORY "${ANDROID_SOURCE_DIR}"
WORKING_DIRECTORY "${ANDROID_BINARY_DIR}"
MAIN_DEPENDENCY AndroidManifest.xml
DEPENDS freerdp-android local.properties
DEPENDS freerdp-android
${CMAKE_CURRENT_BINARY_DIR}/local.properties
)
add_custom_target(android-lib ALL SOURCES "${ANDROIDLIB}")
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "gen;bin")

View File

@ -14,3 +14,7 @@
# 'key.store' for the location of your keystore and
# 'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target.
build.dir=@CMAKE_CURRENT_BINARY_DIR@
source.dir=@CMAKE_CURRENT_SOURCE_DIR@/src
out.dir=@CMAKE_CURRENT_BINARY_DIR@/bin

View File

@ -68,6 +68,7 @@ set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} jnigraphics)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${ANDROID_SOURCE_DIR}/libs/${ANDROID_ABI}")
set_target_properties(${MODULE_NAME}
PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${ANDROID_BINARY_DIR}/libs/${ANDROID_ABI}")
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Android")

View File

@ -11,5 +11,5 @@
#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
# Project target.
target=android-11
target=android-@ANDROID_APP_TARGET_SDK@
android.library=true

View File

@ -64,9 +64,11 @@
</string-array>
<string name="settings_resolution">Resolucion</string>
<string name="resolution_automatic">Automatico</string>
<string name="resolution_fit">Pantalla</string>
<string name="resolution_custom">Manual</string>
<string-array name="resolutions_array">
<item>Automatico</item>
<item>Ajuste a la pantalla</item>
<item>Manual</item>
<item>640x480</item>
<item>720x480</item>
@ -77,9 +79,12 @@
<item>1920x1080</item>
<item>1920x1200</item>
</string-array>
<!-- The strings in resolutions_values_array should not be localized -->
<!-- They are used for text comparison and must remain in english -->
<string-array name="resolutions_values_array">
<item>automatico</item>
<item>manual</item>
<item>automatic</item>
<item>fitscreen</item>
<item>custom</item>
<item>640x480</item>
<item>720x480</item>
<item>800x600</item>
@ -89,6 +94,7 @@
<item>1920x1080</item>
<item>1920x1200</item>
</string-array>
<!-- end protected string section -->
<string name="settings_width">Ancho</string>
<string name="settings_height">Altura</string>
<string name="settings_performance">Rendimiento</string>

View File

@ -63,9 +63,11 @@
</string-array>
<string name="settings_resolution">"Résolution"</string>
<string name="resolution_automatic">"Automatique"</string>
<string name="resolution_fit">"Agrandir la fenêtre"</string>
<string name="resolution_custom">"Personalisé"</string>
<string-array name="resolutions_array">
<item>"Automatique"</item>
<item>"Agrandir la fenêtre"</item>
<item>"Personalisé"</item>
<item>"640x480"</item>
<item>"720x480"</item>
@ -76,18 +78,22 @@
<item>"1920x1080"</item>
<item>"1920x1200"</item>
</string-array>
<!-- The strings in resolutions_values_array should not be localized -->
<!-- They are used for text comparison and must remain in english -->
<string-array name="resolutions_values_array">
<item>"Automatique"</item>
<item>"Personalisé"</item>
<item>"640x480"</item>
<item>"720x480"</item>
<item>"800x600"</item>
<item>"1024x768"</item>
<item>"1280x1024"</item>
<item>"1440x900"</item>
<item>"1920x1080"</item>
<item>"1920x1200"</item>
<item>automatic</item>
<item>fitscreen</item>
<item>custom</item>
<item>640x480</item>
<item>720x480</item>
<item>800x600</item>
<item>1024x768</item>
<item>1280x1024</item>
<item>1440x900</item>
<item>1920x1080</item>
<item>1920x1200</item>
</string-array>
<!-- end protected string section -->
<string name="settings_width">"Largeur"</string>
<string name="settings_height">"Hauteur"</string>
<string name="settings_performance">"Performance"</string>

View File

@ -64,9 +64,11 @@
</string-array>
<string name="settings_resolution">Resolutie</string>
<string name="resolution_automatic">Automatisch</string>
<string name="resolution_fit">Schermvullend</string>
<string name="resolution_custom">Aangepast</string>
<string-array name="resolutions_array">
<item>Automatisch</item>
<item>Schermvullend</item>
<item>Aangepast</item>
<item>640x480</item>
<item>720x480</item>
@ -77,9 +79,12 @@
<item>1920x1080</item>
<item>1920x1200</item>
</string-array>
<!-- The strings in resolutions_values_array should not be localized -->
<!-- They are used for text comparison and must remain in english -->
<string-array name="resolutions_values_array">
<item>Automatisch</item>
<item>Aangepast</item>
<item>automatic</item>
<item>fitscreen</item>
<item>custom</item>
<item>640x480</item>
<item>720x480</item>
<item>800x600</item>
@ -89,6 +94,7 @@
<item>1920x1080</item>
<item>1920x1200</item>
</string-array>
<!-- end protected string section -->
<string name="settings_width">Breedte</string>
<string name="settings_height">Hoogte</string>
<string name="settings_performance">Prestatie</string>

View File

@ -64,9 +64,11 @@
</string-array>
<string name="settings_resolution">Resolution</string>
<string name="resolution_automatic">Automatic</string>
<string name="resolution_fit">Fitscreen</string>
<string name="resolution_custom">Custom</string>
<string-array name="resolutions_array">
<item>Automatic</item>
<item>Fit Screen</item>
<item>Custom</item>
<item>640x480</item>
<item>720x480</item>
@ -79,6 +81,7 @@
</string-array>
<string-array name="resolutions_values_array">
<item>automatic</item>
<item>fitscreen</item>
<item>custom</item>
<item>640x480</item>
<item>720x480</item>

View File

@ -143,6 +143,7 @@ public class BookmarkBase implements Parcelable, Cloneable
// Screen Settings class
public static class ScreenSettings implements Parcelable
{
public static final int FITSCREEN = -2;
public static final int AUTOMATIC = -1;
public static final int CUSTOM = 0;
public static final int PREDEFINED = 1;
@ -174,7 +175,7 @@ public class BookmarkBase implements Parcelable, Cloneable
{
this.resolution = resolution;
if (resolution == AUTOMATIC) {
if (resolution == AUTOMATIC || resolution == FITSCREEN) {
width = 0;
height = 0;
}
@ -194,9 +195,14 @@ public class BookmarkBase implements Parcelable, Cloneable
this.height = height;
this.resolution = CUSTOM;
}
else if (resolution.equalsIgnoreCase("fitscreen"))
{
this.width = this.height = 0;
this.resolution = FITSCREEN;
}
else
{
this.width = this.height = 0;
this.width = this.height = 0;
this.resolution = AUTOMATIC;
}
}
@ -210,8 +216,8 @@ public class BookmarkBase implements Parcelable, Cloneable
{
if (isPredefined())
return (width + "x" + height);
return (isAutomatic() ? "automatic" : "custom");
return (isFitScreen() ? "fitscreen" : isAutomatic() ? "automatic" : "custom");
}
public boolean isPredefined() {
@ -221,7 +227,11 @@ public class BookmarkBase implements Parcelable, Cloneable
public boolean isAutomatic() {
return (resolution == AUTOMATIC);
}
public boolean isFitScreen() {
return (resolution == FITSCREEN);
}
public boolean isCustom() {
return (resolution == CUSTOM);
}

View File

@ -343,10 +343,17 @@ public class BookmarkActivity extends PreferenceActivity implements OnSharedPref
else if (key.equals("bookmark.resolution") || key.equals("bookmark.colors") || key.equals("bookmark.width") || key.equals("bookmark.height"))
{
String resolution = sharedPreferences.getString("bookmark.resolution", "800x600");
if (resolution.equals("automatic"))
//compare english string from resolutions_values_array array, decode to localized
//text for display
if (resolution.equals("automatic")) {
resolution = getResources().getString(R.string.resolution_automatic);
else if (resolution.equals("custom"))
}
if (resolution.equals("custom")) {
resolution = getResources().getString(R.string.resolution_custom);
}
if (resolution.equals("fitscreen")) {
resolution = getResources().getString(R.string.resolution_fit);
}
resolution += "@" + sharedPreferences.getInt("bookmark.colors", 16);
findPreference("bookmark.screen").setSummary(resolution);
}
@ -451,7 +458,7 @@ public class BookmarkActivity extends PreferenceActivity implements OnSharedPref
ListPreference listPreference = (ListPreference)findPreference(key);
listPreference.setSummary(listPreference.getEntry());
boolean enabled = listPreference.getValue().equals("custom");
boolean enabled = listPreference.getValue().equalsIgnoreCase(getResources().getString(R.string.resolution_custom));
if (key.equals("bookmark.resolution"))
{
findPreference("bookmark.width").setEnabled(enabled);

View File

@ -624,6 +624,10 @@ public class SessionActivity extends Activity
screenSettings.setWidth((int)((float)screenMax * 1.6f));
}
}
if (screenSettings.isFitScreen()) {
screenSettings.setHeight(screen_height);
screenSettings.setWidth(screen_width);
}
progressDialog = new ProgressDialog(this);
progressDialog.setTitle(bookmark.getLabel());

View File

@ -6,7 +6,7 @@
android:versionCode="3"
android:versionName="@GIT_REVISION@" >
<uses-sdk android:targetSdkVersion="8" android:minSdkVersion="8"/>
<uses-sdk android:targetSdkVersion="@ANDROID_APP_TARGET_SDK@" android:minSdkVersion="@ANDROID_APP_MIN_SDK@"/>
<supports-screens android:anyDensity="true" android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:xlargeScreens="true" />
<application android:name="com.freerdp.afreerdp.application.GlobalApp"

View File

@ -16,29 +16,41 @@
# See the License for the specific language governing permissions and
# limitations under the License.
set(ANDROID_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(ANDROID_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
set(ANDROID_PACKAGE_NAME "aFreeRDP")
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml.cmake ${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/AndroidManifest.xml.cmake
${CMAKE_CURRENT_BINARY_DIR}/AndroidManifest.xml @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/build.xml.cmake
${CMAKE_CURRENT_BINARY_DIR}/build.xml @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/project.properties.cmake
${CMAKE_CURRENT_BINARY_DIR}/project.properties @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/ant.properties.cmake
${CMAKE_CURRENT_BINARY_DIR}/ant.properties @ONLY)
file(COPY res DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
file(COPY assets DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
if (ANDROID_SDK)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/local.properties.cmake ${CMAKE_CURRENT_SOURCE_DIR}/local.properties @ONLY)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/local.properties.cmake
${CMAKE_CURRENT_BINARY_DIR}/local.properties @ONLY)
endif()
if(ANDROID_BUILD_JAVA)
if(ANDROID_BUILD_JAVA_DEBUG)
set(APK "${ANDROID_SOURCE_DIR}/bin/${ANDROID_PACKAGE_NAME}-release-unsigned.apk")
if(NOT ANDROID_BUILD_JAVA_DEBUG)
set(APK "${ANDROID_BINARY_DIR}/bin/${ANDROID_PACKAGE_NAME}-release-unsigned.apk")
else()
set(APK "${ANDROID_SOURCE_DIR}/bin/${ANDROID_PACKAGE_NAME}-debug.apk")
set(APK "${ANDROID_BINARY_DIR}/bin/${ANDROID_PACKAGE_NAME}-debug.apk")
endif()
# command to create the android package
add_custom_command(
OUTPUT "${APK}"
COMMAND ${ANT_COMMAND} ${ANDROID_BUILD_TYPE}
WORKING_DIRECTORY "${ANDROID_SOURCE_DIR}"
WORKING_DIRECTORY "${ANDROID_BINARY_DIR}"
MAIN_DEPENDENCY AndroidManifest.xml
DEPENDS freerdp-android local.properties #android-lib
DEPENDS freerdp-android
${CMAKE_CURRENT_BINARY_DIR}/local.properties
)
add_custom_target(android-package ALL SOURCES "${APK}")
SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "gen;bin")

View File

@ -0,0 +1,20 @@
# This file is used to override default values used by the Ant build system.
#
# This file must be checked into Version Control Systems, as it is
# integral to the build system of your project.
# This file is only used by the Ant script.
# You can use this to override default values such as
# 'source.dir' for the location of your java source folder and
# 'out.dir' for the location of your output folder.
# You can also use it define how the release builds are signed by declaring
# the following properties:
# 'key.store' for the location of your keystore and
# 'key.alias' for the name of the key to use.
# The password will be asked during the build when you use the 'release' target.
build.dir=@CMAKE_CURRENT_BINARY_DIR@
source.dir=@CMAKE_CURRENT_SOURCE_DIR@/src
out.dir=@CMAKE_CURRENT_BINARY_DIR@/bin

View File

@ -8,6 +8,6 @@
# project structure.
# Project target.
target=android-11
target=android-@ANDROID_APP_TARGET_SDK@
android.library.reference.1=../FreeRDPCore
manifestmerger.enabled=true

View File

@ -151,7 +151,7 @@ endif()
COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/$(CONFIGURATION)/${MODULE_OUTPUT_NAME}.framework/Versions/${MACOSX_BUNDLE_SHORT_VERSION_STRING}/Resources)
# Compile the .xib files using the 'ibtool' program with the destination being the app package
foreach(xib ${${MODULE_NAME}_XIBS})
foreach(xib ${${MODULE_PREFIX}_XIBS})
get_filename_component(XIB_WE ${xib} NAME_WE)
add_custom_command (TARGET ${MODULE_NAME} POST_BUILD

View File

@ -139,6 +139,16 @@ struct rgba_data
e.handle = (void*) self;
PubSub_OnEmbedWindow(context->pubSub, context, &e);
NSScreen *screen = [[NSScreen screens] objectAtIndex:0];
NSRect screenFrame = [screen frame];
if(instance->settings->Fullscreen)
{
instance->settings->DesktopWidth = screenFrame.size.width;
instance->settings->DesktopHeight = screenFrame.size.height;
}
mfc->thread = CreateThread(NULL, 0, mac_client_thread, (void*) context, 0, &mfc->mainThreadId);
return 0;
@ -469,20 +479,23 @@ DWORD mac_client_thread(void* param)
NSPoint loc = [event locationInWindow];
int x = (int) loc.x;
int y = (int) loc.y;
y = height - y;
flags = PTR_FLAGS_WHEEL;
if ([event deltaY] < 0)
flags |= PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
else
flags |= 0x0078;
x += (int) [event deltaX];
y += (int) [event deltaY];
instance->input->MouseEvent(instance->input, flags, x, y);
/* 1 event = 120 units */
int units = [event deltaY] * 120;
/* send out all accumulated rotations */
while(units != 0)
{
/* limit to maximum value in WheelRotationMask (9bit signed value) */
int step = MIN(MAX(-256, units), 255);
instance->input->MouseEvent(instance->input, flags | ((UINT16)step & WheelRotationMask), x, y);
units -= step;
}
}
/** *********************************************************************
@ -705,7 +718,8 @@ DWORD mac_client_thread(void* param)
CGImageRef cgImage = CGBitmapContextCreateImage(self->bitmap_context);
CGContextClipToRect(cgContext, CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height));
CGContextDrawImage(cgContext, CGRectMake(0, 0, [self bounds].size.width, [self bounds].size.height), cgImage);
CGContextDrawImage(cgContext, CGRectMake(0,
0, [self bounds].size.width, [self bounds].size.height), cgImage);
CGImageRelease(cgImage);
}

View File

@ -239,7 +239,7 @@
<int key="NSCellFlags2">272630784</int>
<string key="NSContents"/>
<reference key="NSSupport" ref="461722316"/>
<string key="NSPlaceholderString">billg</string>
<string key="NSPlaceholderString">Username</string>
<string key="NSCellIdentifier">_NS:9</string>
<reference key="NSControlView" ref="385178766"/>
<bool key="NSDrawsBackground">YES</bool>

View File

@ -10,6 +10,7 @@
#import "MacFreeRDP/mfreerdp.h"
#import "MacFreeRDP/mf_client.h"
#import "MacFreeRDP/MRDPView.h"
#import <freerdp/client/cmdline.h>
static AppDelegate* _singleDelegate = nil;
void AppDelegate_EmbedWindowEventHandler(void* context, EmbedWindowEventArgs* e);
@ -93,6 +94,7 @@ void mac_set_view_size(rdpContext* context, MRDPView* view);
}
status = freerdp_client_parse_command_line(context, argc, argv);
status = freerdp_client_command_line_status_print(context->argc, context->argv, context->settings, status);
return status;
}
@ -224,37 +226,27 @@ void AppDelegate_ErrorInfoEventHandler(void* ctx, ErrorInfoEventArgs* e)
void mac_set_view_size(rdpContext* context, MRDPView* view)
{
// compute difference between window and client area
NSRect outerRect = [[view window] frame];
NSRect innerRect = [view frame];
int widthDiff = outerRect.size.width - innerRect.size.width;
int heightDiff = outerRect.size.height - innerRect.size.height;
NSSize desktopSize;
desktopSize.width = context->settings->DesktopWidth;
desktopSize.height = context->settings->DesktopHeight;
// we are not in RemoteApp mode, disable resizing
outerRect.size.width = desktopSize.width + widthDiff;
outerRect.size.height = desktopSize.height + heightDiff;
[[view window] setMaxSize:outerRect.size];
[[view window] setMinSize:outerRect.size];
@try
{
[[view window] setFrame:outerRect display:YES];
}
@catch (NSException * e) {
NSLog(@"Exception: %@", e);
}
@finally {
}
// set client area to specified dimensions
innerRect.size.width = desktopSize.width;
innerRect.size.height = desktopSize.height;
NSRect innerRect;
innerRect.origin.x = 0;
innerRect.origin.y = 0;
innerRect.size.width = context->settings->DesktopWidth;
innerRect.size.height = context->settings->DesktopHeight;
[view setFrame:innerRect];
// calculate window of same size, but keep position
NSRect outerRect = [[view window] frame];
outerRect.size = [[view window] frameRectForContentRect:innerRect].size;
// we are not in RemoteApp mode, disable larger than resolution
[[view window] setContentMaxSize:innerRect.size];
// set window to given area
[[view window] setFrame:outerRect display:YES];
if(context->settings->Fullscreen)
[[view window] toggleFullScreen:nil];
}
int mac_client_start(rdpContext* context)

View File

@ -206,9 +206,6 @@ int tfreerdp_run(freerdp* instance)
fd_set wfds_set;
rdpChannels* channels;
ZeroMemory(rfds, sizeof(rfds));
ZeroMemory(wfds, sizeof(wfds));
channels = instance->context->channels;
freerdp_connect(instance);
@ -218,6 +215,8 @@ int tfreerdp_run(freerdp* instance)
rcount = 0;
wcount = 0;
ZeroMemory(rfds, sizeof(rfds));
ZeroMemory(wfds, sizeof(wfds));
if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
{
printf("Failed to get FreeRDP file descriptor\n");

View File

@ -33,6 +33,7 @@
#include <stdlib.h>
#include <string.h>
#include <tchar.h>
#include <assert.h>
#include <sys/types.h>
#ifdef _MSC_VER
@ -371,7 +372,7 @@ BOOL wf_post_connect(freerdp* instance)
if (settings->RemoteFxCodec)
{
wfc->tile = wf_image_new(wfc, 64, 64, 32, NULL);
wfc->rfx_context = rfx_context_new();
wfc->rfx_context = rfx_context_new(FALSE);
}
if (settings->NSCodec)
@ -569,7 +570,10 @@ DWORD WINAPI wf_client_thread(LPVOID lpParam)
rdpChannels* channels;
instance = (freerdp*) lpParam;
assert(NULL != instance);
wfc = (wfContext*) instance->context;
assert(NULL != wfc);
ZeroMemory(rfds, sizeof(rfds));
ZeroMemory(wfds, sizeof(wfds));
@ -690,13 +694,13 @@ DWORD WINAPI wf_client_thread(LPVOID lpParam)
}
/* cleanup */
wfc->mainThreadId = 0;
freerdp_channels_close(channels, instance);
freerdp_disconnect(instance);
printf("Main thread exited.\n");
ExitThread(0);
return 0;
}
@ -708,6 +712,7 @@ DWORD WINAPI wf_keyboard_thread(LPVOID lpParam)
HHOOK hook_handle;
wfc = (wfContext*) lpParam;
assert(NULL != wfc);
hook_handle = SetWindowsHookEx(WH_KEYBOARD_LL, wf_ll_kbd_proc, wfc->hInstance, 0);
@ -734,9 +739,9 @@ DWORD WINAPI wf_keyboard_thread(LPVOID lpParam)
fprintf(stderr, "failed to install keyboard hook\n");
}
wfc->keyboardThreadId = 0;
printf("Keyboard thread exited.\n");
ExitThread(0);
return (DWORD) NULL;
}
@ -1078,12 +1083,27 @@ int wfreerdp_client_stop(rdpContext* context)
{
wfContext* wfc = (wfContext*) context;
if (wfc->mainThreadId)
if (wfc->thread)
{
PostThreadMessage(wfc->mainThreadId, WM_QUIT, 0, 0);
if (wfc->keyboardThreadId)
WaitForSingleObject(wfc->thread, INFINITE);
CloseHandle(wfc->thread);
wfc->thread = NULL;
wfc->mainThreadId = 0;
}
if (wfc->keyboardThread)
{
PostThreadMessage(wfc->keyboardThreadId, WM_QUIT, 0, 0);
WaitForSingleObject(wfc->keyboardThread, INFINITE);
CloseHandle(wfc->keyboardThread);
wfc->keyboardThread = NULL;
wfc->keyboardThreadId = 0;
}
return 0;
}

View File

@ -92,8 +92,6 @@ if(WITH_MANPAGES)
MODULE freerdp
MODULES freerdp-core freerdp-utils)
message(WARNING "GAD_LIBS: ${GAD_LIBS}")
target_link_libraries(generate_argument_docbook ${GAD_LIBS})
add_custom_command(OUTPUT xfreerdp.1

View File

@ -11,7 +11,7 @@
LPSTR tmp = NULL;
LPCSTR tr_esc_str(LPCSTR arg)
LPSTR tr_esc_str(LPSTR arg)
{
size_t cs = 0, x, ds;
size_t s;
@ -26,7 +26,8 @@ LPCSTR tr_esc_str(LPCSTR arg)
s--;
/* Prepare a initial buffer with the size of the result string. */
tmp = malloc(s * sizeof(LPCSTR));
if (s)
tmp = (LPSTR)malloc(s * sizeof(CHAR));
if( NULL == tmp )
{
fprintf(stderr, "Could not allocate string buffer.");
@ -41,7 +42,7 @@ LPCSTR tr_esc_str(LPCSTR arg)
{
case '<':
ds += 3;
tmp = realloc(tmp, ds * sizeof(LPCSTR));
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if( NULL == tmp )
{
fprintf(stderr, "Could not reallocate string buffer.");
@ -54,7 +55,7 @@ LPCSTR tr_esc_str(LPCSTR arg)
break;
case '>':
ds += 3;
tmp = realloc(tmp, ds * sizeof(LPCSTR));
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if( NULL == tmp )
{
fprintf(stderr, "Could not reallocate string buffer.");
@ -67,7 +68,7 @@ LPCSTR tr_esc_str(LPCSTR arg)
break;
case '\'':
ds += 5;
tmp = realloc(tmp, ds * sizeof(LPCSTR));
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if( NULL == tmp )
{
fprintf(stderr, "Could not reallocate string buffer.");
@ -82,7 +83,7 @@ LPCSTR tr_esc_str(LPCSTR arg)
break;
case '"':
ds += 5;
tmp = realloc(tmp, ds * sizeof(LPCSTR));
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if( NULL == tmp )
{
fprintf(stderr, "Could not reallocate string buffer.");
@ -97,7 +98,7 @@ LPCSTR tr_esc_str(LPCSTR arg)
break;
case '&':
ds += 4;
tmp = realloc(tmp, ds * sizeof(LPCSTR));
tmp = (LPSTR)realloc(tmp, ds * sizeof(CHAR));
if( NULL == tmp )
{
fprintf(stderr, "Could not reallocate string buffer.");
@ -154,12 +155,12 @@ int main(int argc, char *argv[])
const COMMAND_LINE_ARGUMENT_A *arg = &args[x];
fprintf(fp, "\t\t\t<varlistentry>\n");
if( COMMAND_LINE_VALUE_REQUIRED == arg->Flags )
fprintf(fp, "\t\t\t\t<term><option>/%s</option> <replaceable>%s</replaceable></term>\n", tr_esc_str(arg->Name), tr_esc_str(arg->Format) );
if ( COMMAND_LINE_VALUE_REQUIRED == arg->Flags)
fprintf(fp, "\t\t\t\t<term><option>/%s</option> <replaceable>%s</replaceable></term>\n", tr_esc_str((LPSTR) arg->Name), tr_esc_str(arg->Format) );
else
fprintf(fp, "\t\t\t\t<term><option>/%s</option></term>\n", tr_esc_str(arg->Name) );
fprintf(fp, "\t\t\t\t<term><option>/%s</option></term>\n", tr_esc_str((LPSTR) arg->Name));
fprintf(fp, "\t\t\t\t<listitem>\n");
fprintf(fp, "\t\t\t\t\t<para>%s</para>\n", tr_esc_str(arg->Text));
fprintf(fp, "\t\t\t\t\t<para>%s</para>\n", tr_esc_str((LPSTR) arg->Text));
fprintf(fp, "\t\t\t\t</listitem>\n");
fprintf(fp, "\t\t\t</varlistentry>\n");

View File

@ -773,12 +773,12 @@ BOOL xf_pre_connect(freerdp* instance)
if (settings->Username == NULL)
{
fprintf(stderr, "--authonly, but no -u username. Please provide one.\n");
exit(1);
return FALSE;
}
if (settings->Password == NULL)
{
fprintf(stderr, "--authonly, but no -p password. Please provide one.\n");
exit(1);
return FALSE;
}
fprintf(stderr, "%s:%d: Authentication only. Don't connect to X.\n", __FILE__, __LINE__);
/* Avoid XWindows initialization and configuration below. */
@ -908,7 +908,7 @@ BOOL xf_post_connect(freerdp* instance)
if (instance->settings->RemoteFxCodec)
{
rfx_context = (void*) rfx_context_new();
rfx_context = (void*) rfx_context_new(FALSE);
xfc->rfx_context = rfx_context;
}
@ -1224,6 +1224,8 @@ void* xf_update_thread(void* arg)
wMessageQueue* queue;
freerdp* instance = (freerdp*) arg;
assert( NULL != instance);
status = 1;
queue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
@ -1241,6 +1243,7 @@ void* xf_update_thread(void* arg)
break;
}
ExitThread(0);
return NULL;
}
@ -1253,9 +1256,12 @@ void* xf_input_thread(void* arg)
int pending_status = 1;
int process_status = 1;
freerdp* instance = (freerdp*) arg;
assert(NULL != instance);
xfc = (xfContext*) instance->context;
assert(NULL != xfc);
queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
event = CreateFileDescriptorEvent(NULL, FALSE, FALSE, xfc->xfds);
while (WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0)
@ -1288,9 +1294,8 @@ void* xf_input_thread(void* arg)
break;
}
queue = freerdp_get_message_queue(instance, FREERDP_INPUT_MESSAGE_QUEUE);
MessageQueue_PostQuit(queue, 0);
ExitThread(0);
return NULL;
}
@ -1301,8 +1306,10 @@ void* xf_channels_thread(void* arg)
HANDLE event;
rdpChannels* channels;
freerdp* instance = (freerdp*) arg;
assert(NULL != instance);
xfc = (xfContext*) instance->context;
assert(NULL != xfc);
channels = instance->context->channels;
event = freerdp_channels_get_event_handle(instance);
@ -1310,9 +1317,13 @@ void* xf_channels_thread(void* arg)
while (WaitForSingleObject(event, INFINITE) == WAIT_OBJECT_0)
{
status = freerdp_channels_process_pending_messages(instance);
if (!status)
break;
xf_process_channel_event(channels, instance);
}
ExitThread(0);
return NULL;
}
@ -1356,6 +1367,7 @@ void* xf_thread(void* param)
input_event = NULL;
instance = (freerdp*) param;
assert(NULL != instance);
ZeroMemory(rfds, sizeof(rfds));
ZeroMemory(wfds, sizeof(wfds));
@ -1364,6 +1376,7 @@ void* xf_thread(void* param)
status = freerdp_connect(instance);
xfc = (xfContext*) instance->context;
assert(NULL != xfc);
/* Connection succeeded. --authonly ? */
if (instance->settings->AuthenticationOnly)
@ -1407,9 +1420,15 @@ void* xf_thread(void* param)
rcount = 0;
wcount = 0;
/*
* win8 and server 2k12 seem to have some timing issue/race condition
* when a initial sync request is send to sync the keyboard inidcators
* sending the sync event twice fixed this problem
*/
if (freerdp_focus_required(instance))
{
xf_kbd_focus_in(xfc);
xf_kbd_focus_in(xfc);
}
if (!async_transport)
@ -1527,6 +1546,10 @@ void* xf_thread(void* param)
}
}
/* Close the channels first. This will signal the internal message pipes
* that the threads should quit. */
freerdp_channels_close(channels, instance);
if (async_update)
{
wMessageQueue* update_queue = freerdp_get_message_queue(instance, FREERDP_UPDATE_MESSAGE_QUEUE);
@ -1535,6 +1558,20 @@ void* xf_thread(void* param)
CloseHandle(update_thread);
}
if (async_input)
{
wMessageQueue* 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);
}
FILE* fin = fopen("/tmp/tsmf.tid", "rt");
if (fin)
@ -1571,7 +1608,6 @@ void* xf_thread(void* param)
if (!exit_code)
exit_code = freerdp_error_info(instance);
freerdp_channels_close(channels, instance);
freerdp_channels_free(channels);
freerdp_disconnect(instance);
gdi_free(instance);
@ -1650,7 +1686,7 @@ void xf_ParamChangeEventHandler(rdpContext* context, ParamChangeEventArgs* e)
}
}
void xf_ScalingFactorChangeEventHandler(rdpContext* context, ScalingFactorChangeEventArgs* e)
static void xf_ScalingFactorChangeEventHandler(rdpContext* context, ScalingFactorChangeEventArgs* e)
{
xfContext* xfc = (xfContext*) context;
@ -1668,12 +1704,12 @@ void xf_ScalingFactorChangeEventHandler(rdpContext* context, ScalingFactorChange
xf_transform_window(xfc);
{
ResizeWindowEventArgs e;
ResizeWindowEventArgs ev;
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);
EventArgsInit(&ev, "xfreerdp");
ev.width = (int) xfc->originalWidth * xfc->settings->ScalingFactor;
ev.height = (int) xfc->originalHeight * xfc->settings->ScalingFactor;
PubSub_OnResizeWindow(((rdpContext*) xfc)->pubSub, xfc, &ev);
}
xf_draw_screen_scaled(xfc, 0, 0, 0, 0, FALSE);
@ -1683,19 +1719,19 @@ void xf_ScalingFactorChangeEventHandler(rdpContext* context, ScalingFactorChange
* Client Interface
*/
void xfreerdp_client_global_init()
static void xfreerdp_client_global_init()
{
setlocale(LC_ALL, "");
freerdp_handle_signals();
freerdp_channels_global_init();
}
void xfreerdp_client_global_uninit()
static void xfreerdp_client_global_uninit()
{
freerdp_channels_global_uninit();
}
int xfreerdp_client_start(rdpContext* context)
static int xfreerdp_client_start(rdpContext* context)
{
xfContext* xfc = (xfContext*) context;
@ -1707,15 +1743,17 @@ int xfreerdp_client_start(rdpContext* context)
return -1;
}
xfc->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_thread, context->instance, 0, NULL);
xfc->thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE) xf_thread,
context->instance, 0, NULL);
return 0;
}
int xfreerdp_client_stop(rdpContext* context)
static int xfreerdp_client_stop(rdpContext* context)
{
xfContext* xfc = (xfContext*) context;
assert(NULL != context);
if (context->settings->AsyncInput)
{
wMessageQueue* queue;
@ -1729,13 +1767,16 @@ int xfreerdp_client_stop(rdpContext* context)
xfc->disconnect = TRUE;
}
WaitForSingleObject(xfc->thread, INFINITE);
CloseHandle(xfc->thread);
if (xfc->thread)
{
CloseHandle(xfc->thread);
xfc->thread = NULL;
}
return 0;
}
int xfreerdp_client_new(freerdp* instance, rdpContext* context)
static int xfreerdp_client_new(freerdp* instance, rdpContext* context)
{
xfContext* xfc;
rdpSettings* settings;
@ -1791,7 +1832,7 @@ int xfreerdp_client_new(freerdp* instance, rdpContext* context)
return 0;
}
void xfreerdp_client_free(freerdp* instance, rdpContext* context)
static void xfreerdp_client_free(freerdp* instance, rdpContext* context)
{
xfContext* xfc = (xfContext*) context;

View File

@ -998,6 +998,8 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
surface_bits_command->destLeft, surface_bits_command->destTop,
surface_bits_command->width, surface_bits_command->height);
XFree(image);
free(xfc->bmp_codec_nsc);
xfc->bmp_codec_nsc = NULL;
xf_gdi_surface_update_frame(xfc,
surface_bits_command->destLeft, surface_bits_command->destTop,
@ -1026,6 +1028,8 @@ void xf_gdi_surface_bits(rdpContext* context, SURFACE_BITS_COMMAND* surface_bits
surface_bits_command->destLeft, surface_bits_command->destTop,
surface_bits_command->width, surface_bits_command->height);
XFree(image);
free(xfc->bmp_codec_none);
xfc->bmp_codec_none = NULL;
xf_gdi_surface_update_frame(xfc,
surface_bits_command->destLeft, surface_bits_command->destTop,

View File

@ -565,7 +565,7 @@ const char* movetype_names[] =
void xf_process_rail_server_localmovesize_event(xfContext* xfc, rdpChannels* channels, wMessage* event)
{
int x, y;
int x = 0, y = 0;
rdpRail* rail;
int direction = 0;
Window child_window;

View File

@ -832,6 +832,7 @@ void xf_SetWindowIcon(xfContext* xfc, xfWindow* window, rdpIcon* icon)
PropModeReplace, (BYTE*) propdata, propsize);
XFlush(xfc->display);
free(propdata);
}
void xf_SetWindowRects(xfContext* xfc, xfWindow* window, RECTANGLE_16* rects, int nrects)

View File

@ -23,8 +23,10 @@
#include <freerdp/client.h>
#include <freerdp/addin.h>
#include <freerdp/client/file.h>
#include <freerdp/client/cmdline.h>
#include <freerdp/client/channels.h>
int freerdp_client_common_new(freerdp* instance, rdpContext* context)
{
@ -59,6 +61,8 @@ rdpContext* freerdp_client_context_new(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
context->instance = instance;
context->settings = instance->settings;
freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0);
return context;
}
@ -113,7 +117,7 @@ int freerdp_client_parse_command_line(rdpContext* context, int argc, char** argv
if (settings->ConnectionFile)
{
return freerdp_client_parse_connection_file(context, settings->ConnectionFile);
status = freerdp_client_parse_connection_file(context, settings->ConnectionFile);
}
return status;
@ -134,35 +138,37 @@ int freerdp_client_parse_connection_file(rdpContext* context, const char* filena
int freerdp_client_parse_connection_file_buffer(rdpContext* context, BYTE* buffer, size_t size)
{
rdpFile* file;
int status = -1;
int status = -1;
file = freerdp_client_rdp_file_new();
if (freerdp_client_parse_rdp_file_buffer(file, buffer, size)
&& freerdp_client_populate_settings_from_rdp_file(file, context->settings))
{
status = 0;
}
if (freerdp_client_parse_rdp_file_buffer(file, buffer, size)
&& freerdp_client_populate_settings_from_rdp_file(file, context->settings))
{
status = 0;
}
freerdp_client_rdp_file_free(file);
return status;
return status;
}
int freerdp_client_write_connection_file(rdpContext* context, const char* filename, BOOL unicode)
{
rdpFile* file;
int status = -1;
rdpFile* file;
int status = -1;
file = freerdp_client_rdp_file_new();
if (freerdp_client_populate_rdp_file_from_settings(file, context->settings))
{
if (freerdp_client_write_rdp_file(file, filename, unicode))
{
status = 0;
}
}
file = freerdp_client_rdp_file_new();
freerdp_client_rdp_file_free(file);
if (freerdp_client_populate_rdp_file_from_settings(file, context->settings))
{
if (freerdp_client_write_rdp_file(file, filename, unicode))
{
status = 0;
}
}
return status;
freerdp_client_rdp_file_free(file);
return status;
}

View File

@ -86,7 +86,7 @@ COMMAND_LINE_ARGUMENT_A args[] =
{ "clipboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect clipboard" },
{ "serial", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, "tty", "Redirect serial device" },
{ "parallel", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Redirect parallel device" },
{ "smartcard", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Redirect smartcard device" },
{ "smartcard", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Redirect smartcard device" },
{ "printer", COMMAND_LINE_VALUE_OPTIONAL, NULL, NULL, NULL, -1, NULL, "Redirect printer device" },
{ "usb", COMMAND_LINE_VALUE_REQUIRED, NULL, NULL, NULL, -1, NULL, "Redirect USB device" },
{ "multitouch", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect multitouch input" },
@ -319,15 +319,15 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p
{
RDPDR_SMARTCARD* smartcard;
if (count < 2)
if (count < 1)
return -1;
smartcard = (RDPDR_SMARTCARD*) malloc(sizeof(RDPDR_SMARTCARD));
ZeroMemory(smartcard, sizeof(RDPDR_SMARTCARD));
smartcard->Type = RDPDR_DTYP_SMARTCARD;
smartcard->Name = _strdup(params[1]);
if (count > 1)
smartcard->Name = _strdup(params[1]);
if (count > 2)
smartcard->Path = _strdup(params[2]);
@ -340,15 +340,17 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p
{
RDPDR_SERIAL* serial;
if (count < 2)
if (count < 1)
return -1;
serial = (RDPDR_SERIAL*) malloc(sizeof(RDPDR_SERIAL));
ZeroMemory(serial, sizeof(RDPDR_SERIAL));
serial->Type = RDPDR_DTYP_SERIAL;
serial->Name = _strdup(params[1]);
serial->Path = _strdup(params[2]);
if (count > 1)
serial->Name = _strdup(params[1]);
if (count > 2)
serial->Path = _strdup(params[2]);
freerdp_device_collection_add(settings, (RDPDR_DEVICE*) serial);
settings->DeviceRedirection = TRUE;
@ -359,15 +361,17 @@ int freerdp_client_add_device_channel(rdpSettings* settings, int count, char** p
{
RDPDR_PARALLEL* parallel;
if (count < 2)
if (count < 1)
return -1;
parallel = (RDPDR_PARALLEL*) malloc(sizeof(RDPDR_PARALLEL));
ZeroMemory(parallel, sizeof(RDPDR_PARALLEL));
parallel->Type = RDPDR_DTYP_PARALLEL;
parallel->Name = _strdup(params[1]);
parallel->Path = _strdup(params[2]);
if (count > 1)
parallel->Name = _strdup(params[1]);
if (count > 1)
parallel->Path = _strdup(params[2]);
freerdp_device_collection_add(settings, (RDPDR_DEVICE*) parallel);
settings->DeviceRedirection = TRUE;
@ -424,6 +428,9 @@ char** freerdp_command_line_parse_comma_separated_values(char* list, int* count)
nArgs = nCommas = 0;
if (!list)
return NULL;
for (index = 0; list[index]; index++)
nCommas += (list[index] == ',') ? 1 : 0;
@ -856,6 +863,26 @@ int freerdp_map_keyboard_layout_name_to_id(char* name)
return 0;
}
int freerdp_detect_command_line_pre_filter(void* context, int index, int argc, LPCSTR* argv)
{
int length;
if (index == 1)
{
length = strlen(argv[index]);
if (length > 4)
{
if (_stricmp(&(argv[index])[length - 4], ".rdp") == 0)
{
return 1;
}
}
}
return 0;
}
int freerdp_detect_windows_style_command_line_syntax(int argc, char** argv, int* count)
{
int status;
@ -869,7 +896,12 @@ int freerdp_detect_windows_style_command_line_syntax(int argc, char** argv, int*
*count = 0;
detect_status = 0;
CommandLineClearArgumentsA(args);
status = CommandLineParseArgumentsA(argc, (const char**) argv, args, flags, NULL, NULL, NULL);
status = CommandLineParseArgumentsA(argc, (const char**) argv, args, flags,
NULL, freerdp_detect_command_line_pre_filter, NULL);
if (status < 0)
return status;
arg = args;
@ -902,7 +934,12 @@ int freerdp_detect_posix_style_command_line_syntax(int argc, char** argv, int* c
*count = 0;
detect_status = 0;
CommandLineClearArgumentsA(args);
status = CommandLineParseArgumentsA(argc, (const char**) argv, args, flags, NULL, NULL, NULL);
status = CommandLineParseArgumentsA(argc, (const char**) argv, args, flags,
NULL, freerdp_detect_command_line_pre_filter, NULL);
if (status < 0)
return status;
arg = args;
@ -945,8 +982,10 @@ BOOL freerdp_client_detect_command_line(int argc, char** argv, DWORD* flags)
*flags = COMMAND_LINE_SEPARATOR_COLON;
*flags |= COMMAND_LINE_SIGIL_SLASH | COMMAND_LINE_SIGIL_PLUS_MINUS;
}
else
else if (old_cli_status >= 0)
{
/* Ignore legacy parsing in case there is an error in the command line. */
if ((old_cli_status == 1) || ((old_cli_count > posix_cli_count) && (old_cli_status != -1)))
{
*flags = COMMAND_LINE_SEPARATOR_SPACE;
@ -966,12 +1005,7 @@ int freerdp_client_command_line_status_print(int argc, char** argv, rdpSettings*
{
COMMAND_LINE_ARGUMENT_A* arg;
if (status == COMMAND_LINE_STATUS_PRINT_HELP)
{
freerdp_client_print_command_line_help(argc, argv);
return COMMAND_LINE_STATUS_PRINT_HELP;
}
else if (status == COMMAND_LINE_STATUS_PRINT_VERSION)
if (status == COMMAND_LINE_STATUS_PRINT_VERSION)
{
freerdp_client_print_version();
return COMMAND_LINE_STATUS_PRINT_VERSION;
@ -1015,6 +1049,11 @@ int freerdp_client_command_line_status_print(int argc, char** argv, rdpSettings*
return COMMAND_LINE_STATUS_PRINT;
}
else if (status < 0)
{
freerdp_client_print_command_line_help(argc, argv);
return COMMAND_LINE_STATUS_PRINT_HELP;
}
return 0;
}
@ -1029,8 +1068,6 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
BOOL compatibility;
COMMAND_LINE_ARGUMENT_A* arg;
freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0);
compatibility = freerdp_client_detect_command_line(argc, argv, &flags);
if (compatibility)
@ -1041,8 +1078,12 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
else
{
CommandLineClearArgumentsA(args);
status = CommandLineParseArgumentsA(argc, (const char**) argv, args, flags, settings,
freerdp_client_command_line_pre_filter, freerdp_client_command_line_post_filter);
if (status < 0)
return status;
}
@ -1153,6 +1194,8 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
{
settings->MonitorIds[i] = atoi(p[i]);
}
free(p);
}
}
CommandLineSwitchCase(arg, "monitor-list")
@ -1423,7 +1466,6 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
settings->RemoteFxCodec = TRUE;
settings->FastPathOutput = TRUE;
settings->ColorDepth = 32;
settings->PerformanceFlags = PERF_FLAG_NONE;
settings->LargePointerFlag = TRUE;
settings->FrameMarkerCommandEnabled = TRUE;
}
@ -1624,32 +1666,13 @@ int freerdp_client_parse_command_line_arguments(int argc, char** argv, rdpSettin
}
CommandLineSwitchDefault(arg)
{
}
CommandLineSwitchEnd(arg)
}
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
settings->PerformanceFlags = PERF_FLAG_NONE;
if (settings->AllowFontSmoothing)
settings->PerformanceFlags |= PERF_ENABLE_FONT_SMOOTHING;
if (settings->AllowDesktopComposition)
settings->PerformanceFlags |= PERF_ENABLE_DESKTOP_COMPOSITION;
if (settings->DisableWallpaper)
settings->PerformanceFlags |= PERF_DISABLE_WALLPAPER;
if (settings->DisableFullWindowDrag)
settings->PerformanceFlags |= PERF_DISABLE_FULLWINDOWDRAG;
if (settings->DisableMenuAnims)
settings->PerformanceFlags |= PERF_DISABLE_MENUANIMATIONS;
if (settings->DisableThemes)
settings->PerformanceFlags |= PERF_DISABLE_THEMING;
freerdp_performance_flags_make(settings);
if (settings->GatewayEnabled)
{

View File

@ -125,6 +125,9 @@ int freerdp_client_old_process_plugin(rdpSettings* settings, ADDIN_ARGV* args)
}
else if (strcmp(args->argv[0], "rdpdr") == 0)
{
if (args->argc < 2)
return -1;
if ((strcmp(args->argv[1], "disk") == 0) ||
(strcmp(args->argv[1], "drive") == 0))
{
@ -156,11 +159,17 @@ int freerdp_client_old_process_plugin(rdpSettings* settings, ADDIN_ARGV* args)
}
else if (strcmp(args->argv[0], "rdpsnd") == 0)
{
if (args->argc < 2)
return -1;
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)
{
if (args->argc < 2)
return -1;
settings->RemoteApplicationProgram = _strdup(args->argv[1]);
}
else
@ -246,10 +255,9 @@ int freerdp_client_old_command_line_pre_filter(void* context, int index, int arg
a = p;
}
p = strchr(p, ':');
if (p != NULL)
{
p = strchr(p, ':');
length = p - a;
args->argv[j + 1] = malloc(length + 1);
CopyMemory(args->argv[j + 1], a, length);
@ -279,6 +287,11 @@ int freerdp_client_old_command_line_pre_filter(void* context, int index, int arg
}
}
for (i=0; i<args->argc; i++)
free(args->argv[i]);
free(args->argv);
free(args);
return (index - old_index);
}
@ -302,6 +315,7 @@ int freerdp_detect_old_command_line_syntax(int argc, char** argv, int* count)
detect_status = 0;
flags = COMMAND_LINE_SEPARATOR_SPACE;
flags |= COMMAND_LINE_SIGIL_DASH | COMMAND_LINE_SIGIL_DOUBLE_DASH;
flags |= COMMAND_LINE_SIGIL_NOT_ESCAPED;
settings = (rdpSettings*) malloc(sizeof(rdpSettings));
ZeroMemory(settings, sizeof(rdpSettings));
@ -309,6 +323,8 @@ int freerdp_detect_old_command_line_syntax(int argc, char** argv, int* count)
CommandLineClearArgumentsA(old_args);
status = CommandLineParseArgumentsA(argc, (const char**) argv, old_args, flags, settings,
freerdp_client_old_command_line_pre_filter, NULL);
if (status < 0)
return status;
arg = old_args;
@ -370,16 +386,12 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
flags = COMMAND_LINE_SEPARATOR_SPACE;
flags |= COMMAND_LINE_SIGIL_DASH | COMMAND_LINE_SIGIL_DOUBLE_DASH;
flags |= COMMAND_LINE_SIGIL_ENABLE_DISABLE;
flags |= COMMAND_LINE_SIGIL_NOT_ESCAPED;
status = CommandLineParseArgumentsA(argc, (const char**) argv, old_args, flags, settings,
freerdp_client_old_command_line_pre_filter, freerdp_client_old_command_line_post_filter);
if (status == COMMAND_LINE_STATUS_PRINT_HELP)
{
freerdp_client_print_command_line_help(argc, argv);
return COMMAND_LINE_STATUS_PRINT_HELP;
}
else if (status == COMMAND_LINE_STATUS_PRINT_VERSION)
if (status == COMMAND_LINE_STATUS_PRINT_VERSION)
{
freerdp_client_print_version();
return COMMAND_LINE_STATUS_PRINT_VERSION;
@ -388,6 +400,15 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
{
return COMMAND_LINE_STATUS_PRINT;
}
else if (status < 0)
{
if (status != COMMAND_LINE_STATUS_PRINT_HELP)
{
}
freerdp_client_print_command_line_help(argc, argv);
return COMMAND_LINE_STATUS_PRINT_HELP;
}
arg = old_args;
@ -515,6 +536,7 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
else
{
settings->PerformanceFlags = type;
freerdp_performance_flags_split(settings);
}
fprintf(stderr, "-x %s -> /network:", arg->Value);

View File

@ -42,7 +42,7 @@
#include <winpr/crt.h>
#define DEBUG_CLIENT_FILE 1
//#define DEBUG_CLIENT_FILE 1
static BYTE BOM_UTF16_LE[2] = { 0xFF, 0xFE };
static WCHAR CR_LF_STR_W[] = { '\r', '\n', '\0' };
@ -269,6 +269,18 @@ BOOL freerdp_client_rdp_file_set_string(rdpFile* file, char* name, char* value)
return TRUE;
}
void freerdp_client_add_option(rdpFile* file, char* option)
{
while ((file->argc + 1) > file->argSize)
{
file->argSize *= 2;
file->argv = (char**) realloc(file->argv, file->argSize * sizeof(char*));
}
file->argv[file->argc] = _strdup(option);
(file->argc)++;
}
void freerdp_client_parse_rdp_file_string_unicode(rdpFile* file, WCHAR* name, WCHAR* value)
{
int length;
@ -296,6 +308,21 @@ void freerdp_client_parse_rdp_file_string_ascii(rdpFile* file, char* name, char*
freerdp_client_rdp_file_set_string(file, name, value);
}
void freerdp_client_parse_rdp_file_option_unicode(rdpFile* file, WCHAR* option)
{
char* optionA = NULL;
ConvertFromUnicode(CP_UTF8, 0, option, -1, &optionA, 0, NULL, NULL);
freerdp_client_add_option(file, optionA);
free(optionA);
}
void freerdp_client_parse_rdp_file_option_ascii(rdpFile* file, char* option)
{
freerdp_client_add_option(file, option);
}
BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, BYTE* buffer, size_t size)
{
int length;
@ -317,6 +344,12 @@ BOOL freerdp_client_parse_rdp_file_buffer_ascii(rdpFile* file, BYTE* buffer, siz
beg = line;
end = &line[length - 1];
if (beg[0] == '/')
{
freerdp_client_parse_rdp_file_option_ascii(file, line);
goto next_line; /* FreeRDP option */
}
d1 = strchr(line, ':');
if (!d1)
@ -383,6 +416,13 @@ BOOL freerdp_client_parse_rdp_file_buffer_unicode(rdpFile* file, BYTE* buffer, s
beg = line;
end = &line[length - 1];
if (beg[0] == '/')
{
/* FreeRDP option */
freerdp_client_parse_rdp_file_option_unicode(file, line);
goto next_line;
}
d1 = _wcschr(line, ':');
if (!d1)
@ -456,7 +496,10 @@ BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name)
fseek(fp, 0, SEEK_SET);
if (file_size < 1)
{
fclose(fp);
return FALSE;
}
buffer = (BYTE*) malloc(file_size + 2);
read_size = fread(buffer, file_size, 1, fp);
@ -466,6 +509,7 @@ BOOL freerdp_client_parse_rdp_file(rdpFile* file, const char* name)
if (!ferror(fp))
read_size = file_size;
}
fclose(fp);
if (read_size < 1)
{
@ -529,16 +573,16 @@ BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, rdpSettings*
return TRUE;
}
BOOL freerdp_client_write_rdp_file(rdpFile* file, const char* name, BOOL unicode)
{
int rc = 0;
int rc = 0;
char* buffer;
int len, len2;
FILE* fp = NULL;
WCHAR* unicodestr = NULL;
len = freerdp_client_write_rdp_file_buffer(file, NULL, 0);
if (len <= 0)
{
fprintf(stderr, "freerdp_client_write_rdp_file: Error determining buffer size.\n");
@ -547,9 +591,11 @@ BOOL freerdp_client_write_rdp_file(rdpFile* file, const char* name, BOOL unicode
buffer = (char*) malloc((len + 1) * sizeof(char));
len2 = freerdp_client_write_rdp_file_buffer(file, buffer, len + 1);
if (len2 == len)
{
fp = fopen(name, "w+b");
if (fp != NULL)
{
if (unicode)
@ -560,22 +606,22 @@ BOOL freerdp_client_write_rdp_file(rdpFile* file, const char* name, BOOL unicode
fwrite(BOM_UTF16_LE, sizeof(BYTE), 2, fp);
fwrite(unicodestr, 2, len, fp);
free(unicodestr);
free(unicodestr);
}
else
{
fwrite(buffer, 1, len, fp);
}
rc = fflush(fp);
rc = fclose(fp);
rc = fflush(fp);
rc = fclose(fp);
}
}
if (buffer != NULL)
free(buffer);
return (rc == 0);
return (rc == 0);
}
#define WRITE_RDP_FILE_DECLARE(_file, _buffer, _size) \
@ -661,7 +707,6 @@ size_t freerdp_client_write_rdp_file_buffer(rdpFile* file, char* buffer, size_t
WRITE_RDP_FILE_VALUE_RETURN
}
BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings* settings)
{
if (~((size_t) file->Domain))
@ -669,14 +714,20 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
if (~((size_t) file->Username))
{
char* user;
char* domain;
char* user = NULL;
char* domain = NULL;
freerdp_parse_username(file->Username, &user, &domain);
freerdp_set_param_string(settings, FreeRDP_Username, user);
if (domain != NULL)
if (domain)
freerdp_set_param_string(settings, FreeRDP_Domain, domain);
if (user)
free(user);
if (domain)
free(domain);
}
if (~file->ServerPort)
@ -703,12 +754,52 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
if (~((size_t) file->ShellWorkingDirectory))
freerdp_set_param_string(settings, FreeRDP_ShellWorkingDirectory, file->ShellWorkingDirectory);
if (~file->ScreenModeId)
{
/**
* Screen Mode Id:
* http://technet.microsoft.com/en-us/library/ff393692/
*
* This setting corresponds to the selection in the Display
* configuration slider on the Display tab under Options in RDC.
*
* Values:
*
* 0: The remote session will appear in a window.
* 1: The remote session will appear full screen.
*/
freerdp_set_param_bool(settings, FreeRDP_Fullscreen,
(file->ScreenModeId == 1) ? TRUE : FALSE);
}
if (~((size_t) file->LoadBalanceInfo))
{
settings->LoadBalanceInfo = (BYTE*) _strdup(file->LoadBalanceInfo);
settings->LoadBalanceInfoLength = strlen((char*) settings->LoadBalanceInfo);
}
if (~file->AuthenticationLevel)
{
/**
* Authentication Level:
* http://technet.microsoft.com/en-us/library/ff393709/
*
* This setting corresponds to the selection in the If server authentication
* fails drop-down list on the Advanced tab under Options in RDC.
*
* Values:
*
* 0: If server authentication fails, connect to the computer without warning (Connect and dont warn me).
* 1: If server authentication fails, do not establish a connection (Do not connect).
* 2: If server authentication fails, show a warning and allow me to connect or refuse the connection (Warn me).
* 3: No authentication requirement is specified.
*/
freerdp_set_param_bool(settings, FreeRDP_IgnoreCertificate,
(file->AuthenticationLevel == 0) ? TRUE : FALSE);
}
if (~file->ConnectionType)
freerdp_set_param_uint32(settings, FreeRDP_ConnectionType, file->ConnectionType);
@ -729,6 +820,9 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
}
}
if (~file->Compression)
freerdp_set_param_bool(settings, FreeRDP_CompressionEnabled, file->Compression);
if (~((size_t) file->GatewayHostname))
freerdp_set_param_string(settings, FreeRDP_GatewayHostname, file->GatewayHostname);
@ -765,6 +859,106 @@ BOOL freerdp_client_populate_settings_from_rdp_file(rdpFile* file, rdpSettings*
if (~file->UseMultiMon)
freerdp_set_param_bool(settings, FreeRDP_UseMultimon, file->UseMultiMon);
if (~file->AllowFontSmoothing)
freerdp_set_param_bool(settings, FreeRDP_AllowFontSmoothing, file->AllowFontSmoothing);
if (~file->DisableWallpaper)
freerdp_set_param_bool(settings, FreeRDP_DisableWallpaper, file->DisableWallpaper);
if (~file->DisableFullWindowDrag)
freerdp_set_param_bool(settings, FreeRDP_DisableFullWindowDrag, file->DisableFullWindowDrag);
if (~file->DisableMenuAnims)
freerdp_set_param_bool(settings, FreeRDP_DisableMenuAnims, file->DisableMenuAnims);
if (~file->DisableThemes)
freerdp_set_param_bool(settings, FreeRDP_DisableThemes, file->DisableThemes);
if (~file->AllowDesktopComposition)
freerdp_set_param_bool(settings, FreeRDP_DisableCursorShadow, file->AllowDesktopComposition);
if (~file->BitmapCachePersistEnable)
freerdp_set_param_bool(settings, FreeRDP_BitmapCachePersistEnabled, file->BitmapCachePersistEnable);
if (~file->DisableRemoteAppCapsCheck)
freerdp_set_param_bool(settings, FreeRDP_DisableRemoteAppCapsCheck, file->DisableRemoteAppCapsCheck);
if (~file->AutoReconnectionEnabled)
freerdp_set_param_bool(settings, FreeRDP_AutoReconnectionEnabled, file->AutoReconnectionEnabled);
if (~file->AutoReconnectMaxRetries)
freerdp_set_param_uint32(settings, FreeRDP_AutoReconnectMaxRetries, file->AutoReconnectMaxRetries);
if (~file->RedirectSmartCards)
freerdp_set_param_bool(settings, FreeRDP_RedirectSmartCards, file->RedirectSmartCards);
if (~file->RedirectClipboard)
freerdp_set_param_bool(settings, FreeRDP_RedirectClipboard, file->RedirectClipboard);
if (~file->RedirectPrinters)
freerdp_set_param_bool(settings, FreeRDP_RedirectPrinters, file->RedirectPrinters);
if (~file->RedirectDrives)
freerdp_set_param_bool(settings, FreeRDP_RedirectDrives, file->RedirectDrives);
if (~file->RedirectPosDevices)
{
freerdp_set_param_bool(settings, FreeRDP_RedirectSerialPorts, file->RedirectComPorts);
freerdp_set_param_bool(settings, FreeRDP_RedirectParallelPorts, file->RedirectComPorts);
}
if (~file->RedirectComPorts)
{
freerdp_set_param_bool(settings, FreeRDP_RedirectSerialPorts, file->RedirectComPorts);
freerdp_set_param_bool(settings, FreeRDP_RedirectParallelPorts, file->RedirectComPorts);
}
if (~file->RedirectDirectX)
{
/* What is this?! */
}
if (~((size_t) file->DevicesToRedirect))
{
/**
* Devices to redirect:
* http://technet.microsoft.com/en-us/library/ff393728/
*
* This setting corresponds to the selections for Other supported Plug and Play
* (PnP) devices under More on the Local Resources tab under Options in RDC.
*
* Values:
*
* '*':
* Redirect all supported Plug and Play devices.
*
* 'DynamicDevices':
* Redirect any supported Plug and Play devices that are connected later.
*
* The hardware ID for the supported Plug and Play device:
* Redirect the specified supported Plug and Play device.
*
* Examples:
* devicestoredirect:s:*
* devicestoredirect:s:DynamicDevices
* devicestoredirect:s:USB\VID_04A9&PID_30C1\6&4BD985D&0&2;,DynamicDevices
*
*/
freerdp_set_param_bool(settings, FreeRDP_RedirectDrives, TRUE);
}
if (~((size_t) file->DrivesToRedirect))
{
/*
* Drives to redirect:
*
* Very similar to DevicesToRedirect, but can contain a
* comma-separated list of drive letters to redirect.
*/
freerdp_set_param_bool(settings, FreeRDP_RedirectDrives, TRUE);
}
if (file->argc > 1)
{
freerdp_client_parse_command_line_arguments(file->argc, file->argv, settings);
}
return TRUE;
}
@ -773,12 +967,35 @@ rdpFile* freerdp_client_rdp_file_new()
rdpFile* file;
file = (rdpFile*) malloc(sizeof(rdpFile));
FillMemory(file, sizeof(rdpFile), 0xFF);
if (file)
{
FillMemory(file, sizeof(rdpFile), 0xFF);
file->argc = 0;
file->argSize = 32;
file->argv = (char**) malloc(file->argSize * sizeof(char*));
freerdp_client_add_option(file, "freerdp");
}
return file;
}
void freerdp_client_rdp_file_free(rdpFile* file)
{
free(file);
int i;
if (file)
{
if (file->argv)
{
for (i = 0; i < file->argc; i++)
free(file->argv[i]);
free(file->argv);
}
free(file);
}
}

View File

@ -15,6 +15,16 @@
# See the License for the specific language governing permissions and
# limitations under the License.
set(JAVA_DEBUG_DEFAULT "off")
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
set(JAVA_DEBUG_DEFAULT "on")
endif()
option(WITH_DEBUG_ANDROID_JNI "Enable debug output for android jni bindings" ${DEFAULT_DEBUG_OPTION})
option(ANDROID_BUILD_JAVA "Automatically android java code - build type depends on CMAKE_BUILD_TYPE" ON)
option(ANDROID_BUILD_JAVA_DEBUG "Create a android debug package" ON)
option(ANDROID_BUILD_JAVA_DEBUG "Create a android debug package" ${JAVA_DEBUG_DEFAULT})
set(ANDROID_APP_TARGET_SDK 11 CACHE STRING "Application target android SDK")
set(ANDROID_APP_MIN_SDK 8 CACHE STRING "Application minimum android SDK requirement")
set(ANDROID_APP_GOOGLE_TARGET_SDK "16" CACHE STRING "Application target google SDK")

View File

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

View File

@ -156,3 +156,10 @@ Java classes:
After that you need to implement the functionality in client/Android/jni/android_freerdp.c and add
the call to client/Android/jni/generated/android_freerdp_jni.c.
After that FreeRDP and the Android package need to be rebuilt to include the latest libfreerdp-android in the package.
Android CMake related Variables
-------------------------------
ANDROID_APP_TARGET_SDK ... specifies the desired android target SDK, currently 11
ANDROID_APP_MIN_SDK ... specifies the minimum android SDK version supported, currently 8
ANDROID_APP_GOOGLE_TARGET_SDK ... specifies the minimum google SDK requirement, currently 16

View File

@ -21,6 +21,7 @@
#ifndef FREERDP_CHANNEL_RDPDR_H
#define FREERDP_CHANNEL_RDPDR_H
#include <winpr/nt.h>
#include <winpr/crt.h>
#include <winpr/file.h>
#include <winpr/synch.h>
@ -102,54 +103,16 @@ enum IRP_MN
};
/* DR_CREATE_REQ.CreateDisposition */
enum FILE_CREATE_DISPOSITION
{
FILE_SUPERSEDE = 0x00000000,
FILE_OPEN = 0x00000001,
FILE_CREATE = 0x00000002,
FILE_OPEN_IF = 0x00000003,
FILE_OVERWRITE = 0x00000004,
FILE_OVERWRITE_IF = 0x00000005
};
/* DR_CREATE_REQ.CreateOptions [MS-SMB2] */
enum FILE_CREATE_OPTION
{
FILE_DIRECTORY_FILE = 0x00000001,
FILE_NON_DIRECTORY_FILE = 0x00000040,
FILE_COMPLETE_IF_OPLOCKED = 0x00000100,
FILE_DELETE_ON_CLOSE = 0x00001000,
FILE_OPEN_REPARSE_POINT = 0x00200000,
FILE_OPEN_FOR_FREE_SPACE_QUERY = 0x00800000
};
/* DR_CREATE_REQ.DesiredAccess [MS-SMB2] */
#ifndef _WIN32
#if 0
#define FILE_READ_DATA 0x00000001
#define FILE_WRITE_DATA 0x00000002
#define FILE_APPEND_DATA 0x00000004
#define FILE_READ_EA 0x00000008
#define FILE_WRITE_EA 0x00000010
#define FILE_EXECUTE 0x00000020
#define FILE_READ_ATTRIBUTES 0x00000080
#define FILE_WRITE_ATTRIBUTES 0x00000100
#endif
#include <winpr/io.h>
#endif
/* DR_CREATE_RSP.Information */
/* DR_DRIVE_CREATE_RSP.DeviceCreateResponse */
enum FILE_RESPONSE
{
FILE_SUPERSEDED = 0x00000000,
FILE_OPENED = 0x00000001,
FILE_OVERWRITTEN = 0x00000003
};
#define FILE_OPENED 0x00000001
#define FILE_OVERWRITTEN 0x00000003
/* DR_CORE_CLIENT_ANNOUNCE_RSP.VersionMinor */
enum RDPDR_MINOR_RDP_VERSION
@ -211,73 +174,6 @@ enum RDP_LOWIO_OP
RDP_LOWIO_OP_UNLOCK_MULTIPLE = 0x00000005
};
/* NTSTATUS values */
/* http://msdn.microsoft.com/en-us/library/cc704588.aspx */
enum NTSTATUS
{
STATUS_SUCCESS = 0x00000000,
#ifndef _WIN32
STATUS_TIMEOUT = 0x00000102,
STATUS_PENDING = 0x00000103,
#endif
STATUS_REPARSE = 0x00000104,
STATUS_MORE_ENTRIES = 0x00000105,
STATUS_NOT_ALL_ASSIGNED = 0x00000106,
STATUS_OPLOCK_BREAK_IN_PROGRESS = 0x00000108,
STATUS_VOLUME_MOUNTED = 0x00000109,
STATUS_NOTIFY_CLEANUP = 0x0000010B,
STATUS_NOTIFY_ENUM_DIR = 0x0000010C,
STATUS_NO_QUOTAS_FOR_ACCOUNT = 0x0000010D,
STATUS_FILE_LOCKED_WITH_ONLY_READERS = 0x0000012A,
STATUS_FILE_LOCKED_WITH_WRITERS = 0x0000012B,
STATUS_WAIT_FOR_OPLOCK = 0x00000367,
STATUS_OBJECT_NAME_EXISTS = 0x40000000,
STATUS_BAD_CURRENT_DIRECTORY = 0x40000007,
STATUS_NO_MORE_FILES = 0x80000006,
STATUS_DEVICE_PAPER_EMPTY = 0x8000000E,
STATUS_DEVICE_POWERED_OFF = 0x8000000F,
STATUS_DEVICE_OFF_LINE = 0x80000010,
STATUS_DEVICE_BUSY = 0x80000011,
STATUS_NO_MORE_ENTRIES = 0x8000001A,
STATUS_UNSUCCESSFUL = 0xC0000001,
STATUS_NOT_IMPLEMENTED = 0xC0000002,
STATUS_INVALID_INFO_CLASS = 0xC0000003,
#ifndef _WIN32
STATUS_INVALID_HANDLE = 0xC0000008,
STATUS_INVALID_PARAMETER = 0xC000000D,
#endif
STATUS_NO_SUCH_DEVICE = 0xC000000E,
STATUS_NO_SUCH_FILE = 0xC000000F,
STATUS_INVALID_DEVICE_REQUEST = 0xC0000010,
STATUS_END_OF_FILE = 0xC0000011,
STATUS_NO_MEDIA_IN_DEVICE = 0xC0000013,
STATUS_UNRECOGNIZED_MEDIA = 0xC0000014,
STATUS_ACCESS_DENIED = 0xc0000022,
STATUS_OBJECT_NAME_INVALID = 0xC0000033,
STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034,
STATUS_OBJECT_NAME_COLLISION = 0xc0000035,
STATUS_PORT_DISCONNECTED = 0xC0000037,
STATUS_OBJECT_PATH_INVALID = 0xC0000039,
STATUS_OBJECT_PATH_NOT_FOUND = 0xC000003A,
STATUS_INVALID_PORT_HANDLE = 0xC0000042,
STATUS_DELETE_PENDING = 0xC0000056,
STATUS_DISK_FULL = 0xC000007F,
STATUS_DEVICE_NOT_READY = 0xC00000A3,
STATUS_IO_TIMEOUT = 0xC00000B5,
STATUS_FILE_IS_A_DIRECTORY = 0xC00000BA,
STATUS_NOT_SUPPORTED = 0xC00000BB,
STATUS_PRINT_QUEUE_FULL = 0xC00000C6,
STATUS_PRINT_CANCELLED = 0xC00000C8,
STATUS_DIRECTORY_NOT_EMPTY = 0xC0000101,
STATUS_FILE_CORRUPT_ERROR = 0xC0000102,
STATUS_NOT_A_DIRECTORY = 0xC0000103,
STATUS_NAME_TOO_LONG = 0xC0000106,
STATUS_CANCELLED = 0xC0000120,
STATUS_CANNOT_DELETE = 0xC0000121,
STATUS_FILE_DELETED = 0xC0000123,
STATUS_FILE_CLOSED = 0xC0000128
};
enum RDPDR_PRINTER_ANNOUNCE_FLAG
{
RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII = 0x00000001,
@ -384,50 +280,6 @@ enum FILE_FS_DEVICE_FLAG
FILE_DEVICE_SECURE_OPEN = 0x00000100
};
enum FILE_INFORMATION_CLASS
{
FileDirectoryInformation = 1,
FileFullDirectoryInformation,
FileBothDirectoryInformation,
FileBasicInformation,
FileStandardInformation,
FileInternalInformation,
FileEaInformation,
FileAccessInformation,
FileNameInformation,
FileRenameInformation,
FileLinkInformation,
FileNamesInformation,
FileDispositionInformation,
FilePositionInformation,
FileFullEaInformation,
FileModeInformation,
FileAlignmentInformation,
FileAllInformation,
FileAllocationInformation,
FileEndOfFileInformation,
FileAlternateNameInformation,
FileStreamInformation,
FilePipeInformation,
FilePipeLocalInformation,
FilePipeRemoteInformation,
FileMailslotQueryInformation,
FileMailslotSetInformation,
FileCompressionInformation,
FileObjectIdInformation,
FileUnknownInformation1,
FileMoveClusterInformation,
FileQuotaInformation,
FileReparsePointInformation,
FileNetworkOpenInformation,
FileAttributeTagInformation,
FileTrackingInformation,
FileIdBothDirectoryInformation,
FileIdFullDirectoryInformation,
FileValidDataLengthInformation,
FileShortNameInformation
};
enum FILE_FS_INFORMATION_CLASS
{
FileFsVolumeInformation = 1,

View File

@ -35,17 +35,27 @@
#include <freerdp/types.h>
#include <freerdp/peer.h>
typedef struct WTSVirtualChannelManager WTSVirtualChannelManager;
#define WTS_CHANNEL_OPTION_DYNAMIC 0x00000001
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
//#include <winpr/wtsapi.h>
typedef enum _WTS_VIRTUAL_CLASS
{
WTSVirtualClientData,
WTSVirtualFileHandle,
WTSVirtualChannelReady
WTSVirtualEventHandle, /* Extended */
WTSVirtualChannelReady /* Extended */
} WTS_VIRTUAL_CLASS;
#define WTS_CHANNEL_OPTION_DYNAMIC 0x00000001
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_LOW 0x00000000
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED 0x00000002
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_HIGH 0x00000004
#define WTS_CHANNEL_OPTION_DYNAMIC_PRI_REAL 0x00000006
#define WTS_CHANNEL_OPTION_DYNAMIC_NO_COMPRESS 0x00000008
typedef struct WTSVirtualChannelManager WTSVirtualChannelManager;
#ifdef __cplusplus
extern "C" {
#endif
@ -55,9 +65,10 @@ extern "C" {
*/
FREERDP_API WTSVirtualChannelManager* WTSCreateVirtualChannelManager(freerdp_peer* client);
FREERDP_API void WTSDestroyVirtualChannelManager(WTSVirtualChannelManager* vcm);
FREERDP_API void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm,
void** fds, int* fds_count);
FREERDP_API void WTSVirtualChannelManagerGetFileDescriptor(WTSVirtualChannelManager* vcm, void** fds, int* fds_count);
FREERDP_API BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelManager* vcm);
FREERDP_API HANDLE WTSVirtualChannelManagerGetEventHandle(WTSVirtualChannelManager* vcm);
/**
* Opens a static or dynamic virtual channel and return the handle. If the
@ -69,10 +80,10 @@ FREERDP_API BOOL WTSVirtualChannelManagerCheckFileDescriptor(WTSVirtualChannelMa
* Static virtual channels must be opened from the main thread. Dynamic virtual channels
* can be opened from any thread.
*/
FREERDP_API void* WTSVirtualChannelOpenEx(
/* __in */ WTSVirtualChannelManager* vcm,
/* __in */ const char* pVirtualName,
/* __in */ UINT32 flags);
// WINPR_API HANDLE WTSVirtualChannelOpenEx(DWORD SessionId, LPSTR pVirtualName, DWORD flags);
WINPR_API HANDLE WTSVirtualChannelManagerOpenEx(WTSVirtualChannelManager* vcm, LPSTR pVirtualName, DWORD flags);
/**
* Returns information about a specified virtual channel.
@ -80,17 +91,14 @@ FREERDP_API void* WTSVirtualChannelOpenEx(
* Servers use this function to gain access to a virtual channel file handle
* that can be used for asynchronous I/O.
*/
FREERDP_API BOOL WTSVirtualChannelQuery(
/* __in */ void* hChannelHandle,
/* __in */ WTS_VIRTUAL_CLASS WtsVirtualClass,
/* __out */ void** ppBuffer,
/* __out */ UINT32* pBytesReturned);
WINPR_API BOOL WTSVirtualChannelQuery(HANDLE hChannelHandle, WTS_VIRTUAL_CLASS WtsVirtualClass, PVOID* ppBuffer, DWORD* pBytesReturned);
/**
* Frees memory allocated by WTSVirtualChannelQuery
*/
FREERDP_API void WTSFreeMemory(
/* __in */ void* pMemory);
WINPR_API VOID WTSFreeMemory(PVOID pMemory);
/**
* Reads data from the server end of a virtual channel.
@ -109,27 +117,20 @@ FREERDP_API void WTSFreeMemory(
* The caller should use the file handle returned by WTSVirtualChannelQuery to
* determine whether a packet has arrived.
*/
FREERDP_API BOOL WTSVirtualChannelRead(
/* __in */ void* hChannelHandle,
/* __in */ UINT32 TimeOut,
/* __out */ BYTE* Buffer,
/* __in */ UINT32 BufferSize,
/* __out */ UINT32* pBytesRead);
WINPR_API BOOL WTSVirtualChannelRead(HANDLE hChannelHandle, ULONG TimeOut, PCHAR Buffer, ULONG BufferSize, PULONG pBytesRead);
/**
* Writes data to the server end of a virtual channel.
*/
FREERDP_API BOOL WTSVirtualChannelWrite(
/* __in */ void* hChannelHandle,
/* __in */ BYTE* Buffer,
/* __in */ UINT32 Length,
/* __out */ UINT32* pBytesWritten);
WINPR_API BOOL WTSVirtualChannelWrite(HANDLE hChannelHandle, PCHAR Buffer, ULONG Length, PULONG pBytesWritten);
/**
* Closes an open virtual channel handle.
*/
FREERDP_API BOOL WTSVirtualChannelClose(
/* __in */ void* hChannelHandle);
WINPR_API BOOL WTSVirtualChannelClose(HANDLE hChannelHandle);
#ifdef __cplusplus
}

View File

@ -20,6 +20,8 @@
#ifndef FREERDP_CHANNEL_CLIENT_CLIPRDR_H
#define FREERDP_CHANNEL_CLIENT_CLIPRDR_H
#include <freerdp/types.h>
/**
* Client Interface
*/
@ -52,6 +54,48 @@ struct _cliprdr_client_context
#define CB_FORMAT_JPEG 0xD012
#define CB_FORMAT_GIF 0xD013
/* CLIPRDR_HEADER.msgType */
#define CB_MONITOR_READY 0x0001
#define CB_FORMAT_LIST 0x0002
#define CB_FORMAT_LIST_RESPONSE 0x0003
#define CB_FORMAT_DATA_REQUEST 0x0004
#define CB_FORMAT_DATA_RESPONSE 0x0005
#define CB_TEMP_DIRECTORY 0x0006
#define CB_CLIP_CAPS 0x0007
#define CB_FILECONTENTS_REQUEST 0x0008
#define CB_FILECONTENTS_RESPONSE 0x0009
#define CB_LOCK_CLIPDATA 0x000A
#define CB_UNLOCK_CLIPDATA 0x000B
/* CLIPRDR_HEADER.msgFlags */
#define CB_RESPONSE_OK 0x0001
#define CB_RESPONSE_FAIL 0x0002
#define CB_ASCII_NAMES 0x0004
/* CLIPRDR_CAPS_SET.capabilitySetType */
#define CB_CAPSTYPE_GENERAL 0x0001
/* CLIPRDR_GENERAL_CAPABILITY.lengthCapability */
#define CB_CAPSTYPE_GENERAL_LEN 12
/* CLIPRDR_GENERAL_CAPABILITY.version */
#define CB_CAPS_VERSION_1 0x00000001
#define CB_CAPS_VERSION_2 0x00000002
/* CLIPRDR_GENERAL_CAPABILITY.generalFlags */
#define CB_USE_LONG_FORMAT_NAMES 0x00000002
#define CB_STREAM_FILECLIP_ENABLED 0x00000004
#define CB_FILECLIP_NO_FILE_PATHS 0x00000008
#define CB_CAN_LOCK_CLIPDATA 0x00000010
struct _CLIPRDR_FORMAT_NAME
{
UINT32 id;
char* name;
int length;
};
typedef struct _CLIPRDR_FORMAT_NAME CLIPRDR_FORMAT_NAME;
/**
* Clipboard Events
*/

View File

@ -129,6 +129,10 @@ struct rdp_file
LPSTR DrivesToRedirect; /* drivestoredirect */
LPSTR DevicesToRedirect; /* devicestoredirect */
LPSTR WinPosStr; /* winposstr */
int argc;
char** argv;
int argSize;
};
typedef struct rdp_file rdpFile;

View File

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

View File

@ -56,7 +56,6 @@ struct _RFX_TILE
BYTE* data;
int scanline;
BOOL allocated;
BYTE quantIdxY;
BYTE quantIdxCb;
BYTE quantIdxCr;
@ -68,6 +67,7 @@ struct _RFX_TILE
BYTE* YData;
BYTE* CbData;
BYTE* CrData;
BYTE* YCbCrData;
};
typedef struct _RFX_TILE RFX_TILE;
@ -118,6 +118,7 @@ struct _RFX_CONTEXT
{
RFX_STATE state;
BOOL encoder;
UINT16 flags;
UINT16 properties;
UINT16 width;
@ -153,7 +154,7 @@ struct _RFX_CONTEXT
};
typedef struct _RFX_CONTEXT RFX_CONTEXT;
FREERDP_API RFX_CONTEXT* rfx_context_new(void);
FREERDP_API RFX_CONTEXT* rfx_context_new(BOOL encoder);
FREERDP_API void rfx_context_free(RFX_CONTEXT* context);
FREERDP_API void rfx_context_set_pixel_format(RFX_CONTEXT* context, RDP_PIXEL_FORMAT pixel_format);
FREERDP_API void rfx_context_reset(RFX_CONTEXT* context);

View File

@ -118,7 +118,10 @@ FREERDP_API CryptoCert crypto_cert_read(BYTE* data, UINT32 length);
FREERDP_API char* crypto_cert_fingerprint(X509* xcert);
FREERDP_API char* crypto_cert_subject(X509* xcert);
FREERDP_API char* crypto_cert_subject_common_name(X509* xcert, int* length);
FREERDP_API char** crypto_cert_subject_alt_name(X509* xcert, int* count, int** lengths);
FREERDP_API char** crypto_cert_subject_alt_name(X509* xcert, int* count,
int** lengths);
FREERDP_API void crypto_cert_subject_alt_name_free(int count, int *lengths,
char** alt_name);
FREERDP_API char* crypto_cert_issuer(X509* xcert);
FREERDP_API void crypto_cert_print_info(X509* xcert);
FREERDP_API void crypto_cert_free(CryptoCert cert);

View File

@ -0,0 +1,51 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Clipboard Virtual Channel Server Interface
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CHANNEL_SERVER_CLIPRDR_H
#define FREERDP_CHANNEL_SERVER_CLIPRDR_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/channels/wtsvc.h>
#include <freerdp/client/cliprdr.h>
/**
* Server Interface
*/
typedef struct _cliprdr_server_context CliprdrServerContext;
typedef struct _cliprdr_server_private CliprdrServerPrivate;
typedef int (*psCliprdrStart)(CliprdrServerContext* context);
typedef int (*psCliprdrStop)(CliprdrServerContext* context);
struct _cliprdr_server_context
{
WTSVirtualChannelManager* vcm;
psCliprdrStart Start;
psCliprdrStop Stop;
CliprdrServerPrivate* priv;
};
FREERDP_API CliprdrServerContext* cliprdr_server_context_new(WTSVirtualChannelManager* vcm);
FREERDP_API void cliprdr_server_context_free(CliprdrServerContext* context);
#endif /* FREERDP_CHANNEL_SERVER_CLIPRDR_H */

View File

@ -0,0 +1,50 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Dynamic Virtual Channel Extension
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CHANNEL_SERVER_DRDYNVC_H
#define FREERDP_CHANNEL_SERVER_DRDYNVC_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/channels/wtsvc.h>
/**
* Server Interface
*/
typedef struct _drdynvc_client_context DrdynvcServerContext;
typedef struct _drdynvc_server_private DrdynvcServerPrivate;
typedef int (*psDrdynvcStart)(DrdynvcServerContext* context);
typedef int (*psDrdynvcStop)(DrdynvcServerContext* context);
struct _drdynvc_client_context
{
WTSVirtualChannelManager* vcm;
psDrdynvcStart Start;
psDrdynvcStop Stop;
DrdynvcServerPrivate* priv;
};
FREERDP_API DrdynvcServerContext* drdynvc_server_context_new(WTSVirtualChannelManager* vcm);
FREERDP_API void drdynvc_server_context_free(DrdynvcServerContext* context);
#endif /* FREERDP_CHANNEL_SERVER_DRDYNVC_H */

View File

@ -0,0 +1,51 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Device Redirection Virtual Channel Server Interface
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CHANNEL_SERVER_RDPDR_H
#define FREERDP_CHANNEL_SERVER_RDPDR_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/channels/wtsvc.h>
#include <freerdp/channels/rdpdr.h>
/**
* Server Interface
*/
typedef struct _rdpdr_server_context RdpdrServerContext;
typedef struct _rdpdr_server_private RdpdrServerPrivate;
typedef int (*psRdpdrStart)(RdpdrServerContext* context);
typedef int (*psRdpdrStop)(RdpdrServerContext* context);
struct _rdpdr_server_context
{
WTSVirtualChannelManager* vcm;
psRdpdrStart Start;
psRdpdrStop Stop;
RdpdrServerPrivate* priv;
};
FREERDP_API RdpdrServerContext* rdpdr_server_context_new(WTSVirtualChannelManager* vcm);
FREERDP_API void rdpdr_server_context_free(RdpdrServerContext* context);
#endif /* FREERDP_CHANNEL_SERVER_RDPDR_H */

View File

@ -23,20 +23,30 @@
#include <freerdp/channels/wtsvc.h>
#include <freerdp/channels/rdpsnd.h>
typedef struct _rdpsnd_server_context RdpsndServerContext;
typedef struct _rdpsnd_server_context rdpsnd_server_context;
typedef struct _rdpsnd_server_private RdpsndServerPrivate;
typedef BOOL (*psRdpsndServerInitialize)(rdpsnd_server_context* context);
typedef void (*psRdpsndServerSelectFormat)(rdpsnd_server_context* context, int client_format_index);
typedef BOOL (*psRdpsndServerSendSamples)(rdpsnd_server_context* context, const void* buf, int nframes);
typedef BOOL (*psRdpsndServerSetVolume)(rdpsnd_server_context* context, int left, int right);
typedef BOOL (*psRdpsndServerClose)(rdpsnd_server_context* context);
typedef int (*psRdpsndStart)(RdpsndServerContext* context);
typedef int (*psRdpsndStop)(RdpsndServerContext* context);
typedef void (*psRdpsndServerActivated)(rdpsnd_server_context* context);
typedef BOOL (*psRdpsndServerInitialize)(RdpsndServerContext* context);
typedef void (*psRdpsndServerSelectFormat)(RdpsndServerContext* context, int client_format_index);
typedef BOOL (*psRdpsndServerSendSamples)(RdpsndServerContext* context, const void* buf, int nframes);
typedef BOOL (*psRdpsndServerSetVolume)(RdpsndServerContext* context, int left, int right);
typedef BOOL (*psRdpsndServerClose)(RdpsndServerContext* context);
typedef void (*psRdpsndServerActivated)(RdpsndServerContext* context);
struct _rdpsnd_server_context
{
WTSVirtualChannelManager* vcm;
psRdpsndStart Start;
psRdpsndStop Stop;
RdpsndServerPrivate* priv;
/* Server self-defined pointer. */
void* data;
@ -95,8 +105,8 @@ struct _rdpsnd_server_context
extern "C" {
#endif
FREERDP_API rdpsnd_server_context* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm);
FREERDP_API void rdpsnd_server_context_free(rdpsnd_server_context* context);
FREERDP_API RdpsndServerContext* rdpsnd_server_context_new(WTSVirtualChannelManager* vcm);
FREERDP_API void rdpsnd_server_context_free(RdpsndServerContext* context);
#ifdef __cplusplus
}

View File

@ -1046,7 +1046,7 @@ struct rdp_settings
ALIGN64 char* RemoteApplicationCmdLine; /* 2118 */
ALIGN64 DWORD RemoteApplicationExpandCmdLine; /* 2119 */
ALIGN64 DWORD RemoteApplicationExpandWorkingDir; /* 2120 */
ALIGN64 DWORD DisableRemoteAppCapsCheck; /* 2121 */
ALIGN64 BOOL DisableRemoteAppCapsCheck; /* 2121 */
ALIGN64 UINT32 RemoteAppNumIconCaches; /* 2122 */
ALIGN64 UINT32 RemoteAppNumIconCacheEntries; /* 2123 */
ALIGN64 BOOL RemoteAppLanguageBarSupported; /* 2124 */
@ -1317,6 +1317,9 @@ FREERDP_API void freerdp_dynamic_channel_collection_add(rdpSettings* settings, A
FREERDP_API ADDIN_ARGV* freerdp_dynamic_channel_collection_find(rdpSettings* settings, const char* name);
FREERDP_API void freerdp_dynamic_channel_collection_free(rdpSettings* settings);
FREERDP_API void freerdp_performance_flags_make(rdpSettings* settings);
FREERDP_API void freerdp_performance_flags_split(rdpSettings* settings);
FREERDP_API BOOL freerdp_get_param_bool(rdpSettings* settings, int id);
FREERDP_API int freerdp_set_param_bool(rdpSettings* settings, int id, BOOL param);

View File

@ -23,12 +23,17 @@
#include <stdio.h>
#define DEBUG_NULL(fmt, ...) do { } while (0)
#define DEBUG_PRINT(_dbg_str, fmt, ...) fprintf(stderr, _dbg_str fmt "\n" , __FUNCTION__, __LINE__, ## __VA_ARGS__)
#define DEBUG_CLASS(_dbg_class, fmt, ...) DEBUG_PRINT("DBG_" #_dbg_class " %s (%d): ", fmt, ## __VA_ARGS__)
#define DEBUG_WARN(fmt, ...) DEBUG_PRINT("Warning %s (%d): ", fmt, ## __VA_ARGS__)
#define DEBUG_PRINT(_dbg_str, fmt, ...) do { \
fprintf(stderr, _dbg_str, __FUNCTION__, __FILE__, __LINE__); \
fprintf(stderr, fmt, ## __VA_ARGS__); \
fprintf(stderr, "\n"); \
} while( 0 )
#define DEBUG_CLASS(_dbg_class, fmt, ...) DEBUG_PRINT("DBG_" #_dbg_class " %s (%s:%d): ", fmt, ## __VA_ARGS__)
#define DEBUG_WARN(fmt, ...) DEBUG_PRINT("Warning %s (%s:%d): ", fmt, ## __VA_ARGS__)
#ifdef WITH_DEBUG
#define DEBUG_MSG(fmt, ...) DEBUG_PRINT("DBG %s (%d): ", fmt, ## __VA_ARGS__)
#define DEBUG_MSG(fmt, ...) DEBUG_PRINT("DBG %s (%s:%d): ", fmt, ## __VA_ARGS__)
#else
#define DEBUG_MSG(fmt, ...) DEBUG_NULL(fmt, ## __VA_ARGS__)
#endif

View File

@ -22,7 +22,7 @@
#endif
#include <stdio.h>
#include <assert.h>
#include <winpr/crt.h>
#include <freerdp/update.h>
@ -73,7 +73,7 @@ void update_gdi_polygon_cb(rdpContext* context, POLYGON_CB_ORDER* polygon_cb)
brush->style = style;
}
void update_gdi_cache_brush(rdpContext* context, CACHE_BRUSH_ORDER* cache_brush)
static void update_gdi_cache_brush(rdpContext* context, CACHE_BRUSH_ORDER* cache_brush)
{
int length;
void* data = NULL;
@ -91,6 +91,9 @@ void* brush_cache_get(rdpBrushCache* brush, UINT32 index, UINT32* bpp)
{
void* entry;
assert(brush);
assert(bpp);
if (*bpp == 1)
{
if (index >= brush->maxMonoEntries)
@ -132,6 +135,8 @@ void brush_cache_put(rdpBrushCache* brush, UINT32 index, void* entry, UINT32 bpp
if (index >= brush->maxMonoEntries)
{
fprintf(stderr, "invalid brush (%d bpp) index: 0x%04X\n", bpp, index);
if (entry)
free(entry);
return;
}
@ -148,6 +153,8 @@ void brush_cache_put(rdpBrushCache* brush, UINT32 index, void* entry, UINT32 bpp
if (index >= brush->maxEntries)
{
fprintf(stderr, "invalid brush (%d bpp) index: 0x%04X\n", bpp, index);
if (entry)
free(entry);
return;
}

View File

@ -48,6 +48,7 @@ void update_process_glyph(rdpContext* context, BYTE* data, int* index,
if ((ulCharInc == 0) && (!(flAccel & SO_CHAR_INC_EQUAL_BM_BASE)))
{
/* Contrary to fragments, the offset is added before the glyph. */
(*index)++;
offset = data[*index];
@ -111,6 +112,12 @@ void update_process_glyph_fragments(rdpContext* context, BYTE* data, UINT32 leng
if (fragments != NULL)
{
for (n = 0; n < (int) size; n++)
{
update_process_glyph(context, fragments, &n, &x, &y, cacheId, ulCharInc, flAccel);
}
/* Contrary to glyphs, the offset is added after the fragment. */
if ((ulCharInc == 0) && (!(flAccel & SO_CHAR_INC_EQUAL_BM_BASE)))
{
if (flAccel & SO_VERTICAL)
@ -118,11 +125,6 @@ void update_process_glyph_fragments(rdpContext* context, BYTE* data, UINT32 leng
else
x += data[index + 2];
}
for (n = 0; n < (int) size; n++)
{
update_process_glyph(context, fragments, &n, &x, &y, cacheId, ulCharInc, flAccel);
}
}
index += (index + 2 < (int) length) ? 3 : 2;
@ -277,7 +279,7 @@ void update_gdi_fast_glyph(rdpContext* context, FAST_GLYPH_ORDER* fast_glyph)
if (y == -32768)
y = fast_glyph->bkTop;
if (fast_glyph->cbData > 1)
if (fast_glyph->cbData > 1 && NULL != fast_glyph->glyphData.aj)
{
/* got option font that needs to go into cache */
glyph_data = &fast_glyph->glyphData;
@ -288,7 +290,8 @@ void update_gdi_fast_glyph(rdpContext* context, FAST_GLYPH_ORDER* fast_glyph)
glyph->cx = glyph_data->cx;
glyph->cy = glyph_data->cy;
glyph->cb = glyph_data->cb;
glyph->aj = glyph_data->aj;
glyph->aj = malloc(glyph_data->cb);
CopyMemory(glyph->aj, glyph_data->aj, glyph->cb);
Glyph_New(context, glyph);
glyph_cache_put(cache->glyph, fast_glyph->cacheId, fast_glyph->data[0], glyph);
@ -368,16 +371,14 @@ rdpGlyph* glyph_cache_get(rdpGlyphCache* glyph_cache, UINT32 id, UINT32 index)
if (index > glyph_cache->glyphCache[id].number)
{
fprintf(stderr, "invalid glyph cache index: %d in cache id: %d\n", index, id);
fprintf(stderr, "index %d out of range for cache id: %d\n", index, id);
return NULL;
}
glyph = glyph_cache->glyphCache[id].entries[index];
if (glyph == NULL)
{
fprintf(stderr, "invalid glyph at cache index: %d in cache id: %d\n", index, id);
}
fprintf(stderr, "no glyph found at cache index: %d in cache id: %d\n", index, id);
return glyph;
}
@ -403,7 +404,8 @@ void glyph_cache_put(rdpGlyphCache* glyph_cache, UINT32 id, UINT32 index, rdpGly
if (prevGlyph != NULL)
{
Glyph_Free(glyph_cache->context, prevGlyph);
free(prevGlyph->aj);
if (NULL != prevGlyph->aj)
free(prevGlyph->aj);
free(prevGlyph);
}
@ -418,9 +420,7 @@ void* glyph_cache_fragment_get(rdpGlyphCache* glyph_cache, UINT32 index, UINT32*
*size = (BYTE) glyph_cache->fragCache.entries[index].size;
if (fragment == NULL)
{
fprintf(stderr, "invalid glyph fragment at index:%d\n", index);
}
return fragment;
}
@ -435,9 +435,7 @@ void glyph_cache_fragment_put(rdpGlyphCache* glyph_cache, UINT32 index, UINT32 s
glyph_cache->fragCache.entries[index].size = size;
if (prevFragment != NULL)
{
free(prevFragment);
}
}
void glyph_cache_register_callbacks(rdpUpdate* update)
@ -498,12 +496,14 @@ void glyph_cache_free(rdpGlyphCache* glyph_cache)
if (glyph != NULL)
{
Glyph_Free(glyph_cache->context, glyph);
free(glyph->aj);
if (glyph->aj)
free(glyph->aj);
free(glyph);
glyph_cache->glyphCache[i].entries[j] = NULL;
}
}
free(glyph_cache->glyphCache[i].entries);
glyph_cache->glyphCache[i].entries = NULL;
}
for (i = 0; i < 255; i++)

View File

@ -27,7 +27,8 @@
#include <freerdp/cache/palette.h>
void update_gdi_cache_color_table(rdpContext* context, CACHE_COLOR_TABLE_ORDER* cache_color_table)
static void update_gdi_cache_color_table(rdpContext* context,
CACHE_COLOR_TABLE_ORDER* cache_color_table)
{
UINT32* colorTable;
rdpCache* cache = context->cache;
@ -49,7 +50,6 @@ void* palette_cache_get(rdpPaletteCache* palette_cache, UINT32 index)
}
entry = palette_cache->entries[index].entry;
if (entry == NULL)
{
fprintf(stderr, "invalid color table at index: 0x%04X\n", index);
@ -64,9 +64,14 @@ void palette_cache_put(rdpPaletteCache* palette_cache, UINT32 index, void* entry
if (index >= palette_cache->maxEntries)
{
fprintf(stderr, "invalid color table index: 0x%04X\n", index);
if (entry)
free(entry);
return;
}
if(NULL == palette_cache->entries[index].entry)
free(palette_cache->entries[index].entry);
palette_cache->entries[index].entry = entry;
}
@ -97,6 +102,13 @@ void palette_cache_free(rdpPaletteCache* palette_cache)
{
if (palette_cache != NULL)
{
int i;
for (i=0; i<palette_cache->maxEntries; i++)
{
if (palette_cache->entries[i].entry)
free(palette_cache->entries[i].entry);
}
free(palette_cache->entries);
free(palette_cache);
}

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