Merged changes from FreeRDP branch, notably support for fullscreen on mac os x.
This commit is contained in:
commit
7198ee2def
@ -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")
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -540,3 +540,4 @@ int freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEnt
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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"
|
||||
|
@ -18,7 +18,6 @@
|
||||
define_channel_client("cliprdr")
|
||||
|
||||
set(${MODULE_PREFIX}_SRCS
|
||||
cliprdr_constants.h
|
||||
cliprdr_format.c
|
||||
cliprdr_format.h
|
||||
cliprdr_main.c
|
||||
|
@ -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 */
|
@ -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);
|
||||
|
@ -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:
|
||||
|
@ -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;
|
||||
|
35
channels/cliprdr/server/CMakeLists.txt
Normal file
35
channels/cliprdr/server/CMakeLists.txt
Normal 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")
|
536
channels/cliprdr/server/cliprdr_main.c
Normal file
536
channels/cliprdr/server/cliprdr_main.c
Normal 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);
|
||||
}
|
||||
}
|
56
channels/cliprdr/server/cliprdr_main.h
Normal file
56
channels/cliprdr/server/cliprdr_main.h
Normal 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 */
|
@ -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()
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
}
|
||||
|
35
channels/drdynvc/server/CMakeLists.txt
Normal file
35
channels/drdynvc/server/CMakeLists.txt
Normal 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")
|
149
channels/drdynvc/server/drdynvc_main.c
Normal file
149
channels/drdynvc/server/drdynvc_main.c
Normal 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);
|
||||
}
|
||||
}
|
37
channels/drdynvc/server/drdynvc_main.h
Normal file
37
channels/drdynvc/server/drdynvc_main.h
Normal 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 */
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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"
|
||||
|
@ -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);
|
||||
}
|
||||
|
35
channels/rdpdr/server/CMakeLists.txt
Normal file
35
channels/rdpdr/server/CMakeLists.txt
Normal 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")
|
699
channels/rdpdr/server/rdpdr_main.c
Normal file
699
channels/rdpdr/server/rdpdr_main.c
Normal 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);
|
||||
}
|
||||
}
|
70
channels/rdpdr/server/rdpdr_main.h
Normal file
70
channels/rdpdr/server/rdpdr_main.h
Normal 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 */
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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")
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
572
channels/rdpsnd/server/rdpsnd_main.c
Normal file
572
channels/rdpsnd/server/rdpsnd_main.c
Normal 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);
|
||||
}
|
48
channels/rdpsnd/server/rdpsnd_main.h
Normal file
48
channels/rdpsnd/server/rdpsnd_main.h
Normal 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 */
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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"/>
|
||||
|
@ -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")
|
||||
|
@ -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
|
||||
|
@ -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")
|
||||
|
@ -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
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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>
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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());
|
||||
|
@ -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"
|
||||
|
@ -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")
|
||||
|
20
client/Android/aFreeRDP/ant.properties.cmake
Normal file
20
client/Android/aFreeRDP/ant.properties.cmake
Normal 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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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>
|
||||
|
@ -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)
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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 don’t 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);
|
||||
}
|
||||
}
|
||||
|
@ -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")
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#cmakedefine HAVE_EVENTFD_H
|
||||
#cmakedefine HAVE_TIMERFD_H
|
||||
#cmakedefine HAVE_TM_GMTOFF
|
||||
#cmakedefine HAVE_AIO_H
|
||||
|
||||
|
||||
/* Options */
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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;
|
||||
|
@ -50,6 +50,7 @@ struct _NSC_MESSAGE
|
||||
UINT32 height;
|
||||
BYTE* data;
|
||||
int scanline;
|
||||
BYTE* PlaneBuffer;
|
||||
UINT32 MaxPlaneSize;
|
||||
BYTE* PlaneBuffers[5];
|
||||
UINT32 OrgByteCount[4];
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
51
include/freerdp/server/cliprdr.h
Normal file
51
include/freerdp/server/cliprdr.h
Normal 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 */
|
50
include/freerdp/server/drdynvc.h
Normal file
50
include/freerdp/server/drdynvc.h
Normal 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 */
|
51
include/freerdp/server/rdpdr.h
Normal file
51
include/freerdp/server/rdpdr.h
Normal 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 */
|
@ -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
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
11
libfreerdp/cache/brush.c
vendored
11
libfreerdp/cache/brush.c
vendored
@ -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;
|
||||
}
|
||||
|
||||
|
34
libfreerdp/cache/glyph.c
vendored
34
libfreerdp/cache/glyph.c
vendored
@ -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++)
|
||||
|
16
libfreerdp/cache/palette.c
vendored
16
libfreerdp/cache/palette.c
vendored
@ -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
Loading…
Reference in New Issue
Block a user