New upstream version 2.0.0~git20190204.1.2693389a+dfsg1

This commit is contained in:
Mike Gabriel 2019-02-04 10:00:57 +01:00
parent d8a8133ee5
commit 7084cb4b53
220 changed files with 12306 additions and 6446 deletions

View File

@ -1 +1 @@
e21b72c95+debian
2693389a+debian

View File

@ -77,7 +77,7 @@ if ($ENV{BUILD_NUMBER})
endif()
set(WITH_LIBRARY_VERSIONING "ON")
set(RAW_VERSTION_STRING "2.0.0-rc4")
set(RAW_VERSTION_STRING "2.0.0-dev5")
if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag")
file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSTION_STRING)
elseif(USE_VERSION_FROM_GIT_TAG)
@ -482,7 +482,7 @@ if(WIN32)
add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS)
set(CMAKE_USE_RELATIVE_PATH ON)
if (${CMAKE_GENERATOR} MATCHES "NMake Makefile*" OR ${CMAKE_GENERATOR} MATCHES "Ninja*")
if (${CMAKE_GENERATOR} MATCHES "NMake Makefile*" OR ${CMAKE_GENERATOR} MATCHES "Ninja*" OR ${CMAKE_GENERATOR} MATCHES "Unix Makefiles")
set(CMAKE_PDB_BINARY_DIR ${CMAKE_BINARY_DIR})
elseif (${CMAKE_GENERATOR} MATCHES "Visual Studio*")
set(CMAKE_PDB_BINARY_DIR "${CMAKE_BINARY_DIR}/\${CMAKE_INSTALL_CONFIG_NAME}")
@ -490,12 +490,6 @@ if(WIN32)
message(FATAL_ERROR "Unknown generator ${CMAKE_GENERATOR}")
endif()
# Set product and vendor for dll and exe version information.
set(RC_VERSION_VENDOR ${VENDOR})
set(RC_VERSION_PRODUCT ${PRODUCT})
set(RC_VERSION_PATCH ${BUILD_NUMBER})
set(RC_VERSION_DESCRIPTION ${GIT_REVISION})
string(TIMESTAMP RC_VERSION_YEAR "%Y")
if(NOT DEFINED CMAKE_WINDOWS_VERSION)
@ -512,6 +506,12 @@ if(WIN32)
add_definitions(-DWINVER=0x0A00 -D_WIN32_WINNT=0x0A00)
endif()
# Set product and vendor for dll and exe version information.
set(RC_VERSION_VENDOR ${VENDOR})
set(RC_VERSION_PRODUCT ${PRODUCT})
set(RC_VERSION_PATCH ${BUILD_NUMBER})
set(RC_VERSION_DESCRIPTION "${FREERDP_VERSION_FULL} ${GIT_REVISION} ${CMAKE_WINDOWS_VERSION} ${CMAKE_SYSTEM_PROCESSOR}")
if (FREERDP_EXTERNAL_SSL_PATH)
set(OPENSSL_ROOT_DIR ${FREERDP_EXTERNAL_SSL_PATH})
endif()
@ -682,10 +682,6 @@ set(X11_FEATURE_DESCRIPTION "X11 client and server")
set(WAYLAND_FEATURE_PURPOSE "Wayland")
set(WAYLAND_FEATURE_DESCRIPTION "Wayland client")
set(DIRECTFB_FEATURE_TYPE "OPTIONAL")
set(DIRECTFB_FEATURE_PURPOSE "DirectFB")
set(DIRECTFB_FEATURE_DESCRIPTION "DirectFB client")
set(ZLIB_FEATURE_TYPE "REQUIRED")
set(ZLIB_FEATURE_PURPOSE "compression")
set(ZLIB_FEATURE_DESCRIPTION "data compression")
@ -782,7 +778,6 @@ if(WIN32)
set(X11_FEATURE_TYPE "DISABLED")
set(WAYLAND_FEATURE_TYPE "DISABLED")
set(ZLIB_FEATURE_TYPE "DISABLED")
set(DIRECTFB_FEATURE_TYPE "DISABLED")
set(OSS_FEATURE_TYPE "DISABLED")
set(ALSA_FEATURE_TYPE "DISABLED")
set(PULSE_FEATURE_TYPE "DISABLED")
@ -796,7 +791,6 @@ if(WIN32)
endif()
if(APPLE)
set(DIRECTFB_FEATURE_TYPE "DISABLED")
set(FFMPEG_FEATURE_TYPE "OPTIONAL")
set(VAAPI_FEATURE_TYPE "DISABLED")
set(GSTREAMER_1_0_FEATURE_TYPE "OPTIONAL")
@ -833,7 +827,6 @@ endif(UNIX AND NOT ANDROID)
if(ANDROID)
set(X11_FEATURE_TYPE "DISABLED")
set(WAYLAND_FEATURE_TYPE "DISABLED")
set(DIRECTFB_FEATURE_TYPE "DISABLED")
set(OSS_FEATURE_TYPE "DISABLED")
set(ALSA_FEATURE_TYPE "DISABLED")
set(PULSE_FEATURE_TYPE "DISABLED")
@ -848,10 +841,6 @@ endif()
find_feature(X11 ${X11_FEATURE_TYPE} ${X11_FEATURE_PURPOSE} ${X11_FEATURE_DESCRIPTION})
find_feature(Wayland ${WAYLAND_FEATURE_TYPE} ${WAYLAND_FEATURE_PURPOSE} ${WAYLAND_FEATURE_DESCRIPTION})
find_feature(DirectFB ${DIRECTFB_FEATURE_TYPE} ${DIRECTFB_FEATURE_PURPOSE} ${DIRECTFB_FEATURE_DESCRIPTION})
if (${WITH_DIRECTFB})
message(WARNING "DIRECTFB is orphaned and not maintained see docs/README.directfb for details")
endif()
find_feature(ZLIB ${ZLIB_FEATURE_TYPE} ${ZLIB_FEATURE_PURPOSE} ${ZLIB_FEATURE_DESCRIPTION})
find_feature(OpenSSL ${OPENSSL_FEATURE_TYPE} ${OPENSSL_FEATURE_PURPOSE} ${OPENSSL_FEATURE_DESCRIPTION})
@ -881,6 +870,10 @@ find_feature(soxr ${SOXR_FEATURE_TYPE} ${SOXR_FEATURE_PURPOSE} ${SOXR_FEATURE_DE
find_feature(GSSAPI ${GSSAPI_FEATURE_TYPE} ${GSSAPI_FEATURE_PURPOSE} ${GSSAPI_FEATURE_DESCRIPTION})
if (WITH_OPENH264 AND NOT WITH_OPENH264_LOADING)
set(WITH_OPENH264_LOADING OFF)
endif (WITH_OPENH264 AND NOT WITH_OPENH264_LOADING)
if ((WITH_FFMPEG OR WITH_DSP_FFMPEG) AND NOT FFMPEG_FOUND)
message(FATAL_ERROR "FFMPEG support requested but not detected")
endif()
@ -945,6 +938,7 @@ endif()
if(OPENSSL_FOUND)
add_definitions("-DWITH_OPENSSL")
message(STATUS "Using OpenSSL Version: ${OPENSSL_VERSION}")
include_directories(${OPENSSL_INCLUDE_DIR})
endif()
if(MBEDTLS_FOUND)
@ -1062,7 +1056,7 @@ add_subdirectory(include)
add_subdirectory(libfreerdp)
if (IOS)
set(CMAKE_OSX_DEPLOYMENT_TARGET "")
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.0")
if (IOS_PLATFORM MATCHES "SIMULATOR")
set(CMAKE_OSX_SYSROOT "iphonesimulator")
else()

1409
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@ -93,11 +93,6 @@ static UINT audin_opensles_free(IAudinDevice* device)
WLog_Print(opensles->log, WLOG_DEBUG, "device=%p", (void*) device);
/* The function may have been called out of order,
* ignore duplicate requests. */
if (!opensles)
return CHANNEL_RC_OK;
free(opensles->device_name);
free(opensles);
return CHANNEL_RC_OK;
@ -154,11 +149,6 @@ static UINT audin_opensles_set_format(IAudinDevice* device,
(void*) device, (void*) format, FramesPerPacket);
assert(format);
/* The function may have been called out of order, ignore
* requests before the device is available. */
if (!opensles)
return CHANNEL_RC_OK;
opensles->format = *format;
switch (format->wFormatTag)

View File

@ -279,7 +279,7 @@ static DWORD WINAPI audin_oss_thread_func(LPVOID arg)
err_out:
if (error && oss->rdpcontext)
if (error && oss && oss->rdpcontext)
setChannelError(oss->rdpcontext, error,
"audin_oss_thread_func reported an error");

View File

@ -27,8 +27,8 @@
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
#include <MMSystem.h>
#include <windows.h>
#include <mmsystem.h>
#include <winpr/crt.h>
#include <winpr/cmdline.h>

View File

@ -216,7 +216,7 @@ static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s,
UINT16 length, UINT16 flags)
UINT32 length, UINT16 flags)
{
UINT16 index;
UINT16 lengthCapability;
@ -257,7 +257,6 @@ static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s,
default:
WLog_ERR(TAG, "unknown cliprdr capability set: %"PRIu16"", capabilitySetType);
return CHANNEL_RC_BAD_PROC;
break;
}
}
@ -270,7 +269,7 @@ static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s,
UINT16 length, UINT16 flags)
UINT32 length, UINT16 flags)
{
CLIPRDR_MONITOR_READY monitorReady;
CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr);
@ -587,10 +586,10 @@ static UINT cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s)
* @return 0 on success, otherwise a Win32 error code
*/
static UINT cliprdr_client_capabilities(CliprdrClientContext* context,
CLIPRDR_CAPABILITIES* capabilities)
const CLIPRDR_CAPABILITIES* capabilities)
{
wStream* s;
CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet;
const CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN);
@ -602,7 +601,7 @@ static UINT cliprdr_client_capabilities(CliprdrClientContext* context,
Stream_Write_UINT16(s, 1); /* cCapabilitiesSets */
Stream_Write_UINT16(s, 0); /* pad1 */
generalCapabilitySet = (CLIPRDR_GENERAL_CAPABILITY_SET*)capabilities->capabilitySets;
generalCapabilitySet = (const CLIPRDR_GENERAL_CAPABILITY_SET*)capabilities->capabilitySets;
Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetType); /* capabilitySetType */
Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetLength); /* lengthCapability */
Stream_Write_UINT32(s, generalCapabilitySet->version); /* version */
@ -617,7 +616,7 @@ static UINT cliprdr_client_capabilities(CliprdrClientContext* context,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT cliprdr_temp_directory(CliprdrClientContext* context,
CLIPRDR_TEMP_DIRECTORY* tempDirectory)
const CLIPRDR_TEMP_DIRECTORY* tempDirectory)
{
int length;
wStream* s;
@ -639,8 +638,8 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context,
if (length > 520)
length = 520;
Stream_Write(s, wszTempDir, length * 2);
Stream_Zero(s, (520 - length) * 2);
Stream_Write(s, wszTempDir, (size_t)length * 2);
Stream_Zero(s, (520 - (size_t)length) * 2);
free(wszTempDir);
WLog_Print(cliprdr->log, WLOG_DEBUG, "TempDirectory: %s",
tempDirectory->szTempDir);
@ -653,15 +652,15 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT cliprdr_client_format_list(CliprdrClientContext* context,
CLIPRDR_FORMAT_LIST* formatList)
const CLIPRDR_FORMAT_LIST* formatList)
{
wStream* s;
UINT32 index;
int length = 0;
UINT32 length = 0;
int cchWideChar;
LPWSTR lpWideCharStr;
int formatNameSize;
int formatNameLength;
size_t formatNameSize;
size_t formatNameLength;
char* szFormatName;
WCHAR* wszFormatName;
BOOL asciiNames = FALSE;
@ -703,8 +702,14 @@ static UINT cliprdr_client_format_list(CliprdrClientContext* context,
wszFormatName = NULL;
if (szFormatName)
formatNameSize = ConvertToUnicode(CP_UTF8, 0, szFormatName, -1, &wszFormatName,
0);
{
int rc = ConvertToUnicode(CP_UTF8, 0, szFormatName, -1, &wszFormatName, 0);
if (rc < 0)
return ERROR_INTERNAL_ERROR;
formatNameSize = (size_t)rc;
}
if (formatNameSize > 15)
formatNameSize = 15;
@ -726,8 +731,14 @@ static UINT cliprdr_client_format_list(CliprdrClientContext* context,
formatNameSize = 2;
if (format->formatName)
formatNameSize = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, NULL,
0) * 2;
{
int rc = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, NULL, 0);
if (rc < 0)
return ERROR_INTERNAL_ERROR;
formatNameSize = (size_t)rc * 2;
}
length += formatNameSize;
}
@ -771,14 +782,12 @@ static UINT cliprdr_client_format_list(CliprdrClientContext* context,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT cliprdr_client_format_list_response(CliprdrClientContext* context,
CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
formatListResponse->msgType = CB_FORMAT_LIST_RESPONSE;
formatListResponse->dataLen = 0;
s = cliprdr_packet_new(formatListResponse->msgType,
formatListResponse->msgFlags, formatListResponse->dataLen);
s = cliprdr_packet_new(CB_FORMAT_LIST_RESPONSE,
formatListResponse->msgFlags, 0);
if (!s)
{
@ -796,7 +805,7 @@ static UINT cliprdr_client_format_list_response(CliprdrClientContext* context,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT cliprdr_client_lock_clipboard_data(CliprdrClientContext* context,
CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
@ -821,7 +830,7 @@ static UINT cliprdr_client_lock_clipboard_data(CliprdrClientContext* context,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context,
CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
@ -846,15 +855,12 @@ static UINT cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT cliprdr_client_format_data_request(CliprdrClientContext* context,
CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
formatDataRequest->msgType = CB_FORMAT_DATA_REQUEST;
formatDataRequest->msgFlags = 0;
formatDataRequest->dataLen = 4;
s = cliprdr_packet_new(formatDataRequest->msgType, formatDataRequest->msgFlags,
formatDataRequest->dataLen);
s = cliprdr_packet_new(CB_FORMAT_DATA_REQUEST, 0, 4);
if (!s)
{
@ -873,12 +879,12 @@ static UINT cliprdr_client_format_data_request(CliprdrClientContext* context,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT cliprdr_client_format_data_response(CliprdrClientContext* context,
CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
formatDataResponse->msgType = CB_FORMAT_DATA_RESPONSE;
s = cliprdr_packet_new(formatDataResponse->msgType,
s = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE,
formatDataResponse->msgFlags, formatDataResponse->dataLen);
if (!s)
@ -899,7 +905,7 @@ static UINT cliprdr_client_format_data_response(CliprdrClientContext* context,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT cliprdr_client_file_contents_request(CliprdrClientContext* context,
CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
@ -933,7 +939,7 @@ static UINT cliprdr_client_file_contents_request(CliprdrClientContext* context,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT cliprdr_client_file_contents_response(CliprdrClientContext* context,
CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse)
{
wStream* s;
cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle;
@ -989,7 +995,7 @@ static UINT cliprdr_virtual_channel_event_data_received(cliprdrPlugin* cliprdr,
return CHANNEL_RC_NO_MEMORY;
}
if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength))
if (!Stream_EnsureRemainingCapacity(data_in, dataLength))
{
Stream_Free(cliprdr->data_in, TRUE);
cliprdr->data_in = NULL;
@ -1100,6 +1106,17 @@ static DWORD WINAPI cliprdr_virtual_channel_client_thread(LPVOID arg)
return error;
}
static void cliprdr_free_msg(void* obj)
{
wMessage* msg = (wMessage*)obj;
if (msg)
{
wStream* s = (wStream*)msg->wParam;
Stream_Free(s, TRUE);
}
}
/**
* Function description
*
@ -1109,6 +1126,7 @@ static UINT cliprdr_virtual_channel_event_connected(cliprdrPlugin* cliprdr,
LPVOID pData, UINT32 dataLength)
{
UINT32 status;
wObject obj = { 0 };
status = cliprdr->channelEntryPoints.pVirtualChannelOpenEx(cliprdr->InitHandle,
&cliprdr->OpenHandle, cliprdr->channelDef.name,
cliprdr_virtual_channel_open_event_ex);
@ -1120,7 +1138,8 @@ static UINT cliprdr_virtual_channel_event_connected(cliprdrPlugin* cliprdr,
return status;
}
cliprdr->queue = MessageQueue_New(NULL);
obj.fnObjectFree = cliprdr_free_msg;
cliprdr->queue = MessageQueue_New(&obj);
if (!cliprdr->queue)
{

View File

@ -1447,12 +1447,12 @@ static UINT drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc)
{
UINT status;
if (drdynvc->OpenHandle == 0)
return CHANNEL_RC_OK;
if (!drdynvc)
return CHANNEL_RC_BAD_CHANNEL_HANDLE;
if (drdynvc->OpenHandle == 0)
return CHANNEL_RC_OK;
if (!MessageQueue_PostQuit(drdynvc->queue, 0))
{
status = GetLastError();

View File

@ -54,8 +54,7 @@
static void drive_file_fix_path(WCHAR* path)
{
size_t i;
size_t length;
length = (int) _wcslen(path);
size_t length = _wcslen(path);
for (i = 0; i < length; i++)
{
@ -80,10 +79,10 @@ static void drive_file_fix_path(WCHAR* path)
}
static WCHAR* drive_file_combine_fullpath(const WCHAR* base_path, const WCHAR* path,
UINT32 PathLength)
size_t PathLength)
{
WCHAR* fullpath;
UINT32 base_path_length;
size_t base_path_length;
if (!base_path || !path)
return NULL;
@ -107,11 +106,10 @@ static BOOL drive_file_remove_dir(const WCHAR* path)
{
WIN32_FIND_DATAW findFileData;
BOOL ret = TRUE;
INT len;
HANDLE dir;
WCHAR* fullpath;
WCHAR* path_slash;
UINT32 base_path_length;
size_t base_path_length;
if (!path)
return FALSE;
@ -140,7 +138,7 @@ static BOOL drive_file_remove_dir(const WCHAR* path)
do
{
len = _wcslen(findFileData.cFileName);
size_t len = _wcslen(findFileData.cFileName);
if ((len == 1 && findFileData.cFileName[0] == L'.') || (len == 2 &&
findFileData.cFileName[0] == L'.' && findFileData.cFileName[1] == L'.'))
@ -335,7 +333,7 @@ DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 Pat
file->file_handle = INVALID_HANDLE_VALUE;
file->find_handle = INVALID_HANDLE_VALUE;
file->id = id;
file->basepath = (WCHAR*) base_path;
file->basepath = base_path;
file->FileAttributes = FileAttributes;
file->DesiredAccess = DesiredAccess;
file->CreateDisposition = CreateDisposition;
@ -397,7 +395,10 @@ BOOL drive_file_seek(DRIVE_FILE* file, UINT64 Offset)
if (!file)
return FALSE;
loffset.QuadPart = Offset;
if (Offset > INT64_MAX)
return FALSE;
loffset.QuadPart = (LONGLONG)Offset;
return SetFilePointerEx(file->file_handle, loffset, NULL, FILE_BEGIN);
}
@ -615,6 +616,8 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
return FALSE;
}
liSize.QuadPart = size;
if (!SetFilePointerEx(file->file_handle, liSize, NULL, FILE_BEGIN))
{
WLog_ERR(TAG, "Unable to truncate %s to %d (%"PRId32")", file->fullpath, size, GetLastError());
@ -755,7 +758,10 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
if (!Stream_EnsureRemainingCapacity(output, 4 + 64 + length))
goto out_fail;
Stream_Write_UINT32(output, 64 + length); /* Length */
if (length > UINT32_MAX - 64)
goto out_fail;
Stream_Write_UINT32(output, (UINT32)(64 + length)); /* Length */
Stream_Write_UINT32(output, 0); /* NextEntryOffset */
Stream_Write_UINT32(output, 0); /* FileIndex */
Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwLowDateTime); /* CreationTime */
@ -771,7 +777,7 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* AllocationSize */
Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* AllocationSize */
Stream_Write_UINT32(output, file->find_data.dwFileAttributes); /* FileAttributes */
Stream_Write_UINT32(output, length); /* FileNameLength */
Stream_Write_UINT32(output, (UINT32)length); /* FileNameLength */
Stream_Write(output, file->find_data.cFileName, length);
break;
@ -781,23 +787,26 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
if (!Stream_EnsureRemainingCapacity(output, 4 + 68 + length))
goto out_fail;
Stream_Write_UINT32(output, 68 + length); /* Length */
if (length > UINT32_MAX - 68)
goto out_fail;
Stream_Write_UINT32(output, (UINT32)(68 + length)); /* Length */
Stream_Write_UINT32(output, 0); /* NextEntryOffset */
Stream_Write_UINT32(output, 0); /* FileIndex */
Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwHighDateTime); /* CreationTime */
Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwLowDateTime); /* CreationTime */
Stream_Write_UINT32(output, file->find_data.ftLastAccessTime.dwHighDateTime); /* LastAccessTime */
Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwHighDateTime); /* CreationTime */
Stream_Write_UINT32(output, file->find_data.ftLastAccessTime.dwLowDateTime); /* LastAccessTime */
Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); /* LastWriteTime */
Stream_Write_UINT32(output, file->find_data.ftLastAccessTime.dwHighDateTime); /* LastAccessTime */
Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); /* LastWriteTime */
Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); /* ChangeTime */
Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); /* LastWriteTime */
Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); /* ChangeTime */
Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); /* ChangeTime */
Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* EndOfFile */
Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* EndOfFile */
Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* AllocationSize */
Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* AllocationSize */
Stream_Write_UINT32(output, file->find_data.dwFileAttributes); /* FileAttributes */
Stream_Write_UINT32(output, length); /* FileNameLength */
Stream_Write_UINT32(output, (UINT32)length); /* FileNameLength */
Stream_Write_UINT32(output, 0); /* EaSize */
Stream_Write(output, file->find_data.cFileName, length);
break;
@ -808,7 +817,10 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
if (!Stream_EnsureRemainingCapacity(output, 4 + 93 + length))
goto out_fail;
Stream_Write_UINT32(output, 93 + length); /* Length */
if (length > UINT32_MAX - 93)
goto out_fail;
Stream_Write_UINT32(output, (UINT32)(93 + length)); /* Length */
Stream_Write_UINT32(output, 0); /* NextEntryOffset */
Stream_Write_UINT32(output, 0); /* FileIndex */
Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwLowDateTime); /* CreationTime */
@ -824,7 +836,7 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* AllocationSize */
Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* AllocationSize */
Stream_Write_UINT32(output, file->find_data.dwFileAttributes); /* FileAttributes */
Stream_Write_UINT32(output, length); /* FileNameLength */
Stream_Write_UINT32(output, (UINT32)length); /* FileNameLength */
Stream_Write_UINT32(output, 0); /* EaSize */
Stream_Write_UINT8(output, 0); /* ShortNameLength */
/* Reserved(1), MUST NOT be added! */
@ -838,14 +850,18 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
if (!Stream_EnsureRemainingCapacity(output, 4 + 12 + length))
goto out_fail;
Stream_Write_UINT32(output, 12 + length); /* Length */
if (length > UINT32_MAX - 12)
goto out_fail;
Stream_Write_UINT32(output, (UINT32)(12 + length)); /* Length */
Stream_Write_UINT32(output, 0); /* NextEntryOffset */
Stream_Write_UINT32(output, 0); /* FileIndex */
Stream_Write_UINT32(output, length); /* FileNameLength */
Stream_Write_UINT32(output, (UINT32)length); /* FileNameLength */
Stream_Write(output, file->find_data.cFileName, length);
break;
default:
WLog_ERR(TAG, "unhandled FsInformationClass %"PRIu32, FsInformationClass);
/* Unhandled FsInformationClass */
goto out_fail;
}

View File

@ -40,7 +40,7 @@ struct _DRIVE_FILE
HANDLE file_handle;
HANDLE find_handle;
WIN32_FIND_DATAW find_data;
WCHAR* basepath;
const WCHAR* basepath;
WCHAR* fullpath;
WCHAR* filename;
BOOL delete_pending;

View File

@ -84,7 +84,7 @@ static void printer_cups_get_printjob_name(char* buf, int size)
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT printer_cups_write_printjob(rdpPrintJob* printjob, BYTE* data, int size)
static UINT printer_cups_write_printjob(rdpPrintJob* printjob, const BYTE* data, size_t size)
{
rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*) printjob;

View File

@ -35,8 +35,10 @@
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/interlocked.h>
#include <winpr/path.h>
#include <freerdp/channels/rdpdr.h>
#include <freerdp/crypto/crypto.h>
#include "../printer.h"
@ -71,6 +73,364 @@ struct _PRINTER_DEVICE
char port[64];
};
typedef enum
{
PRN_CONF_PORT = 0,
PRN_CONF_PNP = 1,
PRN_CONF_DRIVER = 2,
PRN_CONF_DATA = 3
}
prn_conf_t;
static const char* filemap[] =
{
"PortDosName",
"PnPName",
"DriverName",
"CachedPrinterConfigData"
};
static char* get_printer_config_path(const rdpSettings* settings, const WCHAR* name, size_t length)
{
char* dir = GetCombinedPath(settings->ConfigPath, "printers");
char* bname = crypto_base64_encode((const BYTE*) name, (int)length);
char* config = GetCombinedPath(dir, bname);
if (config && !PathFileExistsA(config))
{
if (!PathMakePathA(config, NULL))
{
free(config);
config = NULL;
}
}
free(dir);
free(bname);
return config;
}
static BOOL printer_write_setting(const char* path, prn_conf_t type, const void* data,
size_t length)
{
DWORD written = 0;
BOOL rc = FALSE;
HANDLE file;
size_t b64len;
char* base64 = NULL;
const char* name = filemap[type];
char* abs = GetCombinedPath(path, name);
if (!abs)
return FALSE;
file = CreateFileA(abs, GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
free(abs);
if (file == INVALID_HANDLE_VALUE)
return FALSE;
if (length > 0)
{
base64 = crypto_base64_encode(data, length);
if (!base64)
goto fail;
b64len = strlen(base64);
rc = WriteFile(file, base64, b64len, &written, NULL);
if (b64len != written)
rc = FALSE;
}
else
rc = TRUE;
fail:
CloseHandle(file);
free(base64);
return rc;
}
static BOOL printer_config_valid(const char* path)
{
if (!path)
return FALSE;
if (!PathFileExistsA(path))
return FALSE;
return TRUE;
}
static BOOL printer_read_setting(const char* path, prn_conf_t type, void** data, size_t* length)
{
DWORD lowSize, highSize;
DWORD read = 0;
BOOL rc = FALSE;
HANDLE file;
BYTE* fdata = NULL;
const char* name = filemap[type];
char* abs = GetCombinedPath(path, name);
if (!abs)
return FALSE;
file = CreateFileA(abs, GENERIC_READ, 0,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
free(abs);
if (file == INVALID_HANDLE_VALUE)
return FALSE;
lowSize = GetFileSize(file, &highSize);
if ((lowSize == INVALID_FILE_SIZE) || (highSize != 0))
goto fail;
if (lowSize != 0)
{
fdata = malloc(lowSize);
if (!fdata)
goto fail;
rc = ReadFile(file, fdata, lowSize, &read, NULL);
if (lowSize != read)
rc = FALSE;
}
fail:
CloseHandle(file);
if (rc)
{
int blen = 0;
crypto_base64_decode(fdata, lowSize, data, &blen);
if (*data)
*length = blen;
else
{
rc = FALSE;
*length = 0;
}
}
else
{
*length = 0;
*data = NULL;
}
free(fdata);
return rc;
}
static BOOL printer_save_to_config(const rdpSettings* settings,
const char* PortDosName, size_t PortDosNameLen,
const WCHAR* PnPName, size_t PnPNameLen,
const WCHAR* DriverName, size_t DriverNameLen,
const WCHAR* PrinterName, size_t PrintNameLen,
const BYTE* CachedPrinterConfigData, size_t CacheFieldsLen)
{
BOOL rc = FALSE;
char* path = get_printer_config_path(settings, PrinterName, PrintNameLen);
if (!path)
goto fail;
if (!printer_write_setting(path, PRN_CONF_PORT, PortDosName, PortDosNameLen))
goto fail;
if (!printer_write_setting(path, PRN_CONF_PNP, PnPName, PnPNameLen))
goto fail;
if (!printer_write_setting(path, PRN_CONF_DRIVER, DriverName, DriverNameLen))
goto fail;
if (!printer_write_setting(path, PRN_CONF_DATA, CachedPrinterConfigData, CacheFieldsLen))
goto fail;
fail:
free(path);
return rc;
}
static BOOL printer_update_to_config(const rdpSettings* settings, const WCHAR* name, size_t length,
const BYTE* data, size_t datalen)
{
BOOL rc = FALSE;
char* path = get_printer_config_path(settings, name, length);
rc = printer_write_setting(path, PRN_CONF_DATA, data, datalen);
free(path);
return rc;
}
static BOOL printer_remove_config(const rdpSettings* settings, const WCHAR* name, size_t length)
{
BOOL rc = FALSE;
char* path = get_printer_config_path(settings, name, length);
if (!printer_config_valid(path))
goto fail;
rc = RemoveDirectoryA(path);
fail:
free(path);
return rc;
}
static BOOL printer_move_config(const rdpSettings* settings, const WCHAR* oldName, size_t oldLength,
const WCHAR* newName, size_t newLength)
{
BOOL rc = FALSE;
char* oldPath = get_printer_config_path(settings, oldName, oldLength);
char* newPath = get_printer_config_path(settings, newName, newLength);
if (printer_config_valid(oldPath))
rc = MoveFileA(oldPath, newPath);
free(oldPath);
free(newPath);
return rc;
}
static BOOL printer_load_from_config(const rdpSettings* settings, rdpPrinter* printer,
PRINTER_DEVICE* printer_dev)
{
BOOL res = FALSE;
WCHAR* wname = NULL;
size_t wlen;
char* path = NULL;
int rc;
UINT32 flags = 0;
WCHAR* DriverName = NULL;
size_t DriverNameLen = 0;
WCHAR* PnPName = NULL;
size_t PnPNameLen = 0;
BYTE* CachedPrinterConfigData = NULL;
size_t CachedFieldsLen = 0;
size_t PrinterNameLen = 0;
if (!settings || !printer)
return FALSE;
rc = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &wname, 0);
if (rc <= 0)
goto fail;
wlen = _wcslen(wname) + 1;
path = get_printer_config_path(settings, wname, wlen * sizeof(WCHAR));
PrinterNameLen = (wlen + 1) * sizeof(WCHAR);
if (!path)
goto fail;
if (printer->is_default)
flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER;
if (!printer_read_setting(path, PRN_CONF_PNP, &PnPName, &PnPNameLen))
{
}
if (!printer_read_setting(path, PRN_CONF_DRIVER, &DriverName, &DriverNameLen))
{
DriverNameLen = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &DriverName,
0) * 2 + 1;
}
if (!printer_read_setting(path, PRN_CONF_DATA, &CachedPrinterConfigData, &CachedFieldsLen))
{
}
Stream_SetPosition(printer_dev->device.data, 0);
if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, 24))
goto fail;
Stream_Write_UINT32(printer_dev->device.data, flags);
Stream_Write_UINT32(printer_dev->device.data, 0); /* CodePage, reserved */
Stream_Write_UINT32(printer_dev->device.data, PnPNameLen); /* PnPNameLen */
Stream_Write_UINT32(printer_dev->device.data, DriverNameLen);
Stream_Write_UINT32(printer_dev->device.data, PrinterNameLen);
Stream_Write_UINT32(printer_dev->device.data, CachedFieldsLen);
if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, PnPNameLen))
goto fail;
if (PnPNameLen > 0)
Stream_Write(printer_dev->device.data, PnPName, PnPNameLen);
if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, DriverNameLen))
goto fail;
Stream_Write(printer_dev->device.data, DriverName, DriverNameLen);
if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, PrinterNameLen))
goto fail;
Stream_Write(printer_dev->device.data, wname, PrinterNameLen);
if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, CachedFieldsLen))
goto fail;
Stream_Write(printer_dev->device.data, CachedPrinterConfigData, CachedFieldsLen);
res = TRUE;
fail:
free(path);
free(wname);
free(PnPName);
free(DriverName);
free(CachedPrinterConfigData);
return res;
}
static BOOL printer_save_default_config(const rdpSettings* settings, rdpPrinter* printer)
{
BOOL res = FALSE;
WCHAR* wname = NULL;
WCHAR* driver = NULL;
size_t wlen, dlen;
char* path = NULL;
int rc;
if (!settings || !printer)
return FALSE;
rc = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &wname, 0);
if (rc <= 0)
goto fail;
rc = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &driver, 0);
if (rc <= 0)
goto fail;
wlen = _wcslen(wname) + 1;
dlen = _wcslen(driver) + 1;
path = get_printer_config_path(settings, wname, wlen * sizeof(WCHAR));
if (!path)
goto fail;
if (dlen > 1)
{
if (!printer_write_setting(path, PRN_CONF_DRIVER, driver, dlen * sizeof(WCHAR)))
goto fail;
}
res = TRUE;
fail:
free(path);
free(wname);
free(driver);
return res;
}
/**
* Function description
*
@ -293,6 +653,182 @@ static UINT printer_irp_request(DEVICE* device, IRP* irp)
return CHANNEL_RC_OK;
}
static UINT printer_custom_component(DEVICE* device, UINT16 component, UINT16 packetId, wStream* s)
{
UINT32 eventID;
PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) device;
const rdpSettings* settings = printer_dev->rdpcontext->settings;
if (component != RDPDR_CTYP_PRN)
return ERROR_INVALID_DATA;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, eventID);
switch (packetId)
{
case PAKID_PRN_CACHE_DATA:
switch (eventID)
{
case RDPDR_ADD_PRINTER_EVENT:
{
char PortDosName[8];
UINT32 PnPNameLen, DriverNameLen, PrintNameLen, CacheFieldsLen;
const WCHAR* PnPName, *DriverName, *PrinterName;
const BYTE* CachedPrinterConfigData;
if (Stream_GetRemainingLength(s) < 24)
return ERROR_INVALID_DATA;
Stream_Read(s, PortDosName, sizeof(PortDosName));
Stream_Read_UINT32(s, PnPNameLen);
Stream_Read_UINT32(s, DriverNameLen);
Stream_Read_UINT32(s, PrintNameLen);
Stream_Read_UINT32(s, CacheFieldsLen);
if (Stream_GetRemainingLength(s) < PnPNameLen)
return ERROR_INVALID_DATA;
PnPName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, PnPNameLen);
if (Stream_GetRemainingLength(s) < DriverNameLen)
return ERROR_INVALID_DATA;
DriverName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, DriverNameLen);
if (Stream_GetRemainingLength(s) < PrintNameLen)
return ERROR_INVALID_DATA;
PrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, PrintNameLen);
if (Stream_GetRemainingLength(s) < CacheFieldsLen)
return ERROR_INVALID_DATA;
CachedPrinterConfigData = Stream_Pointer(s);
Stream_Seek(s, CacheFieldsLen);
if (!printer_save_to_config(settings,
PortDosName, sizeof(PortDosName),
PnPName, PnPNameLen,
DriverName, DriverNameLen,
PrinterName, PrintNameLen,
CachedPrinterConfigData, CacheFieldsLen))
return ERROR_INTERNAL_ERROR;
}
break;
case RDPDR_UPDATE_PRINTER_EVENT:
{
UINT32 PrinterNameLen, ConfigDataLen;
const WCHAR* PrinterName;
const BYTE* ConfigData;
if (Stream_GetRemainingLength(s) < 8)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, PrinterNameLen);
Stream_Read_UINT32(s, ConfigDataLen);
if (Stream_GetRemainingLength(s) < PrinterNameLen)
return ERROR_INVALID_DATA;
PrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, PrinterNameLen);
if (Stream_GetRemainingLength(s) < ConfigDataLen)
return ERROR_INVALID_DATA;
ConfigData = Stream_Pointer(s);
Stream_Seek(s, ConfigDataLen);
if (!printer_update_to_config(settings, PrinterName, PrinterNameLen, ConfigData, ConfigDataLen))
return ERROR_INTERNAL_ERROR;
}
break;
case RDPDR_DELETE_PRINTER_EVENT:
{
UINT32 PrinterNameLen;
const WCHAR* PrinterName;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, PrinterNameLen);
if (Stream_GetRemainingLength(s) < PrinterNameLen)
return ERROR_INVALID_DATA;
PrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, PrinterNameLen);
printer_remove_config(settings, PrinterName, PrinterNameLen);
}
break;
case RDPDR_RENAME_PRINTER_EVENT:
{
UINT32 OldPrinterNameLen, NewPrinterNameLen;
const WCHAR* OldPrinterName;
const WCHAR* NewPrinterName;
if (Stream_GetRemainingLength(s) < 8)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, OldPrinterNameLen);
Stream_Read_UINT32(s, NewPrinterNameLen);
if (Stream_GetRemainingLength(s) < OldPrinterNameLen)
return ERROR_INVALID_DATA;
OldPrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, OldPrinterNameLen);
if (Stream_GetRemainingLength(s) < NewPrinterNameLen)
return ERROR_INVALID_DATA;
NewPrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, NewPrinterNameLen);
if (!printer_move_config(settings, OldPrinterName, OldPrinterNameLen, NewPrinterName,
NewPrinterNameLen))
return ERROR_INTERNAL_ERROR;
}
break;
default:
WLog_ERR(TAG, "Unknown cache data eventID: 0x%08"PRIX32"", eventID);
return ERROR_INVALID_DATA;
}
break;
case PAKID_PRN_USING_XPS:
{
UINT32 flags;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, flags);
WLog_ERR(TAG,
"Ignoring unhandled message PAKID_PRN_USING_XPS [printerID=%08"PRIx32", flags=%08"PRIx32"]",
eventID, flags);
}
break;
default:
WLog_ERR(TAG, "Unknown printing component packetID: 0x%04"PRIX16"", packetId);
return ERROR_INVALID_DATA;
}
return CHANNEL_RC_OK;
}
/**
* Function description
*
@ -309,7 +845,13 @@ static UINT printer_free(DEVICE* device)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error);
/* The analyzer is confused by this premature return value.
* Since this case can not be handled gracefully silence the
* analyzer here. */
#ifndef __clang_analyzer__
return error;
#endif
}
while ((irp = (IRP*) InterlockedPopEntrySList(printer_dev->pIrpList)) != NULL)
@ -336,15 +878,8 @@ static UINT printer_free(DEVICE* device)
UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
rdpPrinter* printer)
{
UINT32 Flags;
int DriverNameLen;
WCHAR* DriverName = NULL;
int PrintNameLen;
WCHAR* PrintName = NULL;
UINT32 CachedFieldsLen;
BYTE* CachedPrinterConfigData;
PRINTER_DEVICE* printer_dev;
UINT error;
UINT error = ERROR_INTERNAL_ERROR;
printer_dev = (PRINTER_DEVICE*) calloc(1, sizeof(PRINTER_DEVICE));
if (!printer_dev)
@ -353,55 +888,19 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
return CHANNEL_RC_NO_MEMORY;
}
printer_dev->device.data = Stream_New(NULL, 1024);
if (!printer_dev->device.data)
goto error_out;
sprintf_s(printer_dev->port, sizeof(printer_dev->port), "PRN%d", printer->id);
printer_dev->device.type = RDPDR_DTYP_PRINT;
printer_dev->device.name = printer_dev->port;
printer_dev->device.IRPRequest = printer_irp_request;
printer_dev->device.CustomComponentRequest = printer_custom_component;
printer_dev->device.Free = printer_free;
printer_dev->rdpcontext = pEntryPoints->rdpcontext;
printer_dev->printer = printer;
CachedFieldsLen = 0;
CachedPrinterConfigData = NULL;
Flags = 0;
if (printer->is_default)
Flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER;
DriverNameLen = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &DriverName,
0) * 2;
PrintNameLen = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &PrintName,
0) * 2;
printer_dev->device.data = Stream_New(NULL,
28 + DriverNameLen + PrintNameLen + CachedFieldsLen);
if (!printer_dev->device.data)
{
WLog_ERR(TAG, "calloc failed!");
error = CHANNEL_RC_NO_MEMORY;
free(DriverName);
free(PrintName);
goto error_out;
}
Stream_Write_UINT32(printer_dev->device.data, Flags);
Stream_Write_UINT32(printer_dev->device.data, 0); /* CodePage, reserved */
Stream_Write_UINT32(printer_dev->device.data, 0); /* PnPNameLen */
Stream_Write_UINT32(printer_dev->device.data, DriverNameLen + 2);
Stream_Write_UINT32(printer_dev->device.data, PrintNameLen + 2);
Stream_Write_UINT32(printer_dev->device.data, CachedFieldsLen);
Stream_Write(printer_dev->device.data, DriverName, DriverNameLen);
Stream_Write_UINT16(printer_dev->device.data, 0);
Stream_Write(printer_dev->device.data, PrintName, PrintNameLen);
Stream_Write_UINT16(printer_dev->device.data, 0);
if (CachedFieldsLen > 0)
{
Stream_Write(printer_dev->device.data, CachedPrinterConfigData,
CachedFieldsLen);
}
free(DriverName);
free(PrintName);
printer_dev->pIrpList = (WINPR_PSLIST_HEADER) _aligned_malloc(sizeof(
WINPR_SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
@ -412,6 +911,9 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
goto error_out;
}
if (!printer_load_from_config(pEntryPoints->rdpcontext->settings, printer, printer_dev))
goto error_out;
InitializeSListHead(printer_dev->pIrpList);
if (!(printer_dev->event = CreateEvent(NULL, TRUE, FALSE, NULL)))
@ -497,6 +999,9 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
return CHANNEL_RC_INITIALIZATION_ERROR;
}
if (!printer_save_default_config(pEntryPoints->rdpcontext->settings, printer))
return CHANNEL_RC_INITIALIZATION_ERROR;
if ((error = printer_register(pEntryPoints, printer)))
{
WLog_ERR(TAG, "printer_register failed with error %"PRIu32"!", error);

View File

@ -54,7 +54,7 @@ struct rdp_printer
pcFreePrinter Free;
};
typedef UINT (*pcWritePrintJob) (rdpPrintJob* printjob, BYTE* data, int size);
typedef UINT (*pcWritePrintJob) (rdpPrintJob* printjob, const BYTE* data, size_t size);
typedef void (*pcClosePrintJob) (rdpPrintJob* printjob);
struct rdp_print_job

View File

@ -68,8 +68,8 @@ DEVMAN* devman_new(rdpdrPlugin* rdpdr)
devman->plugin = (void*) rdpdr;
devman->id_sequence = 1;
devman->devices = ListDictionary_New(TRUE);
if (!devman->devices)
{
WLog_INFO(TAG, "ListDictionary_New failed!");
@ -78,7 +78,6 @@ DEVMAN* devman_new(rdpdrPlugin* rdpdr)
}
ListDictionary_ValueObject(devman->devices)->fnObjectFree = devman_device_free;
return devman;
}
@ -114,26 +113,57 @@ static UINT devman_register_device(DEVMAN* devman, DEVICE* device)
return ERROR_INVALID_PARAMETER;
device->id = devman->id_sequence++;
key = (void*) (size_t) device->id;
key = (void*)(size_t) device->id;
if (!ListDictionary_Add(devman->devices, key, device))
{
WLog_INFO(TAG, "ListDictionary_Add failed!");
return ERROR_INTERNAL_ERROR;
}
return CHANNEL_RC_OK;
}
DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id)
{
DEVICE* device = NULL;
void* key = (void*) (size_t) id;
void* key = (void*)(size_t) id;
if (!devman)
return NULL;
device = (DEVICE*) ListDictionary_GetItemValue(devman->devices, key);
return device;
}
DEVICE* devman_get_device_by_type(DEVMAN* devman, UINT32 type)
{
DEVICE* device = NULL;
ULONG_PTR* keys;
int count, x;
if (!devman)
return NULL;
ListDictionary_Lock(devman->devices);
count = ListDictionary_GetKeys(devman->devices, &keys);
for (x = 0; x < count; x++)
{
DEVICE* cur = (DEVICE*) ListDictionary_GetItemValue(devman->devices, (void*)keys[x]);
if (!cur)
continue;
if (cur->type != type)
continue;
device = cur;
break;
}
free(keys);
ListDictionary_Unlock(devman->devices);
return device;
}
@ -178,7 +208,9 @@ UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext
WLog_INFO(TAG, "Loading device service %s [%s] (static)", ServiceName, device->Name);
else
WLog_INFO(TAG, "Loading device service %s (static)", ServiceName);
entry = (PDEVICE_SERVICE_ENTRY) freerdp_load_channel_addin_entry(ServiceName, NULL, "DeviceServiceEntry", 0);
entry = (PDEVICE_SERVICE_ENTRY) freerdp_load_channel_addin_entry(ServiceName, NULL,
"DeviceServiceEntry", 0);
if (!entry)
{
@ -190,6 +222,5 @@ UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext
ep.RegisterDevice = devman_register_device;
ep.device = device;
ep.rdpcontext = rdpcontext;
return entry(&ep);
}

View File

@ -28,6 +28,7 @@
void devman_unregister_device(DEVMAN* devman, void* key);
UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext* rdpcontext);
DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id);
DEVICE* devman_get_device_by_type(DEVMAN* devman, UINT32 type);
DEVMAN* devman_new(rdpdrPlugin* rdpdr);
void devman_free(DEVMAN* devman);

View File

@ -135,7 +135,8 @@ BOOL check_path(char* path)
{
UINT type = GetDriveTypeA(path);
if (!(type == DRIVE_FIXED ||type == DRIVE_REMOVABLE || type == DRIVE_CDROM || type == DRIVE_REMOTE))
if (!(type == DRIVE_FIXED || type == DRIVE_REMOVABLE || type == DRIVE_CDROM ||
type == DRIVE_REMOTE))
return FALSE;
return GetVolumeInformationA(path, NULL, 0, NULL, NULL, NULL, NULL, 0);
@ -1324,6 +1325,31 @@ static UINT rdpdr_process_irp(rdpdrPlugin* rdpdr, wStream* s)
return error;
}
static UINT rdpdr_process_component(rdpdrPlugin* rdpdr, UINT16 component, UINT16 packetId,
wStream* s)
{
UINT32 type;
DEVICE* device;
switch (component)
{
case RDPDR_CTYP_PRN:
type = RDPDR_DTYP_PRINT;
break;
default:
return ERROR_INVALID_DATA;
}
device = devman_get_device_by_type(rdpdr->devman, type);
if (!device)
return ERROR_INVALID_PARAMETER;
return IFCALLRESULT(ERROR_INVALID_PARAMETER, device->CustomComponentRequest, device, component,
packetId, s);
}
/**
* Function description
*
@ -1368,141 +1394,114 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s)
UINT16 packetId;
UINT32 deviceId;
UINT32 status;
UINT error;
UINT error = ERROR_INVALID_DATA;
if (!rdpdr || !s)
return CHANNEL_RC_NULL_DATA;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT16(s, component); /* Component (2 bytes) */
Stream_Read_UINT16(s, packetId); /* PacketId (2 bytes) */
if (component == RDPDR_CTYP_CORE)
if (Stream_GetRemainingLength(s) >= 4)
{
switch (packetId)
Stream_Read_UINT16(s, component); /* Component (2 bytes) */
Stream_Read_UINT16(s, packetId); /* PacketId (2 bytes) */
if (component == RDPDR_CTYP_CORE)
{
case PAKID_CORE_SERVER_ANNOUNCE:
if ((error = rdpdr_process_server_announce_request(rdpdr, s)))
return error;
switch (packetId)
{
case PAKID_CORE_SERVER_ANNOUNCE:
if ((error = rdpdr_process_server_announce_request(rdpdr, s)))
{
}
else if ((error = rdpdr_send_client_announce_reply(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_send_client_announce_reply failed with error %"PRIu32"", error);
}
else if ((error = rdpdr_send_client_name_request(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_send_client_name_request failed with error %"PRIu32"", error);
}
else if ((error = rdpdr_process_init(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_process_init failed with error %"PRIu32"", error);
}
if ((error = rdpdr_send_client_announce_reply(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_send_client_announce_reply failed with error %"PRIu32"", error);
return error;
}
break;
if ((error = rdpdr_send_client_name_request(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_send_client_name_request failed with error %"PRIu32"", error);
return error;
}
case PAKID_CORE_SERVER_CAPABILITY:
if ((error = rdpdr_process_capability_request(rdpdr, s)))
{
}
else if ((error = rdpdr_send_capability_response(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_send_capability_response failed with error %"PRIu32"", error);
}
if ((error = rdpdr_process_init(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_process_init failed with error %"PRIu32"", error);
return error;
}
break;
break;
case PAKID_CORE_CLIENTID_CONFIRM:
if ((error = rdpdr_process_server_clientid_confirm(rdpdr, s)))
{
}
else if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE)))
{
WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %"PRIu32"",
error);
}
case PAKID_CORE_SERVER_CAPABILITY:
if ((error = rdpdr_process_capability_request(rdpdr, s)))
return error;
break;
if ((error = rdpdr_send_capability_response(rdpdr)))
{
WLog_ERR(TAG, "rdpdr_send_capability_response failed with error %"PRIu32"", error);
return error;
}
case PAKID_CORE_USER_LOGGEDON:
if ((error = rdpdr_send_device_list_announce_request(rdpdr, TRUE)))
{
WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %"PRIu32"",
error);
}
break;
break;
case PAKID_CORE_CLIENTID_CONFIRM:
if ((error = rdpdr_process_server_clientid_confirm(rdpdr, s)))
return error;
case PAKID_CORE_DEVICE_REPLY:
if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE)))
{
WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %"PRIu32"",
error);
return error;
}
/* connect to a specific resource */
if (Stream_GetRemainingLength(s) >= 8)
{
Stream_Read_UINT32(s, deviceId);
Stream_Read_UINT32(s, status);
error = CHANNEL_RC_OK;
}
break;
break;
case PAKID_CORE_USER_LOGGEDON:
if ((error = rdpdr_send_device_list_announce_request(rdpdr, TRUE)))
{
WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %"PRIu32"",
error);
return error;
}
case PAKID_CORE_DEVICE_IOREQUEST:
if ((error = rdpdr_process_irp(rdpdr, s)))
{
WLog_ERR(TAG, "rdpdr_process_irp failed with error %"PRIu32"", error);
return error;
}
else
s = NULL;
break;
break;
case PAKID_CORE_DEVICE_REPLY:
/* connect to a specific resource */
if (Stream_GetRemainingLength(s) < 8)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, deviceId);
Stream_Read_UINT32(s, status);
break;
case PAKID_CORE_DEVICE_IOREQUEST:
if ((error = rdpdr_process_irp(rdpdr, s)))
{
WLog_ERR(TAG, "rdpdr_process_irp failed with error %"PRIu32"", error);
return error;
}
s = NULL;
break;
default:
WLog_ERR(TAG, "RDPDR_CTYP_CORE unknown PacketId: 0x%04"PRIX16"", packetId);
return ERROR_INVALID_DATA;
break;
default:
WLog_ERR(TAG, "RDPDR_CTYP_CORE unknown PacketId: 0x%04"PRIX16"", packetId);
error = ERROR_INVALID_DATA;
break;
}
}
}
else if (component == RDPDR_CTYP_PRN)
{
switch (packetId)
else
{
case PAKID_PRN_CACHE_DATA:
{
UINT32 eventID;
error = rdpdr_process_component(rdpdr, component, packetId, s);
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, eventID);
WLog_ERR(TAG,
"Ignoring unhandled message PAKID_PRN_CACHE_DATA (EventID: 0x%08"PRIX32")", eventID);
}
break;
case PAKID_PRN_USING_XPS:
WLog_ERR(TAG, "Ignoring unhandled message PAKID_PRN_USING_XPS");
break;
default:
WLog_ERR(TAG, "Unknown printing component packetID: 0x%04"PRIX16"", packetId);
return ERROR_INVALID_DATA;
if (error != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "Unknown message: Component: 0x%04"PRIX16" PacketId: 0x%04"PRIX16"", component,
packetId);
}
}
}
else
{
WLog_ERR(TAG, "Unknown message: Component: 0x%04"PRIX16" PacketId: 0x%04"PRIX16"", component,
packetId);
return ERROR_INVALID_DATA;
}
Stream_Free(s, TRUE);
return CHANNEL_RC_OK;
return error;
}
/**

View File

@ -243,10 +243,7 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd
h264.bitstream[1].length = Stream_GetRemainingLength(s);
}
else
{
h264.bitstream[0].length = Stream_GetRemainingLength(s);
memset(&h264.bitstream[1], 0, sizeof(h264.bitstream[1]));
}
cmd->extra = (void*) &h264;

View File

@ -29,8 +29,8 @@
#include <stdlib.h>
#include <string.h>
#include <Windows.h>
#include <MMSystem.h>
#include <windows.h>
#include <mmsystem.h>
#include <winpr/crt.h>
#include <winpr/cmdline.h>
@ -102,14 +102,12 @@ static void CALLBACK rdpsnd_winmm_callback_function(HWAVEOUT hwo, UINT uMsg, DWO
case MM_WOM_CLOSE:
WLog_DBG(TAG, "MM_WOM_CLOSE");
SetEvent(winmm->next);
break;
case MM_WOM_DONE:
WLog_DBG(TAG, "MM_WOM_DONE");
lpWaveHdr = (LPWAVEHDR) dwParam1;
free(lpWaveHdr);
SetEvent(winmm->next);
break;
default:
@ -176,7 +174,6 @@ static void rdpsnd_winmm_free(rdpsndDevicePlugin* device)
if (winmm)
{
rdpsnd_winmm_close(device);
CloseHandle(winmm->next);
free(winmm);
}
}
@ -269,7 +266,6 @@ static UINT rdpsnd_winmm_play(rdpsndDevicePlugin* device, const BYTE* data, size
return 0;
}
WaitForSingleObject(winmm->next, INFINITE);
return 10; /* TODO: Get real latencry in [ms] */
}
@ -305,13 +301,6 @@ UINT freerdp_rdpsnd_client_subsystem_entry(PFREERDP_RDPSND_DEVICE_ENTRY_POINTS p
winmm->device.Play = rdpsnd_winmm_play;
winmm->device.Close = rdpsnd_winmm_close;
winmm->device.Free = rdpsnd_winmm_free;
winmm->next = CreateEventA(NULL, FALSE, FALSE, "winmm-play-event");
if (!winmm->next)
{
free(winmm);
return CHANNEL_RC_NO_MEMORY;
}
args = pEntryPoints->args;
rdpsnd_winmm_parse_addin_args((rdpsndDevicePlugin*) winmm, args);

View File

@ -255,7 +255,13 @@ static UINT remdesk_recv_ctl_version_info_pdu(remdeskPlugin* remdesk,
Stream_Read_UINT32(s, versionMajor); /* versionMajor (4 bytes) */
Stream_Read_UINT32(s, versionMinor); /* versionMinor (4 bytes) */
remdesk->Version = versionMajor;
if ((versionMajor != 1) || (versionMinor > 2) || (versionMinor == 0))
{
WLog_ERR(TAG, "Unsupported protocol version %"PRId32".%"PRId32, versionMajor, versionMinor);
}
remdesk->Version = versionMinor;
return CHANNEL_RC_OK;
}

View File

@ -55,7 +55,7 @@ struct remdesk_plugin
UINT32 Version;
char* ExpertBlob;
BYTE* EncryptedPassStub;
int EncryptedPassStubSize;
size_t EncryptedPassStubSize;
rdpContext* rdpcontext;
};
typedef struct remdesk_plugin remdeskPlugin;

View File

@ -161,7 +161,7 @@ LONG smartcard_pack_write_size_align(SMARTCARD_DEVICE* smartcard, wStream* s, UI
SCARDCONTEXT smartcard_scard_context_native_from_redir(SMARTCARD_DEVICE* smartcard,
REDIR_SCARDCONTEXT* context)
{
SCARDCONTEXT hContext = 0;
SCARDCONTEXT hContext = { 0 };
if ((context->cbContext != sizeof(ULONG_PTR)) && (context->cbContext != 0))
{
@ -173,8 +173,6 @@ SCARDCONTEXT smartcard_scard_context_native_from_redir(SMARTCARD_DEVICE* smartca
if (context->cbContext)
CopyMemory(&hContext, &(context->pbContext), context->cbContext);
else
ZeroMemory(&hContext, sizeof(ULONG_PTR));
return hContext;
}

View File

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

View File

@ -1,13 +1,11 @@
set(OPTION_DEFAULT OFF)
set(OPTION_CLIENT_DEFAULT OFF)
set(OPTION_SERVER_DEFAULT OFF)
define_channel_options(NAME "sshagent" TYPE "dynamic"
DESCRIPTION "SSH Agent Forwarding Extension"
DESCRIPTION "SSH Agent Forwarding (experimental)"
SPECIFICATIONS ""
DEFAULT ${OPTION_DEFAULT})
define_channel_client_options(${OPTION_CLIENT_DEFAULT})
define_channel_server_options(${OPTION_SERVER_DEFAULT})

View File

@ -1,31 +0,0 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
# Copyright 2017 Ben Cohen
#
# 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("sshagent")
set(${MODULE_PREFIX}_SRCS
sshagent_main.c)
add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "DVCPluginEntry")
target_link_libraries(${MODULE_NAME} freerdp)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server")

View File

@ -1,422 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* SSH Agent Virtual Channel Extension
*
* Copyright 2012-2013 Jay Sorg
* Copyright 2012-2013 Laxmikant Rashinkar
* Copyright 2017 Ben Cohen
*
* 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.
*/
/*
* Portions are from OpenSSH, under the following license:
*
* Author: Tatu Ylonen <ylo@cs.hut.fi>
* Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
* All rights reserved
* The authentication agent program.
*
* As far as I am concerned, the code I have written for this software
* can be used freely for any purpose. Any derived versions of this
* software must be clearly marked as such, and if the derived work is
* incompatible with the protocol description in the RFC file, it must be
* called by a name other than "ssh" or "Secure Shell".
*
* Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* xrdp-ssh-agent.c: program to forward ssh-agent protocol from xrdp session
*
* This performs the equivalent function of ssh-agent on a server you connect
* to via ssh, but the ssh-agent protocol is over an RDP dynamic virtual
* channel and not an SSH channel.
*
* This will print out variables to set in your environment (specifically,
* $SSH_AUTH_SOCK) for ssh clients to find the agent's socket, then it will
* run in the background. This is suitable to run just as you would run the
* normal ssh-agent, e.g. in your Xsession or /etc/xrdp/startwm.sh.
*
* Your RDP client needs to be running a compatible client-side plugin
* that can see a local ssh-agent.
*
* usage (from within an xrdp session):
* xrdp-ssh-agent
*
* build instructions:
* gcc xrdp-ssh-agent.c -o xrdp-ssh-agent -L./.libs -lxrdpapi -Wall
*
* protocol specification:
* Forward data verbatim over RDP dynamic virtual channel named "sshagent"
* between a ssh client on the xrdp server and the real ssh-agent where
* the RDP client is running. Each connection by a separate client to
* xrdp-ssh-agent gets a separate DVC invocation.
*/
#if defined(HAVE_CONFIG_H)
#include <config.h>
#endif
#ifdef __WIN32__
#include <mstsapi.h>
#endif
#include <freerdp/channels/wtsvc.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/resource.h>
#define _PATH_DEVNULL "/dev/null"
static char socket_name[PATH_MAX];
static char socket_dir[PATH_MAX];
static int sa_uds_fd = -1;
static int is_going = 1;
/* Make a template filename for mk[sd]temp() */
/* This is from mktemp_proto() in misc.c from openssh */
void
mktemp_proto(char* s, size_t len)
{
const char* tmpdir;
int r;
if ((tmpdir = getenv("TMPDIR")) != NULL)
{
r = snprintf(s, len, "%s/ssh-XXXXXXXXXXXX", tmpdir);
if (r > 0 && (size_t)r < len)
return;
}
r = snprintf(s, len, "/tmp/ssh-XXXXXXXXXXXX");
if (r < 0 || (size_t)r >= len)
{
fprintf(stderr, "%s: template string too short", __func__);
exit(1);
}
}
/* This uses parts of main() in ssh-agent.c from openssh */
static void
setup_ssh_agent(struct sockaddr_un* addr)
{
int rc;
/* Create private directory for agent socket */
mktemp_proto(socket_dir, sizeof(socket_dir));
if (mkdtemp(socket_dir) == NULL)
{
perror("mkdtemp: private socket dir");
exit(1);
}
snprintf(socket_name, sizeof(socket_name), "%s/agent.%ld", socket_dir,
(long)getpid());
/* Create unix domain socket */
unlink(socket_name);
sa_uds_fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (sa_uds_fd == -1)
{
fprintf(stderr, "sshagent: socket creation failed");
exit(2);
}
memset(addr, 0, sizeof(struct sockaddr_un));
addr->sun_family = AF_UNIX;
strncpy(addr->sun_path, socket_name, sizeof(addr->sun_path));
addr->sun_path[sizeof(addr->sun_path) - 1] = 0;
/* Create with privileges rw------- so other users can't access the UDS */
mode_t umask_sav = umask(0177);
rc = bind(sa_uds_fd, (struct sockaddr*)addr, sizeof(struct sockaddr_un));
if (rc != 0)
{
fprintf(stderr, "sshagent: bind failed");
close(sa_uds_fd);
unlink(socket_name);
exit(3);
}
umask(umask_sav);
rc = listen(sa_uds_fd, /* backlog = */ 5);
if (rc != 0)
{
fprintf(stderr, "listen failed\n");
close(sa_uds_fd);
unlink(socket_name);
exit(1);
}
/* Now fork: the child becomes the ssh-agent daemon and the parent prints
* out the pid and socket name. */
pid_t pid = fork();
if (pid == -1)
{
perror("fork");
exit(1);
}
else if (pid != 0)
{
/* Parent */
close(sa_uds_fd);
printf("SSH_AUTH_SOCK=%s; export SSH_AUTH_SOCK;\n", socket_name);
printf("SSH_AGENT_PID=%d; export SSH_AGENT_PID;\n", pid);
printf("echo Agent pid %d;\n", pid);
exit(0);
}
/* Child */
if (setsid() == -1)
{
fprintf(stderr, "setsid failed");
exit(1);
}
(void)chdir("/");
int devnullfd;
if ((devnullfd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1)
{
/* XXX might close listen socket */
(void)dup2(devnullfd, STDIN_FILENO);
(void)dup2(devnullfd, STDOUT_FILENO);
(void)dup2(devnullfd, STDERR_FILENO);
if (devnullfd > 2)
close(devnullfd);
}
/* deny core dumps, since memory contains unencrypted private keys */
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max = 0;
if (setrlimit(RLIMIT_CORE, &rlim) < 0)
{
fprintf(stderr, "setrlimit RLIMIT_CORE: %s", strerror(errno));
exit(1);
}
}
static void
handle_connection(int client_fd)
{
int rdp_fd = -1;
int rc;
void* channel = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION,
"SSHAGENT",
WTS_CHANNEL_OPTION_DYNAMIC_PRI_MED);
if (channel == NULL)
{
fprintf(stderr, "WTSVirtualChannelOpenEx() failed\n");
}
unsigned int retlen;
int* retdata;
rc = WTSVirtualChannelQuery(channel,
WTSVirtualFileHandle,
(void**)&retdata,
&retlen);
if (!rc)
{
fprintf(stderr, "WTSVirtualChannelQuery() failed\n");
}
if (retlen != sizeof(rdp_fd))
{
fprintf(stderr, "WTSVirtualChannelQuery() returned wrong length %d\n",
retlen);
}
rdp_fd = *retdata;
int client_going = 1;
while (client_going)
{
/* Wait for data from RDP or the client */
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(client_fd, &readfds);
FD_SET(rdp_fd, &readfds);
select(FD_SETSIZE, &readfds, NULL, NULL, NULL);
if (FD_ISSET(rdp_fd, &readfds))
{
/* Read from RDP and write to the client */
char buffer[4096];
unsigned int bytes_to_write;
rc = WTSVirtualChannelRead(channel,
/* TimeOut = */ 5000,
buffer,
sizeof(buffer),
&bytes_to_write);
if (rc == 1)
{
char* pos = buffer;
errno = 0;
while (bytes_to_write > 0)
{
int bytes_written = send(client_fd, pos, bytes_to_write, 0);
if (bytes_written > 0)
{
bytes_to_write -= bytes_written;
pos += bytes_written;
}
else if (bytes_written == 0)
{
fprintf(stderr, "send() returned 0!\n");
}
else if (errno != EINTR)
{
/* Error */
fprintf(stderr, "Error %d on recv\n", errno);
client_going = 0;
}
}
}
else
{
/* Error */
fprintf(stderr, "WTSVirtualChannelRead() failed: %d\n", errno);
client_going = 0;
}
}
if (FD_ISSET(client_fd, &readfds))
{
/* Read from the client and write to RDP */
char buffer[4096];
ssize_t bytes_to_write = recv(client_fd, buffer, sizeof(buffer), 0);
if (bytes_to_write > 0)
{
char* pos = buffer;
while (bytes_to_write > 0)
{
unsigned int bytes_written;
int rc = WTSVirtualChannelWrite(channel,
pos,
bytes_to_write,
&bytes_written);
if (rc == 0)
{
fprintf(stderr, "WTSVirtualChannelWrite() failed: %d\n",
errno);
client_going = 0;
}
else
{
bytes_to_write -= bytes_written;
pos += bytes_written;
}
}
}
else if (bytes_to_write == 0)
{
/* Client has closed connection */
client_going = 0;
}
else
{
/* Error */
fprintf(stderr, "Error %d on recv\n", errno);
client_going = 0;
}
}
}
WTSVirtualChannelClose(channel);
}
int
main(int argc, char** argv)
{
/* Setup the Unix domain socket and daemon process */
struct sockaddr_un addr;
setup_ssh_agent(&addr);
/* Wait for a client to connect to the socket */
while (is_going)
{
fd_set readfds;
FD_ZERO(&readfds);
FD_SET(sa_uds_fd, &readfds);
select(FD_SETSIZE, &readfds, NULL, NULL, NULL);
/* If something connected then get it...
* (You can test this using "socat - UNIX-CONNECT:<udspath>".) */
if (FD_ISSET(sa_uds_fd, &readfds))
{
socklen_t addrsize = sizeof(addr);
int client_fd = accept(sa_uds_fd,
(struct sockaddr*)&addr,
&addrsize);
handle_connection(client_fd);
close(client_fd);
}
}
close(sa_uds_fd);
unlink(socket_name);
return 0;
}
/* vim: set sw=4:ts=4:et: */

View File

@ -151,11 +151,7 @@ static BOOL tsmf_gstreamer_change_volume(ITSMFDecoder* decoder, UINT32 newVolume
return TRUE;
}
#ifdef __OpenBSD__
static inline GstClockTime tsmf_gstreamer_timestamp_ms_to_gst(UINT64 ms_timestamp)
#else
static inline const GstClockTime tsmf_gstreamer_timestamp_ms_to_gst(UINT64 ms_timestamp)
#endif
{
/*
* Convert Microsoft 100ns timestamps to Gstreamer 1ns units.
@ -633,7 +629,8 @@ BOOL tsmf_gstreamer_pipeline_build(TSMFGstreamerDecoder* mdecoder)
{
tsmf_gstreamer_need_data,
tsmf_gstreamer_enough_data,
tsmf_gstreamer_seek_data
tsmf_gstreamer_seek_data,
{ NULL }
};
g_object_set(mdecoder->src, "format", GST_FORMAT_TIME, NULL);
g_object_set(mdecoder->src, "is-live", FALSE, NULL);

View File

@ -702,16 +702,8 @@ static BOOL tsmf_sample_playback(TSMF_SAMPLE* sample)
buffer_filled = FALSE;
}
if (buffer_filled)
{
ack_anticipation_time += (sample->duration / 2 < MAX_ACK_TIME) ?
sample->duration / 2 : MAX_ACK_TIME;
}
else
{
ack_anticipation_time += (sample->duration / 2 < MAX_ACK_TIME) ?
sample->duration / 2 : MAX_ACK_TIME;
}
ack_anticipation_time += (sample->duration / 2 < MAX_ACK_TIME) ?
sample->duration / 2 : MAX_ACK_TIME;
switch (sample->stream->major_type)
{

View File

@ -1387,7 +1387,7 @@ static int libusb_udev_isoch_transfer(IUDEVICE* idev, UINT32 RequestId, UINT32 E
if (iso_transfer == NULL)
{
WLog_ERR(TAG, "Error: libusb_alloc_transfer.");
status = -1;
return -1;
}
/** process URB_FUNCTION_IOSCH_TRANSFER */

1
client/.gitignore vendored
View File

@ -1,7 +1,6 @@
/*
!/Android
!/common
!/DirectFB
!/iOS
!/Mac
!/Sample

View File

@ -26,10 +26,6 @@ if(FREERDP_VENDOR AND WITH_CLIENT)
if(WITH_SAMPLE)
add_subdirectory(Sample)
endif()
if(WITH_DIRECTFB)
add_subdirectory(DirectFB)
endif()
endif()
if(WITH_X11)

View File

@ -1,40 +0,0 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP DirectFB Client
#
# 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.
set(MODULE_NAME "dfreerdp")
set(MODULE_PREFIX "FREERDP_CLIENT_DIRECTFB")
include_directories(${DIRECTFB_INCLUDE_DIRS})
set(${MODULE_PREFIX}_SRCS
df_event.c
df_event.h
df_graphics.c
df_graphics.c
dfreerdp.c
dfreerdp.h)
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
set(${MODULE_PREFIX}_LIBS ${DIRECTFB_LIBRARIES})
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-client)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr freerdp)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR})
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/DirectFB")

View File

@ -1,4 +0,0 @@
set(FREERDP_CLIENT_NAME "dfreerdp")
set(FREERDP_CLIENT_PLATFORM "DirectFB")
set(FREERDP_CLIENT_VENDOR "FreeRDP")

View File

@ -1,271 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* DirectFB Event Handling
*
* Copyright 2011 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.
*/
#include <winpr/crt.h>
#include <winpr/input.h>
#include <freerdp/locale/keyboard.h>
#include "df_event.h"
static BYTE keymap[256];
static BYTE functionmap[128];
void df_keyboard_init()
{
ZeroMemory(keymap, sizeof(keymap));
/* Map DirectFB keycodes to Virtual Key Codes */
keymap[DIKI_A - DIKI_UNKNOWN] = VK_KEY_A;
keymap[DIKI_B - DIKI_UNKNOWN] = VK_KEY_B;
keymap[DIKI_C - DIKI_UNKNOWN] = VK_KEY_C;
keymap[DIKI_D - DIKI_UNKNOWN] = VK_KEY_D;
keymap[DIKI_E - DIKI_UNKNOWN] = VK_KEY_E;
keymap[DIKI_F - DIKI_UNKNOWN] = VK_KEY_F;
keymap[DIKI_G - DIKI_UNKNOWN] = VK_KEY_G;
keymap[DIKI_H - DIKI_UNKNOWN] = VK_KEY_H;
keymap[DIKI_I - DIKI_UNKNOWN] = VK_KEY_I;
keymap[DIKI_J - DIKI_UNKNOWN] = VK_KEY_J;
keymap[DIKI_K - DIKI_UNKNOWN] = VK_KEY_K;
keymap[DIKI_L - DIKI_UNKNOWN] = VK_KEY_L;
keymap[DIKI_M - DIKI_UNKNOWN] = VK_KEY_M;
keymap[DIKI_N - DIKI_UNKNOWN] = VK_KEY_N;
keymap[DIKI_O - DIKI_UNKNOWN] = VK_KEY_O;
keymap[DIKI_P - DIKI_UNKNOWN] = VK_KEY_P;
keymap[DIKI_Q - DIKI_UNKNOWN] = VK_KEY_Q;
keymap[DIKI_R - DIKI_UNKNOWN] = VK_KEY_R;
keymap[DIKI_S - DIKI_UNKNOWN] = VK_KEY_S;
keymap[DIKI_T - DIKI_UNKNOWN] = VK_KEY_T;
keymap[DIKI_U - DIKI_UNKNOWN] = VK_KEY_U;
keymap[DIKI_V - DIKI_UNKNOWN] = VK_KEY_V;
keymap[DIKI_W - DIKI_UNKNOWN] = VK_KEY_W;
keymap[DIKI_X - DIKI_UNKNOWN] = VK_KEY_X;
keymap[DIKI_Y - DIKI_UNKNOWN] = VK_KEY_Y;
keymap[DIKI_Z - DIKI_UNKNOWN] = VK_KEY_Z;
keymap[DIKI_0 - DIKI_UNKNOWN] = VK_KEY_0;
keymap[DIKI_1 - DIKI_UNKNOWN] = VK_KEY_1;
keymap[DIKI_2 - DIKI_UNKNOWN] = VK_KEY_2;
keymap[DIKI_3 - DIKI_UNKNOWN] = VK_KEY_3;
keymap[DIKI_4 - DIKI_UNKNOWN] = VK_KEY_4;
keymap[DIKI_5 - DIKI_UNKNOWN] = VK_KEY_5;
keymap[DIKI_6 - DIKI_UNKNOWN] = VK_KEY_6;
keymap[DIKI_7 - DIKI_UNKNOWN] = VK_KEY_7;
keymap[DIKI_8 - DIKI_UNKNOWN] = VK_KEY_8;
keymap[DIKI_9 - DIKI_UNKNOWN] = VK_KEY_9;
keymap[DIKI_F1 - DIKI_UNKNOWN] = VK_F1;
keymap[DIKI_F2 - DIKI_UNKNOWN] = VK_F2;
keymap[DIKI_F3 - DIKI_UNKNOWN] = VK_F3;
keymap[DIKI_F4 - DIKI_UNKNOWN] = VK_F4;
keymap[DIKI_F5 - DIKI_UNKNOWN] = VK_F5;
keymap[DIKI_F6 - DIKI_UNKNOWN] = VK_F6;
keymap[DIKI_F7 - DIKI_UNKNOWN] = VK_F7;
keymap[DIKI_F8 - DIKI_UNKNOWN] = VK_F8;
keymap[DIKI_F9 - DIKI_UNKNOWN] = VK_F9;
keymap[DIKI_F10 - DIKI_UNKNOWN] = VK_F10;
keymap[DIKI_F11 - DIKI_UNKNOWN] = VK_F11;
keymap[DIKI_F12 - DIKI_UNKNOWN] = VK_F12;
keymap[DIKI_COMMA - DIKI_UNKNOWN] = VK_OEM_COMMA;
keymap[DIKI_PERIOD - DIKI_UNKNOWN] = VK_OEM_PERIOD;
keymap[DIKI_MINUS_SIGN - DIKI_UNKNOWN] = VK_OEM_MINUS;
keymap[DIKI_EQUALS_SIGN - DIKI_UNKNOWN] = VK_OEM_PLUS;
keymap[DIKI_ESCAPE - DIKI_UNKNOWN] = VK_ESCAPE;
keymap[DIKI_LEFT - DIKI_UNKNOWN] = VK_LEFT;
keymap[DIKI_RIGHT - DIKI_UNKNOWN] = VK_RIGHT;
keymap[DIKI_UP - DIKI_UNKNOWN] = VK_UP;
keymap[DIKI_DOWN - DIKI_UNKNOWN] = VK_DOWN;
keymap[DIKI_CONTROL_L - DIKI_UNKNOWN] = VK_LCONTROL;
keymap[DIKI_CONTROL_R - DIKI_UNKNOWN] = VK_RCONTROL;
keymap[DIKI_SHIFT_L - DIKI_UNKNOWN] = VK_LSHIFT;
keymap[DIKI_SHIFT_R - DIKI_UNKNOWN] = VK_RSHIFT;
keymap[DIKI_ALT_L - DIKI_UNKNOWN] = VK_LMENU;
keymap[DIKI_ALT_R - DIKI_UNKNOWN] = VK_RMENU;
keymap[DIKI_TAB - DIKI_UNKNOWN] = VK_TAB;
keymap[DIKI_ENTER - DIKI_UNKNOWN] = VK_RETURN;
keymap[DIKI_SPACE - DIKI_UNKNOWN] = VK_SPACE;
keymap[DIKI_BACKSPACE - DIKI_UNKNOWN] = VK_BACK;
keymap[DIKI_INSERT - DIKI_UNKNOWN] = VK_INSERT;
keymap[DIKI_DELETE - DIKI_UNKNOWN] = VK_DELETE;
keymap[DIKI_HOME - DIKI_UNKNOWN] = VK_HOME;
keymap[DIKI_END - DIKI_UNKNOWN] = VK_END;
keymap[DIKI_PAGE_UP - DIKI_UNKNOWN] = VK_PRIOR;
keymap[DIKI_PAGE_DOWN - DIKI_UNKNOWN] = VK_NEXT;
keymap[DIKI_CAPS_LOCK - DIKI_UNKNOWN] = VK_CAPITAL;
keymap[DIKI_NUM_LOCK - DIKI_UNKNOWN] = VK_NUMLOCK;
keymap[DIKI_SCROLL_LOCK - DIKI_UNKNOWN] = VK_SCROLL;
keymap[DIKI_PRINT - DIKI_UNKNOWN] = VK_PRINT;
keymap[DIKI_PAUSE - DIKI_UNKNOWN] = VK_PAUSE;
keymap[DIKI_KP_DIV - DIKI_UNKNOWN] = VK_DIVIDE;
keymap[DIKI_KP_MULT - DIKI_UNKNOWN] = VK_MULTIPLY;
keymap[DIKI_KP_MINUS - DIKI_UNKNOWN] = VK_SUBTRACT;
keymap[DIKI_KP_PLUS - DIKI_UNKNOWN] = VK_ADD;
keymap[DIKI_KP_ENTER - DIKI_UNKNOWN] = VK_RETURN;
keymap[DIKI_KP_DECIMAL - DIKI_UNKNOWN] = VK_DECIMAL;
keymap[DIKI_QUOTE_LEFT - DIKI_UNKNOWN] = VK_OEM_3;
keymap[DIKI_BRACKET_LEFT - DIKI_UNKNOWN] = VK_OEM_4;
keymap[DIKI_BRACKET_RIGHT - DIKI_UNKNOWN] = VK_OEM_6;
keymap[DIKI_BACKSLASH - DIKI_UNKNOWN] = VK_OEM_5;
keymap[DIKI_SEMICOLON - DIKI_UNKNOWN] = VK_OEM_1;
keymap[DIKI_QUOTE_RIGHT - DIKI_UNKNOWN] = VK_OEM_7;
keymap[DIKI_COMMA - DIKI_UNKNOWN] = VK_OEM_COMMA;
keymap[DIKI_PERIOD - DIKI_UNKNOWN] = VK_OEM_PERIOD;
keymap[DIKI_SLASH - DIKI_UNKNOWN] = VK_OEM_2;
keymap[DIKI_LESS_SIGN - DIKI_UNKNOWN] = 0;
keymap[DIKI_KP_0 - DIKI_UNKNOWN] = VK_NUMPAD0;
keymap[DIKI_KP_1 - DIKI_UNKNOWN] = VK_NUMPAD1;
keymap[DIKI_KP_2 - DIKI_UNKNOWN] = VK_NUMPAD2;
keymap[DIKI_KP_3 - DIKI_UNKNOWN] = VK_NUMPAD3;
keymap[DIKI_KP_4 - DIKI_UNKNOWN] = VK_NUMPAD4;
keymap[DIKI_KP_5 - DIKI_UNKNOWN] = VK_NUMPAD5;
keymap[DIKI_KP_6 - DIKI_UNKNOWN] = VK_NUMPAD6;
keymap[DIKI_KP_7 - DIKI_UNKNOWN] = VK_NUMPAD7;
keymap[DIKI_KP_8 - DIKI_UNKNOWN] = VK_NUMPAD8;
keymap[DIKI_KP_9 - DIKI_UNKNOWN] = VK_NUMPAD9;
keymap[DIKI_META_L - DIKI_UNKNOWN] = VK_LWIN;
keymap[DIKI_META_R - DIKI_UNKNOWN] = VK_RWIN;
keymap[DIKI_SUPER_L - DIKI_UNKNOWN] = VK_APPS;
ZeroMemory(functionmap, sizeof(functionmap));
functionmap[DFB_FUNCTION_KEY(23) - DFB_FUNCTION_KEY(0)] = VK_HANGUL;
functionmap[DFB_FUNCTION_KEY(24) - DFB_FUNCTION_KEY(0)] = VK_HANJA;
}
void df_send_mouse_button_event(rdpInput* input, BOOL down, UINT32 button, UINT16 x, UINT16 y)
{
UINT16 flags;
flags = (down) ? PTR_FLAGS_DOWN : 0;
if (button == DIBI_LEFT)
flags |= PTR_FLAGS_BUTTON1;
else if (button == DIBI_RIGHT)
flags |= PTR_FLAGS_BUTTON2;
else if (button == DIBI_MIDDLE)
flags |= PTR_FLAGS_BUTTON3;
if (flags != 0)
input->MouseEvent(input, flags, x, y);
}
void df_send_mouse_motion_event(rdpInput* input, UINT16 x, UINT16 y)
{
input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
}
void df_send_mouse_wheel_event(rdpInput* input, INT16 axisrel, UINT16 x, UINT16 y)
{
UINT16 flags = PTR_FLAGS_WHEEL;
if (axisrel < 0)
flags |= 0x0078;
else
flags |= PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
input->MouseEvent(input, flags, x, y);
}
void df_send_keyboard_event(rdpInput* input, BOOL down, BYTE keycode, BYTE function)
{
DWORD scancode = 0;
BYTE vkcode = VK_NONE;
if (keycode)
vkcode = keymap[keycode];
else if (function)
vkcode = functionmap[function];
if (vkcode != VK_NONE)
scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, input->context->settings->KeyboardType);
if (scancode)
freerdp_input_send_keyboard_event_ex(input, down, scancode);
}
BOOL df_event_process(freerdp* instance, DFBEvent* event)
{
int flags;
rdpGdi* gdi;
dfInfo* dfi;
int pointer_x;
int pointer_y;
DFBInputEvent* input_event;
gdi = instance->context->gdi;
dfi = ((dfContext*) instance->context)->dfi;
dfi->layer->GetCursorPosition(dfi->layer, &pointer_x, &pointer_y);
if (event->clazz == DFEC_INPUT)
{
flags = 0;
input_event = (DFBInputEvent*) event;
switch (input_event->type)
{
case DIET_AXISMOTION:
if (pointer_x > (gdi->width - 1))
pointer_x = gdi->width - 1;
if (pointer_y > (gdi->height - 1))
pointer_y = gdi->height - 1;
if (input_event->axis == DIAI_Z)
{
df_send_mouse_wheel_event(instance->input, input_event->axisrel, pointer_x, pointer_y);
}
else
{
df_send_mouse_motion_event(instance->input, pointer_x, pointer_y);
}
break;
case DIET_BUTTONPRESS:
df_send_mouse_button_event(instance->input, TRUE, input_event->button, pointer_x, pointer_y);
break;
case DIET_BUTTONRELEASE:
df_send_mouse_button_event(instance->input, FALSE, input_event->button, pointer_x, pointer_y);
break;
case DIET_KEYPRESS:
df_send_keyboard_event(instance->input, TRUE, input_event->key_id - DIKI_UNKNOWN, input_event->key_symbol - DFB_FUNCTION_KEY(0));
break;
case DIET_KEYRELEASE:
df_send_keyboard_event(instance->input, FALSE, input_event->key_id - DIKI_UNKNOWN, input_event->key_symbol - DFB_FUNCTION_KEY(0));
break;
case DIET_UNKNOWN:
break;
}
}
return TRUE;
}

View File

@ -1,139 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* DirectFB Graphical Objects
*
* Copyright 2011 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.
*/
#include <winpr/crt.h>
#include "df_graphics.h"
/* Pointer Class */
void df_Pointer_New(rdpContext* context, rdpPointer* pointer)
{
dfInfo* dfi;
DFBResult result;
dfPointer* df_pointer;
DFBSurfaceDescription dsc;
dfi = ((dfContext*) context)->dfi;
df_pointer = (dfPointer*) pointer;
dsc.flags = DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT;
dsc.caps = DSCAPS_SYSTEMONLY;
dsc.width = pointer->width;
dsc.height = pointer->height;
dsc.pixelformat = DSPF_ARGB;
result = dfi->dfb->CreateSurface(dfi->dfb, &dsc, &(df_pointer->surface));
if (result == DFB_OK)
{
int pitch;
BYTE* point = NULL;
df_pointer->xhot = pointer->xPos;
df_pointer->yhot = pointer->yPos;
result = df_pointer->surface->Lock(df_pointer->surface,
DSLF_WRITE, (void**) &point, &pitch);
if (result != DFB_OK)
{
DirectFBErrorFatal("Error while creating pointer surface", result);
return;
}
if ((pointer->andMaskData != 0) && (pointer->xorMaskData != 0))
{
freerdp_alpha_cursor_convert(point, pointer->xorMaskData, pointer->andMaskData,
pointer->width, pointer->height, pointer->xorBpp, dfi->clrconv);
}
if (pointer->xorBpp > 24)
{
freerdp_image_swap_color_order(point, pointer->width, pointer->height);
}
df_pointer->surface->Unlock(df_pointer->surface);
}
}
void df_Pointer_Free(rdpContext* context, rdpPointer* pointer)
{
dfPointer* df_pointer = (dfPointer*) pointer;
df_pointer->surface->Release(df_pointer->surface);
}
void df_Pointer_Set(rdpContext* context, rdpPointer* pointer)
{
dfInfo* dfi;
DFBResult result;
dfPointer* df_pointer;
dfi = ((dfContext*) context)->dfi;
df_pointer = (dfPointer*) pointer;
dfi->layer->SetCooperativeLevel(dfi->layer, DLSCL_ADMINISTRATIVE);
dfi->layer->SetCursorOpacity(dfi->layer, df_pointer ? 255: 0);
if(df_pointer != NULL)
{
result = dfi->layer->SetCursorShape(dfi->layer,
df_pointer->surface, df_pointer->xhot, df_pointer->yhot);
if (result != DFB_OK)
{
DirectFBErrorFatal("SetCursorShape Error", result);
return;
}
}
dfi->layer->SetCooperativeLevel(dfi->layer, DLSCL_SHARED);
}
void df_Pointer_SetNull(rdpContext* context)
{
df_Pointer_Set(context, NULL);
}
void df_Pointer_SetDefault(rdpContext* context)
{
}
/* Graphics Module */
void df_register_graphics(rdpGraphics* graphics)
{
rdpPointer* pointer;
pointer = (rdpPointer*) malloc(sizeof(rdpPointer));
ZeroMemory(pointer, sizeof(rdpPointer));
pointer->size = sizeof(dfPointer);
pointer->New = df_Pointer_New;
pointer->Free = df_Pointer_Free;
pointer->Set = df_Pointer_Set;
pointer->SetNull = df_Pointer_SetNull;
pointer->SetDefault = df_Pointer_SetDefault;
graphics_register_pointer(graphics, pointer);
free(pointer);
}

View File

@ -1,469 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* DirectFB Client
*
* Copyright 2011 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.
*/
#include <errno.h>
#include <pthread.h>
#include <locale.h>
#include <freerdp/freerdp.h>
#include <freerdp/constants.h>
#include <freerdp/utils/event.h>
#include <freerdp/client/file.h>
#include <freerdp/client/cmdline.h>
#include <freerdp/client/channels.h>
#include <freerdp/client/cliprdr.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
#include "df_event.h"
#include "df_graphics.h"
#include "dfreerdp.h"
#include <freerdp/log.h>
#define TAG CLIENT_TAG("directFB")
static HANDLE g_sem;
static int g_thread_count = 0;
struct thread_data
{
freerdp* instance;
};
BOOL df_context_new(freerdp* instance, rdpContext* context)
{
return TRUE;
}
void df_context_free(freerdp* instance, rdpContext* context)
{
}
void df_begin_paint(rdpContext* context)
{
rdpGdi* gdi = context->gdi;
gdi->primary->hdc->hwnd->invalid->null = TRUE;
}
void df_end_paint(rdpContext* context)
{
rdpGdi* gdi;
dfInfo* dfi;
gdi = context->gdi;
dfi = ((dfContext*) context)->dfi;
if (gdi->primary->hdc->hwnd->invalid->null)
return;
#if 1
dfi->update_rect.x = gdi->primary->hdc->hwnd->invalid->x;
dfi->update_rect.y = gdi->primary->hdc->hwnd->invalid->y;
dfi->update_rect.w = gdi->primary->hdc->hwnd->invalid->w;
dfi->update_rect.h = gdi->primary->hdc->hwnd->invalid->h;
#else
dfi->update_rect.x = 0;
dfi->update_rect.y = 0;
dfi->update_rect.w = gdi->width;
dfi->update_rect.h = gdi->height;
#endif
dfi->primary->Blit(dfi->primary, dfi->surface, &(dfi->update_rect),
dfi->update_rect.x, dfi->update_rect.y);
}
BOOL df_get_fds(freerdp* instance, void** rfds, int* rcount, void** wfds,
int* wcount)
{
dfInfo* dfi;
dfi = ((dfContext*) instance->context)->dfi;
rfds[*rcount] = (void*)(long)(dfi->read_fds);
(*rcount)++;
return TRUE;
}
BOOL df_check_fds(freerdp* instance, fd_set* set)
{
dfInfo* dfi;
dfi = ((dfContext*) instance->context)->dfi;
if (!FD_ISSET(dfi->read_fds, set))
return TRUE;
if (read(dfi->read_fds, &(dfi->event), sizeof(dfi->event)) > 0)
df_event_process(instance, &(dfi->event));
return TRUE;
}
BOOL df_pre_connect(freerdp* instance)
{
dfInfo* dfi;
BOOL bitmap_cache;
dfContext* context;
rdpSettings* settings;
dfi = (dfInfo*) malloc(sizeof(dfInfo));
ZeroMemory(dfi, sizeof(dfInfo));
context = ((dfContext*) instance->context);
context->dfi = dfi;
settings = instance->settings;
bitmap_cache = settings->BitmapCacheEnabled;
settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
settings->OrderSupport[NEG_LINETO_INDEX] = TRUE;
settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
settings->OrderSupport[NEG_MEMBLT_INDEX] = bitmap_cache;
settings->OrderSupport[NEG_MEM3BLT_INDEX] = FALSE;
settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = bitmap_cache;
settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE;
settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = FALSE;
settings->OrderSupport[NEG_FAST_INDEX_INDEX] = FALSE;
settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = FALSE;
settings->OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE;
settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE;
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
dfi->clrconv = (CLRCONV*) malloc(sizeof(CLRCONV));
ZeroMemory(dfi->clrconv, sizeof(CLRCONV));
dfi->clrconv->alpha = 1;
dfi->clrconv->invert = 0;
dfi->clrconv->rgb555 = 0;
dfi->clrconv->palette = (rdpPalette*) malloc(sizeof(rdpPalette));
ZeroMemory(dfi->clrconv->palette, sizeof(rdpPalette));
return (instance->context->cache = cache_new(instance->settings)) != NULL;
}
BOOL df_post_connect(freerdp* instance)
{
rdpGdi* gdi;
dfInfo* dfi;
dfContext* context;
context = ((dfContext*) instance->context);
dfi = context->dfi;
if (!gdi_init(instance, CLRCONV_ALPHA | CLRCONV_INVERT | CLRBUF_16BPP |
CLRBUF_32BPP, NULL))
return FALSE;
gdi = instance->context->gdi;
dfi->err = DirectFBCreate(&(dfi->dfb));
dfi->dsc.flags = DSDESC_CAPS;
dfi->dsc.caps = DSCAPS_PRIMARY;
dfi->err = dfi->dfb->CreateSurface(dfi->dfb, &(dfi->dsc), &(dfi->primary));
dfi->err = dfi->primary->GetSize(dfi->primary, &(gdi->width), &(gdi->height));
dfi->dfb->SetVideoMode(dfi->dfb, gdi->width, gdi->height, gdi->dstBpp);
dfi->dfb->CreateInputEventBuffer(dfi->dfb, DICAPS_ALL, DFB_TRUE,
&(dfi->event_buffer));
dfi->event_buffer->CreateFileDescriptor(dfi->event_buffer, &(dfi->read_fds));
dfi->dfb->GetDisplayLayer(dfi->dfb, 0, &(dfi->layer));
dfi->layer->EnableCursor(dfi->layer, 1);
dfi->dsc.flags = DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT |
DSDESC_PREALLOCATED | DSDESC_PIXELFORMAT;
dfi->dsc.caps = DSCAPS_SYSTEMONLY;
dfi->dsc.width = gdi->width;
dfi->dsc.height = gdi->height;
if (gdi->dstBpp == 32 || gdi->dstBpp == 24)
dfi->dsc.pixelformat = DSPF_AiRGB;
else if (gdi->dstBpp == 16 || gdi->dstBpp == 15)
dfi->dsc.pixelformat = DSPF_RGB16;
else if (gdi->dstBpp == 8)
dfi->dsc.pixelformat = DSPF_RGB332;
else
dfi->dsc.pixelformat = DSPF_AiRGB;
dfi->dsc.preallocated[0].data = gdi->primary_buffer;
dfi->dsc.preallocated[0].pitch = gdi->width * gdi->bytesPerPixel;
dfi->dfb->CreateSurface(dfi->dfb, &(dfi->dsc), &(dfi->surface));
instance->update->BeginPaint = df_begin_paint;
instance->update->EndPaint = df_end_paint;
df_keyboard_init();
df_register_graphics(instance->context->graphics);
return TRUE;
}
BOOL df_verify_certificate(freerdp* instance, char* subject, char* issuer,
char* fingerprint)
{
char answer;
WLog_INFO(TAG, "Certificate details:");
WLog_INFO(TAG, "\tSubject: %s", subject);
WLog_INFO(TAG, "\tIssuer: %s", issuer);
WLog_INFO(TAG, "\tThumbprint: %s", fingerprint);
WLog_INFO(TAG,
"The above X.509 certificate could not be verified, possibly because you do not have "
"the CA certificate in your certificate store, or the certificate has expired. "
"Please look at the OpenSSL documentation on how to add a private CA to the store.");
while (1)
{
WLog_INFO(TAG, "Do you trust the above certificate? (Y/N) ");
answer = fgetc(stdin);
if (answer == 'y' || answer == 'Y')
{
return TRUE;
}
else if (answer == 'n' || answer == 'N')
{
break;
}
}
return FALSE;
}
static int df_receive_channel_data(freerdp* instance, UINT16 channelId,
BYTE* data, int size, int flags, int total_size)
{
return freerdp_channels_data(instance, channelId, data, size, flags,
total_size);
}
static void df_process_cb_monitor_ready_event(rdpChannels* channels,
freerdp* instance)
{
wMessage* event;
RDP_CB_FORMAT_LIST_EVENT* format_list_event;
event = freerdp_event_new(CliprdrChannel_Class, CliprdrChannel_FormatList, NULL,
NULL);
format_list_event = (RDP_CB_FORMAT_LIST_EVENT*) event;
format_list_event->num_formats = 0;
freerdp_channels_send_event(channels, event);
}
static void df_process_channel_event(rdpChannels* channels, freerdp* instance)
{
wMessage* event;
event = freerdp_channels_pop_event(channels);
if (event)
{
switch (GetMessageType(event->id))
{
case CliprdrChannel_MonitorReady:
df_process_cb_monitor_ready_event(channels, instance);
break;
default:
WLog_ERR(TAG, "df_process_channel_event: unknown event type %"PRIu32"",
GetMessageType(event->id));
break;
}
freerdp_event_free(event);
}
}
static void df_free(dfInfo* dfi)
{
dfi->dfb->Release(dfi->dfb);
free(dfi);
}
int dfreerdp_run(freerdp* instance)
{
int i;
int fds;
int max_fds;
int rcount;
int wcount;
void* rfds[32];
void* wfds[32];
fd_set rfds_set;
fd_set wfds_set;
dfInfo* dfi;
dfContext* context;
rdpChannels* channels;
ZeroMemory(rfds, sizeof(rfds));
ZeroMemory(wfds, sizeof(wfds));
if (!freerdp_connect(instance))
return 0;
context = (dfContext*) instance->context;
dfi = context->dfi;
channels = instance->context->channels;
while (1)
{
rcount = 0;
wcount = 0;
if (freerdp_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
{
WLog_ERR(TAG, "Failed to get FreeRDP file descriptor");
break;
}
if (freerdp_channels_get_fds(channels, instance, rfds, &rcount, wfds,
&wcount) != TRUE)
{
WLog_ERR(TAG, "Failed to get channel manager file descriptor");
break;
}
if (df_get_fds(instance, rfds, &rcount, wfds, &wcount) != TRUE)
{
WLog_ERR(TAG, "Failed to get dfreerdp file descriptor");
break;
}
max_fds = 0;
FD_ZERO(&rfds_set);
FD_ZERO(&wfds_set);
for (i = 0; i < rcount; i++)
{
fds = (int)(long)(rfds[i]);
if (fds > max_fds)
max_fds = fds;
FD_SET(fds, &rfds_set);
}
if (max_fds == 0)
break;
if (select(max_fds + 1, &rfds_set, &wfds_set, NULL, NULL) == -1)
{
/* these are not really errors */
if (!((errno == EAGAIN) ||
(errno == EWOULDBLOCK) ||
(errno == EINPROGRESS) ||
(errno == EINTR))) /* signal occurred */
{
WLog_ERR(TAG, "dfreerdp_run: select failed");
break;
}
}
if (freerdp_check_fds(instance) != TRUE)
{
WLog_ERR(TAG, "Failed to check FreeRDP file descriptor");
break;
}
if (df_check_fds(instance, &rfds_set) != TRUE)
{
WLog_ERR(TAG, "Failed to check dfreerdp file descriptor");
break;
}
if (freerdp_channels_check_fds(channels, instance) != TRUE)
{
WLog_ERR(TAG, "Failed to check channel manager file descriptor");
break;
}
df_process_channel_event(channels, instance);
}
freerdp_disconnect(instance);
df_free(dfi);
gdi_free(instance);
freerdp_free(instance);
return 0;
}
void* thread_func(void* param)
{
struct thread_data* data;
data = (struct thread_data*) param;
dfreerdp_run(data->instance);
free(data);
pthread_detach(pthread_self());
g_thread_count--;
if (g_thread_count < 1)
ReleaseSemaphore(g_sem, 1, NULL);
return NULL;
}
int main(int argc, char* argv[])
{
int status;
pthread_t thread;
freerdp* instance;
dfContext* context;
rdpChannels* channels;
struct thread_data* data;
setlocale(LC_ALL, "");
if (!(g_sem = CreateSemaphore(NULL, 0, 1, NULL)))
{
WLog_ERR(TAG, "Failed to create semaphore");
return 1;
}
instance = freerdp_new();
instance->PreConnect = df_pre_connect;
instance->PostConnect = df_post_connect;
instance->VerifyCertificate = df_verify_certificate;
instance->ReceiveChannelData = df_receive_channel_data;
instance->ContextSize = sizeof(dfContext);
instance->ContextNew = df_context_new;
instance->ContextFree = df_context_free;
if (!freerdp_context_new(instance))
{
WLog_ERR(TAG, "Failed to create FreeRDP context");
return 1;
}
context = (dfContext*) instance->context;
channels = instance->context->channels;
DirectFBInit(&argc, &argv);
instance->context->argc = argc;
instance->context->argv = argv;
status = freerdp_client_settings_parse_command_line(instance->settings, argc,
argv, FALSE);
if (status < 0)
return 0;
if (!freerdp_client_load_addins(instance->context->channels,
instance->settings))
return -1;
data = (struct thread_data*) malloc(sizeof(struct thread_data));
ZeroMemory(data, sizeof(sizeof(struct thread_data)));
data->instance = instance;
g_thread_count++;
pthread_create(&thread, 0, thread_func, data);
while (g_thread_count > 0)
{
WaitForSingleObject(g_sem, INFINITE);
}
return 0;
}

View File

@ -1,70 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* DirectFB Client
*
* Copyright 2011 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_CLIENT_DF_FREERDP_H
#define FREERDP_CLIENT_DF_FREERDP_H
#include "config.h"
#include <freerdp/freerdp.h>
#include <freerdp/graphics.h>
#include <freerdp/gdi/gdi.h>
#include <freerdp/codec/color.h>
#include <freerdp/channels/channels.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <directfb.h>
typedef struct df_info dfInfo;
struct df_context
{
rdpContext _p;
dfInfo* dfi;
rdpSettings* settings;
};
typedef struct df_context dfContext;
struct df_pointer
{
rdpPointer pointer;
IDirectFBSurface* surface;
UINT32 xhot;
UINT32 yhot;
};
typedef struct df_pointer dfPointer;
struct df_info
{
int read_fds;
DFBResult err;
IDirectFB* dfb;
DFBEvent event;
HCLRCONV clrconv;
DFBRectangle update_rect;
DFBSurfaceDescription dsc;
IDirectFBSurface* primary;
IDirectFBSurface* surface;
IDirectFBDisplayLayer* layer;
IDirectFBEventBuffer* event_buffer;
};
#endif /* FREERDP_CLIENT_DF_FREERDP_H */

View File

@ -19,7 +19,10 @@ set(MODULE_NAME "sfreerdp")
set(MODULE_PREFIX "FREERDP_CLIENT_SAMPLE")
set(${MODULE_PREFIX}_SRCS
freerdp.c)
tf_channels.c
tf_channels.h
tf_freerdp.h
tf_freerdp.c)
# On windows create dll version information.
# Vendor, product and year are already set in top level CMakeLists.txt

View File

@ -1,212 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Test UI
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2016 Armin Novak <armin.novak@thincast.com>
* Copyright 2016 Thincast Technologies GmbH
*
* 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 <errno.h>
#include <stdio.h>
#include <string.h>
#include <freerdp/freerdp.h>
#include <freerdp/constants.h>
#include <freerdp/gdi/gdi.h>
#include <freerdp/client/file.h>
#include <freerdp/client/cmdline.h>
#include <freerdp/client/cliprdr.h>
#include <freerdp/client/channels.h>
#include <freerdp/channels/channels.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <freerdp/log.h>
#define TAG CLIENT_TAG("sample")
struct tf_context
{
rdpContext _p;
};
typedef struct tf_context tfContext;
static BOOL tf_context_new(freerdp* instance, rdpContext* context)
{
return TRUE;
}
static void tf_context_free(freerdp* instance, rdpContext* context)
{
}
static BOOL tf_begin_paint(rdpContext* context)
{
rdpGdi* gdi = context->gdi;
gdi->primary->hdc->hwnd->invalid->null = TRUE;
return TRUE;
}
static BOOL tf_end_paint(rdpContext* context)
{
rdpGdi* gdi = context->gdi;
if (gdi->primary->hdc->hwnd->invalid->null)
return TRUE;
return TRUE;
}
static BOOL tf_pre_connect(freerdp* instance)
{
rdpSettings* settings;
settings = instance->settings;
settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = TRUE;
settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = TRUE;
settings->OrderSupport[NEG_LINETO_INDEX] = TRUE;
settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
settings->OrderSupport[NEG_MEMBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_MEM3BLT_INDEX] = TRUE;
settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = TRUE;
settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE;
settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE;
settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE;
settings->OrderSupport[NEG_POLYGON_SC_INDEX] = TRUE;
settings->OrderSupport[NEG_POLYGON_CB_INDEX] = TRUE;
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = TRUE;
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = TRUE;
return TRUE;
}
static BOOL tf_post_connect(freerdp* instance)
{
if (!gdi_init(instance, PIXEL_FORMAT_XRGB32))
return FALSE;
instance->update->BeginPaint = tf_begin_paint;
instance->update->EndPaint = tf_end_paint;
return TRUE;
}
static DWORD WINAPI tf_client_thread_proc(LPVOID arg)
{
freerdp* instance = (freerdp*)arg;
DWORD nCount;
DWORD status;
HANDLE handles[64];
if (!freerdp_connect(instance))
{
WLog_ERR(TAG, "connection failure");
return 0;
}
while (!freerdp_shall_disconnect(instance))
{
nCount = freerdp_get_event_handles(instance->context, &handles[0], 64);
if (nCount == 0)
{
WLog_ERR(TAG, "%s: freerdp_get_event_handles failed", __FUNCTION__);
break;
}
status = WaitForMultipleObjects(nCount, handles, FALSE, 100);
if (status == WAIT_FAILED)
{
WLog_ERR(TAG, "%s: WaitForMultipleObjects failed with %"PRIu32"", __FUNCTION__,
status);
break;
}
if (!freerdp_check_event_handles(instance->context))
{
if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_SUCCESS)
WLog_ERR(TAG, "Failed to check FreeRDP event handles");
break;
}
}
freerdp_disconnect(instance);
ExitThread(0);
return 0;
}
int main(int argc, char* argv[])
{
int status;
HANDLE thread;
freerdp* instance;
instance = freerdp_new();
if (!instance)
{
WLog_ERR(TAG, "Couldn't create instance");
return 1;
}
instance->PreConnect = tf_pre_connect;
instance->PostConnect = tf_post_connect;
instance->ContextSize = sizeof(tfContext);
instance->ContextNew = tf_context_new;
instance->ContextFree = tf_context_free;
freerdp_register_addin_provider(freerdp_channels_load_static_addin_entry, 0);
if (!freerdp_context_new(instance))
{
WLog_ERR(TAG, "Couldn't create context");
return 1;
}
status = freerdp_client_settings_parse_command_line(instance->settings, argc,
argv, FALSE);
if (status < 0)
{
return 0;
}
if (!freerdp_client_load_addins(instance->context->channels,
instance->settings))
return -1;
if (!(thread = CreateThread(NULL, 0, tf_client_thread_proc, instance, 0, NULL)))
{
WLog_ERR(TAG, "Failed to create client thread");
}
else
{
WaitForSingleObject(thread, INFINITE);
}
freerdp_context_free(instance);
freerdp_free(instance);
return 0;
}

127
client/Sample/tf_channels.c Normal file
View File

@ -0,0 +1,127 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Sample Client Channels
*
* Copyright 2018 Armin Novak <armin.novak@thincast.com>
* Copyright 2018 Thincast Technologies GmbH
*
* 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 <freerdp/gdi/gfx.h>
#include <freerdp/client/rdpei.h>
#include <freerdp/client/tsmf.h>
#include <freerdp/client/rail.h>
#include <freerdp/client/cliprdr.h>
#include <freerdp/client/rdpgfx.h>
#include <freerdp/client/encomsp.h>
#include "tf_channels.h"
#include "tf_freerdp.h"
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT tf_encomsp_participant_created(EncomspClientContext* context,
ENCOMSP_PARTICIPANT_CREATED_PDU* participantCreated)
{
return CHANNEL_RC_OK;
}
static void tf_encomsp_init(tfContext* tf, EncomspClientContext* encomsp)
{
tf->encomsp = encomsp;
encomsp->custom = (void*) tf;
encomsp->ParticipantCreated = tf_encomsp_participant_created;
}
static void tf_encomsp_uninit(tfContext* tf, EncomspClientContext* encomsp)
{
if (encomsp)
{
encomsp->custom = NULL;
encomsp->ParticipantCreated = NULL;
}
if (tf)
tf->encomsp = NULL;
}
void tf_OnChannelConnectedEventHandler(void* context,
ChannelConnectedEventArgs* e)
{
tfContext* tf = (tfContext*) context;
rdpSettings* settings;
settings = tf->context.settings;
if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
{
tf->rdpei = (RdpeiClientContext*) e->pInterface;
}
else if (strcmp(e->name, TSMF_DVC_CHANNEL_NAME) == 0)
{
}
else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
gdi_graphics_pipeline_init(tf->context.gdi, (RdpgfxClientContext*) e->pInterface);
}
else if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) == 0)
{
}
else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
{
}
else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
{
tf_encomsp_init(tf, (EncomspClientContext*) e->pInterface);
}
}
void tf_OnChannelDisconnectedEventHandler(void* context,
ChannelDisconnectedEventArgs* e)
{
tfContext* tf = (tfContext*) context;
rdpSettings* settings;
settings = tf->context.settings;
if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
{
tf->rdpei = NULL;
}
else if (strcmp(e->name, TSMF_DVC_CHANNEL_NAME) == 0)
{
}
else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
gdi_graphics_pipeline_uninit(tf->context.gdi,
(RdpgfxClientContext*) e->pInterface);
}
else if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) == 0)
{
}
else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
{
}
else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
{
tf_encomsp_uninit(tf, (EncomspClientContext*) e->pInterface);
}
}

View File

@ -0,0 +1,37 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Sample Client Channels
*
* Copyright 2018 Armin Novak <armin.novak@thincast.com>
* Copyright 2018 Thincast Technologies GmbH
*
* 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_CLIENT_SAMPLE_CHANNELS_H
#define FREERDP_CLIENT_SAMPLE_CHANNELS_H
#include <freerdp/freerdp.h>
#include <freerdp/client/channels.h>
int tf_on_channel_connected(freerdp* instance, const char* name,
void* pInterface);
int tf_on_channel_disconnected(freerdp* instance, const char* name,
void* pInterface);
void tf_OnChannelConnectedEventHandler(void* context,
ChannelConnectedEventArgs* e);
void tf_OnChannelDisconnectedEventHandler(void* context,
ChannelDisconnectedEventArgs* e);
#endif /* FREERDP_CLIENT_SAMPLE_CHANNELS_H */

339
client/Sample/tf_freerdp.c Normal file
View File

@ -0,0 +1,339 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* FreeRDP Test UI
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2016,2018 Armin Novak <armin.novak@thincast.com>
* Copyright 2016,2018 Thincast Technologies GmbH
*
* 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 <errno.h>
#include <stdio.h>
#include <string.h>
#include <freerdp/freerdp.h>
#include <freerdp/constants.h>
#include <freerdp/gdi/gdi.h>
#include <freerdp/utils/signal.h>
#include <freerdp/client/file.h>
#include <freerdp/client/cmdline.h>
#include <freerdp/client/cliprdr.h>
#include <freerdp/client/channels.h>
#include <freerdp/channels/channels.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <freerdp/log.h>
#include "tf_channels.h"
#include "tf_freerdp.h"
#define TAG CLIENT_TAG("sample")
/* This function is called whenever a new frame starts.
* It can be used to reset invalidated areas. */
static BOOL tf_begin_paint(rdpContext* context)
{
rdpGdi* gdi = context->gdi;
gdi->primary->hdc->hwnd->invalid->null = TRUE;
return TRUE;
}
/* This function is called when the library completed composing a new
* frame. Read out the changed areas and blit them to your output device.
* The image buffer will have the format specified by gdi_init
*/
static BOOL tf_end_paint(rdpContext* context)
{
rdpGdi* gdi = context->gdi;
if (gdi->primary->hdc->hwnd->invalid->null)
return TRUE;
return TRUE;
}
/* This function is called to output a System BEEP */
static BOOL tf_play_sound(rdpContext* context,
const PLAY_SOUND_UPDATE* play_sound)
{
/* TODO: Implement */
return TRUE;
}
/* This function is called to update the keyboard indocator LED */
static BOOL tf_keyboard_set_indicators(rdpContext* context, UINT16 led_flags)
{
/* TODO: Set local keyboard indicator LED status */
return TRUE;
}
/* This function is called to set the IME state */
static BOOL tf_keyboard_set_ime_status(rdpContext* context, UINT16 imeId, UINT32 imeState,
UINT32 imeConvMode)
{
if (!context)
return FALSE;
WLog_WARN(TAG,
"KeyboardSetImeStatus(unitId=%04"PRIx16", imeState=%08"PRIx32", imeConvMode=%08"PRIx32") ignored",
imeId, imeState, imeConvMode);
return TRUE;
}
/* Called before a connection is established.
* Set all configuration options to support and load channels here. */
static BOOL tf_pre_connect(freerdp* instance)
{
rdpSettings* settings;
settings = instance->settings;
/* Optional OS identifier sent to server */
settings->OsMajorType = OSMAJORTYPE_UNIX;
settings->OsMinorType = OSMINORTYPE_NATIVE_XSERVER;
/* settings->OrderSupport is initialized at this point.
* Only override it if you plan to implement custom order
* callbacks or deactiveate certain features. */
/* Register the channel listeners.
* They are required to set up / tear down channels if they are loaded. */
PubSub_SubscribeChannelConnected(instance->context->pubSub,
tf_OnChannelConnectedEventHandler);
PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
tf_OnChannelDisconnectedEventHandler);
/* Load all required plugins / channels / libraries specified by current
* settings. */
if (!freerdp_client_load_addins(instance->context->channels,
instance->settings))
return FALSE;
/* TODO: Any code your client requires */
return TRUE;
}
/* Called after a RDP connection was successfully established.
* Settings might have changed during negociation of client / server feature
* support.
*
* Set up local framebuffers and paing callbacks.
* If required, register pointer callbacks to change the local mouse cursor
* when hovering over the RDP window
*/
static BOOL tf_post_connect(freerdp* instance)
{
if (!gdi_init(instance, PIXEL_FORMAT_XRGB32))
return FALSE;
instance->update->BeginPaint = tf_begin_paint;
instance->update->EndPaint = tf_end_paint;
instance->update->PlaySound = tf_play_sound;
instance->update->SetKeyboardIndicators = tf_keyboard_set_indicators;
instance->update->SetKeyboardImeStatus = tf_keyboard_set_ime_status;
return TRUE;
}
/* This function is called whether a session ends by failure or success.
* Clean up everything allocated by pre_connect and post_connect.
*/
static void tf_post_disconnect(freerdp* instance)
{
tfContext* context;
if (!instance)
return;
if (!instance->context)
return;
context = (tfContext*) instance->context;
PubSub_UnsubscribeChannelConnected(instance->context->pubSub,
tf_OnChannelConnectedEventHandler);
PubSub_UnsubscribeChannelDisconnected(instance->context->pubSub,
tf_OnChannelDisconnectedEventHandler);
gdi_free(instance);
/* TODO : Clean up custom stuff */
}
/* RDP main loop.
* Connects RDP, loops while running and handles event and dispatch, cleans up
* after the connection ends. */
static DWORD WINAPI tf_client_thread_proc(LPVOID arg)
{
freerdp* instance = (freerdp*)arg;
DWORD nCount;
DWORD status;
HANDLE handles[64];
if (!freerdp_connect(instance))
{
WLog_ERR(TAG, "connection failure");
return 0;
}
while (!freerdp_shall_disconnect(instance))
{
nCount = freerdp_get_event_handles(instance->context, &handles[0], 64);
if (nCount == 0)
{
WLog_ERR(TAG, "%s: freerdp_get_event_handles failed", __FUNCTION__);
break;
}
status = WaitForMultipleObjects(nCount, handles, FALSE, 100);
if (status == WAIT_FAILED)
{
WLog_ERR(TAG, "%s: WaitForMultipleObjects failed with %"PRIu32"", __FUNCTION__,
status);
break;
}
if (!freerdp_check_event_handles(instance->context))
{
if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_SUCCESS)
WLog_ERR(TAG, "Failed to check FreeRDP event handles");
break;
}
}
freerdp_disconnect(instance);
return 0;
}
/* Optional global initializer.
* Here we just register a signal handler to print out stack traces
* if available. */
static BOOL tf_client_global_init(void)
{
if (freerdp_handle_signals() != 0)
return FALSE;
return TRUE;
}
/* Optional global tear down */
static void tf_client_global_uninit(void)
{
}
static int tf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
{
tfContext* tf;
const char* str_data = freerdp_get_logon_error_info_data(data);
const char* str_type = freerdp_get_logon_error_info_type(type);
if (!instance || !instance->context)
return -1;
tf = (tfContext*) instance->context;
WLog_INFO(TAG, "Logon Error Info %s [%s]", str_data, str_type);
return 1;
}
static BOOL tf_client_new(freerdp* instance, rdpContext* context)
{
tfContext* tf = (tfContext*) context;
if (!instance || !context)
return FALSE;
instance->PreConnect = tf_pre_connect;
instance->PostConnect = tf_post_connect;
instance->PostDisconnect = tf_post_disconnect;
instance->Authenticate = client_cli_authenticate;
instance->GatewayAuthenticate = client_cli_gw_authenticate;
instance->VerifyCertificateEx = client_cli_verify_certificate_ex;
instance->VerifyChangedCertificateEx = client_cli_verify_changed_certificate_ex;
instance->LogonErrorInfo = tf_logon_error_info;
/* TODO: Client display set up */
return TRUE;
}
static void tf_client_free(freerdp* instance, rdpContext* context)
{
tfContext* tf = (tfContext*) instance->context;
if (!context)
return;
/* TODO: Client display tear down */
}
static int tf_client_start(rdpContext* context)
{
/* TODO: Start client related stuff */
return 0;
}
static int tf_client_stop(rdpContext* context)
{
/* TODO: Stop client related stuff */
return 0;
}
static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
{
ZeroMemory(pEntryPoints, sizeof(RDP_CLIENT_ENTRY_POINTS));
pEntryPoints->Version = RDP_CLIENT_INTERFACE_VERSION;
pEntryPoints->Size = sizeof(RDP_CLIENT_ENTRY_POINTS_V1);
pEntryPoints->GlobalInit = tf_client_global_init;
pEntryPoints->GlobalUninit = tf_client_global_uninit;
pEntryPoints->ContextSize = sizeof(tfContext);
pEntryPoints->ClientNew = tf_client_new;
pEntryPoints->ClientFree = tf_client_free;
pEntryPoints->ClientStart = tf_client_start;
pEntryPoints->ClientStop = tf_client_stop;
return 0;
}
int main(int argc, char* argv[])
{
int rc = -1;
DWORD status;
RDP_CLIENT_ENTRY_POINTS clientEntryPoints;
rdpContext* context;
RdpClientEntry(&clientEntryPoints);
context = freerdp_client_context_new(&clientEntryPoints);
if (!context)
goto fail;
status = freerdp_client_settings_parse_command_line(context->settings, argc,
argv, FALSE);
status = freerdp_client_settings_command_line_status_print(context->settings,
status, argc, argv);
if (status)
return 0;
if (freerdp_client_start(context) != 0)
goto fail;
rc = tf_client_thread_proc(context->instance);
if (freerdp_client_stop(context) != 0)
rc = -1;
fail:
freerdp_client_context_free(context);
return rc;
}

View File

@ -0,0 +1,43 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Sample Client
*
* Copyright 2018 Armin Novak <armin.novak@thincast.com>
* Copyright 2018 Thincast Technologies GmbH
*
* 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_CLIENT_SAMPLE_H
#define FREERDP_CLIENT_SAMPLE_H
#include <freerdp/freerdp.h>
#include <freerdp/client/rdpei.h>
#include <freerdp/client/tsmf.h>
#include <freerdp/client/rail.h>
#include <freerdp/client/cliprdr.h>
#include <freerdp/client/rdpgfx.h>
#include <freerdp/client/encomsp.h>
struct tf_context
{
rdpContext context;
/* Channels */
RdpeiClientContext* rdpei;
RdpgfxClientContext* gfx;
EncomspClientContext* encomsp;
};
typedef struct tf_context tfContext;
#endif /* FREERDP_CLIENT_SAMPLE_H */

View File

@ -25,8 +25,14 @@ include_directories(${CMAKE_SOURCE_DIR}/uwac/include)
set(${MODULE_PREFIX}_SRCS
wlfreerdp.c
wlfreerdp.h
wlf_disp.c
wlf_disp.h
wlf_pointer.c
wlf_pointer.h
wlf_input.c
wlf_input.h
wlf_cliprdr.c
wlf_cliprdr.h
wlf_channels.c
wlf_channels.h
)

View File

@ -24,6 +24,8 @@
#include <freerdp/gdi/gfx.h>
#include "wlf_channels.h"
#include "wlf_cliprdr.h"
#include "wlf_disp.h"
#include "wlfreerdp.h"
/**
@ -62,7 +64,6 @@ void wlf_OnChannelConnectedEventHandler(void* context,
{
wlfContext* wlf = (wlfContext*) context;
rdpSettings* settings;
settings = wlf->context.settings;
if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
@ -74,19 +75,23 @@ void wlf_OnChannelConnectedEventHandler(void* context,
}
else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
if (settings->SoftwareGdi)
gdi_graphics_pipeline_init(wlf->context.gdi, (RdpgfxClientContext*) e->pInterface);
gdi_graphics_pipeline_init(wlf->context.gdi, (RdpgfxClientContext*) e->pInterface);
}
else if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) == 0)
{
}
else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
{
wlf_cliprdr_init(wlf->clipboard, (CliprdrClientContext*)e->pInterface);
}
else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
{
wlf_encomsp_init(wlf, (EncomspClientContext*) e->pInterface);
}
else if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0)
{
wlf_disp_init(wlf->disp, (DispClientContext*)e->pInterface);
}
}
void wlf_OnChannelDisconnectedEventHandler(void* context,
@ -94,7 +99,6 @@ void wlf_OnChannelDisconnectedEventHandler(void* context,
{
wlfContext* wlf = (wlfContext*) context;
rdpSettings* settings;
settings = wlf->context.settings;
if (strcmp(e->name, RDPEI_DVC_CHANNEL_NAME) == 0)
@ -106,18 +110,22 @@ void wlf_OnChannelDisconnectedEventHandler(void* context,
}
else if (strcmp(e->name, RDPGFX_DVC_CHANNEL_NAME) == 0)
{
if (settings->SoftwareGdi)
gdi_graphics_pipeline_uninit(wlf->context.gdi,
(RdpgfxClientContext*) e->pInterface);
gdi_graphics_pipeline_uninit(wlf->context.gdi,
(RdpgfxClientContext*) e->pInterface);
}
else if (strcmp(e->name, RAIL_SVC_CHANNEL_NAME) == 0)
{
}
else if (strcmp(e->name, CLIPRDR_SVC_CHANNEL_NAME) == 0)
{
wlf_cliprdr_uninit(wlf->clipboard, (CliprdrClientContext*)e->pInterface);
}
else if (strcmp(e->name, ENCOMSP_SVC_CHANNEL_NAME) == 0)
{
wlf_encomsp_uninit(wlf, (EncomspClientContext*) e->pInterface);
}
else if (strcmp(e->name, DISP_DVC_CHANNEL_NAME) == 0)
{
wlf_disp_uninit(wlf->disp, (DispClientContext*)e->pInterface);
}
}

View File

@ -0,0 +1,895 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Wayland Clipboard Redirection
*
* Copyright 2018 Armin Novak <armin.novak@thincast.com>
* Copyright 2018 Thincast Technologies GmbH
*
* 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 <stdlib.h>
#include <winpr/crt.h>
#include <winpr/image.h>
#include <winpr/stream.h>
#include <winpr/clipboard.h>
#include <freerdp/log.h>
#include <freerdp/client/cliprdr.h>
#include <freerdp/channels/channels.h>
#include <freerdp/channels/cliprdr.h>
#include "wlf_cliprdr.h"
#define MAX_CLIPBOARD_FORMATS 255
static const char* mime_text[] =
{
"text/plain",
"text/plain;charset=utf-8",
"UTF8_STRING",
"COMPOUND_TEXT",
"TEXT",
"STRING"
};
static const char* mime_image[] =
{
"image/png",
"image/bmp",
"image/x-bmp",
"image/x-MS-bmp",
"image/x-icon",
"image/x-ico",
"image/x-win-bitmap",
"image/vmd.microsoft.icon",
"application/ico",
"image/ico",
"image/icon",
"image/jpeg",
"image/tiff"
};
static const char* mime_html[] =
{
"text/html"
};
struct wlf_clipboard
{
wlfContext* wfc;
rdpChannels* channels;
CliprdrClientContext* context;
wLog* log;
UwacSeat* seat;
wClipboard* system;
wClipboardDelegate* delegate;
size_t numClientFormats;
CLIPRDR_FORMAT* clientFormats;
size_t numServerFormats;
CLIPRDR_FORMAT* serverFormats;
BOOL sync;
/* File clipping */
BOOL streams_supported;
BOOL file_formats_registered;
/* Server response stuff */
FILE* responseFile;
UINT32 responseFormat;
const char* responseMime;
};
static BOOL wlf_mime_is_text(const char* mime)
{
size_t x;
for (x = 0; x < ARRAYSIZE(mime_text); x++)
{
if (strcmp(mime, mime_text[x]) == 0)
return TRUE;
}
return FALSE;
}
static BOOL wlf_mime_is_image(const char* mime)
{
size_t x;
for (x = 0; x < ARRAYSIZE(mime_image); x++)
{
if (strcmp(mime, mime_image[x]) == 0)
return TRUE;
}
return FALSE;
}
static BOOL wlf_mime_is_html(const char* mime)
{
size_t x;
for (x = 0; x < ARRAYSIZE(mime_html); x++)
{
if (strcmp(mime, mime_html[x]) == 0)
return TRUE;
}
return FALSE;
}
static void wlf_cliprdr_free_server_formats(wfClipboard* clipboard)
{
if (clipboard && clipboard->serverFormats)
{
size_t j;
for (j = 0; j < clipboard->numServerFormats; j++)
{
CLIPRDR_FORMAT* format = &clipboard->serverFormats[j];
free(format->formatName);
}
free(clipboard->serverFormats);
clipboard->serverFormats = NULL;
clipboard->numServerFormats = 0;
}
if (clipboard)
UwacClipboardOfferDestroy(clipboard->seat);
}
static void wlf_cliprdr_free_client_formats(wfClipboard* clipboard)
{
if (clipboard && clipboard->numClientFormats)
{
size_t j;
for (j = 0; j < clipboard->numClientFormats; j++)
{
CLIPRDR_FORMAT* format = &clipboard->clientFormats[j];
free(format->formatName);
}
free(clipboard->clientFormats);
clipboard->clientFormats = NULL;
clipboard->numClientFormats = 0;
}
if (clipboard)
UwacClipboardOfferDestroy(clipboard->seat);
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT wlf_cliprdr_send_client_format_list(wfClipboard* clipboard)
{
CLIPRDR_FORMAT_LIST formatList = { 0 };
formatList.msgFlags = CB_RESPONSE_OK;
formatList.numFormats = (UINT32)clipboard->numClientFormats;
formatList.formats = clipboard->clientFormats;
return clipboard->context->ClientFormatList(clipboard->context, &formatList);
}
static void wfl_cliprdr_add_client_format_id(wfClipboard* clipboard, UINT32 formatId)
{
size_t x;
CLIPRDR_FORMAT* format;
const char* name = ClipboardGetFormatName(clipboard->system, formatId);
for (x = 0; x < clipboard->numClientFormats; x++)
{
format = &clipboard->clientFormats[x];
if (format->formatId == formatId)
return;
}
format = realloc(clipboard->clientFormats,
(clipboard->numClientFormats + 1) * sizeof(CLIPRDR_FORMAT));
if (!format)
return;
clipboard->clientFormats = format;
format = &clipboard->clientFormats[clipboard->numClientFormats++];
format->formatId = formatId;
format->formatName = NULL;
if (name && (formatId >= CF_MAX))
format->formatName = _strdup(name);
}
static void wlf_cliprdr_add_client_format(wfClipboard* clipboard, const char* mime)
{
if (wlf_mime_is_html(mime))
{
UINT32 formatId = ClipboardGetFormatId(clipboard->system, "HTML Format");
wfl_cliprdr_add_client_format_id(clipboard, formatId);
}
else if (wlf_mime_is_text(mime))
{
wfl_cliprdr_add_client_format_id(clipboard, CF_TEXT);
wfl_cliprdr_add_client_format_id(clipboard, CF_OEMTEXT);
wfl_cliprdr_add_client_format_id(clipboard, CF_UNICODETEXT);
}
else if (wlf_mime_is_image(mime))
{
UINT32 formatId = ClipboardGetFormatId(clipboard->system, "image/bmp");
wfl_cliprdr_add_client_format_id(clipboard, formatId);
wfl_cliprdr_add_client_format_id(clipboard, CF_DIB);
}
wlf_cliprdr_send_client_format_list(clipboard);
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT wlf_cliprdr_send_data_request(wfClipboard* clipboard,
UINT32 formatId)
{
CLIPRDR_FORMAT_DATA_REQUEST request = { 0 };
request.requestedFormatId = formatId;
return clipboard->context->ClientFormatDataRequest(clipboard->context,
&request);
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT wlf_cliprdr_send_data_response(wfClipboard* clipboard, const BYTE* data,
size_t size)
{
CLIPRDR_FORMAT_DATA_RESPONSE response = { 0 };
if (size > UINT32_MAX)
return ERROR_INVALID_PARAMETER;
response.msgFlags = (data) ? CB_RESPONSE_OK : CB_RESPONSE_FAIL;
response.dataLen = (UINT32)size;
response.requestedFormatData = data;
return clipboard->context->ClientFormatDataResponse(clipboard->context,
&response);
}
BOOL wlf_cliprdr_handle_event(wfClipboard* clipboard, const UwacClipboardEvent* event)
{
if (!clipboard || !event)
return FALSE;
if (!clipboard->context)
return TRUE;
switch (event->type)
{
case UWAC_EVENT_CLIPBOARD_AVAILABLE:
clipboard->seat = event->seat;
return TRUE;
case UWAC_EVENT_CLIPBOARD_OFFER:
WLog_Print(clipboard->log, WLOG_INFO, "client announces mime %s", event->mime);
wlf_cliprdr_add_client_format(clipboard, event->mime);
return TRUE;
case UWAC_EVENT_CLIPBOARD_SELECT:
WLog_Print(clipboard->log, WLOG_DEBUG, "client announces new data");
wlf_cliprdr_free_client_formats(clipboard);
return TRUE;
default:
return FALSE;
}
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT wlf_cliprdr_send_client_capabilities(wfClipboard* clipboard)
{
CLIPRDR_CAPABILITIES capabilities;
CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet;
capabilities.cCapabilitiesSets = 1;
capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &
(generalCapabilitySet);
generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
generalCapabilitySet.capabilitySetLength = 12;
generalCapabilitySet.version = CB_CAPS_VERSION_2;
generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES;
if (clipboard->streams_supported && clipboard->file_formats_registered)
generalCapabilitySet.generalFlags |=
CB_STREAM_FILECLIP_ENABLED | CB_FILECLIP_NO_FILE_PATHS;
return clipboard->context->ClientCapabilities(clipboard->context,
&capabilities);
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT wlf_cliprdr_send_client_format_list_response(wfClipboard* clipboard,
BOOL status)
{
CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse;
formatListResponse.msgType = CB_FORMAT_LIST_RESPONSE;
formatListResponse.msgFlags = status ? CB_RESPONSE_OK : CB_RESPONSE_FAIL;
formatListResponse.dataLen = 0;
return clipboard->context->ClientFormatListResponse(clipboard->context,
&formatListResponse);
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT wlf_cliprdr_monitor_ready(CliprdrClientContext* context,
const CLIPRDR_MONITOR_READY* monitorReady)
{
wfClipboard* clipboard = (wfClipboard*) context->custom;
UINT ret;
WINPR_UNUSED(monitorReady);
if ((ret = wlf_cliprdr_send_client_capabilities(clipboard)) != CHANNEL_RC_OK)
return ret;
if ((ret = wlf_cliprdr_send_client_format_list(clipboard)) != CHANNEL_RC_OK)
return ret;
clipboard->sync = TRUE;
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT wlf_cliprdr_server_capabilities(CliprdrClientContext* context,
const CLIPRDR_CAPABILITIES* capabilities)
{
UINT32 i;
const BYTE* capsPtr = (const BYTE*) capabilities->capabilitySets;
wfClipboard* clipboard = (wfClipboard*) context->custom;
clipboard->streams_supported = FALSE;
for (i = 0; i < capabilities->cCapabilitiesSets; i++)
{
const CLIPRDR_CAPABILITY_SET* caps = (const CLIPRDR_CAPABILITY_SET*) capsPtr;
if (caps->capabilitySetType == CB_CAPSTYPE_GENERAL)
{
const CLIPRDR_GENERAL_CAPABILITY_SET* generalCaps = (const CLIPRDR_GENERAL_CAPABILITY_SET*) caps;
if (generalCaps->generalFlags & CB_STREAM_FILECLIP_ENABLED)
{
clipboard->streams_supported = TRUE;
}
}
capsPtr += caps->capabilitySetLength;
}
return CHANNEL_RC_OK;
}
static void wlf_cliprdr_transfer_data(UwacSeat* seat, void* context, const char* mime, int fd)
{
wfClipboard* clipboard = (wfClipboard*)context;
size_t x;
WINPR_UNUSED(seat);
clipboard->responseMime = NULL;
for (x = 0; x < ARRAYSIZE(mime_html); x++)
{
const char* mime_cur = mime_html[x];
if (strcmp(mime_cur, mime) == 0)
{
clipboard->responseMime = mime_cur;
clipboard->responseFormat = ClipboardGetFormatId(clipboard->system, "HTML Format");
break;
}
}
for (x = 0; x < ARRAYSIZE(mime_text); x++)
{
const char* mime_cur = mime_text[x];
if (strcmp(mime_cur, mime) == 0)
{
clipboard->responseMime = mime_cur;
clipboard->responseFormat = CF_UNICODETEXT;
break;
}
}
for (x = 0; x < ARRAYSIZE(mime_image); x++)
{
const char* mime_cur = mime_image[x];
if (strcmp(mime_cur, mime) == 0)
{
clipboard->responseMime = mime_cur;
clipboard->responseFormat = CF_DIB;
break;
}
}
if (clipboard->responseMime != NULL)
{
clipboard->responseFile = fdopen(fd, "w");
if (clipboard->responseFile)
wlf_cliprdr_send_data_request(clipboard, clipboard->responseFormat);
else
WLog_Print(clipboard->log, WLOG_ERROR, "failed to open clipboard file descriptor for MIME %s",
clipboard->responseMime);
}
}
static void wlf_cliprdr_cancel_data(UwacSeat* seat, void* context)
{
WINPR_UNUSED(seat);
WINPR_UNUSED(context);
}
/**
* Called when the clipboard changes server side.
*
* Clear the local clipboard offer and replace it with a new one
* that announces the formats we get listed here.
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT wlf_cliprdr_server_format_list(CliprdrClientContext* context,
const CLIPRDR_FORMAT_LIST* formatList)
{
UINT32 i;
wfClipboard* clipboard;
BOOL html = FALSE;
BOOL text = FALSE;
BOOL image = FALSE;
if (!context || !context->custom)
return ERROR_INVALID_PARAMETER;
clipboard = (wfClipboard*) context->custom;
wlf_cliprdr_free_server_formats(clipboard);
if (!(clipboard->serverFormats = (CLIPRDR_FORMAT*) calloc(
formatList->numFormats, sizeof(CLIPRDR_FORMAT))))
{
WLog_Print(clipboard->log, WLOG_ERROR, "failed to allocate %"PRIuz" CLIPRDR_FORMAT structs",
clipboard->numServerFormats);
return CHANNEL_RC_NO_MEMORY;
}
clipboard->numServerFormats = formatList->numFormats;
if (!clipboard->seat)
{
WLog_Print(clipboard->log, WLOG_ERROR, "clipboard->seat=NULL, check your client implementation");
return ERROR_INTERNAL_ERROR;
}
for (i = 0; i < formatList->numFormats; i++)
{
const CLIPRDR_FORMAT* format = &formatList->formats[i];
CLIPRDR_FORMAT* srvFormat = &clipboard->serverFormats[i];
srvFormat->formatId = format->formatId;
if (format->formatName)
{
srvFormat->formatName = _strdup(format->formatName);
if (!srvFormat->formatName)
{
wlf_cliprdr_free_server_formats(clipboard);
return CHANNEL_RC_NO_MEMORY;
}
}
if (format->formatName)
{
if (strcmp(format->formatName, "HTML Format") == 0)
{
text = TRUE;
html = TRUE;
}
}
else
{
switch (format->formatId)
{
case CF_TEXT:
case CF_OEMTEXT:
case CF_UNICODETEXT:
text = TRUE;
break;
case CF_DIB:
image = TRUE;
break;
default:
break;
}
}
}
if (html)
{
size_t x;
for (x = 0; x < ARRAYSIZE(mime_html); x++)
UwacClipboardOfferCreate(clipboard->seat, mime_html[x]);
}
if (text)
{
size_t x;
for (x = 0; x < ARRAYSIZE(mime_text); x++)
UwacClipboardOfferCreate(clipboard->seat, mime_text[x]);
}
if (image)
{
size_t x;
for (x = 0; x < ARRAYSIZE(mime_image); x++)
UwacClipboardOfferCreate(clipboard->seat, mime_image[x]);
}
UwacClipboardOfferAnnounce(clipboard->seat, clipboard, wlf_cliprdr_transfer_data,
wlf_cliprdr_cancel_data);
return wlf_cliprdr_send_client_format_list_response(clipboard, TRUE);
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT wlf_cliprdr_server_format_list_response(CliprdrClientContext*
context, const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
{
//wfClipboard* clipboard = (wfClipboard*) context->custom;
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT wlf_cliprdr_server_format_data_request(CliprdrClientContext* context,
const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
{
int cnv;
UINT rc;
BYTE* data;
LPWSTR cdata;
size_t size;
const char* mime;
UINT32 formatId = formatDataRequest->requestedFormatId;
wfClipboard* clipboard = (wfClipboard*) context->custom;
switch (formatId)
{
case CF_TEXT:
case CF_OEMTEXT:
case CF_UNICODETEXT:
mime = "text/plain;charset=utf-8";
break;
case CF_DIB:
case CF_DIBV5:
mime = "image/bmp";
break;
default:
if (formatId == ClipboardGetFormatId(clipboard->system, "HTML Format"))
mime = "text/html";
else if (formatId == ClipboardGetFormatId(clipboard->system, "image/bmp"))
mime = "image/bmp";
else
mime = ClipboardGetFormatName(clipboard->system, formatId);
break;
}
data = UwacClipboardDataGet(clipboard->seat, mime, &size);
if (!data)
return ERROR_INTERNAL_ERROR;
switch (formatId)
{
case CF_UNICODETEXT:
if (size > INT_MAX)
rc = ERROR_INTERNAL_ERROR;
else
{
cnv = ConvertToUnicode(CP_UTF8, 0, (LPCSTR)data, (int)size, &cdata, 0);
free(data);
data = NULL;
if (cnv < 0)
rc = ERROR_INTERNAL_ERROR;
else
{
size = (size_t)cnv;
data = (BYTE*)cdata;
size *= sizeof(WCHAR);
}
}
break;
default:
// TODO: Image conversions
break;
}
rc = wlf_cliprdr_send_data_response(clipboard, data, size);
free(data);
return rc;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT wlf_cliprdr_server_format_data_response(CliprdrClientContext*
context, const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
{
int cnv;
UINT rc = ERROR_INTERNAL_ERROR;
UINT32 size = formatDataResponse->dataLen;
LPSTR cdata = NULL;
LPCSTR data = (LPCSTR)formatDataResponse->requestedFormatData;
const WCHAR* wdata = (const WCHAR*)formatDataResponse->requestedFormatData;
wfClipboard* clipboard = (wfClipboard*) context->custom;
if (size > INT_MAX * sizeof(WCHAR))
return ERROR_INTERNAL_ERROR;
switch (clipboard->responseFormat)
{
case CF_UNICODETEXT:
cnv = ConvertFromUnicode(CP_UTF8, 0, wdata, (int)(size / sizeof(WCHAR)), &cdata, 0, NULL, NULL);
if (cnv < 0)
return ERROR_INTERNAL_ERROR;
size = (size_t)cnv;
data = cdata;
break;
default:
// TODO: Image conversions
break;
}
fwrite(data, 1, size, clipboard->responseFile);
fclose(clipboard->responseFile);
rc = CHANNEL_RC_OK;
free(cdata);
return rc;
}
static UINT wlf_cliprdr_server_file_size_request(wfClipboard* clipboard,
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
wClipboardFileSizeRequest request = { 0 };
request.streamId = fileContentsRequest->streamId;
request.listIndex = fileContentsRequest->listIndex;
if (fileContentsRequest->cbRequested != sizeof(UINT64))
{
WLog_Print(clipboard->log, WLOG_WARN, "unexpected FILECONTENTS_SIZE request: %"PRIu32" bytes",
fileContentsRequest->cbRequested);
}
return clipboard->delegate->ClientRequestFileSize(clipboard->delegate, &request);
}
static UINT wlf_cliprdr_server_file_range_request(wfClipboard* clipboard,
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
wClipboardFileRangeRequest request = { 0 };
request.streamId = fileContentsRequest->streamId;
request.listIndex = fileContentsRequest->listIndex;
request.nPositionLow = fileContentsRequest->nPositionLow;
request.nPositionHigh = fileContentsRequest->nPositionHigh;
request.cbRequested = fileContentsRequest->cbRequested;
return clipboard->delegate->ClientRequestFileRange(clipboard->delegate, &request);
}
static UINT wlf_cliprdr_send_file_contents_failure(CliprdrClientContext* context,
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
response.msgFlags = CB_RESPONSE_FAIL;
response.streamId = fileContentsRequest->streamId;
response.dwFlags = fileContentsRequest->dwFlags;
return context->ClientFileContentsResponse(context, &response);
}
static UINT wlf_cliprdr_server_file_contents_request(CliprdrClientContext* context,
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
UINT error = NO_ERROR;
wfClipboard* clipboard = context->custom;
/*
* MS-RDPECLIP 2.2.5.3 File Contents Request PDU (CLIPRDR_FILECONTENTS_REQUEST):
* The FILECONTENTS_SIZE and FILECONTENTS_RANGE flags MUST NOT be set at the same time.
*/
if ((fileContentsRequest->dwFlags & (FILECONTENTS_SIZE | FILECONTENTS_RANGE)) ==
(FILECONTENTS_SIZE | FILECONTENTS_RANGE))
{
WLog_Print(clipboard->log, WLOG_ERROR, "invalid CLIPRDR_FILECONTENTS_REQUEST.dwFlags");
return wlf_cliprdr_send_file_contents_failure(context, fileContentsRequest);
}
if (fileContentsRequest->dwFlags & FILECONTENTS_SIZE)
error = wlf_cliprdr_server_file_size_request(clipboard, fileContentsRequest);
if (fileContentsRequest->dwFlags & FILECONTENTS_RANGE)
error = wlf_cliprdr_server_file_range_request(clipboard, fileContentsRequest);
if (error)
{
WLog_Print(clipboard->log, WLOG_ERROR, "failed to handle CLIPRDR_FILECONTENTS_REQUEST: 0x%08X",
error);
return wlf_cliprdr_send_file_contents_failure(context, fileContentsRequest);
}
return CHANNEL_RC_OK;
}
static UINT wlf_cliprdr_clipboard_file_size_success(wClipboardDelegate* delegate,
const wClipboardFileSizeRequest* request, UINT64 fileSize)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
wfClipboard* clipboard = delegate->custom;
response.msgFlags = CB_RESPONSE_OK;
response.streamId = request->streamId;
response.dwFlags = FILECONTENTS_SIZE;
response.cbRequested = sizeof(UINT64);
response.requestedData = (BYTE*) &fileSize;
return clipboard->context->ClientFileContentsResponse(clipboard->context, &response);
}
static UINT wlf_cliprdr_clipboard_file_size_failure(wClipboardDelegate* delegate,
const wClipboardFileSizeRequest* request, UINT errorCode)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
wfClipboard* clipboard = delegate->custom;
WINPR_UNUSED(errorCode);
response.msgFlags = CB_RESPONSE_FAIL;
response.streamId = request->streamId;
response.dwFlags = FILECONTENTS_SIZE;
return clipboard->context->ClientFileContentsResponse(clipboard->context, &response);
}
static UINT wlf_cliprdr_clipboard_file_range_success(wClipboardDelegate* delegate,
const wClipboardFileRangeRequest* request, const BYTE* data, UINT32 size)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
wfClipboard* clipboard = delegate->custom;
response.msgFlags = CB_RESPONSE_OK;
response.streamId = request->streamId;
response.dwFlags = FILECONTENTS_RANGE;
response.cbRequested = size;
response.requestedData = (const BYTE*) data;
return clipboard->context->ClientFileContentsResponse(clipboard->context, &response);
}
static UINT wlf_cliprdr_clipboard_file_range_failure(wClipboardDelegate* delegate,
const wClipboardFileRangeRequest* request, UINT errorCode)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
wfClipboard* clipboard = delegate->custom;
WINPR_UNUSED(errorCode);
response.msgFlags = CB_RESPONSE_FAIL;
response.streamId = request->streamId;
response.dwFlags = FILECONTENTS_RANGE;
return clipboard->context->ClientFileContentsResponse(clipboard->context, &response);
}
wfClipboard* wlf_clipboard_new(wlfContext* wfc)
{
rdpChannels* channels;
wfClipboard* clipboard;
if (!(clipboard = (wfClipboard*) calloc(1, sizeof(wfClipboard))))
return NULL;
clipboard->wfc = wfc;
channels = wfc->context.channels;
clipboard->log = WLog_Get(TAG);
clipboard->channels = channels;
clipboard->system = ClipboardCreate();
clipboard->delegate = ClipboardGetDelegate(clipboard->system);
clipboard->delegate->custom = clipboard;
clipboard->delegate->ClipboardFileSizeSuccess = wlf_cliprdr_clipboard_file_size_success;
clipboard->delegate->ClipboardFileSizeFailure = wlf_cliprdr_clipboard_file_size_failure;
clipboard->delegate->ClipboardFileRangeSuccess = wlf_cliprdr_clipboard_file_range_success;
clipboard->delegate->ClipboardFileRangeFailure = wlf_cliprdr_clipboard_file_range_failure;
return clipboard;
}
void wlf_clipboard_free(wfClipboard* clipboard)
{
if (!clipboard)
return;
wlf_cliprdr_free_server_formats(clipboard);
wlf_cliprdr_free_client_formats(clipboard);
ClipboardDestroy(clipboard->system);
free(clipboard);
}
BOOL wlf_cliprdr_init(wfClipboard* clipboard, CliprdrClientContext* cliprdr)
{
if (!cliprdr || !clipboard)
return FALSE;
clipboard->context = cliprdr;
cliprdr->custom = (void*) clipboard;
cliprdr->MonitorReady = wlf_cliprdr_monitor_ready;
cliprdr->ServerCapabilities = wlf_cliprdr_server_capabilities;
cliprdr->ServerFormatList = wlf_cliprdr_server_format_list;
cliprdr->ServerFormatListResponse = wlf_cliprdr_server_format_list_response;
cliprdr->ServerFormatDataRequest = wlf_cliprdr_server_format_data_request;
cliprdr->ServerFormatDataResponse = wlf_cliprdr_server_format_data_response;
cliprdr->ServerFileContentsRequest = wlf_cliprdr_server_file_contents_request;
return TRUE;
}
BOOL wlf_cliprdr_uninit(wfClipboard* clipboard, CliprdrClientContext* cliprdr)
{
if (cliprdr)
cliprdr->custom = NULL;
if (clipboard)
clipboard->context = NULL;
return TRUE;
}

View File

@ -0,0 +1,36 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Wayland Clipboard Redirection
*
* Copyright 2018 Armin Novak <armin.novak@thincast.com>
* Copyright 2018 Thincast Technologies GmbH
*
* 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_CLIENT_WAYLAND_CLIPRDR_H
#define FREERDP_CLIENT_WAYLAND_CLIPRDR_H
#include "wlfreerdp.h"
#include <freerdp/client/cliprdr.h>
wfClipboard* wlf_clipboard_new(wlfContext* wlc);
void wlf_clipboard_free(wfClipboard* clipboard);
BOOL wlf_cliprdr_init(wfClipboard* clipboard, CliprdrClientContext* cliprdr);
BOOL wlf_cliprdr_uninit(wfClipboard* clipboard, CliprdrClientContext* cliprdr);
BOOL wlf_cliprdr_handle_event(wfClipboard* clipboard, const UwacClipboardEvent* event);
#endif /* FREERDP_CLIENT_WAYLAND_CLIPRDR_H */

374
client/Wayland/wlf_disp.c Normal file
View File

@ -0,0 +1,374 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Wayland Display Control Channel
*
* Copyright 2018 Armin Novak <armin.novak@thincast.com>
* Copyright 2018 Thincast Technologies GmbH
*
* 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.
*/
#include <winpr/sysinfo.h>
#include "wlf_disp.h"
#define RESIZE_MIN_DELAY 200 /* minimum delay in ms between two resizes */
struct _wlfDispContext
{
wlfContext* wlc;
DispClientContext* disp;
BOOL haveXRandr;
int eventBase, errorBase;
int lastSentWidth, lastSentHeight;
UINT64 lastSentDate;
int targetWidth, targetHeight;
BOOL activated;
BOOL waitingResize;
BOOL fullscreen;
UINT16 lastSentDesktopOrientation;
UINT32 lastSentDesktopScaleFactor;
UINT32 lastSentDeviceScaleFactor;
};
static UINT wlf_disp_sendLayout(DispClientContext* disp, rdpMonitor* monitors, size_t nmonitors);
static BOOL wlf_disp_settings_changed(wlfDispContext* wlfDisp)
{
rdpSettings* settings = wlfDisp->wlc->context.settings;
if (wlfDisp->lastSentWidth != wlfDisp->targetWidth)
return TRUE;
if (wlfDisp->lastSentHeight != wlfDisp->targetHeight)
return TRUE;
if (wlfDisp->lastSentDesktopOrientation != settings->DesktopOrientation)
return TRUE;
if (wlfDisp->lastSentDesktopScaleFactor != settings->DesktopScaleFactor)
return TRUE;
if (wlfDisp->lastSentDeviceScaleFactor != settings->DeviceScaleFactor)
return TRUE;
if (wlfDisp->fullscreen != wlfDisp->wlc->fullscreen)
return TRUE;
return FALSE;
}
static BOOL wlf_update_last_sent(wlfDispContext* wlfDisp)
{
rdpSettings* settings = wlfDisp->wlc->context.settings;
wlfDisp->lastSentWidth = wlfDisp->targetWidth;
wlfDisp->lastSentHeight = wlfDisp->targetHeight;
wlfDisp->lastSentDesktopOrientation = settings->DesktopOrientation;
wlfDisp->lastSentDesktopScaleFactor = settings->DesktopScaleFactor;
wlfDisp->lastSentDeviceScaleFactor = settings->DeviceScaleFactor;
wlfDisp->fullscreen = wlfDisp->wlc->fullscreen;
return TRUE;
}
static BOOL wlf_disp_sendResize(wlfDispContext* wlfDisp)
{
DISPLAY_CONTROL_MONITOR_LAYOUT layout;
wlfContext* wlc;
rdpSettings* settings;
if (!wlfDisp || !wlfDisp->wlc)
return FALSE;
wlc = wlfDisp->wlc;
settings = wlc->context.settings;
if (!settings)
return FALSE;
if (!wlfDisp->activated || !wlfDisp->disp)
return TRUE;
if (GetTickCount64() - wlfDisp->lastSentDate < RESIZE_MIN_DELAY)
return TRUE;
wlfDisp->lastSentDate = GetTickCount64();
if (!wlf_disp_settings_changed(wlfDisp))
return TRUE;
/* TODO: Multimonitor support for wayland
if (wlc->fullscreen && (settings->MonitorCount > 0))
{
if (wlf_disp_sendLayout(wlfDisp->disp, settings->MonitorDefArray,
settings->MonitorCount) != CHANNEL_RC_OK)
return FALSE;
}
else
*/
{
wlfDisp->waitingResize = TRUE;
layout.Flags = DISPLAY_CONTROL_MONITOR_PRIMARY;
layout.Top = layout.Left = 0;
layout.Width = wlfDisp->targetWidth;
layout.Height = wlfDisp->targetHeight;
layout.Orientation = settings->DesktopOrientation;
layout.DesktopScaleFactor = settings->DesktopScaleFactor;
layout.DeviceScaleFactor = settings->DeviceScaleFactor;
layout.PhysicalWidth = wlfDisp->targetWidth;
layout.PhysicalHeight = wlfDisp->targetHeight;
if (IFCALLRESULT(CHANNEL_RC_OK, wlfDisp->disp->SendMonitorLayout, wlfDisp->disp, 1,
&layout) != CHANNEL_RC_OK)
return FALSE;
}
return wlf_update_last_sent(wlfDisp);
}
static BOOL wlf_disp_set_window_resizable(wlfDispContext* wlfDisp)
{
#if 0 // TODO
#endif
return TRUE;
}
static BOOL wlf_disp_check_context(void* context, wlfContext** ppwlc, wlfDispContext** ppwlfDisp,
rdpSettings** ppSettings)
{
wlfContext* wlc;
if (!context)
return FALSE;
wlc = (wlfContext*)context;
if (!(wlc->disp))
return FALSE;
if (!wlc->context.settings)
return FALSE;
*ppwlc = wlc;
*ppwlfDisp = wlc->disp;
*ppSettings = wlc->context.settings;
return TRUE;
}
static void wlf_disp_OnActivated(void* context, ActivatedEventArgs* e)
{
wlfContext* wlc;
wlfDispContext* wlfDisp;
rdpSettings* settings;
if (!wlf_disp_check_context(context, &wlc, &wlfDisp, &settings))
return;
wlfDisp->waitingResize = FALSE;
if (wlfDisp->activated && !settings->Fullscreen)
{
wlf_disp_set_window_resizable(wlfDisp);
if (e->firstActivation)
return;
wlf_disp_sendResize(wlfDisp);
}
}
static void wlf_disp_OnGraphicsReset(void* context, GraphicsResetEventArgs* e)
{
wlfContext* wlc;
wlfDispContext* wlfDisp;
rdpSettings* settings;
if (!wlf_disp_check_context(context, &wlc, &wlfDisp, &settings))
return;
wlfDisp->waitingResize = FALSE;
if (wlfDisp->activated && !settings->Fullscreen)
{
wlf_disp_set_window_resizable(wlfDisp);
wlf_disp_sendResize(wlfDisp);
}
}
static void wlf_disp_OnTimer(void* context, TimerEventArgs* e)
{
wlfContext* wlc;
wlfDispContext* wlfDisp;
rdpSettings* settings;
if (!wlf_disp_check_context(context, &wlc, &wlfDisp, &settings))
return;
if (!wlfDisp->activated || settings->Fullscreen)
return;
wlf_disp_sendResize(wlfDisp);
}
wlfDispContext* wlf_disp_new(wlfContext* wlc)
{
wlfDispContext* ret;
if (!wlc || !wlc->context.settings || !wlc->context.pubSub)
return NULL;
ret = calloc(1, sizeof(wlfDispContext));
if (!ret)
return NULL;
ret->wlc = wlc;
ret->lastSentWidth = ret->targetWidth = wlc->context.settings->DesktopWidth;
ret->lastSentHeight = ret->targetHeight = wlc->context.settings->DesktopHeight;
PubSub_SubscribeActivated(wlc->context.pubSub, wlf_disp_OnActivated);
PubSub_SubscribeGraphicsReset(wlc->context.pubSub, wlf_disp_OnGraphicsReset);
PubSub_SubscribeTimer(wlc->context.pubSub, wlf_disp_OnTimer);
return ret;
}
void wlf_disp_free(wlfDispContext* disp)
{
if (!disp)
return;
if (disp->wlc)
{
PubSub_UnsubscribeActivated(disp->wlc->context.pubSub, wlf_disp_OnActivated);
PubSub_UnsubscribeGraphicsReset(disp->wlc->context.pubSub, wlf_disp_OnGraphicsReset);
PubSub_UnsubscribeTimer(disp->wlc->context.pubSub, wlf_disp_OnTimer);
}
free(disp);
}
UINT wlf_disp_sendLayout(DispClientContext* disp, rdpMonitor* monitors, size_t nmonitors)
{
UINT ret = CHANNEL_RC_OK;
DISPLAY_CONTROL_MONITOR_LAYOUT* layouts;
size_t i;
wlfDispContext* wlfDisp = (wlfDispContext*)disp->custom;
rdpSettings* settings = wlfDisp->wlc->context.settings;
layouts = calloc(nmonitors, sizeof(DISPLAY_CONTROL_MONITOR_LAYOUT));
if (!layouts)
return CHANNEL_RC_NO_MEMORY;
for (i = 0; i < nmonitors; i++)
{
layouts[i].Flags = (monitors[i].is_primary ? DISPLAY_CONTROL_MONITOR_PRIMARY : 0);
layouts[i].Left = monitors[i].x;
layouts[i].Top = monitors[i].y;
layouts[i].Width = monitors[i].width;
layouts[i].Height = monitors[i].height;
layouts[i].Orientation = ORIENTATION_LANDSCAPE;
layouts[i].PhysicalWidth = monitors[i].attributes.physicalWidth;
layouts[i].PhysicalHeight = monitors[i].attributes.physicalHeight;
switch (monitors[i].attributes.orientation)
{
case 90:
layouts[i].Orientation = ORIENTATION_PORTRAIT;
break;
case 180:
layouts[i].Orientation = ORIENTATION_LANDSCAPE_FLIPPED;
break;
case 270:
layouts[i].Orientation = ORIENTATION_PORTRAIT_FLIPPED;
break;
case 0:
default:
/* MS-RDPEDISP - 2.2.2.2.1:
* Orientation (4 bytes): A 32-bit unsigned integer that specifies the
* orientation of the monitor in degrees. Valid values are 0, 90, 180
* or 270
*
* So we default to ORIENTATION_LANDSCAPE
*/
layouts[i].Orientation = ORIENTATION_LANDSCAPE;
break;
}
layouts[i].DesktopScaleFactor = settings->DesktopScaleFactor;
layouts[i].DeviceScaleFactor = settings->DeviceScaleFactor;
}
ret = IFCALLRESULT(CHANNEL_RC_OK, disp->SendMonitorLayout, disp, nmonitors, layouts);
free(layouts);
return ret;
}
BOOL wlf_disp_handle_configure(wlfDispContext* disp, int32_t width, int32_t height)
{
if (!disp)
return FALSE;
disp->targetWidth = width;
disp->targetHeight = height;
return wlf_disp_sendResize(disp);
}
static UINT wlf_DisplayControlCaps(DispClientContext* disp, UINT32 maxNumMonitors,
UINT32 maxMonitorAreaFactorA, UINT32 maxMonitorAreaFactorB)
{
/* we're called only if dynamic resolution update is activated */
wlfDispContext* wlfDisp = (wlfDispContext*)disp->custom;
rdpSettings* settings = wlfDisp->wlc->context.settings;
WLog_DBG(TAG,
"DisplayControlCapsPdu: MaxNumMonitors: %"PRIu32" MaxMonitorAreaFactorA: %"PRIu32" MaxMonitorAreaFactorB: %"PRIu32"",
maxNumMonitors, maxMonitorAreaFactorA, maxMonitorAreaFactorB);
wlfDisp->activated = TRUE;
if (settings->Fullscreen)
return CHANNEL_RC_OK;
WLog_DBG(TAG, "DisplayControlCapsPdu: setting the window as resizable");
return wlf_disp_set_window_resizable(wlfDisp) ? CHANNEL_RC_OK : CHANNEL_RC_NO_MEMORY;
}
BOOL wlf_disp_init(wlfDispContext* wlfDisp, DispClientContext* disp)
{
rdpSettings* settings;
if (!wlfDisp || !wlfDisp->wlc || !disp)
return FALSE;
settings = wlfDisp->wlc->context.settings;
if (!settings)
return FALSE;
wlfDisp->disp = disp;
disp->custom = (void*) wlfDisp;
if (settings->DynamicResolutionUpdate)
{
disp->DisplayControlCaps = wlf_DisplayControlCaps;
}
return TRUE;
}
BOOL wlf_disp_uninit(wlfDispContext* wlfDisp, DispClientContext* disp)
{
if (!wlfDisp || !disp)
return FALSE;
wlfDisp->disp = NULL;
return TRUE;
}

36
client/Wayland/wlf_disp.h Normal file
View File

@ -0,0 +1,36 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Wayland Display Control Channel
*
* Copyright 2018 Armin Novak <armin.novak@thincast.com>
* Copyright 2018 Thincast Technologies GmbH
*
* 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_CLIENT_WAYLAND_DISP_H
#define FREERDP_CLIENT_WAYLAND_DISP_H
#include <freerdp/types.h>
#include <freerdp/client/disp.h>
#include "wlfreerdp.h"
FREERDP_API BOOL wlf_disp_init(wlfDispContext* xfDisp, DispClientContext* disp);
FREERDP_API BOOL wlf_disp_uninit(wlfDispContext* xfDisp, DispClientContext* disp);
wlfDispContext* wlf_disp_new(wlfContext* wlc);
void wlf_disp_free(wlfDispContext* disp);
BOOL wlf_disp_handle_configure(wlfDispContext* disp, int32_t width, int32_t height);
void wlf_disp_resized(wlfDispContext* disp);
#endif /* FREERDP_CLIENT_WAYLAND_DISP_H */

View File

@ -44,7 +44,8 @@ BOOL wlf_handle_pointer_motion(freerdp* instance, UwacPointerMotionEvent* ev)
BOOL wlf_handle_pointer_buttons(freerdp* instance, UwacPointerButtonEvent* ev)
{
rdpInput* input;
UINT16 flags;
UINT16 flags = 0;
UINT16 xflags = 0;
if (!instance || !ev || !instance->input)
return FALSE;
@ -52,9 +53,10 @@ BOOL wlf_handle_pointer_buttons(freerdp* instance, UwacPointerButtonEvent* ev)
input = instance->input;
if (ev->state == WL_POINTER_BUTTON_STATE_PRESSED)
flags = PTR_FLAGS_DOWN;
else
flags = 0;
{
flags |= PTR_FLAGS_DOWN;
xflags |= PTR_XFLAGS_DOWN;
}
switch (ev->button)
{
@ -70,36 +72,59 @@ BOOL wlf_handle_pointer_buttons(freerdp* instance, UwacPointerButtonEvent* ev)
flags |= PTR_FLAGS_BUTTON3;
break;
case BTN_SIDE:
xflags |= PTR_XFLAGS_BUTTON1;
break;
case BTN_EXTRA:
xflags |= PTR_XFLAGS_BUTTON2;
break;
default:
return TRUE;
}
return freerdp_input_send_mouse_event(input, flags, ev->x, ev->y);
if ((flags & ~PTR_FLAGS_DOWN) != 0)
return freerdp_input_send_mouse_event(input, flags, ev->x, ev->y);
if ((xflags & ~PTR_XFLAGS_DOWN) != 0)
return freerdp_input_send_extended_mouse_event(input, xflags, ev->x, ev->y);
return FALSE;
}
BOOL wlf_handle_pointer_axis(freerdp* instance, UwacPointerAxisEvent* ev)
{
rdpInput* input;
UINT16 flags;
UINT16 flags = 0;
int direction;
if (!instance || !ev || !instance->input)
return FALSE;
input = instance->input;
flags = PTR_FLAGS_WHEEL;
if (ev->axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
switch (ev->axis)
{
direction = wl_fixed_to_int(ev->value);
case WL_POINTER_AXIS_VERTICAL_SCROLL:
flags |= PTR_FLAGS_WHEEL;
break;
if (direction < 0)
flags |= 0x0078;
else
flags |= PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
flags |= PTR_FLAGS_HWHEEL;
break;
default:
return FALSE;
}
direction = wl_fixed_to_int(ev->value);
flags |= 0x0078; /* TODO: Calculate the distance with the provided value size */
if (direction < 0)
flags |= PTR_FLAGS_WHEEL_NEGATIVE;
return freerdp_input_send_mouse_event(input, flags, ev->x, ev->y);
}
@ -129,5 +154,5 @@ BOOL wlf_keyboard_enter(freerdp* instance, UwacKeyboardEnterLeaveEvent* ev)
input = instance->input;
return freerdp_input_send_focus_in_event(input, 0) &&
freerdp_input_send_mouse_event(input, PTR_FLAGS_MOVE, 0, 0);
freerdp_input_send_mouse_event(input, PTR_FLAGS_MOVE, 0, 0);
}

View File

@ -0,0 +1,133 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Wayland Mouse Pointer
*
* Copyright 2019 Armin Novak <armin.novak@thincast.com>
* Copyright 2019 Thincast Technologies GmbH
*
* 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 "wlf_pointer.h"
#include "wlfreerdp.h"
struct wlf_pointer
{
rdpPointer pointer;
size_t size;
void* data;
};
typedef struct wlf_pointer wlfPointer;
static BOOL wlf_Pointer_New(rdpContext* context, rdpPointer* pointer)
{
wlfPointer* ptr = (wlfPointer*)pointer;
if (!ptr)
return FALSE;
ptr->size = pointer->width * pointer->height * 4;
ptr->data = _aligned_malloc(ptr->size, 16);
if (!ptr->data)
return FALSE;
if (!freerdp_image_copy_from_pointer_data(
ptr->data, PIXEL_FORMAT_RGBA32,
0, 0, 0, pointer->width, pointer->height,
pointer->xorMaskData, pointer->lengthXorMask,
pointer->andMaskData, pointer->lengthAndMask,
pointer->xorBpp, &context->gdi->palette))
{
_aligned_free(ptr->data);
return FALSE;
}
return TRUE;
}
static void wlf_Pointer_Free(rdpContext* context, rdpPointer* pointer)
{
wlfPointer* ptr = (wlfPointer*)pointer;
WINPR_UNUSED(context);
if (ptr)
_aligned_free(ptr->data);
}
static BOOL wlf_Pointer_Set(rdpContext* context,
const rdpPointer* pointer)
{
wlfContext* wlf = (wlfContext*)context;
wlfPointer* ptr = (wlfPointer*)pointer;
if (!wlf || !wlf->seat)
return FALSE;
// TODO: Scale according to SmartSizing
if (UwacSeatSetMouseCursor(wlf->seat, ptr->data, ptr->size, pointer->width, pointer->height, pointer->xPos, pointer->yPos) != UWAC_SUCCESS)
return FALSE;
return TRUE;
}
static BOOL wlf_Pointer_SetNull(rdpContext* context)
{
wlfContext* wlf = (wlfContext*)context;
if (!wlf || !wlf->seat)
return FALSE;
if (UwacSeatSetMouseCursor(wlf->seat, NULL, 0, 0, 0, 0, 0) != UWAC_SUCCESS)
return FALSE;
return TRUE;
}
static BOOL wlf_Pointer_SetDefault(rdpContext* context)
{
wlfContext* wlf = (wlfContext*)context;
if (!wlf || !wlf->seat)
return FALSE;
if (UwacSeatSetMouseCursor(wlf->seat, NULL, 1, 0, 0, 0, 0) != UWAC_SUCCESS)
return FALSE;
return TRUE;
}
static BOOL wlf_Pointer_SetPosition(rdpContext* context, UINT32 x, UINT32 y)
{
// TODO
WLog_WARN(TAG, "%s not implemented", __FUNCTION__);
return TRUE;
}
BOOL wlf_register_pointer(rdpGraphics* graphics)
{
rdpPointer* pointer = NULL;
if (!(pointer = (rdpPointer*) calloc(1, sizeof(rdpPointer))))
return FALSE;
pointer->size = sizeof(wlfPointer);
pointer->New = wlf_Pointer_New;
pointer->Free = wlf_Pointer_Free;
pointer->Set = wlf_Pointer_Set;
pointer->SetNull = wlf_Pointer_SetNull;
pointer->SetDefault = wlf_Pointer_SetDefault;
pointer->SetPosition = wlf_Pointer_SetPosition;
graphics_register_pointer(graphics, pointer);
free(pointer);
return TRUE;
}

View File

@ -1,8 +1,9 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* DirectFB Event Handling
* Wayland Mouse Pointer
*
* Copyright 2011 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2019 Armin Novak <armin.novak@thincast.com>
* Copyright 2019 Thincast Technologies GmbH
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,12 +18,11 @@
* limitations under the License.
*/
#ifndef FREERDP_CLIENT_DF_EVENT_H
#define FREERDP_CLIENT_DF_EVENT_H
#ifndef FREERDP_CLIENT_WAYLAND_POINTER_H
#define FREERDP_CLIENT_WAYLAND_POINTER_H
#include "dfreerdp.h"
#include <freerdp/graphics.h>
void df_keyboard_init(void);
BOOL df_event_process(freerdp* instance, DFBEvent* event);
BOOL wlf_register_pointer(rdpGraphics* graphics);
#endif /* FREERDP_CLIENT_DF_EVENT_H */
#endif /* FREERDP_CLIENT_WAYLAND_POINTER_H */

View File

@ -36,22 +36,10 @@
#include "wlfreerdp.h"
#include "wlf_input.h"
#include "wlf_cliprdr.h"
#include "wlf_disp.h"
#include "wlf_channels.h"
static BOOL wl_update_content(wlfContext* context_w)
{
if (!context_w)
return FALSE;
if (!context_w->waitingFrameDone && context_w->haveDamage)
{
UwacWindowSubmitBuffer(context_w->window, true);
context_w->waitingFrameDone = TRUE;
context_w->haveDamage = FALSE;
}
return TRUE;
}
#include "wlf_pointer.h"
static BOOL wl_begin_paint(rdpContext* context)
{
@ -69,15 +57,68 @@ static BOOL wl_begin_paint(rdpContext* context)
return TRUE;
}
static BOOL wl_update_buffer(wlfContext* context_w, INT32 ix, INT32 iy, INT32 iw, INT32 ih)
{
rdpGdi* gdi;
char* data;
size_t baseSrcOffset;
size_t baseDstOffset;
UINT32 i, x, y, w, h;
UwacSize geometry;
size_t stride;
UwacReturnCode rc;
if (!context_w)
return FALSE;
if ((ix < 0) || (iy < 0) || (iw < 0) || (ih < 0))
return FALSE;
x = (UINT32)ix;
y = (UINT32)iy;
w = (UINT32)iw;
h = (UINT32)ih;
rc = UwacWindowGetDrawingBufferGeometry(context_w->window, &geometry, &stride);
data = UwacWindowGetDrawingBuffer(context_w->window);
if (!data || (rc != UWAC_SUCCESS))
return FALSE;
gdi = context_w->context.gdi;
if (!gdi)
return FALSE;
/* Ignore output if the surface size does not match. */
if ((x > geometry.width) || (y > geometry.height))
return TRUE;
baseSrcOffset = y * gdi->stride + x * GetBytesPerPixel(gdi->dstFormat);
baseDstOffset = y * stride + x * 4;
for (i = 0; i < MIN(h, geometry.height - y); i++)
{
const size_t srcOffset = i * gdi->stride + baseSrcOffset;
const size_t dstOffset = i * stride + baseDstOffset;
memcpy(data + dstOffset, gdi->primary_buffer + srcOffset,
MIN(w, geometry.width - x) * GetBytesPerPixel(gdi->dstFormat));
}
if (UwacWindowAddDamage(context_w->window, x, y, w, h) != UWAC_SUCCESS)
return FALSE;
if (UwacWindowSubmitBuffer(context_w->window, true) != UWAC_SUCCESS)
return FALSE;
return TRUE;
}
static BOOL wl_end_paint(rdpContext* context)
{
rdpGdi* gdi;
char* data;
wlfContext* context_w;
INT32 x, y;
UINT32 w, h;
UINT32 i;
INT32 w, h;
if (!context || !context->gdi || !context->gdi->primary)
return FALSE;
@ -92,27 +133,31 @@ static BOOL wl_end_paint(rdpContext* context)
w = gdi->primary->hdc->hwnd->invalid->w;
h = gdi->primary->hdc->hwnd->invalid->h;
context_w = (wlfContext*) context;
data = UwacWindowGetDrawingBuffer(context_w->window);
if (!data)
return FALSE;
for (i = 0; i < h; i++)
{
memcpy(data + ((i + y) * (gdi->width * GetBytesPerPixel(
gdi->dstFormat))) + x * GetBytesPerPixel(gdi->dstFormat),
gdi->primary_buffer + ((i + y) * (gdi->width * GetBytesPerPixel(
gdi->dstFormat))) + x * GetBytesPerPixel(gdi->dstFormat),
w * GetBytesPerPixel(gdi->dstFormat));
}
if (UwacWindowAddDamage(context_w->window, x, y, w, h) != UWAC_SUCCESS)
return FALSE;
context_w->haveDamage = TRUE;
return wl_update_content(context_w);
return wl_update_buffer(context_w, x, y, w, h);
}
static BOOL wl_refresh_display(wlfContext* context)
{
rdpGdi* gdi;
if (!context || !context->context.gdi)
return FALSE;
gdi = context->context.gdi;
return wl_update_buffer(context, 0, 0, gdi->width, gdi->height);
}
static BOOL wl_resize_display(rdpContext* context)
{
wlfContext* wlc = (wlfContext*)context;
rdpGdi* gdi = context->gdi;
rdpSettings* settings = context->settings;
if (!gdi_resize(gdi, settings->DesktopWidth, settings->DesktopHeight))
return FALSE;
return wl_refresh_display(wlc);
}
static BOOL wl_pre_connect(freerdp* instance)
{
@ -132,31 +177,6 @@ static BOOL wl_pre_connect(freerdp* instance)
settings->OsMajorType = OSMAJORTYPE_UNIX;
settings->OsMinorType = OSMINORTYPE_NATIVE_WAYLAND;
ZeroMemory(settings->OrderSupport, 32);
settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
settings->OrderSupport[NEG_LINETO_INDEX] = TRUE;
settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
settings->OrderSupport[NEG_MEMBLT_INDEX] = settings->BitmapCacheEnabled;
settings->OrderSupport[NEG_MEM3BLT_INDEX] = settings->BitmapCacheEnabled;
settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = settings->BitmapCacheEnabled;
settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = settings->BitmapCacheEnabled;
settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE;
settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE;
settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE;
settings->OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE;
settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE;
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
PubSub_SubscribeChannelConnected(instance->context->pubSub,
wlf_OnChannelConnectedEventHandler);
PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
@ -190,6 +210,7 @@ static BOOL wl_post_connect(freerdp* instance)
rdpGdi* gdi;
UwacWindow* window;
wlfContext* context;
UINT32 w, h;
if (!instance || !instance->context)
return FALSE;
@ -199,27 +220,37 @@ static BOOL wl_post_connect(freerdp* instance)
gdi = instance->context->gdi;
if (!gdi)
if (!gdi || (gdi->width < 0) || (gdi->height < 0))
return FALSE;
if (!wlf_register_pointer(instance->context->graphics))
return FALSE;
w = (UINT32)gdi->width;
h = (UINT32)gdi->height;
context = (wlfContext*) instance->context;
context->window = window = UwacCreateWindowShm(context->display, gdi->width,
gdi->height, WL_SHM_FORMAT_XRGB8888);
context->window = window = UwacCreateWindowShm(context->display, w, h, WL_SHM_FORMAT_XRGB8888);
if (!window)
return FALSE;
UwacWindowSetFullscreenState(window, NULL, instance->context->settings->Fullscreen);
UwacWindowSetTitle(window, "FreeRDP");
UwacWindowSetOpaqueRegion(context->window, 0, 0, gdi->width, gdi->height);
UwacWindowSetOpaqueRegion(context->window, 0, 0, w, h);
instance->update->BeginPaint = wl_begin_paint;
instance->update->EndPaint = wl_end_paint;
memcpy(UwacWindowGetDrawingBuffer(context->window), gdi->primary_buffer,
gdi->width * gdi->height * 4);
UwacWindowAddDamage(context->window, 0, 0, gdi->width, gdi->height);
context->haveDamage = TRUE;
instance->update->DesktopResize = wl_resize_display;
freerdp_keyboard_init(instance->context->settings->KeyboardLayout);
return wl_update_content(context);
if (!(context->disp = wlf_disp_new(context)))
return FALSE;
context->clipboard = wlf_clipboard_new(context);
if (!context->clipboard)
return FALSE;
return wl_refresh_display(context);
}
static void wl_post_disconnect(freerdp* instance)
@ -234,6 +265,8 @@ static void wl_post_disconnect(freerdp* instance)
context = (wlfContext*) instance->context;
gdi_free(instance);
wlf_clipboard_free(context->clipboard);
wlf_disp_free(context->disp);
if (context->window)
UwacDestroyWindow(&context->window);
@ -247,6 +280,8 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display)
if (UwacDisplayDispatch(display, 1) < 0)
return FALSE;
context = (wlfContext*)instance->context;
while (UwacHasEvent(display))
{
if (UwacNextEvent(display, &event) != UWAC_SUCCESS)
@ -255,16 +290,15 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display)
/*printf("UWAC event type %d\n", event.type);*/
switch (event.type)
{
case UWAC_EVENT_NEW_SEAT:
context->seat = event.seat_new.seat;
break;
case UWAC_EVENT_REMOVED_SEAT:
context->seat = NULL;
break;
case UWAC_EVENT_FRAME_DONE:
if (!instance)
continue;
context = (wlfContext*)instance->context;
context->waitingFrameDone = FALSE;
if (context->haveDamage && !wl_update_content(context))
return FALSE;
break;
case UWAC_EVENT_POINTER_ENTER:
@ -298,11 +332,30 @@ static BOOL handle_uwac_events(freerdp* instance, UwacDisplay* display)
break;
case UWAC_EVENT_KEYBOARD_ENTER:
if (instance->context->settings->GrabKeyboard)
UwacSeatInhibitShortcuts(event.keyboard_enter_leave.seat, true);
if (!wlf_keyboard_enter(instance, &event.keyboard_enter_leave))
return FALSE;
break;
case UWAC_EVENT_CONFIGURE:
if (!wlf_disp_handle_configure(context->disp, event.configure.width, event.configure.height))
return FALSE;
if (!wl_refresh_display(context))
return FALSE;
break;
case UWAC_EVENT_CLIPBOARD_AVAILABLE:
case UWAC_EVENT_CLIPBOARD_OFFER:
case UWAC_EVENT_CLIPBOARD_SELECT:
if (!wlf_cliprdr_handle_event(context->clipboard, &event.clipboard))
return FALSE;
break;
default:
break;
}
@ -328,7 +381,7 @@ static int wlfreerdp_run(freerdp* instance)
if (!freerdp_connect(instance))
{
printf("Failed to connect\n");
WLog_Print(context->log, WLOG_ERROR, "Failed to connect");
return -1;
}
@ -339,7 +392,7 @@ static int wlfreerdp_run(freerdp* instance)
if (count <= 1)
{
printf("Failed to get FreeRDP file descriptor\n");
WLog_Print(context->log, WLOG_ERROR, "Failed to get FreeRDP file descriptor");
break;
}
@ -347,20 +400,20 @@ static int wlfreerdp_run(freerdp* instance)
if (WAIT_FAILED == status)
{
printf("%s: WaitForMultipleObjects failed\n", __FUNCTION__);
WLog_Print(context->log, WLOG_ERROR, "%s: WaitForMultipleObjects failed", __FUNCTION__);
break;
}
if (!handle_uwac_events(instance, context->display))
{
printf("error handling UWAC events\n");
WLog_Print(context->log, WLOG_ERROR, "error handling UWAC events");
break;
}
if (freerdp_check_event_handles(instance->context) != TRUE)
{
if (freerdp_get_last_error(instance->context) == FREERDP_ERROR_SUCCESS)
printf("Failed to check FreeRDP file descriptor\n");
WLog_Print(context->log, WLOG_ERROR, "Failed to check FreeRDP file descriptor");
break;
}
@ -394,7 +447,7 @@ static int wlf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
return -1;
wlf = (wlfContext*) instance->context;
WLog_INFO(TAG, "Logon Error Info %s [%s]", str_data, str_type);
WLog_Print(wlf->log, WLOG_INFO, "Logon Error Info %s [%s]", str_data, str_type);
return 1;
}
@ -411,12 +464,13 @@ static BOOL wlf_client_new(freerdp* instance, rdpContext* context)
instance->PostDisconnect = wl_post_disconnect;
instance->Authenticate = client_cli_authenticate;
instance->GatewayAuthenticate = client_cli_gw_authenticate;
instance->VerifyCertificate = client_cli_verify_certificate;
instance->VerifyChangedCertificate = client_cli_verify_changed_certificate;
instance->VerifyCertificateEx = client_cli_verify_certificate_ex;
instance->VerifyChangedCertificateEx = client_cli_verify_changed_certificate_ex;
instance->LogonErrorInfo = wlf_logon_error_info;
wfl->log = WLog_Get(TAG);
wfl->display = UwacOpenDisplay(NULL, &status);
if (!wfl->display || (status != UWAC_SUCCESS))
if (!wfl->display || (status != UWAC_SUCCESS) || !wfl->log)
return FALSE;
wfl->displayHandle = CreateFileDescriptorEvent(NULL, FALSE, FALSE,
@ -445,11 +499,13 @@ static void wlf_client_free(freerdp* instance, rdpContext* context)
static int wfl_client_start(rdpContext* context)
{
WINPR_UNUSED(context);
return 0;
}
static int wfl_client_stop(rdpContext* context)
{
WINPR_UNUSED(context);
return 0;
}
@ -471,7 +527,7 @@ static int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints)
int main(int argc, char* argv[])
{
int rc = -1;
DWORD status;
int status;
RDP_CLIENT_ENTRY_POINTS clientEntryPoints;
rdpContext* context;
RdpClientEntry(&clientEntryPoints);

View File

@ -31,7 +31,8 @@
#define TAG CLIENT_TAG("wayland")
typedef struct wlf_context wlfContext;
typedef struct wlf_clipboard wfClipboard;
typedef struct _wlfDispContext wlfDispContext;
struct wlf_context
{
@ -40,14 +41,17 @@ struct wlf_context
UwacDisplay* display;
HANDLE displayHandle;
UwacWindow* window;
UwacSeat* seat;
BOOL waitingFrameDone;
BOOL haveDamage;
BOOL fullscreen;
/* Channels */
RdpeiClientContext* rdpei;
RdpgfxClientContext* gfx;
EncomspClientContext* encomsp;
wfClipboard* clipboard;
wlfDispContext* disp;
wLog* log;
};
#endif /* FREERDP_CLIENT_WAYLAND_FREERDP_H */

View File

@ -501,6 +501,37 @@ static BOOL xf_process_x_events(freerdp* instance)
return status;
}
static char* xf_window_get_title(rdpSettings* settings)
{
BOOL port;
char* windowTitle;
size_t size;
char* name;
const char* prefix = "FreeRDP:";
if (!settings)
return NULL;
name = settings->ServerHostname;
if (settings->WindowTitle)
return _strdup(settings->WindowTitle);
port = (settings->ServerPort != 3389);
size = strlen(name) + 16;
windowTitle = calloc(size, sizeof(char));
if (!windowTitle)
return NULL;
if (!port)
sprintf_s(windowTitle, size, "%s %s", prefix, name);
else
sprintf_s(windowTitle, size, "%s %s:%i", prefix, name, settings->ServerPort);
return windowTitle;
}
BOOL xf_create_window(xfContext* xfc)
{
XGCValues gcv;
@ -532,37 +563,10 @@ BOOL xf_create_window(xfContext* xfc)
xfc->offset_x = 0;
xfc->offset_y = 0;
#endif
windowTitle = xf_window_get_title(settings);
if (settings->WindowTitle)
{
windowTitle = _strdup(settings->WindowTitle);
if (!windowTitle)
return FALSE;
}
else if (settings->ServerPort == 3389)
{
size_t size = 1 + sizeof("FreeRDP: ") + strlen(
settings->ServerHostname);
windowTitle = malloc(size);
if (!windowTitle)
return FALSE;
sprintf_s(windowTitle, size, "FreeRDP: %s", settings->ServerHostname);
}
else
{
size_t size = 1 + sizeof("FreeRDP: ") + strlen(settings->ServerHostname)
+ sizeof(":00000");
windowTitle = malloc(size);
if (!windowTitle)
return FALSE;
sprintf_s(windowTitle, size, "FreeRDP: %s:%i", settings->ServerHostname,
settings->ServerPort);
}
if (!windowTitle)
return FALSE;
#ifdef WITH_XRENDER
@ -1032,26 +1036,55 @@ static void xf_get_x11_button_map(xfContext* xfc, unsigned char* x11_map)
/* Assignment of physical (not logical) mouse buttons to wire flags. */
/* Notice that the middle button is 2 in X11, but 3 in RDP. */
static const int xf_button_flags[NUM_BUTTONS_MAPPED] =
static const button_map xf_button_flags[NUM_BUTTONS_MAPPED] =
{
PTR_FLAGS_BUTTON1,
PTR_FLAGS_BUTTON3,
PTR_FLAGS_BUTTON2
{Button1, PTR_FLAGS_BUTTON1},
{Button2, PTR_FLAGS_BUTTON3},
{Button3, PTR_FLAGS_BUTTON2},
{Button4, PTR_FLAGS_WHEEL | 0x78},
{Button5, PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x78},
{6, PTR_FLAGS_HWHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x78},
{7, PTR_FLAGS_HWHEEL | 0x78},
{8, PTR_XFLAGS_BUTTON1},
{9, PTR_XFLAGS_BUTTON2},
{97, PTR_XFLAGS_BUTTON1},
{112, PTR_XFLAGS_BUTTON2}
};
static UINT16 get_flags_for_button(int button)
{
size_t x;
for (x = 0; x < ARRAYSIZE(xf_button_flags); x++)
{
const button_map* map = &xf_button_flags[x];
if (map->button == button)
return map->flags;
}
return 0;
}
static void xf_button_map_init(xfContext* xfc)
{
size_t pos = 0;
/* loop counter for array initialization */
int physical;
int logical;
size_t physical;
/* logical mouse button which is used for each physical mouse */
/* button (indexed from zero). This is the default map. */
unsigned char x11_map[NUM_BUTTONS_MAPPED] =
{
Button1,
Button2,
Button3
};
unsigned char x11_map[112] = { 0 };
x11_map[0] = Button1;
x11_map[1] = Button2;
x11_map[2] = Button3;
x11_map[3] = Button4;
x11_map[4] = Button5;
x11_map[5] = 6;
x11_map[6] = 7;
x11_map[7] = 8;
x11_map[8] = 9;
x11_map[96] = 97;
x11_map[111] = 112;
/* query system for actual remapping */
if (!xfc->context.settings->UnmapButtons)
@ -1062,18 +1095,23 @@ static void xf_button_map_init(xfContext* xfc)
/* iterate over all (mapped) physical buttons; for each of them */
/* find the logical button in X11, and assign to this the */
/* appropriate value to send over the RDP wire. */
for (physical = 0; physical < NUM_BUTTONS_MAPPED; ++physical)
for (physical = 0; physical < ARRAYSIZE(x11_map); ++physical)
{
logical = x11_map[physical];
const unsigned char logical = x11_map[physical];
const UINT16 flags = get_flags_for_button(logical);
if (Button1 <= logical && logical <= Button3)
if ((logical != 0) && (flags != 0))
{
xfc->button_map[logical - BUTTON_BASE] = xf_button_flags[physical];
}
else
{
WLog_ERR(TAG, "Mouse physical button %d is mapped to logical button %d",
physical, logical);
if (pos >= NUM_BUTTONS_MAPPED)
{
WLog_ERR(TAG, "Failed to map mouse button to RDP button, no space");
}
else
{
button_map* map = &xfc->button_map[pos++];
map->button = physical + Button1;
map->flags = get_flags_for_button(logical);
}
}
}
}
@ -1100,31 +1138,6 @@ static BOOL xf_pre_connect(freerdp* instance)
channels = context->channels;
settings->OsMajorType = OSMAJORTYPE_UNIX;
settings->OsMinorType = OSMINORTYPE_NATIVE_XSERVER;
ZeroMemory(settings->OrderSupport, 32);
settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE;
settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE;
settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE;
settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE;
settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE;
settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE;
settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE;
settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE;
settings->OrderSupport[NEG_LINETO_INDEX] = TRUE;
settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE;
settings->OrderSupport[NEG_MEMBLT_INDEX] = settings->BitmapCacheEnabled;
settings->OrderSupport[NEG_MEM3BLT_INDEX] = settings->BitmapCacheEnabled;
settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = settings->BitmapCacheEnabled;
settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = settings->BitmapCacheEnabled;
settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE;
settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = settings->GlyphSupportLevel != GLYPH_SUPPORT_NONE;
settings->OrderSupport[NEG_FAST_INDEX_INDEX] = settings->GlyphSupportLevel != GLYPH_SUPPORT_NONE;
settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = settings->GlyphSupportLevel != GLYPH_SUPPORT_NONE;
settings->OrderSupport[NEG_POLYGON_SC_INDEX] = FALSE;
settings->OrderSupport[NEG_POLYGON_CB_INDEX] = FALSE;
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE;
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE;
PubSub_SubscribeChannelConnected(instance->context->pubSub,
xf_OnChannelConnectedEventHandler);
PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
@ -1189,7 +1202,6 @@ static BOOL xf_pre_connect(freerdp* instance)
xfc->decorations = settings->Decorations;
xfc->grab_keyboard = settings->GrabKeyboard;
xfc->fullscreen_toggle = settings->ToggleFullscreen;
xfc->floatbar = settings->Floatbar;
xf_button_map_init(xfc);
return TRUE;
}
@ -1571,8 +1583,8 @@ static DWORD WINAPI xf_client_thread(LPVOID param)
nCount += tmp;
}
if (xfc->floatbar && xfc->fullscreen && !xfc->remote_app)
xf_floatbar_hide_and_show(xfc);
if (xfc->window)
xf_floatbar_hide_and_show(xfc->window->floatbar);
waitStatus = WaitForMultipleObjects(nCount, handles, FALSE, INFINITE);
@ -1788,8 +1800,8 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
instance->PostDisconnect = xf_post_disconnect;
instance->Authenticate = client_cli_authenticate;
instance->GatewayAuthenticate = client_cli_gw_authenticate;
instance->VerifyCertificate = client_cli_verify_certificate;
instance->VerifyChangedCertificate = client_cli_verify_changed_certificate;
instance->VerifyCertificateEx = client_cli_verify_certificate_ex;
instance->VerifyChangedCertificateEx = client_cli_verify_changed_certificate_ex;
instance->LogonErrorInfo = xf_logon_error_info;
PubSub_SubscribeTerminate(context->pubSub,
xf_TerminateEventHandler);
@ -1884,7 +1896,7 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
xfc->_NET_WM_WINDOW_TYPE_POPUP = XInternAtom(xfc->display,
"_NET_WM_WINDOW_TYPE_POPUP", False);
xfc->_NET_WM_WINDOW_TYPE_POPUP_MENU = XInternAtom(xfc->display,
"_NET_WM_WINDOW_TYPE_POPUP_MENU", False);
"_NET_WM_WINDOW_TYPE_POPUP_MENU", False);
xfc->_NET_WM_WINDOW_TYPE_UTILITY = XInternAtom(xfc->display,
"_NET_WM_WINDOW_TYPE_UTILITY", False);
xfc->_NET_WM_WINDOW_TYPE_DROPDOWN_MENU = XInternAtom(xfc->display,

View File

@ -266,8 +266,7 @@ static CLIPRDR_FORMAT* xf_cliprdr_get_server_format_by_atom(
static UINT xf_cliprdr_send_data_request(xfClipboard* clipboard,
UINT32 formatId)
{
CLIPRDR_FORMAT_DATA_REQUEST request;
ZeroMemory(&request, sizeof(CLIPRDR_FORMAT_DATA_REQUEST));
CLIPRDR_FORMAT_DATA_REQUEST request = { 0 };
request.requestedFormatId = formatId;
return clipboard->context->ClientFormatDataRequest(clipboard->context,
&request);
@ -281,8 +280,7 @@ static UINT xf_cliprdr_send_data_request(xfClipboard* clipboard,
static UINT xf_cliprdr_send_data_response(xfClipboard* clipboard, BYTE* data,
int size)
{
CLIPRDR_FORMAT_DATA_RESPONSE response;
ZeroMemory(&response, sizeof(CLIPRDR_FORMAT_DATA_RESPONSE));
CLIPRDR_FORMAT_DATA_RESPONSE response = { 0 };
response.msgFlags = (data) ? CB_RESPONSE_OK : CB_RESPONSE_FAIL;
response.dataLen = size;
response.requestedFormatData = data;
@ -545,9 +543,8 @@ static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard)
{
UINT32 numFormats = 0;
CLIPRDR_FORMAT* formats = NULL;
CLIPRDR_FORMAT_LIST formatList;
CLIPRDR_FORMAT_LIST formatList = { 0 };
formats = xf_cliprdr_get_client_formats(clipboard, &numFormats);
ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST));
formatList.msgFlags = CB_RESPONSE_OK;
formatList.numFormats = numFormats;
formatList.formats = formats;
@ -1096,10 +1093,9 @@ static UINT xf_cliprdr_send_client_format_list(xfClipboard* clipboard)
{
UINT32 i, numFormats;
CLIPRDR_FORMAT* formats = NULL;
CLIPRDR_FORMAT_LIST formatList;
CLIPRDR_FORMAT_LIST formatList = { 0 };
xfContext* xfc = clipboard->xfc;
UINT ret;
ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST));
numFormats = clipboard->numClientFormats;
if (numFormats)
@ -1155,7 +1151,7 @@ static UINT xf_cliprdr_send_client_format_list_response(xfClipboard* clipboard,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT xf_cliprdr_monitor_ready(CliprdrClientContext* context,
CLIPRDR_MONITOR_READY* monitorReady)
const CLIPRDR_MONITOR_READY* monitorReady)
{
xfClipboard* clipboard = (xfClipboard*) context->custom;
UINT ret;
@ -1176,7 +1172,7 @@ static UINT xf_cliprdr_monitor_ready(CliprdrClientContext* context,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT xf_cliprdr_server_capabilities(CliprdrClientContext* context,
CLIPRDR_CAPABILITIES* capabilities)
const CLIPRDR_CAPABILITIES* capabilities)
{
UINT32 i;
const CLIPRDR_CAPABILITY_SET* caps;
@ -1211,7 +1207,7 @@ static UINT xf_cliprdr_server_capabilities(CliprdrClientContext* context,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context,
CLIPRDR_FORMAT_LIST* formatList)
const CLIPRDR_FORMAT_LIST* formatList)
{
UINT32 i;
int j;
@ -1301,7 +1297,7 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT xf_cliprdr_server_format_list_response(CliprdrClientContext*
context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
context, const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse)
{
//xfClipboard* clipboard = (xfClipboard*) context->custom;
return CHANNEL_RC_OK;
@ -1313,7 +1309,7 @@ static UINT xf_cliprdr_server_format_list_response(CliprdrClientContext*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT xf_cliprdr_server_format_data_request(CliprdrClientContext* context,
CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
{
BOOL rawTransfer;
xfCliprdrFormat* format = NULL;
@ -1348,7 +1344,7 @@ static UINT xf_cliprdr_server_format_data_request(CliprdrClientContext* context,
* @return 0 on success, otherwise a Win32 error code
*/
static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext*
context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
context, const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
{
BOOL bSuccess;
BYTE* pDstData;
@ -1477,8 +1473,7 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext*
static UINT xf_cliprdr_server_file_size_request(xfClipboard* clipboard,
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
wClipboardFileSizeRequest request;
ZeroMemory(&request, sizeof(request));
wClipboardFileSizeRequest request = { 0 };
request.streamId = fileContentsRequest->streamId;
request.listIndex = fileContentsRequest->listIndex;
@ -1494,8 +1489,7 @@ static UINT xf_cliprdr_server_file_size_request(xfClipboard* clipboard,
static UINT xf_cliprdr_server_file_range_request(xfClipboard* clipboard,
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
wClipboardFileRangeRequest request;
ZeroMemory(&request, sizeof(request));
wClipboardFileRangeRequest request = { 0 };
request.streamId = fileContentsRequest->streamId;
request.listIndex = fileContentsRequest->listIndex;
request.nPositionLow = fileContentsRequest->nPositionLow;
@ -1507,8 +1501,7 @@ static UINT xf_cliprdr_server_file_range_request(xfClipboard* clipboard,
static UINT xf_cliprdr_send_file_contents_failure(CliprdrClientContext* context,
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response;
ZeroMemory(&response, sizeof(response));
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
response.msgFlags = CB_RESPONSE_FAIL;
response.streamId = fileContentsRequest->streamId;
response.dwFlags = fileContentsRequest->dwFlags;
@ -1516,7 +1509,7 @@ static UINT xf_cliprdr_send_file_contents_failure(CliprdrClientContext* context,
}
static UINT xf_cliprdr_server_file_contents_request(CliprdrClientContext* context,
CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest)
{
UINT error = NO_ERROR;
xfClipboard* clipboard = context->custom;
@ -1550,9 +1543,8 @@ static UINT xf_cliprdr_server_file_contents_request(CliprdrClientContext* contex
static UINT xf_cliprdr_clipboard_file_size_success(wClipboardDelegate* delegate,
const wClipboardFileSizeRequest* request, UINT64 fileSize)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response;
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
xfClipboard* clipboard = delegate->custom;
ZeroMemory(&response, sizeof(response));
response.msgFlags = CB_RESPONSE_OK;
response.streamId = request->streamId;
response.dwFlags = FILECONTENTS_SIZE;
@ -1564,9 +1556,8 @@ static UINT xf_cliprdr_clipboard_file_size_success(wClipboardDelegate* delegate,
static UINT xf_cliprdr_clipboard_file_size_failure(wClipboardDelegate* delegate,
const wClipboardFileSizeRequest* request, UINT errorCode)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response;
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
xfClipboard* clipboard = delegate->custom;
ZeroMemory(&response, sizeof(response));
response.msgFlags = CB_RESPONSE_FAIL;
response.streamId = request->streamId;
response.dwFlags = FILECONTENTS_SIZE;
@ -1576,9 +1567,8 @@ static UINT xf_cliprdr_clipboard_file_size_failure(wClipboardDelegate* delegate,
static UINT xf_cliprdr_clipboard_file_range_success(wClipboardDelegate* delegate,
const wClipboardFileRangeRequest* request, const BYTE* data, UINT32 size)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response;
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
xfClipboard* clipboard = delegate->custom;
ZeroMemory(&response, sizeof(response));
response.msgFlags = CB_RESPONSE_OK;
response.streamId = request->streamId;
response.dwFlags = FILECONTENTS_RANGE;
@ -1590,9 +1580,8 @@ static UINT xf_cliprdr_clipboard_file_range_success(wClipboardDelegate* delegate
static UINT xf_cliprdr_clipboard_file_range_failure(wClipboardDelegate* delegate,
const wClipboardFileRangeRequest* request, UINT errorCode)
{
CLIPRDR_FILE_CONTENTS_RESPONSE response;
CLIPRDR_FILE_CONTENTS_RESPONSE response = { 0 };
xfClipboard* clipboard = delegate->custom;
ZeroMemory(&response, sizeof(response));
response.msgFlags = CB_RESPONSE_FAIL;
response.streamId = request->streamId;
response.dwFlags = FILECONTENTS_RANGE;

View File

@ -409,7 +409,7 @@ static UINT xf_DisplayControlCaps(DispClientContext* disp, UINT32 maxNumMonitors
if (settings->Fullscreen)
return CHANNEL_RC_OK;
WLog_DBG(TAG, "DisplayControlCapsPdu: setting the window as resizeable");
WLog_DBG(TAG, "DisplayControlCapsPdu: setting the window as resizable");
return xf_disp_set_window_resizable(xfDisp) ? CHANNEL_RC_OK : CHANNEL_RC_NO_MEMORY;
}

View File

@ -213,7 +213,7 @@ static BOOL xf_event_execute_action_script(xfContext* xfc, XEvent* event)
char buffer[1024] = { 0 };
char command[1024] = { 0 };
if (!xfc->actionScriptExists || !xfc->xevents)
if (!xfc->actionScriptExists || !xfc->xevents || !xfc->window)
return FALSE;
if (event->type > LASTEvent)
@ -367,79 +367,58 @@ static BOOL xf_event_MotionNotify(xfContext* xfc, XEvent* event, BOOL app)
if (xfc->use_xinput)
return TRUE;
if(xfc->floatbar && !(app))
xf_floatbar_set_root_y(xfc, event->xmotion.y);
if (xfc->window)
xf_floatbar_set_root_y(xfc->window->floatbar, event->xmotion.y);
return xf_generic_MotionNotify(xfc, event->xmotion.x, event->xmotion.y,
event->xmotion.state, event->xmotion.window, app);
}
BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button,
Window window, BOOL app)
BOOL xf_generic_ButtonEvent(xfContext* xfc, int x, int y, int button,
Window window, BOOL app, BOOL down)
{
int flags;
BOOL wheel;
BOOL extended;
UINT16 flags = 0;
rdpInput* input;
Window childWindow;
wheel = FALSE;
extended = FALSE;
input = xfc->context.input;
size_t i;
switch (button)
for (i = 0; i < ARRAYSIZE(xfc->button_map); i++)
{
case Button1:
case Button2:
case Button3:
flags = PTR_FLAGS_DOWN | xfc->button_map[button - BUTTON_BASE];
break;
const button_map* cur = &xfc->button_map[i];
case 4:
wheel = TRUE;
flags = PTR_FLAGS_WHEEL | 0x0078;
break;
case 5:
wheel = TRUE;
flags = PTR_FLAGS_WHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0078;
break;
case 8: /* back */
case 97: /* Xming */
extended = TRUE;
flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON1;
break;
case 9: /* forward */
case 112: /* Xming */
extended = TRUE;
flags = PTR_XFLAGS_DOWN | PTR_XFLAGS_BUTTON2;
break;
case 6: /* wheel left */
wheel = TRUE;
flags = PTR_FLAGS_HWHEEL | PTR_FLAGS_WHEEL_NEGATIVE | 0x0078;
break;
case 7: /* wheel right */
wheel = TRUE;
flags = PTR_FLAGS_HWHEEL | 0x0078;
break;
default:
x = 0;
y = 0;
flags = 0;
if (cur->button == button)
{
flags = cur->flags;
break;
}
}
input = xfc->context.input;
if (flags != 0)
{
if (wheel)
if (flags & (PTR_FLAGS_WHEEL | PTR_FLAGS_HWHEEL))
{
freerdp_input_send_mouse_event(input, flags, 0, 0);
if (down)
freerdp_input_send_mouse_event(input, flags, 0, 0);
}
else
{
BOOL extended = FALSE;
if (flags & (PTR_XFLAGS_BUTTON1 | PTR_XFLAGS_BUTTON2))
{
extended = TRUE;
if (down)
flags |= PTR_XFLAGS_DOWN;
}
else if (flags & (PTR_FLAGS_BUTTON1 | PTR_FLAGS_BUTTON2 | PTR_FLAGS_BUTTON3))
{
if (down)
flags |= PTR_FLAGS_DOWN;
}
if (app)
{
/* make sure window exists */
@ -468,80 +447,17 @@ static BOOL xf_event_ButtonPress(xfContext* xfc, XEvent* event, BOOL app)
if (xfc->use_xinput)
return TRUE;
return xf_generic_ButtonPress(xfc, event->xbutton.x, event->xbutton.y,
event->xbutton.button, event->xbutton.window, app);
return xf_generic_ButtonEvent(xfc, event->xbutton.x, event->xbutton.y,
event->xbutton.button, event->xbutton.window, app, TRUE);
}
BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button,
Window window, BOOL app)
{
int flags = 0;
BOOL extended = FALSE;
rdpInput* input;
Window childWindow;
if (!xfc || !xfc->context.input)
return FALSE;
input = xfc->context.input;
switch (button)
{
case Button1:
case Button2:
case Button3:
flags = xfc->button_map[button - BUTTON_BASE];
break;
case 6:
case 8:
case 97:
extended = TRUE;
flags = PTR_XFLAGS_BUTTON1;
break;
case 7:
case 9:
case 112:
extended = TRUE;
flags = PTR_XFLAGS_BUTTON2;
break;
default:
flags = 0;
break;
}
if (flags != 0)
{
if (app)
{
/* make sure window exists */
if (!xf_AppWindowFromX11Window(xfc, window))
return TRUE;
/* Translate to desktop coordinates */
XTranslateCoordinates(xfc->display, window,
RootWindowOfScreen(xfc->screen),
x, y, &x, &y, &childWindow);
}
xf_event_adjust_coordinates(xfc, &x, &y);
if (extended)
freerdp_input_send_extended_mouse_event(input, flags, x, y);
else
freerdp_input_send_mouse_event(input, flags, x, y);
}
return TRUE;
}
static BOOL xf_event_ButtonRelease(xfContext* xfc, XEvent* event, BOOL app)
{
if (xfc->use_xinput)
return TRUE;
return xf_generic_ButtonRelease(xfc, event->xbutton.x, event->xbutton.y,
event->xbutton.button, event->xbutton.window, app);
return xf_generic_ButtonEvent(xfc, event->xbutton.x, event->xbutton.y,
event->xbutton.button, event->xbutton.window, app, FALSE);
}
static BOOL xf_event_KeyPress(xfContext* xfc, XEvent* event, BOOL app)
{
@ -561,6 +477,9 @@ static BOOL xf_event_KeyRelease(xfContext* xfc, XEvent* event, BOOL app)
}
static BOOL xf_event_FocusIn(xfContext* xfc, XEvent* event, BOOL app)
{
if (!xfc->window)
return FALSE;
if (event->xfocus.mode == NotifyGrab)
return TRUE;
@ -644,6 +563,9 @@ static BOOL xf_event_ClientMessage(xfContext* xfc, XEvent* event, BOOL app)
}
static BOOL xf_event_EnterNotify(xfContext* xfc, XEvent* event, BOOL app)
{
if (!xfc->window)
return FALSE;
if (!app)
{
xfc->mouse_active = TRUE;
@ -685,7 +607,12 @@ static BOOL xf_event_ConfigureNotify(xfContext* xfc, XEvent* event, BOOL app)
{
Window childWindow;
xfAppWindow* appWindow;
rdpSettings* settings = xfc->context.settings;
rdpSettings* settings;
if (!xfc->window)
return FALSE;
settings = xfc->context.settings;
if (!app)
{
@ -900,7 +827,7 @@ static BOOL xf_event_PropertyNotify(xfContext* xfc, XEvent* event, BOOL app)
xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_MINIMIZE);
}
else if (!minimized && !maxVert && !maxHorz
&& (appWindow->rail_state != WINDOW_SHOW))
&& (appWindow->rail_state != WINDOW_SHOW) && (appWindow->rail_state != WINDOW_HIDE))
{
appWindow->rail_state = WINDOW_SHOW;
xf_rail_send_client_system_command(xfc, appWindow->windowId, SC_RESTORE);
@ -1018,10 +945,13 @@ BOOL xf_event_process(freerdp* instance, XEvent* event)
}
}
if (xfc->floatbar && xf_floatbar_check_event(xfc, event))
if (xfc->window)
{
xf_floatbar_event_process(xfc, event);
return TRUE;
if (xf_floatbar_check_event(xfc->window->floatbar, event))
{
xf_floatbar_event_process(xfc->window->floatbar, event);
return TRUE;
}
}
xf_event_execute_action_script(xfc, event);

View File

@ -29,12 +29,14 @@ BOOL xf_event_action_script_init(xfContext* xfc);
void xf_event_action_script_free(xfContext* xfc);
BOOL xf_event_process(freerdp* instance, XEvent* event);
void xf_event_SendClientEvent(xfContext* xfc, xfWindow* window, Atom atom, unsigned int numArgs, ...);
void xf_event_SendClientEvent(xfContext* xfc, xfWindow* window, Atom atom, unsigned int numArgs,
...);
void xf_event_adjust_coordinates(xfContext* xfc, int* x, int *y);
void xf_event_adjust_coordinates(xfContext* xfc, int* x, int* y);
BOOL xf_generic_MotionNotify(xfContext* xfc, int x, int y, int state, Window window, BOOL app);
BOOL xf_generic_ButtonPress(xfContext* xfc, int x, int y, int button, Window window, BOOL app);
BOOL xf_generic_ButtonRelease(xfContext* xfc, int x, int y, int button, Window window, BOOL app);
BOOL xf_generic_ButtonEvent(xfContext* xfc, int x, int y, int button, Window window, BOOL app,
BOOL down);
#endif /* FREERDP_CLIENT_X11_EVENT_H */

View File

@ -57,6 +57,8 @@
#define XF_FLOATBAR_BUTTON_MINIMIZE 3
#define XF_FLOATBAR_BUTTON_LOCKED 4
typedef BOOL(*OnClick)(xfFloatbar*);
typedef struct xf_floatbar_button xfFloatbarButton;
struct xf_floatbar
@ -71,6 +73,12 @@ struct xf_floatbar
bool locked;
xfFloatbarButton* buttons[4];
Window handle;
BOOL hasCursor;
xfContext* xfc;
DWORD flags;
BOOL created;
Window root_window;
char* title;
};
struct xf_floatbar_button
@ -84,43 +92,70 @@ struct xf_floatbar_button
Window handle;
};
static void xf_floatbar_button_onclick_close(xfContext* xfc)
static xfFloatbarButton* xf_floatbar_new_button(xfFloatbar* floatbar, int type);
static BOOL xf_floatbar_button_onclick_close(xfFloatbar* floatbar)
{
ExitProcess(EXIT_SUCCESS);
if (!floatbar)
return FALSE;
return freerdp_abort_connect(floatbar->xfc->context.instance);
}
static void xf_floatbar_button_onclick_minimize(xfContext* xfc)
static BOOL xf_floatbar_button_onclick_minimize(xfFloatbar* floatbar)
{
xfContext* xfc;
if (!floatbar || !floatbar->xfc)
return FALSE;
xfc = floatbar->xfc;
xf_SetWindowMinimized(xfc, xfc->window);
return TRUE;
}
static void xf_floatbar_button_onclick_restore(xfContext* xfc)
static BOOL xf_floatbar_button_onclick_restore(xfFloatbar* floatbar)
{
xf_toggle_fullscreen(xfc);
if (!floatbar)
return FALSE;
xf_toggle_fullscreen(floatbar->xfc);
return TRUE;
}
static void xf_floatbar_button_onclick_locked(xfContext* xfc)
static BOOL xf_floatbar_button_onclick_locked(xfFloatbar* floatbar)
{
xfFloatbar* floatbar;
floatbar = xfc->window->floatbar;
if (!floatbar)
return FALSE;
floatbar->locked = (floatbar->locked) ? FALSE : TRUE;
return xf_floatbar_hide_and_show(floatbar);
}
void xf_floatbar_set_root_y(xfContext* xfc, int y)
BOOL xf_floatbar_set_root_y(xfFloatbar* floatbar, int y)
{
xfFloatbar* floatbar;
floatbar = xfc->window->floatbar;
if (!floatbar)
return FALSE;
floatbar->last_motion_y_root = y;
return TRUE;
}
void xf_floatbar_hide_and_show(xfContext* xfc)
BOOL xf_floatbar_hide_and_show(xfFloatbar* floatbar)
{
xfFloatbar* floatbar;
floatbar = xfc->window->floatbar;
xfContext* xfc;
if (!floatbar || !floatbar->xfc)
return FALSE;
if (!floatbar->created)
return TRUE;
xfc = floatbar->xfc;
if (!floatbar->locked)
{
if ((floatbar->mode == 0) && (floatbar->last_motion_y_root > 10) &&
if ((floatbar->mode == XF_FLOATBAR_MODE_NONE) && (floatbar->last_motion_y_root > 10) &&
(floatbar->y > (FLOATBAR_HEIGHT * -1)))
{
floatbar->y = floatbar->y - 1;
@ -132,16 +167,70 @@ void xf_floatbar_hide_and_show(xfContext* xfc)
XMoveWindow(xfc->display, floatbar->handle, floatbar->x, floatbar->y);
}
}
return TRUE;
}
void xf_floatbar_toggle_visibility(xfContext* xfc, bool visible)
static BOOL create_floatbar(xfFloatbar* floatbar)
{
xfContext* xfc;
Status status;
XWindowAttributes attr;
if (floatbar->created)
return TRUE;
xfc = floatbar->xfc;
status = XGetWindowAttributes(xfc->display, floatbar->root_window, &attr);
floatbar->x = attr.x + attr.width / 2 - FLOATBAR_DEFAULT_WIDTH / 2;
floatbar->y = 0;
if (((floatbar->flags & 0x0004) == 0) && !floatbar->locked)
floatbar->y = -FLOATBAR_HEIGHT + 1;
floatbar->handle = XCreateWindow(xfc->display, floatbar->root_window,
floatbar->x, 0, FLOATBAR_DEFAULT_WIDTH,
FLOATBAR_HEIGHT, 0,
CopyFromParent, InputOutput, CopyFromParent, 0, NULL);
floatbar->width = FLOATBAR_DEFAULT_WIDTH;
floatbar->height = FLOATBAR_HEIGHT;
floatbar->mode = XF_FLOATBAR_MODE_NONE;
floatbar->buttons[0] = xf_floatbar_new_button(floatbar, XF_FLOATBAR_BUTTON_CLOSE);
floatbar->buttons[1] = xf_floatbar_new_button(floatbar, XF_FLOATBAR_BUTTON_RESTORE);
floatbar->buttons[2] = xf_floatbar_new_button(floatbar, XF_FLOATBAR_BUTTON_MINIMIZE);
floatbar->buttons[3] = xf_floatbar_new_button(floatbar, XF_FLOATBAR_BUTTON_LOCKED);
XSelectInput(xfc->display, floatbar->handle, ExposureMask | ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | StructureNotifyMask |
PropertyChangeMask);
floatbar->created = TRUE;
return TRUE;
}
BOOL xf_floatbar_toggle_fullscreen(xfFloatbar* floatbar, bool fullscreen)
{
xfFloatbar* floatbar;
int i, size;
floatbar = xfc->window->floatbar;
bool visible = False;
xfContext* xfc;
if (!floatbar || !floatbar->xfc)
return FALSE;
xfc = floatbar->xfc;
/* Only visible if enabled */
if (floatbar->flags & 0x0001)
{
/* Visible if fullscreen and flag visible in fullscreen mode */
visible |= ((floatbar->flags & 0x0010) != 0) && fullscreen;
/* Visible if window and flag visible in window mode */
visible |= ((floatbar->flags & 0x0020) != 0) && !fullscreen;
}
if (visible)
{
if (!create_floatbar(floatbar))
return FALSE;
XMapWindow(xfc->display, floatbar->handle);
size = ARRAYSIZE(floatbar->buttons);
@ -149,15 +238,23 @@ void xf_floatbar_toggle_visibility(xfContext* xfc, bool visible)
{
XMapWindow(xfc->display, floatbar->buttons[i]->handle);
}
/* If default is hidden (and not sticky) don't show on fullscreen state changes */
if (((floatbar->flags & 0x0004) == 0) && !floatbar->locked)
floatbar->y = -FLOATBAR_HEIGHT + 1;
xf_floatbar_hide_and_show(floatbar);
}
else
else if (floatbar->created)
{
XUnmapSubwindows(xfc->display, floatbar->handle);
XUnmapWindow(xfc->display, floatbar->handle);
}
return TRUE;
}
static xfFloatbarButton* xf_floatbar_new_button(xfContext* xfc, xfFloatbar* floatbar, int type)
xfFloatbarButton* xf_floatbar_new_button(xfFloatbar* floatbar, int type)
{
xfFloatbarButton* button;
button = (xfFloatbarButton*) calloc(1, sizeof(xfFloatbarButton));
@ -191,74 +288,74 @@ static xfFloatbarButton* xf_floatbar_new_button(xfContext* xfc, xfFloatbar* floa
button->y = 0;
button->focus = FALSE;
button->handle = XCreateWindow(xfc->display, floatbar->handle, button->x, 0, FLOATBAR_BUTTON_WIDTH,
button->handle = XCreateWindow(floatbar->xfc->display, floatbar->handle, button->x, 0,
FLOATBAR_BUTTON_WIDTH,
FLOATBAR_BUTTON_WIDTH, 0, CopyFromParent, InputOutput, CopyFromParent, 0, NULL);
XSelectInput(xfc->display, button->handle, ExposureMask | ButtonPressMask | ButtonReleaseMask |
XSelectInput(floatbar->xfc->display, button->handle,
ExposureMask | ButtonPressMask | ButtonReleaseMask |
FocusChangeMask | LeaveWindowMask | EnterWindowMask | StructureNotifyMask);
return button;
}
xfFloatbar* xf_floatbar_new(xfContext* xfc, Window window)
xfFloatbar* xf_floatbar_new(xfContext* xfc, Window window, const char* name, DWORD flags)
{
xfFloatbar* floatbar;
XWindowAttributes attr;
int i, width;
/* Floatbar not enabled */
if ((flags & 0x0001) == 0)
return NULL;
if (!xfc)
return NULL;
/* Force disable with remote app */
if (xfc->remote_app)
return NULL;
floatbar = (xfFloatbar*) calloc(1, sizeof(xfFloatbar));
floatbar->locked = TRUE;
XGetWindowAttributes(xfc->display, window, &attr);
for (i = 0; i < xfc->vscreen.nmonitors; i++)
{
if (attr.x >= xfc->vscreen.monitors[i].area.left && attr.x <= xfc->vscreen.monitors[i].area.right)
{
width = xfc->vscreen.monitors[i].area.right - xfc->vscreen.monitors[i].area.left;
floatbar->x = width / 2 + xfc->vscreen.monitors[i].area.left - FLOATBAR_DEFAULT_WIDTH / 2;
}
}
if (!floatbar)
return NULL;
floatbar->y = 0;
floatbar->handle = XCreateWindow(xfc->display, window, floatbar->x, 0, FLOATBAR_DEFAULT_WIDTH,
FLOATBAR_HEIGHT, 0,
CopyFromParent, InputOutput, CopyFromParent, 0, NULL);
floatbar->width = FLOATBAR_DEFAULT_WIDTH;
floatbar->height = FLOATBAR_HEIGHT;
floatbar->mode = XF_FLOATBAR_MODE_NONE;
floatbar->buttons[0] = xf_floatbar_new_button(xfc, floatbar, XF_FLOATBAR_BUTTON_CLOSE);
floatbar->buttons[1] = xf_floatbar_new_button(xfc, floatbar, XF_FLOATBAR_BUTTON_RESTORE);
floatbar->buttons[2] = xf_floatbar_new_button(xfc, floatbar, XF_FLOATBAR_BUTTON_MINIMIZE);
floatbar->buttons[3] = xf_floatbar_new_button(xfc, floatbar, XF_FLOATBAR_BUTTON_LOCKED);
XSelectInput(xfc->display, floatbar->handle, ExposureMask | ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | FocusChangeMask | LeaveWindowMask | EnterWindowMask | StructureNotifyMask |
PropertyChangeMask);
floatbar->title = _strdup(name);
if (!floatbar->title)
goto fail;
floatbar->root_window = window;
floatbar->flags = flags;
floatbar->xfc = xfc;
floatbar->locked = flags & 0x0002;
xf_floatbar_toggle_fullscreen(floatbar, FALSE);
return floatbar;
fail:
xf_floatbar_free(floatbar);
return NULL;
}
static unsigned long xf_floatbar_get_color(xfContext* xfc, char* rgb_value)
static unsigned long xf_floatbar_get_color(xfFloatbar* floatbar, char* rgb_value)
{
Colormap cmap;
XColor color;
cmap = DefaultColormap(xfc->display, XDefaultScreen(xfc->display));
XParseColor(xfc->display, cmap, rgb_value, &color);
XAllocColor(xfc->display, cmap, &color);
XFreeColormap(xfc->display, cmap);
Display* display = floatbar->xfc->display;
cmap = DefaultColormap(display, XDefaultScreen(display));
XParseColor(display, cmap, rgb_value, &color);
XAllocColor(display, cmap, &color);
XFreeColormap(display, cmap);
return color.pixel;
}
static void xf_floatbar_event_expose(xfContext* xfc, XEvent* event)
static void xf_floatbar_event_expose(xfFloatbar* floatbar, XEvent* event)
{
GC gc, shape_gc;
Pixmap pmap;
XPoint shape[5], border[5];
xfFloatbar* floatbar;
int len;
floatbar = xfc->window->floatbar;
Display* display = floatbar->xfc->display;
/* create the pixmap that we'll use for shaping the window */
pmap = XCreatePixmap(xfc->display, floatbar->handle, floatbar->width, floatbar->height, 1);
gc = XCreateGC(xfc->display, floatbar->handle, 0, 0);
shape_gc = XCreateGC(xfc->display, pmap, 0, 0);
pmap = XCreatePixmap(display, floatbar->handle, floatbar->width, floatbar->height, 1);
gc = XCreateGC(display, floatbar->handle, 0, 0);
shape_gc = XCreateGC(display, pmap, 0, 0);
/* points for drawing the floatbar */
shape[0].x = 0;
shape[0].y = 0;
@ -282,34 +379,32 @@ static void xf_floatbar_event_expose(xfContext* xfc, XEvent* event)
border[4].x = border[0].x;
border[4].y = border[0].y;
/* Fill all pixels with 0 */
XSetForeground(xfc->display, shape_gc, 0);
XFillRectangle(xfc->display, pmap, shape_gc, 0, 0, floatbar->width,
XSetForeground(display, shape_gc, 0);
XFillRectangle(display, pmap, shape_gc, 0, 0, floatbar->width,
floatbar->height);
/* Fill all pixels which should be shown with 1 */
XSetForeground(xfc->display, shape_gc, 1);
XFillPolygon(xfc->display, pmap, shape_gc, shape, 5, 0, CoordModeOrigin);
XShapeCombineMask(xfc->display, floatbar->handle, ShapeBounding, 0, 0, pmap, ShapeSet);
XSetForeground(display, shape_gc, 1);
XFillPolygon(display, pmap, shape_gc, shape, 5, 0, CoordModeOrigin);
XShapeCombineMask(display, floatbar->handle, ShapeBounding, 0, 0, pmap, ShapeSet);
/* draw the float bar */
XSetForeground(xfc->display, gc, xf_floatbar_get_color(xfc, FLOATBAR_COLOR_BACKGROUND));
XFillPolygon(xfc->display, floatbar->handle, gc, shape, 4, 0, CoordModeOrigin);
XSetForeground(display, gc, xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_BACKGROUND));
XFillPolygon(display, floatbar->handle, gc, shape, 4, 0, CoordModeOrigin);
/* draw an border for the floatbar */
XSetForeground(xfc->display, gc, xf_floatbar_get_color(xfc, FLOATBAR_COLOR_BORDER));
XDrawLines(xfc->display, floatbar->handle, gc, border, 5, CoordModeOrigin);
XSetForeground(display, gc, xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_BORDER));
XDrawLines(display, floatbar->handle, gc, border, 5, CoordModeOrigin);
/* draw the host name connected to */
len = strlen(xfc->context.settings->ServerHostname);
XSetForeground(xfc->display, gc, xf_floatbar_get_color(xfc, FLOATBAR_COLOR_FOREGROUND));
XDrawString(xfc->display, floatbar->handle, gc, floatbar->width / 2 - len * 2, 15,
xfc->context.settings->ServerHostname, len);
XFreeGC(xfc->display, gc);
XFreeGC(xfc->display, shape_gc);
len = strlen(floatbar->title);
XSetForeground(display, gc, xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_FOREGROUND));
XDrawString(display, floatbar->handle, gc, floatbar->width / 2 - len * 2, 15,
floatbar->title, len);
XFreeGC(display, gc);
XFreeGC(display, shape_gc);
}
static xfFloatbarButton* xf_floatbar_get_button(xfContext* xfc, XEvent* event)
static xfFloatbarButton* xf_floatbar_get_button(xfFloatbar* floatbar, XEvent* event)
{
xfFloatbar* floatbar;
int i, size;
size = ARRAYSIZE(floatbar->buttons);
floatbar = xfc->window->floatbar;
for (i = 0; i < size; i++)
{
@ -322,12 +417,11 @@ static xfFloatbarButton* xf_floatbar_get_button(xfContext* xfc, XEvent* event)
return NULL;
}
static void xf_floatbar_button_update_positon(xfContext* xfc, XEvent* event)
static void xf_floatbar_button_update_positon(xfFloatbar* floatbar, XEvent* event)
{
xfFloatbar* floatbar;
xfFloatbarButton* button;
int i, size;
floatbar = xfc->window->floatbar;
xfContext* xfc = floatbar->xfc;
size = ARRAYSIZE(floatbar->buttons);
for (i = 0; i < size; i++)
@ -353,18 +447,17 @@ static void xf_floatbar_button_update_positon(xfContext* xfc, XEvent* event)
}
XMoveWindow(xfc->display, button->handle, button->x, button->y);
xf_floatbar_event_expose(xfc, event);
xf_floatbar_event_expose(floatbar, event);
}
}
static void xf_floatbar_button_event_expose(xfContext* xfc, XEvent* event)
static void xf_floatbar_button_event_expose(xfFloatbar* floatbar, XEvent* event)
{
xfFloatbar* floatbar;
xfFloatbarButton* button;
xfFloatbarButton* button = xf_floatbar_get_button(floatbar, event);
static unsigned char* bits;
GC gc;
Pixmap pattern;
button = xf_floatbar_get_button(xfc, event);
xfContext* xfc = floatbar->xfc;
if (!button)
return;
@ -402,43 +495,39 @@ static void xf_floatbar_button_event_expose(xfContext* xfc, XEvent* event)
FLOATBAR_BUTTON_WIDTH, FLOATBAR_BUTTON_WIDTH);
if (!(button->focus))
XSetForeground(xfc->display, gc, xf_floatbar_get_color(xfc, FLOATBAR_COLOR_BACKGROUND));
XSetForeground(xfc->display, gc, xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_BACKGROUND));
else
XSetForeground(xfc->display, gc, xf_floatbar_get_color(xfc, FLOATBAR_COLOR_BORDER));
XSetForeground(xfc->display, gc, xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_BORDER));
XSetBackground(xfc->display, gc, xf_floatbar_get_color(xfc, FLOATBAR_COLOR_FOREGROUND));
XSetBackground(xfc->display, gc, xf_floatbar_get_color(floatbar, FLOATBAR_COLOR_FOREGROUND));
XCopyPlane(xfc->display, pattern, button->handle, gc, 0, 0, FLOATBAR_BUTTON_WIDTH,
FLOATBAR_BUTTON_WIDTH, 0, 0, 1);
XFreePixmap(xfc->display, pattern);
XFreeGC(xfc->display, gc);
}
static void xf_floatbar_button_event_buttonpress(xfContext* xfc, XEvent* event)
static void xf_floatbar_button_event_buttonpress(xfFloatbar* floatbar, XEvent* event)
{
xfFloatbarButton* button;
button = xf_floatbar_get_button(xfc, event);
xfFloatbarButton* button = xf_floatbar_get_button(floatbar, event);
if (button)
button->clicked = TRUE;
}
static void xf_floatbar_button_event_buttonrelease(xfContext* xfc, XEvent* event)
static void xf_floatbar_button_event_buttonrelease(xfFloatbar* floatbar, XEvent* event)
{
xfFloatbarButton* button;
button = xf_floatbar_get_button(xfc, event);
button = xf_floatbar_get_button(floatbar, event);
if (button)
{
if (button->clicked)
button->onclick(xfc);
button->onclick(floatbar);
}
}
static void xf_floatbar_event_buttonpress(xfContext* xfc, XEvent* event)
static void xf_floatbar_event_buttonpress(xfFloatbar* floatbar, XEvent* event)
{
xfFloatbar* floatbar;
floatbar = xfc->window->floatbar;
switch (event->xbutton.button)
{
case Button1:
@ -456,12 +545,12 @@ static void xf_floatbar_event_buttonpress(xfContext* xfc, XEvent* event)
}
}
static void xf_floatbar_event_buttonrelease(xfContext* xfc, XEvent* event)
static void xf_floatbar_event_buttonrelease(xfFloatbar* floatbar, XEvent* event)
{
switch (event->xbutton.button)
{
case Button1:
xfc->window->floatbar->mode = XF_FLOATBAR_MODE_NONE;
floatbar->mode = XF_FLOATBAR_MODE_NONE;
break;
default:
@ -469,11 +558,10 @@ static void xf_floatbar_event_buttonrelease(xfContext* xfc, XEvent* event)
}
}
static void xf_floatbar_resize(xfContext* xfc, XEvent* event)
static void xf_floatbar_resize(xfFloatbar* floatbar, XEvent* event)
{
xfFloatbar* floatbar;
floatbar = xfc->window->floatbar;
int x, width, movement;
xfContext* xfc = floatbar->xfc;
/* calculate movement which happened on the root window */
movement = event->xmotion.x_root - floatbar->last_motion_x_root;
@ -498,11 +586,10 @@ static void xf_floatbar_resize(xfContext* xfc, XEvent* event)
}
}
static void xf_floatbar_dragging(xfContext* xfc, XEvent* event)
static void xf_floatbar_dragging(xfFloatbar* floatbar, XEvent* event)
{
xfFloatbar* floatbar;
floatbar = xfc->window->floatbar;
int x, movement;
xfContext* xfc = floatbar->xfc;
/* calculate movement and new x position */
movement = event->xmotion.x_root - floatbar->last_motion_x_root;
x = floatbar->x + movement;
@ -518,78 +605,82 @@ static void xf_floatbar_dragging(xfContext* xfc, XEvent* event)
floatbar->x = x;
}
static void xf_floatbar_event_motionnotify(xfContext* xfc, XEvent* event)
static void xf_floatbar_event_motionnotify(xfFloatbar* floatbar, XEvent* event)
{
int mode;
xfFloatbar* floatbar;
Cursor cursor;
mode = xfc->window->floatbar->mode;
floatbar = xfc->window->floatbar;
xfContext* xfc = floatbar->xfc;
mode = floatbar->mode;
cursor = XCreateFontCursor(xfc->display, XC_arrow);
if ((event->xmotion.state & Button1Mask) && (mode > XF_FLOATBAR_MODE_DRAGGING))
{
xf_floatbar_resize(xfc, event);
xf_floatbar_resize(floatbar, event);
}
else if ((event->xmotion.state & Button1Mask) && (mode == XF_FLOATBAR_MODE_DRAGGING))
{
xf_floatbar_dragging(xfc, event);
xf_floatbar_dragging(floatbar, event);
}
else
{
if (event->xmotion.x <= FLOATBAR_BORDER ||
event->xmotion.x >= xfc->window->floatbar->width - FLOATBAR_BORDER)
event->xmotion.x >= floatbar->width - FLOATBAR_BORDER)
cursor = XCreateFontCursor(xfc->display, XC_sb_h_double_arrow);
}
XDefineCursor(xfc->display, xfc->window->handle, cursor);
XFreeCursor(xfc->display, cursor);
xfc->window->floatbar->last_motion_x_root = event->xmotion.x_root;
floatbar->last_motion_x_root = event->xmotion.x_root;
}
static void xf_floatbar_button_event_focusin(xfContext* xfc, XEvent* event)
static void xf_floatbar_button_event_focusin(xfFloatbar* floatbar, XEvent* event)
{
xfFloatbarButton* button;
button = xf_floatbar_get_button(xfc, event);
button = xf_floatbar_get_button(floatbar, event);
if (button)
{
button->focus = TRUE;
xf_floatbar_button_event_expose(xfc, event);
xf_floatbar_button_event_expose(floatbar, event);
}
}
static void xf_floatbar_button_event_focusout(xfContext* xfc, XEvent* event)
static void xf_floatbar_button_event_focusout(xfFloatbar* floatbar, XEvent* event)
{
xfFloatbarButton* button;
button = xf_floatbar_get_button(xfc, event);
button = xf_floatbar_get_button(floatbar, event);
if (button)
{
button->focus = FALSE;
button->clicked = FALSE;
xf_floatbar_button_event_expose(xfc, event);
xf_floatbar_button_event_expose(floatbar, event);
}
}
static void xf_floatbar_event_focusout(xfContext* xfc, XEvent* event)
static void xf_floatbar_event_focusout(xfFloatbar* floatbar, XEvent* event)
{
Cursor cursor;
cursor = XCreateFontCursor(xfc->display, XC_arrow);
XDefineCursor(xfc->display, xfc->window->handle, cursor);
XFreeCursor(xfc->display, cursor);
xfContext* xfc = floatbar->xfc;
if (xfc->pointer)
{
XDefineCursor(xfc->display, xfc->window->handle, xfc->pointer->cursor);
}
}
BOOL xf_floatbar_check_event(xfContext* xfc, XEvent* event)
BOOL xf_floatbar_check_event(xfFloatbar* floatbar, XEvent* event)
{
xfFloatbar* floatbar;
xfFloatbarButton* button;
size_t i, size;
xfContext* xfc;
if (!xfc || !event || !xfc->window)
if (!floatbar || !floatbar->xfc || !event)
return FALSE;
floatbar = xfc->window->floatbar;
if (!floatbar->created)
return FALSE;
xfc = floatbar->xfc;
if (event->xany.window == floatbar->handle)
return TRUE;
@ -607,70 +698,69 @@ BOOL xf_floatbar_check_event(xfContext* xfc, XEvent* event)
return FALSE;
}
BOOL xf_floatbar_event_process(xfContext* xfc, XEvent* event)
BOOL xf_floatbar_event_process(xfFloatbar* floatbar, XEvent* event)
{
xfFloatbar* floatbar;
if (!xfc || !xfc->window || !event)
if (!floatbar || !floatbar->xfc || !event)
return FALSE;
floatbar = xfc->window->floatbar;
if (!floatbar->created)
return FALSE;
switch (event->type)
{
case Expose:
if (event->xany.window == floatbar->handle)
xf_floatbar_event_expose(xfc, event);
xf_floatbar_event_expose(floatbar, event);
else
xf_floatbar_button_event_expose(xfc, event);
xf_floatbar_button_event_expose(floatbar, event);
break;
case MotionNotify:
xf_floatbar_event_motionnotify(xfc, event);
xf_floatbar_event_motionnotify(floatbar, event);
break;
case ButtonPress:
if (event->xany.window == floatbar->handle)
xf_floatbar_event_buttonpress(xfc, event);
xf_floatbar_event_buttonpress(floatbar, event);
else
xf_floatbar_button_event_buttonpress(xfc, event);
xf_floatbar_button_event_buttonpress(floatbar, event);
break;
case ButtonRelease:
if (event->xany.window == floatbar->handle)
xf_floatbar_event_buttonrelease(xfc, event);
xf_floatbar_event_buttonrelease(floatbar, event);
else
xf_floatbar_button_event_buttonrelease(xfc, event);
xf_floatbar_button_event_buttonrelease(floatbar, event);
break;
case EnterNotify:
case FocusIn:
if (event->xany.window != floatbar->handle)
xf_floatbar_button_event_focusin(xfc, event);
xf_floatbar_button_event_focusin(floatbar, event);
break;
case LeaveNotify:
case FocusOut:
if (event->xany.window == floatbar->handle)
xf_floatbar_event_focusout(xfc, event);
xf_floatbar_event_focusout(floatbar, event);
else
xf_floatbar_button_event_focusout(xfc, event);
xf_floatbar_button_event_focusout(floatbar, event);
break;
case ConfigureNotify:
if (event->xany.window == floatbar->handle)
xf_floatbar_button_update_positon(xfc, event);
xf_floatbar_button_update_positon(floatbar, event);
break;
case PropertyNotify:
if (event->xany.window == floatbar->handle)
xf_floatbar_button_update_positon(xfc, event);
xf_floatbar_button_update_positon(floatbar, event);
break;
@ -695,16 +785,17 @@ static void xf_floatbar_button_free(xfContext* xfc, xfFloatbarButton* button)
free(button);
}
void xf_floatbar_free(xfContext* xfc, xfWindow* window, xfFloatbar* floatbar)
void xf_floatbar_free(xfFloatbar* floatbar)
{
size_t i, size;
size = ARRAYSIZE(floatbar->buttons);
xfContext* xfc;
if (!floatbar)
return;
if (window->floatbar == floatbar)
window->floatbar = NULL;
free(floatbar->title);
xfc = floatbar->xfc;
size = ARRAYSIZE(floatbar->buttons);
for (i = 0; i < size; i++)
{

View File

@ -22,13 +22,13 @@ typedef struct xf_floatbar xfFloatbar;
#include "xfreerdp.h"
typedef void(*OnClick)(xfContext*);
xfFloatbar* xf_floatbar_new(xfContext* xfc, Window window);
BOOL xf_floatbar_event_process(xfContext* xfc, XEvent* event);
BOOL xf_floatbar_check_event(xfContext* xfc, XEvent* event);
void xf_floatbar_toggle_visibility(xfContext* xfc, bool visible);
void xf_floatbar_free(xfContext* xfc, xfWindow* window, xfFloatbar* floatbar);
void xf_floatbar_hide_and_show(xfContext* xfc);
void xf_floatbar_set_root_y(xfContext* xfc, int y);
xfFloatbar* xf_floatbar_new(xfContext* xfc, Window window, const char* title, DWORD flags);
void xf_floatbar_free(xfFloatbar* floatbar);
BOOL xf_floatbar_event_process(xfFloatbar* floatbar, XEvent* event);
BOOL xf_floatbar_check_event(xfFloatbar* floatbar, XEvent* event);
BOOL xf_floatbar_toggle_fullscreen(xfFloatbar* floatbar, bool visible);
BOOL xf_floatbar_hide_and_show(xfFloatbar* floatbar);
BOOL xf_floatbar_set_root_y(xfFloatbar* floatbar, int y);
#endif /* FREERDP_CLIENT_X11_FLOATBAR_H */

View File

@ -129,6 +129,7 @@ static UINT xf_UpdateSurfaces(RdpgfxClientContext* context)
if (gdi->suppressOutput)
return CHANNEL_RC_OK;
EnterCriticalSection(&context->mux);
context->GetSurfaceIds(context, &pSurfaceIds, &count);
for (index = 0; index < count; index++)
@ -145,6 +146,7 @@ static UINT xf_UpdateSurfaces(RdpgfxClientContext* context)
}
free(pSurfaceIds);
LeaveCriticalSection(&context->mux);
return status;
}
@ -153,7 +155,7 @@ UINT xf_OutputExpose(xfContext* xfc, UINT32 x, UINT32 y,
{
UINT16 count;
UINT32 index;
UINT status = CHANNEL_RC_OK;
UINT status = ERROR_INTERNAL_ERROR;
xfGfxSurface* surface;
RECTANGLE_16 invalidRect;
RECTANGLE_16 surfaceRect;
@ -164,7 +166,12 @@ UINT xf_OutputExpose(xfContext* xfc, UINT32 x, UINT32 y,
invalidRect.top = y;
invalidRect.right = x + width;
invalidRect.bottom = y + height;
context->GetSurfaceIds(context, &pSurfaceIds, &count);
status = context->GetSurfaceIds(context, &pSurfaceIds, &count);
if (status != CHANNEL_RC_OK)
goto fail;
EnterCriticalSection(&context->mux);
for (index = 0; index < count; index++)
{
@ -192,7 +199,13 @@ UINT xf_OutputExpose(xfContext* xfc, UINT32 x, UINT32 y,
}
free(pSurfaceIds);
LeaveCriticalSection(&context->mux);
IFCALLRET(context->UpdateSurfaces, status, context);
if (status != CHANNEL_RC_OK)
goto fail;
fail:
return status;
}
@ -343,6 +356,8 @@ static UINT xf_DeleteSurface(RdpgfxClientContext* context,
{
rdpCodecs* codecs = NULL;
xfGfxSurface* surface = NULL;
UINT status;
EnterCriticalSection(&context->mux);
surface = (xfGfxSurface*) context->GetSurfaceData(context,
deleteSurface->surfaceId);
@ -360,13 +375,14 @@ static UINT xf_DeleteSurface(RdpgfxClientContext* context,
free(surface);
}
context->SetSurfaceData(context, deleteSurface->surfaceId, NULL);
status = context->SetSurfaceData(context, deleteSurface->surfaceId, NULL);
if (codecs && codecs->progressive)
progressive_delete_surface_context(codecs->progressive,
deleteSurface->surfaceId);
return CHANNEL_RC_OK;
LeaveCriticalSection(&context->mux);
return status;
}
void xf_graphics_pipeline_init(xfContext* xfc, RdpgfxClientContext* gfx)

View File

@ -581,13 +581,13 @@ static int xf_input_event(xfContext* xfc, XIDeviceEvent* event, int evtype)
switch (evtype)
{
case XI_ButtonPress:
xf_generic_ButtonPress(xfc, (int) event->event_x, (int) event->event_y,
event->detail, event->event, xfc->remote_app);
xf_generic_ButtonEvent(xfc, (int) event->event_x, (int) event->event_y,
event->detail, event->event, xfc->remote_app, TRUE);
break;
case XI_ButtonRelease:
xf_generic_ButtonRelease(xfc, (int) event->event_x, (int) event->event_y,
event->detail, event->event, xfc->remote_app);
xf_generic_ButtonEvent(xfc, (int) event->event_x, (int) event->event_y,
event->detail, event->event, xfc->remote_app, FALSE);
break;
case XI_Motion:

View File

@ -141,7 +141,7 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight)
int monitor_index = 0;
BOOL primaryMonitorFound = FALSE;
VIRTUAL_SCREEN* vscreen;
rdpSettings* settings = xfc->context.settings;
rdpSettings* settings;
int mouse_x, mouse_y, _dummy_i;
Window _dummy_w;
int current_monitor = 0;
@ -154,6 +154,11 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight)
XRRMonitorInfo* rrmonitors = NULL;
BOOL useXRandr = FALSE;
#endif
if (!xfc || !pMaxWidth || !pMaxHeight || !xfc->context.settings)
return FALSE;
settings = xfc->context.settings;
vscreen = &xfc->vscreen;
*pMaxWidth = settings->DesktopWidth;
*pMaxHeight = settings->DesktopHeight;
@ -274,6 +279,9 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight)
if (settings->NumMonitorIds == 1)
{
monitor = vscreen->monitors + current_monitor;
if (!monitor)
return FALSE;
xfc->workArea.x = monitor->area.left;
xfc->workArea.y = monitor->area.top;
xfc->workArea.width = monitor->area.right - monitor->area.left + 1;
@ -305,6 +313,9 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight)
*/
if (vscreen->nmonitors > 0)
{
if (!vscreen->monitors)
return FALSE;
*pMaxWidth = vscreen->monitors[current_monitor].area.right -
vscreen->monitors[current_monitor].area.left + 1;
*pMaxHeight = vscreen->monitors[current_monitor].area.bottom -
@ -346,12 +357,15 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight)
if (!xf_is_monitor_id_active(xfc, i))
continue;
if (!vscreen->monitors)
return FALSE;
settings->MonitorDefArray[nmonitors].x = vscreen->monitors[i].area.left;
settings->MonitorDefArray[nmonitors].y = vscreen->monitors[i].area.top;
settings->MonitorDefArray[nmonitors].width =
MIN(vscreen->monitors[i].area.right - vscreen->monitors[i].area.left + 1, *pMaxWidth);
vscreen->monitors[i].area.right - vscreen->monitors[i].area.left + 1;
settings->MonitorDefArray[nmonitors].height =
MIN(vscreen->monitors[i].area.bottom - vscreen->monitors[i].area.top + 1, *pMaxHeight);
vscreen->monitors[i].area.bottom - vscreen->monitors[i].area.top + 1;
settings->MonitorDefArray[nmonitors].orig_screen = i;
#ifdef USABLE_XRANDR
@ -380,7 +394,10 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight)
/* If no monitor is active(bogus command-line monitor specification) - then lets try to fallback to go fullscreen on the current monitor only */
if (nmonitors == 0 && vscreen->nmonitors > 0)
{
{
if (!vscreen->monitors)
return FALSE;
settings->MonitorDefArray[0].x = vscreen->monitors[current_monitor].area.left;
settings->MonitorDefArray[0].y = vscreen->monitors[current_monitor].area.top;
settings->MonitorDefArray[0].width = MIN(
@ -509,8 +526,8 @@ BOOL xf_detect_monitors(xfContext* xfc, UINT32* pMaxWidth, UINT32* pMaxHeight)
}
/* Set the desktop width and height according to the bounding rectangle around the active monitors */
*pMaxWidth = vscreen->area.right - vscreen->area.left + 1;
*pMaxHeight = vscreen->area.bottom - vscreen->area.top + 1;
*pMaxWidth = MIN(*pMaxWidth, vscreen->area.right - vscreen->area.left + 1);
*pMaxHeight = MIN(*pMaxHeight, vscreen->area.bottom - vscreen->area.top + 1);
}
/* some 2008 server freeze at logon if we announce support for monitor layout PDU with

View File

@ -222,8 +222,7 @@ static void xf_rail_invalidate_region(xfContext* xfc, REGION16* invalidRegion)
for (index = 0; index < count; index++)
{
appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows,
(void*) pKeys[index]);
appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, (void*)pKeys[index]);
if (appWindow)
{
@ -327,14 +326,12 @@ static BOOL xf_rail_window_common(rdpContext* context,
return FALSE;
}
HashTable_Add(xfc->railWindows, (void*)(UINT_PTR) orderInfo->windowId,
(void*) appWindow);
HashTable_Add(xfc->railWindows, &appWindow->windowId, (void*) appWindow);
xf_AppWindowInit(xfc, appWindow);
}
else
{
appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows,
(void*)(UINT_PTR) orderInfo->windowId);
appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, &orderInfo->windowId);
}
if (!appWindow)
@ -544,7 +541,7 @@ static BOOL xf_rail_window_delete(rdpContext* context,
if (!xfc)
return FALSE;
HashTable_Remove(xfc->railWindows, (void*)(UINT_PTR) orderInfo->windowId);
HashTable_Remove(xfc->railWindows, &orderInfo->windowId);
return TRUE;
}
@ -809,8 +806,7 @@ static void xf_rail_set_window_icon(xfContext* xfc,
static xfAppWindow* xf_rail_get_window_by_id(xfContext* xfc, UINT32 windowId)
{
return (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows,
(void*)(UINT_PTR) windowId);
return (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, &windowId);
}
static BOOL xf_rail_window_icon(rdpContext* context,
@ -999,17 +995,24 @@ static UINT xf_rail_server_system_param(RailClientContext* context,
static UINT xf_rail_server_handshake(RailClientContext* context,
const RAIL_HANDSHAKE_ORDER* handshake)
{
RAIL_EXEC_ORDER exec;
RAIL_SYSPARAM_ORDER sysparam;
UINT status;
RAIL_EXEC_ORDER exec = { 0 };
RAIL_SYSPARAM_ORDER sysparam = { 0 };
RAIL_HANDSHAKE_ORDER clientHandshake;
RAIL_CLIENT_STATUS_ORDER clientStatus;
RAIL_CLIENT_STATUS_ORDER clientStatus = { 0 };
xfContext* xfc = (xfContext*) context->custom;
rdpSettings* settings = xfc->context.settings;
clientHandshake.buildNumber = 0x00001DB0;
context->ClientHandshake(context, &clientHandshake);
ZeroMemory(&clientStatus, sizeof(RAIL_CLIENT_STATUS_ORDER));
status = context->ClientHandshake(context, &clientHandshake);
if (status != CHANNEL_RC_OK)
return status;
clientStatus.flags = RAIL_CLIENTSTATUS_ALLOWLOCALMOVESIZE;
context->ClientInformation(context, &clientStatus);
status = context->ClientInformation(context, &clientStatus);
if (status != CHANNEL_RC_OK)
return status;
if (settings->RemoteAppLanguageBarSupported)
{
@ -1018,7 +1021,6 @@ static UINT xf_rail_server_handshake(RailClientContext* context,
context->ClientLanguageBarInfo(context, &langBarInfo);
}
ZeroMemory(&sysparam, sizeof(RAIL_SYSPARAM_ORDER));
sysparam.params = 0;
sysparam.params |= SPI_MASK_SET_HIGH_CONTRAST;
sysparam.highContrast.colorScheme.string = NULL;
@ -1038,13 +1040,15 @@ static UINT xf_rail_server_handshake(RailClientContext* context,
sysparam.workArea.right = settings->DesktopWidth;
sysparam.workArea.bottom = settings->DesktopHeight;
sysparam.dragFullWindows = FALSE;
context->ClientSystemParam(context, &sysparam);
ZeroMemory(&exec, sizeof(RAIL_EXEC_ORDER));
status = context->ClientSystemParam(context, &sysparam);
if (status != CHANNEL_RC_OK)
return status;
exec.RemoteApplicationProgram = settings->RemoteApplicationProgram;
exec.RemoteApplicationWorkingDir = settings->ShellWorkingDirectory;
exec.RemoteApplicationArguments = settings->RemoteApplicationCmdLine;
context->ClientExecute(context, &exec);
return CHANNEL_RC_OK;
return context->ClientExecute(context, &exec);
}
/**
@ -1072,7 +1076,7 @@ static UINT xf_rail_server_local_move_size(RailClientContext* context,
xfAppWindow* appWindow = NULL;
xfContext* xfc = (xfContext*) context->custom;
appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows,
(void*)(UINT_PTR) localMoveSize->windowId);
(void*)&localMoveSize->windowId);
if (!appWindow)
return ERROR_INTERNAL_ERROR;
@ -1167,8 +1171,7 @@ static UINT xf_rail_server_min_max_info(RailClientContext* context,
{
xfAppWindow* appWindow = NULL;
xfContext* xfc = (xfContext*) context->custom;
appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows,
(void*)(UINT_PTR) minMaxInfo->windowId);
appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, (void*)&minMaxInfo->windowId);
if (appWindow)
{
@ -1204,6 +1207,16 @@ static UINT xf_rail_server_get_appid_response(RailClientContext* context,
return CHANNEL_RC_OK;
}
static BOOL rail_window_key_equals(void* key1, void* key2)
{
return *(UINT32*)key1 == *(UINT32*)key2;
}
static UINT32 rail_window_key_hash(void* key)
{
return *(UINT32*)key;
}
static void rail_window_free(void* value)
{
xfAppWindow* appWindow = (xfAppWindow*) value;
@ -1237,6 +1250,8 @@ int xf_rail_init(xfContext* xfc, RailClientContext* rail)
if (!xfc->railWindows)
return 0;
xfc->railWindows->keyCompare = rail_window_key_equals;
xfc->railWindows->hash = rail_window_key_hash;
xfc->railWindows->valueFree = rail_window_free;
xfc->railIconCache = RailIconCache_New(xfc->context.settings);

View File

@ -163,9 +163,7 @@ void xf_SetWindowFullscreen(xfContext* xfc, xfWindow* window, BOOL fullscreen)
/* show/hide decorations (e.g. title bar) as guided by xfc->decorations */
xf_SetWindowDecorations(xfc, window->handle, window->decorations);
DEBUG_X11(TAG, "X window decoration set to %d", (int)window->decorations);
if (xfc->floatbar)
xf_floatbar_toggle_visibility(xfc, fullscreen);
xf_floatbar_toggle_fullscreen(xfc->window->floatbar, fullscreen);
if (fullscreen)
{
@ -587,7 +585,7 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width,
settings->DesktopPosY);
}
window->floatbar = xf_floatbar_new(xfc, window->handle);
window->floatbar = xf_floatbar_new(xfc, window->handle, name, settings->Floatbar);
return window;
}
@ -636,8 +634,7 @@ void xf_DestroyDesktopWindow(xfContext* xfc, xfWindow* window)
if (xfc->window == window)
xfc->window = NULL;
if (window->floatbar)
xf_floatbar_free(xfc, window, window->floatbar);
xf_floatbar_free(window->floatbar);
if (window->gc)
XFreeGC(xfc->display, window->gc);
@ -988,6 +985,8 @@ void xf_ShowWindow(xfContext* xfc, xfAppWindow* appWindow, BYTE state)
if (appWindow->is_transient)
xf_SetWindowUnlisted(xfc, appWindow->handle);
XMapWindow(xfc->display, appWindow->handle);
break;
}
@ -1118,8 +1117,7 @@ xfAppWindow* xf_AppWindowFromX11Window(xfContext* xfc, Window wnd)
for (index = 0; index < count; index++)
{
appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows,
(void*) pKeys[index]);
appWindow = (xfAppWindow*) HashTable_GetItemValue(xfc->railWindows, (void*) pKeys[index]);
if (appWindow->handle == wnd)
{

View File

@ -85,13 +85,14 @@ typedef struct _xfDispContext xfDispContext;
typedef struct _xfVideoContext xfVideoContext;
typedef struct xf_rail_icon_cache xfRailIconCache;
/* Value of the first logical button number in X11 which must be */
/* subtracted to go from a button number in X11 to an index into */
/* a per-button array. */
#define BUTTON_BASE Button1
/* Number of buttons that are mapped from X11 to RDP button events. */
#define NUM_BUTTONS_MAPPED 3
#define NUM_BUTTONS_MAPPED 11
typedef struct
{
int button;
UINT16 flags;
} button_map;
struct xf_context
{
@ -161,7 +162,6 @@ struct xf_context
BOOL use_xinput;
BOOL mouse_active;
BOOL fullscreen_toggle;
BOOL floatbar;
BOOL controlToggle;
UINT32 KeyboardLayout;
BOOL KeyboardState[256];
@ -232,7 +232,7 @@ struct xf_context
BOOL xrenderAvailable;
/* value to be sent over wire for each logical client mouse button */
int button_map[NUM_BUTTONS_MAPPED];
button_map button_map[NUM_BUTTONS_MAPPED];
BYTE savedMaximizedState;
};

View File

@ -303,24 +303,38 @@ out:
}
int freerdp_client_settings_parse_assistance_file(rdpSettings* settings,
const char* filename)
int argc, char* argv[])
{
int status;
int status, x;
int ret = -1;
char* filename;
char* password = NULL;
rdpAssistanceFile* file;
if (!settings || !argv || (argc < 2))
return -1;
filename = argv[1];
for (x = 2; x < argc; x++)
{
const char* key = strstr(argv[x], "assistance:");
if (key)
password = strchr(key, ':') + 1;
}
file = freerdp_assistance_file_new();
if (!file)
return -1;
status = freerdp_assistance_parse_file(file, filename);
status = freerdp_assistance_parse_file(file, filename, password);
if (status < 0)
goto out;
status = freerdp_client_populate_settings_from_assistance_file(file, settings);
if (status < 0)
if (!freerdp_assistance_populate_settings_from_assistance_file(file, settings))
goto out;
ret = 0;
@ -492,6 +506,7 @@ static DWORD client_cli_accept_certificate(rdpSettings* settings)
* when the connection requires it.
* This function will actually be called by tls_verify_certificate().
* @see rdp_client_connect() and tls_connect()
* @deprecated Use client_cli_verify_certificate_ex
* @param instance - pointer to the rdp_freerdp structure that contains the connection settings
* @param common_name
* @param subject
@ -504,6 +519,7 @@ DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name,
const char* subject, const char* issuer,
const char* fingerprint, BOOL host_mismatch)
{
printf("WARNING: This callback is deprecated, migrate to client_cli_verify_certificate_ex\n");
printf("Certificate details:\n");
printf("\tSubject: %s\n", subject);
printf("\tIssuer: %s\n", issuer);
@ -514,10 +530,50 @@ DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name,
return client_cli_accept_certificate(instance->settings);
}
/** Callback set in the rdp_freerdp structure, and used to make a certificate validation
* when the connection requires it.
* This function will actually be called by tls_verify_certificate().
* @see rdp_client_connect() and tls_connect()
* @param instance pointer to the rdp_freerdp structure that contains the connection settings
* @param host The host currently connecting to
* @param port The port currently connecting to
* @param common_name The common name of the certificate, should match host or an alias of it
* @param subject The subject of the certificate
* @param issuer The certificate issuer name
* @param fingerprint The fingerprint of the certificate
* @param flags See VERIFY_CERT_FLAG_* for possible values.
*
* @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise.
*/
DWORD client_cli_verify_certificate_ex(freerdp* instance, const char* host, UINT16 port,
const char* common_name,
const char* subject, const char* issuer,
const char* fingerprint, DWORD flags)
{
const char* type = "RDP-Server";
if (flags & VERIFY_CERT_FLAG_GATEWAY)
type = "RDP-Gateway";
if (flags & VERIFY_CERT_FLAG_REDIRECT)
type = "RDP-Redirect";
printf("Certificate details for %s:%"PRIu16" (%s):\n", host, port, type);
printf("\tCommon Name: %s\n", common_name);
printf("\tSubject: %s\n", subject);
printf("\tIssuer: %s\n", issuer);
printf("\tThumbprint: %s\n", fingerprint);
printf("The above X.509 certificate could not be verified, possibly because you do not have\n"
"the CA certificate in your certificate store, or the certificate has expired.\n"
"Please look at the OpenSSL documentation on how to add a private CA to the store.\n");
return client_cli_accept_certificate(instance->settings);
}
/** Callback set in the rdp_freerdp structure, and used to make a certificate validation
* when a stored certificate does not match the remote counterpart.
* This function will actually be called by tls_verify_certificate().
* @see rdp_client_connect() and tls_connect()
* @deprecated Use client_cli_verify_changed_certificate_ex
* @param instance - pointer to the rdp_freerdp structure that contains the connection settings
* @param common_name
* @param subject
@ -535,6 +591,7 @@ DWORD client_cli_verify_changed_certificate(freerdp* instance,
const char* old_subject, const char* old_issuer,
const char* old_fingerprint)
{
printf("WARNING: This callback is deprecated, migrate to client_cli_verify_changed_certificate_ex\n");
printf("!!! Certificate has changed !!!\n");
printf("\n");
printf("New Certificate details:\n");
@ -553,6 +610,59 @@ DWORD client_cli_verify_changed_certificate(freerdp* instance,
return client_cli_accept_certificate(instance->settings);
}
/** Callback set in the rdp_freerdp structure, and used to make a certificate validation
* when a stored certificate does not match the remote counterpart.
* This function will actually be called by tls_verify_certificate().
* @see rdp_client_connect() and tls_connect()
* @param instance pointer to the rdp_freerdp structure that contains the connection settings
* @param host The host currently connecting to
* @param port The port currently connecting to
* @param common_name The common name of the certificate, should match host or an alias of it
* @param subject The subject of the certificate
* @param issuer The certificate issuer name
* @param fingerprint The fingerprint of the certificate
* @param old_subject The subject of the previous certificate
* @param old_issuer The previous certificate issuer name
* @param old_fingerprint The fingerprint of the previous certificate
* @param flags See VERIFY_CERT_FLAG_* for possible values.
*
* @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise.
*/
DWORD client_cli_verify_changed_certificate_ex(freerdp* instance,
const char* host, UINT16 port,
const char* common_name,
const char* subject, const char* issuer,
const char* fingerprint,
const char* old_subject, const char* old_issuer,
const char* old_fingerprint, DWORD flags)
{
const char* type = "RDP-Server";
if (flags & VERIFY_CERT_FLAG_GATEWAY)
type = "RDP-Gateway";
if (flags & VERIFY_CERT_FLAG_REDIRECT)
type = "RDP-Redirect";
printf("!!!Certificate for %s:%"PRIu16" (%s) has changed!!!\n", host, port, type);
printf("\n");
printf("New Certificate details:\n");
printf("\tCommon Name: %s\n", common_name);
printf("\tSubject: %s\n", subject);
printf("\tIssuer: %s\n", issuer);
printf("\tThumbprint: %s\n", fingerprint);
printf("\n");
printf("Old Certificate details:\n");
printf("\tSubject: %s\n", old_subject);
printf("\tIssuer: %s\n", old_issuer);
printf("\tThumbprint: %s\n", old_fingerprint);
printf("\n");
printf("The above X.509 certificate does not match the certificate used for previous connections.\n"
"This may indicate that the certificate has been tampered with.\n"
"Please contact the administrator of the RDP server and clarify.\n");
return client_cli_accept_certificate(instance->settings);
}
BOOL client_auto_reconnect(freerdp* instance)
{
return client_auto_reconnect_ex(instance, NULL);

File diff suppressed because it is too large Load Diff

View File

@ -46,19 +46,20 @@ static COMMAND_LINE_ARGUMENT_A args[] =
{ "bitmap-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "bitmap cache" },
{ "bpp", COMMAND_LINE_VALUE_REQUIRED, "<depth>", "16", NULL, -1, NULL, "Session bpp (color depth)" },
{ "buildconfig", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_BUILDCONFIG, NULL, NULL, NULL, -1, NULL, "Print the build configuration" },
{ "cert-deny", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Automatically abort connection for any certificate that can not be validated." },
{ "cert-ignore", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Ignore certificate" },
{ "cert-name", COMMAND_LINE_VALUE_REQUIRED, "<name>", NULL, NULL, -1, NULL, "Certificate name" },
{ "cert-tofu", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Automatically accept certificate on first connect" },
{ "client-hostname", COMMAND_LINE_VALUE_REQUIRED, "<name>", NULL, NULL, -1, NULL, "Client Hostname to send to server" },
{ "clipboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Redirect clipboard" },
{ "codec-cache", COMMAND_LINE_VALUE_REQUIRED, "rfx|nsc|jpeg", NULL, NULL, -1, NULL, "Bitmap codec cache" },
{ "codec-cache", COMMAND_LINE_VALUE_REQUIRED, "[rfx|nsc|jpeg]", NULL, NULL, -1, NULL, "Bitmap codec cache" },
{ "compression", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, "z", "compression" },
{ "compression-level", COMMAND_LINE_VALUE_REQUIRED, "<level>", NULL, NULL, -1, NULL, "Compression level (0,1,2)" },
{ "credentials-delegation", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "credentials delegation" },
{ "d", COMMAND_LINE_VALUE_REQUIRED, "<domain>", NULL, NULL, -1, NULL, "Domain" },
{ "decorations", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Window decorations" },
{ "disp", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Display control" },
{ "drive", COMMAND_LINE_VALUE_REQUIRED, "<name>,<path>", NULL, NULL, -1, NULL, "Redirect directory <path> as named share <name>" },
{ "drive", COMMAND_LINE_VALUE_REQUIRED, "<name>,<path>", NULL, NULL, -1, NULL, "Redirect directory <path> as named share <name>. Hotplug support is enabled with /drive:hotplug,*. This argument provides the same function as \"Drives that I plug in later\" option in MSTSC." },
{ "drives", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect all mount points as shares" },
{ "dvc", COMMAND_LINE_VALUE_REQUIRED, "<channel>[,<options>]", NULL, NULL, -1, NULL, "Dynamic virtual channel" },
{ "dynamic-resolution", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Send resolution updates when the window is resized" },
@ -68,19 +69,19 @@ static COMMAND_LINE_ARGUMENT_A args[] =
{ "f", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Fullscreen mode (<Ctrl>+<Alt>+<Enter> toggles fullscreen)" },
{ "fast-path", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "fast-path input/output" },
{ "fipsmode", COMMAND_LINE_VALUE_BOOL, NULL, NULL, NULL, -1, NULL, "FIPS mode" },
{ "floatbar", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "floatbar in fullscreen mode" },
{ "fonts", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "smooth fonts (ClearType)" },
{ "floatbar", COMMAND_LINE_VALUE_OPTIONAL, "sticky:[on|off],default:[visible|hidden],show:[always|fullscreen||window]", NULL, NULL, -1, NULL, "floatbar is disabled by default (when enabled defaults to sticky in fullscreen mode)" },
{ "fonts", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "smooth fonts (ClearType)" },
{ "frame-ack", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Number of frame acknowledgement" },
{ "from-stdin", COMMAND_LINE_VALUE_OPTIONAL, "force", NULL, NULL, -1, NULL, "Read credentials from stdin. With <force> the prompt is done before connection, otherwise on server request." },
{ "g", COMMAND_LINE_VALUE_REQUIRED, "<gateway>[:<port>]", NULL, NULL, -1, NULL, "Gateway Hostname" },
{ "gateway-usage-method", COMMAND_LINE_VALUE_REQUIRED, "direct|detect", NULL, NULL, -1, "gum", "Gateway usage method" },
{ "gateway-usage-method", COMMAND_LINE_VALUE_REQUIRED, "[direct|detect]", NULL, NULL, -1, "gum", "Gateway usage method" },
{ "gd", COMMAND_LINE_VALUE_REQUIRED, "<domain>", NULL, NULL, -1, NULL, "Gateway domain" },
{ "gdi", COMMAND_LINE_VALUE_REQUIRED, "sw|hw", NULL, NULL, -1, NULL, "GDI rendering" },
{ "geometry", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Geometry tracking channel" },
{ "gestures", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Consume multitouch input locally" },
#ifdef WITH_GFX_H264
{ "gfx", COMMAND_LINE_VALUE_OPTIONAL, "RFX|AVC420|AVC444", NULL, NULL, -1, NULL, "RDP8 graphics pipeline (experimental)" },
{ "gfx-h264", COMMAND_LINE_VALUE_OPTIONAL, "AVC420|AVC444", NULL, NULL, -1, NULL, "RDP8.1 graphics pipeline using H264 codec" },
{ "gfx", COMMAND_LINE_VALUE_OPTIONAL, "[RFX|AVC420|AVC444]", NULL, NULL, -1, NULL, "RDP8 graphics pipeline (experimental)" },
{ "gfx-h264", COMMAND_LINE_VALUE_OPTIONAL, "[AVC420|AVC444]", NULL, NULL, -1, NULL, "RDP8.1 graphics pipeline using H264 codec" },
#else
{ "gfx", COMMAND_LINE_VALUE_OPTIONAL, "RFX", NULL, NULL, -1, NULL, "RDP8 graphics pipeline (experimental)" },
#endif
@ -90,8 +91,8 @@ static COMMAND_LINE_ARGUMENT_A args[] =
{ "glyph-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Glyph cache (experimental)" },
{ "gp", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Gateway password" },
{ "grab-keyboard", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Grab keyboard" },
{ "gt", COMMAND_LINE_VALUE_REQUIRED, "rpc|http|auto", NULL, NULL, -1, NULL, "Gateway transport type" },
{ "gu", COMMAND_LINE_VALUE_REQUIRED, "[<domain>\\]<user> or <user>[@<domain>]", NULL, NULL, -1, NULL, "Gateway username" },
{ "gt", COMMAND_LINE_VALUE_REQUIRED, "[rpc|http|auto]", NULL, NULL, -1, NULL, "Gateway transport type" },
{ "gu", COMMAND_LINE_VALUE_REQUIRED, "[[<domain>\\]<user>|<user>[@<domain>]]", NULL, NULL, -1, NULL, "Gateway username" },
{ "gat", COMMAND_LINE_VALUE_REQUIRED, "<access token>", NULL, NULL, -1, NULL, "Gateway Access Token" },
{ "h", COMMAND_LINE_VALUE_REQUIRED, "<height>", "768", NULL, -1, NULL, "Height" },
{ "heartbeat", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support heartbeat PDUs" },
@ -109,7 +110,7 @@ static COMMAND_LINE_ARGUMENT_A args[] =
{ "kbd-type", COMMAND_LINE_VALUE_REQUIRED, "<id>", NULL, NULL, -1, NULL, "Keyboard type" },
{ "load-balance-info", COMMAND_LINE_VALUE_REQUIRED, "<info-string>", NULL, NULL, -1, NULL, "Load balance info" },
{ "log-filters", COMMAND_LINE_VALUE_REQUIRED, "<tag>:<level>[,<tag>:<level>[,...]]", NULL, NULL, -1, NULL, "Set logger filters, see wLog(7) for details" },
{ "log-level", COMMAND_LINE_VALUE_REQUIRED, "OFF|FATAL|ERROR|WARN|INFO|DEBUG|TRACE", NULL, NULL, -1, NULL, "Set the default log level, see wLog(7) for details" },
{ "log-level", COMMAND_LINE_VALUE_REQUIRED, "[OFF|FATAL|ERROR|WARN|INFO|DEBUG|TRACE]", NULL, NULL, -1, NULL, "Set the default log level, see wLog(7) for details" },
{ "max-fast-path-size", COMMAND_LINE_VALUE_REQUIRED, "<size>", NULL, NULL, -1, NULL, "Specify maximum fast-path update size" },
{ "max-loop-time", COMMAND_LINE_VALUE_REQUIRED, "<time>", NULL, NULL, -1, NULL, "Specify maximum time in milliseconds spend treating packets"},
{ "menu-anims", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "menu animations" },
@ -122,10 +123,10 @@ static COMMAND_LINE_ARGUMENT_A args[] =
{ "multitouch", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Redirect multitouch input" },
{ "multitransport", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Support multitransport protocol" },
{ "nego", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "protocol security negotiation" },
{ "network", COMMAND_LINE_VALUE_REQUIRED, "modem|broadband|broadband-low|broadband-high|wan|lan|auto", NULL, NULL, -1, NULL, "Network connection type" },
{ "network", COMMAND_LINE_VALUE_REQUIRED, "[modem|broadband|broadband-low|broadband-high|wan|lan|auto]", NULL, NULL, -1, NULL, "Network connection type" },
{ "nsc", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "nscodec", "NSCodec support" },
{ "offscreen-cache", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "offscreen bitmap cache" },
{ "orientation", COMMAND_LINE_VALUE_REQUIRED, "0|90|180|270", NULL, NULL, -1, NULL, "Orientation of display in degrees" },
{ "orientation", COMMAND_LINE_VALUE_REQUIRED, "[0|90|180|270]", NULL, NULL, -1, NULL, "Orientation of display in degrees" },
{ "old-license", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Use the old license workflow (no CAL and hwId set to 0)"},
{ "p", COMMAND_LINE_VALUE_REQUIRED, "<password>", NULL, NULL, -1, NULL, "Password" },
{ "parallel", COMMAND_LINE_VALUE_OPTIONAL, "<name>[,<path>]", NULL, NULL, -1, NULL, "Redirect parallel device" },
@ -136,21 +137,25 @@ static COMMAND_LINE_ARGUMENT_A args[] =
{ "pheight", COMMAND_LINE_VALUE_REQUIRED, "<height>", NULL, NULL, -1, NULL, "Physical height of display (in millimeters)" },
{ "play-rfx", COMMAND_LINE_VALUE_REQUIRED, "<pcap-file>", NULL, NULL, -1, NULL, "Replay rfx pcap file" },
{ "port", COMMAND_LINE_VALUE_REQUIRED, "<number>", NULL, NULL, -1, NULL, "Server port" },
{ "suppress-output", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "suppress output when minimized" },
{ "print-reconnect-cookie", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Print base64 reconnect cookie after connecting" },
{ "printer", COMMAND_LINE_VALUE_OPTIONAL, "<name>[,<driver>]", NULL, NULL, -1, NULL, "Redirect printer device" },
{ "proxy", COMMAND_LINE_VALUE_REQUIRED, "[<proto>://][<user>:<password>@]<host>:<port>", NULL, NULL, -1, NULL, "Proxy settings: override env.var (see also environment variable below).\n\tProtocol \"socks5\" should be given explicitly where \"http\" is default.\n\tNote: socks proxy is not supported by env. variable" },
{
"proxy", COMMAND_LINE_VALUE_REQUIRED, "[<proto>://][<user>:<password>@]<host>:<port>", NULL, NULL, -1, NULL,
"Proxy settings: override env.var (see also environment variable below). Protocol \"socks5\" should be given explicitly where \"http\" is default. Note: socks proxy is not supported by env. variable"
},
{ "pth", COMMAND_LINE_VALUE_REQUIRED, "<password-hash>", NULL, NULL, -1, "pass-the-hash", "Pass the hash (restricted admin mode)" },
{ "pwidth", COMMAND_LINE_VALUE_REQUIRED, "<width>", NULL, NULL, -1, NULL, "Physical width of display (in millimeters)" },
{ "reconnect-cookie", COMMAND_LINE_VALUE_REQUIRED, "<base64-cookie>", NULL, NULL, -1, NULL, "Pass base64 reconnect cookie to the connection" },
{ "redirect-prefer", COMMAND_LINE_VALUE_REQUIRED, "<FQDN|IP|NETBIOS>[,<FQDN|IP|NETBIOS>[,<FQDN|IP|NETBIOS>]]", NULL, NULL, -1, NULL, "Override the preferred redirection order" },
{ "redirect-prefer", COMMAND_LINE_VALUE_REQUIRED, "<FQDN|IP|NETBIOS>,[...]", NULL, NULL, -1, NULL, "Override the preferred redirection order" },
{ "relax-order-checks", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "relax-order-checks", "Do not check if a RDP order was announced during capability exchange, only use when connecting to a buggy server" },
{ "restricted-admin", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "restrictedAdmin", "Restricted admin mode" },
{ "rfx", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "RemoteFX" },
{ "rfx-mode", COMMAND_LINE_VALUE_REQUIRED, "image|video", NULL, NULL, -1, NULL, "RemoteFX mode" },
{ "scale", COMMAND_LINE_VALUE_REQUIRED, "100|140|180", "100", NULL, -1, NULL, "Scaling factor of the display" },
{ "rfx-mode", COMMAND_LINE_VALUE_REQUIRED, "[image|video]", NULL, NULL, -1, NULL, "RemoteFX mode" },
{ "scale", COMMAND_LINE_VALUE_REQUIRED, "[100|140|180]", "100", NULL, -1, NULL, "Scaling factor of the display" },
{ "scale-desktop", COMMAND_LINE_VALUE_REQUIRED, "<percentage>", "100", NULL, -1, NULL, "Scaling factor for desktop applications (value between 100 and 500)" },
{ "scale-device", COMMAND_LINE_VALUE_REQUIRED, "100|140|180", "100", NULL, -1, NULL, "Scaling factor for app store applications" },
{ "sec", COMMAND_LINE_VALUE_REQUIRED, "rdp|tls|nla|ext", NULL, NULL, -1, NULL, "Force specific protocol security" },
{ "sec", COMMAND_LINE_VALUE_REQUIRED, "[rdp|tls|nla|ext]", NULL, NULL, -1, NULL, "Force specific protocol security" },
{ "sec-ext", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "NLA extended protocol security" },
{ "sec-nla", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "NLA protocol security" },
{ "sec-rdp", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "RDP protocol security" },
@ -160,7 +165,7 @@ static COMMAND_LINE_ARGUMENT_A args[] =
{ "shell-dir", COMMAND_LINE_VALUE_REQUIRED, "<dir>", NULL, NULL, -1, NULL, "Shell working directory" },
{ "size", COMMAND_LINE_VALUE_REQUIRED, "<width>x<height> or <percent>%[wh]", "1024x768", NULL, -1, NULL, "Screen size" },
{ "smart-sizing", COMMAND_LINE_VALUE_OPTIONAL, "<width>x<height>", NULL, NULL, -1, NULL, "Scale remote desktop to window size" },
{ "smartcard", COMMAND_LINE_VALUE_OPTIONAL, "<str>[,<str>]", NULL, NULL, -1, NULL, "Redirect the smartcard devices containing any of the <str> in their names." },
{ "smartcard", COMMAND_LINE_VALUE_OPTIONAL, "<str>[,<str>...]", NULL, NULL, -1, NULL, "Redirect the smartcard devices containing any of the <str> in their names." },
{ "smartcard-logon", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Activates Smartcard Logon authentication. (EXPERIMENTAL: NLA not supported)" },
{ "sound", COMMAND_LINE_VALUE_OPTIONAL, "[sys:<sys>,][dev:<dev>,][format:<format>,][rate:<rate>,][channel:<channel>,][latency:<latency>,][quality:<quality>]", NULL, NULL, -1, "audio", "Audio output (sound)" },
{ "span", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, NULL, "Span screen over multiple monitors" },
@ -168,10 +173,10 @@ static COMMAND_LINE_ARGUMENT_A args[] =
{ "ssh-agent", COMMAND_LINE_VALUE_FLAG, NULL, NULL, NULL, -1, "ssh-agent", "SSH Agent forwarding channel" },
{ "t", COMMAND_LINE_VALUE_REQUIRED, "<title>", NULL, NULL, -1, "title", "Window title" },
{ "themes", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "themes" },
{ "tls-ciphers", COMMAND_LINE_VALUE_REQUIRED, "netmon|ma|ciphers", NULL, NULL, -1, NULL, "Allowed TLS ciphers" },
{ "tls-ciphers", COMMAND_LINE_VALUE_REQUIRED, "[netmon|ma|ciphers]", NULL, NULL, -1, NULL, "Allowed TLS ciphers" },
{ "tls-seclevel", COMMAND_LINE_VALUE_REQUIRED, "<level>", "1", NULL, -1, NULL, "TLS security level - defaults to 1" },
{ "toggle-fullscreen", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Alt+Ctrl+Enter toggles fullscreen" },
{ "u", COMMAND_LINE_VALUE_REQUIRED, "[<domain>\\]<user> or <user>[@<domain>]", NULL, NULL, -1, NULL, "Username" },
{ "toggle-fullscreen", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueTrue, NULL, -1, NULL, "Alt+Ctrl+Enter to toggle fullscreen" },
{ "u", COMMAND_LINE_VALUE_REQUIRED, "[[<domain>\\]<user>|<user>[@<domain>]]", NULL, NULL, -1, NULL, "Username" },
{ "unmap-buttons", COMMAND_LINE_VALUE_BOOL, NULL, BoolValueFalse, NULL, -1, NULL, "Let server see real physical pointer button"},
{ "usb", COMMAND_LINE_VALUE_REQUIRED, "[dbg,][dev:<dev>,][id|addr,][auto]", NULL, NULL, -1, NULL, "Redirect USB device" },
{ "v", COMMAND_LINE_VALUE_REQUIRED, "<server>[:port]", NULL, NULL, -1, NULL, "Server hostname" },

View File

@ -649,9 +649,9 @@ int freerdp_client_parse_old_command_line_arguments(int argc, char** argv, rdpSe
}
CommandLineSwitchCase(arg, "x")
{
long type;
unsigned long type;
char* pEnd;
type = strtol(arg->Value, &pEnd, 16);
type = strtoul(arg->Value, &pEnd, 16);
if (errno != 0)
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;

View File

@ -1133,9 +1133,6 @@ if( APPLE )
mark_as_advanced( CMAKE_INSTALL_NAME_TOOL )
endif()
# Force set compilers because standard identification works badly for us
include( CMakeForceCompiler )
CMAKE_FORCE_C_COMPILER( "${CMAKE_C_COMPILER}" GNU )
if( ANDROID_COMPILER_IS_CLANG )
set( CMAKE_C_COMPILER_ID Clang )
endif()
@ -1147,7 +1144,6 @@ else()
endif()
set( CMAKE_C_HAS_ISYSROOT 1 )
set( CMAKE_C_COMPILER_ABI ELF )
CMAKE_FORCE_CXX_COMPILER( "${CMAKE_CXX_COMPILER}" GNU )
if( ANDROID_COMPILER_IS_CLANG )
set( CMAKE_CXX_COMPILER_ID Clang)
endif()

View File

@ -136,6 +136,7 @@ option(WITH_DEBUG_RINGBUFFER "Enable Ringbuffer debug messages" ${DEFAULT_DEBUG_
option(WITH_DEBUG_SYMBOLS "Pack debug symbols to installer" OFF)
option(WITH_CCACHE "Use ccache support if available" ON)
option(WITH_ICU "Use ICU for unicode conversion" OFF)
option(WITH_GSSAPI "Compile support for kerberos authentication. (EXPERIMENTAL)" OFF)
option(WITH_DSP_EXPERIMENTAL "Enable experimental sound encoder/decoder formats" OFF)
if (WITH_FFMPEG)

View File

@ -1,49 +0,0 @@
# - Find DirectFB
# Find the DirectFB libraries
#
# This module defines the following variables:
# DIRECTFB_FOUND - true if DIRECTFB_INCLUDE_DIR & DIRECTFB_LIBRARY are found
# DIRECTFB_LIBRARIES - Set when DIRECTFB_LIBRARY is found
# DIRECTFB_INCLUDE_DIRS - Set when DIRECTFB_INCLUDE_DIR is found
#
# DIRECTFB_INCLUDE_DIR - where to find CUnit.h, etc.
# DIRECTFB_LIBRARY - the cunit library
#
#=============================================================================
# Copyright 2011 O.S. Systems Software Ltda.
# Copyright 2011 Otavio Salvador <otavio@ossystems.com.br>
# Copyright 2011 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.
#=============================================================================
find_path(DIRECTFB_INCLUDE_DIR NAMES directfb.h
PATH_SUFFIXES directfb
DOC "The directfb include directory"
)
find_library(DIRECTFB_LIBRARY NAMES directfb
DOC "The DirectFB library"
)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(DirectFB DEFAULT_MSG DIRECTFB_LIBRARY DIRECTFB_INCLUDE_DIR)
if(DIRECTFB_FOUND)
set( DIRECTFB_LIBRARIES ${DIRECTFB_LIBRARY} )
set( DIRECTFB_INCLUDE_DIRS ${DIRECTFB_INCLUDE_DIR} )
endif()
mark_as_advanced(DIRECTFB_INCLUDE_DIR DIRECTFB_LIBRARY)

View File

@ -115,7 +115,7 @@ if(NOT GSS_FOUND) # not found by pkg-config. Let's take more traditional approac
string(STRIP "${_GSS_VENDOR}" _GSS_VENDOR)
if((GSS_FLAVOUR STREQUAL "Heimdal" AND NOT _GSS_VENDOR STREQUAL "Heimdal")
OR (GSS_FLAVOUR STREQUAL "MIT" AND NOT _GSS_VENDOR STREQUAL "Massachusetts Institute of Technology"))
message(SEND_ERROR "GSS vendor and GSS flavour are not matching : _GSS_VENDOR=${_GSS_VENDOR} ; GSS_FLAVOUR=${GSS_FLAVOUR}")
message(SEND_ERROR "GSS vendor and GSS flavour are not matching : _GSS_VENDOR=${_GSS_VENDOR} ; GSS_FLAVOUR=${GSS_FLAVOUR}")
message(STATUS "Try to set the path to GSS root folder in the system variable GSS_ROOT_DIR")
endif()
else()
@ -428,13 +428,17 @@ if(GSS_FLAVOUR STREQUAL "MIT")
string(REGEX REPLACE "\\." "" GSS_VERSION_MAJOR "${GSS_VERSION_MAJOR}")
string(REGEX MATCH "\\.([0-9]+)$" GSS_VERSION_MINOR ${GSS_RELEASE_NUMBER})
if(NOT GSS_VERSION_MINOR)
string(REGEX MATCH "\\.([0-9]+)\\." GSS_VERSION_MINOR ${GSS_RELEASE_NUMBER})
string(REGEX REPLACE "\\." "" GSS_VERSION_MINOR "${GSS_VERSION_MINOR}")
string(REGEX REPLACE "\\." "" GSS_VERSION_MINOR "${GSS_VERSION_MINOR}")
string(REGEX MATCH "([0-9]+)$" GSS_VERSION_PATCH ${GSS_RELEASE_NUMBER})
string(REGEX REPLACE "\\." "" GSS_VERSION_PATCH "${GSS_VERSION_PATCH}")
string(REGEX MATCH "\\.([0-9]+)[-\\.]" GSS_VERSION_MINOR ${GSS_RELEASE_NUMBER})
string(REGEX REPLACE "\\." "" GSS_VERSION_MINOR "${GSS_VERSION_MINOR}")
string(REGEX REPLACE "\\." "" GSS_VERSION_MINOR "${GSS_VERSION_MINOR}")
string(REGEX REPLACE "-" "" GSS_VERSION_MINOR "${GSS_VERSION_MINOR}")
string(REGEX MATCH "\\.([0-9]+)$" GSS_VERSION_PATCH "${GSS_RELEASE_NUMBER}")
string(REGEX REPLACE "\\." "" GSS_VERSION_PATCH "${GSS_VERSION_PATCH}")
if(NOT GSS_VERSION_PATCH)
set(GSS_VERSION_PATCH "0")
endif()
else()
string(REGEX REPLACE "\\." "" GSS_VERSION_MINOR "${GSS_VERSION_MINOR}")
string(REGEX REPLACE "\\." "" GSS_VERSION_MINOR "${GSS_VERSION_MINOR}")
set(GSS_VERSION_PATCH "0")
endif()
if(GSS_VERSION_MAJOR AND GSS_VERSION_MINOR)
@ -443,6 +447,7 @@ if(GSS_FLAVOUR STREQUAL "MIT")
else()
message(SEND_ERROR "Failed to retrieved Kerberos version number")
endif()
message(STATUS "Located Kerberos ${GSS_VERSION_MAJOR}.${GSS_VERSION_MINOR}.${GSS_VERSION_PATCH}")
endif()
mark_as_advanced(GSS_INCLUDE_DIR GSS_LIBRARIES)

View File

@ -63,13 +63,13 @@ FIND_PATH(OPENSSL_INCLUDE_DIR
include
)
IF(WIN32)
IF(MSVC)
if(${MSVC_RUNTIME} STREQUAL "static")
set(MSVC_RUNTIME_SUFFIX "MT")
else()
set(MSVC_RUNTIME_SUFFIX "MD")
endif()
ENDIF(WIN32)
ENDIF(MSVC)
IF(ANDROID)
FIND_LIBRARY(OPENSSL_LIBRARIES
@ -108,6 +108,7 @@ ELSEIF(WIN32 AND NOT CYGWIN)
"libeay32${MSVC_RUNTIME_SUFFIX}d"
libeay32
libcrypto
libcrypto-1_1
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
${MSVC_RUNTIME_PATH_SUFFIX}
@ -121,6 +122,7 @@ ELSEIF(WIN32 AND NOT CYGWIN)
"libeay32${MSVC_RUNTIME_SUFFIX}"
libeay32
libcrypto
libcrypto-1_1
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
${MSVC_RUNTIME_PATH_SUFFIX}
@ -135,6 +137,7 @@ ELSEIF(WIN32 AND NOT CYGWIN)
ssleay32
ssl
libssl
libssl-1_1
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
${MSVC_RUNTIME_PATH_SUFFIX}
@ -149,6 +152,7 @@ ELSEIF(WIN32 AND NOT CYGWIN)
ssleay32
ssl
libssl
libssl-1_1
${_OPENSSL_ROOT_HINTS_AND_PATHS}
PATH_SUFFIXES
${MSVC_RUNTIME_PATH_SUFFIX}
@ -193,6 +197,7 @@ ELSEIF(WIN32 AND NOT CYGWIN)
NAMES
libeay32
libcrypto
libcrypto-1_1
HINTS
${_OPENSSL_LIBDIR}
${_OPENSSL_ROOT_HINTS_AND_PATHS}
@ -204,6 +209,7 @@ ELSEIF(WIN32 AND NOT CYGWIN)
NAMES
ssleay32
libssl
libssl-1_1
HINTS
${_OPENSSL_LIBDIR}
${_OPENSSL_ROOT_HINTS_AND_PATHS}
@ -220,6 +226,7 @@ ELSE(WIN32 AND NOT CYGWIN)
NAMES
ssl
ssleay32
libssl-1_1
"ssleay32${MSVC_RUNTIME_SUFFIX}"
HINTS
${_OPENSSL_LIBDIR}
@ -231,6 +238,7 @@ ELSE(WIN32 AND NOT CYGWIN)
FIND_LIBRARY(OPENSSL_CRYPTO_LIBRARY
NAMES
crypto
libcrypto-1_1
HINTS
${_OPENSSL_LIBDIR}
${_OPENSSL_ROOT_HINTS_AND_PATHS}

View File

@ -30,6 +30,7 @@ include(FindPkgConfig)
if(PKG_CONFIG_FOUND)
pkg_check_modules(WAYLAND_SCANNER_PC wayland-scanner)
pkg_check_modules(WAYLAND_CLIENT_PC wayland-client)
pkg_check_modules(WAYLAND_CURSOR_PC wayland-cursor)
pkg_check_modules(XKBCOMMON_PC xkbcommon)
endif()
@ -41,11 +42,20 @@ find_path(WAYLAND_INCLUDE_DIR wayland-client.h
HINTS ${WAYLAND_CLIENT_PC_INCLUDE_DIRS}
)
find_library(WAYLAND_LIBS
find_library(WAYLAND_CLIENT_LIB
NAMES "wayland-client"
HINTS "${WAYLAND_CLIENT_PC_LIBRARY_DIRS}"
)
find_library(WAYLAND_CURSOR_LIB
NAMES "wayland-cursor"
HINTS "${WAYLAND_CURSOR_PC_LIBRARY_DIRS}"
)
if (WAYLAND_CLIENT_LIB AND WAYLAND_CURSOR_LIB)
list(APPEND WAYLAND_LIBS ${WAYLAND_CLIENT_LIB} ${WAYLAND_CURSOR_LIB})
endif (WAYLAND_CLIENT_LIB AND WAYLAND_CURSOR_LIB)
find_path(XKBCOMMON_INCLUDE_DIR xkbcommon/xkbcommon.h
HINTS ${XKBCOMMON_PC_INCLUDE_DIRS}
)

View File

@ -37,7 +37,7 @@ set (APPLE True)
set (IOS True)
# Required as of cmake 2.8.10
set (CMAKE_OSX_DEPLOYMENT_TARGET "" CACHE STRING "Force unset of the deployment target for iOS" FORCE)
#set (CMAKE_OSX_DEPLOYMENT_TARGET "" CACHE STRING "Force unset of the deployment target for iOS" FORCE)
# Determine the cmake host system version so we know where to find the iOS SDKs
find_program (CMAKE_UNAME uname /bin /usr/bin /usr/local/bin)

View File

@ -60,6 +60,7 @@
#cmakedefine WITH_SOXR
#cmakedefine WITH_GFX_H264
#cmakedefine WITH_OPENH264
#cmakedefine WITH_OPENH264_LOADING
#cmakedefine WITH_FFMPEG
#cmakedefine WITH_DSP_EXPERIMENTAL
#cmakedefine WITH_DSP_FFMPEG

View File

@ -1,3 +0,0 @@
The dfreerdp FreeRDP client is currently orphaned and unmaintained so please don't expect it to build and work without problems.
If you are interested to update and maintain the dfreerdp client please let us know.

View File

@ -23,63 +23,38 @@
#include <freerdp/api.h>
#include <freerdp/freerdp.h>
struct rdp_assistance_file
{
UINT32 Type;
char* Username;
char* LHTicket;
char* RCTicket;
char* PassStub;
UINT32 DtStart;
UINT32 DtLength;
BOOL LowSpeed;
BOOL RCTicketEncrypted;
char* ConnectionString1;
char* ConnectionString2;
BYTE* EncryptedPassStub;
int EncryptedPassStubLength;
BYTE* EncryptedLHTicket;
int EncryptedLHTicketLength;
char* MachineAddress;
UINT32 MachinePort;
UINT32 MachineCount;
char** MachineAddresses;
UINT32* MachinePorts;
char* RASessionId;
char* RASpecificParams;
};
typedef struct rdp_assistance_file rdpAssistanceFile;
#ifdef __cplusplus
extern "C" {
#endif
FREERDP_API BYTE* freerdp_assistance_hex_string_to_bin(const char* str, int* size);
FREERDP_API char* freerdp_assistance_bin_to_hex_string(const BYTE* data, int size);
FREERDP_API int freerdp_assistance_parse_connection_string1(rdpAssistanceFile* file);
FREERDP_API int freerdp_assistance_parse_connection_string2(rdpAssistanceFile* file);
FREERDP_API BYTE* freerdp_assistance_hex_string_to_bin(const void* str, size_t* size);
FREERDP_API char* freerdp_assistance_bin_to_hex_string(const void* data, size_t size);
FREERDP_API char* freerdp_assistance_generate_pass_stub(DWORD flags);
FREERDP_API char* freerdp_assistance_construct_expert_blob(const char* name, const char* pass);
FREERDP_API BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* passStub, int* pEncryptedSize);
FREERDP_API BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* passStub,
size_t* pEncryptedSize);
FREERDP_API int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* buffer, size_t size);
FREERDP_API int freerdp_assistance_parse_file(rdpAssistanceFile* file, const char* name);
FREERDP_API int freerdp_assistance_decrypt(rdpAssistanceFile* file, const char* password);
FREERDP_API int freerdp_assistance_set_connection_string2(rdpAssistanceFile* file,
const char* string, const char* password);
FREERDP_API int freerdp_client_populate_settings_from_assistance_file(rdpAssistanceFile* file, rdpSettings* settings);
FREERDP_API int freerdp_assistance_parse_file_buffer(rdpAssistanceFile* file, const char* buffer,
size_t size, const char* password);
FREERDP_API int freerdp_assistance_parse_file(rdpAssistanceFile* file, const char* name,
const char* password);
FREERDP_API BOOL freerdp_assistance_populate_settings_from_assistance_file(rdpAssistanceFile* file,
rdpSettings* settings);
FREERDP_API BOOL freerdp_assistance_get_encrypted_pass_stub(rdpAssistanceFile* file,
const char** pwd, size_t* size);
FREERDP_API rdpAssistanceFile* freerdp_assistance_file_new(void);
FREERDP_API void freerdp_assistance_file_free(rdpAssistanceFile* file);
FREERDP_API void freerdp_assistance_print_file(rdpAssistanceFile* file, wLog* log, DWORD level);
#ifdef __cplusplus
}
#endif

View File

@ -203,7 +203,7 @@ struct _CLIPRDR_FORMAT_DATA_RESPONSE
{
DEFINE_CLIPRDR_HEADER_COMMON();
BYTE* requestedFormatData;
const BYTE* requestedFormatData;
};
typedef struct _CLIPRDR_FORMAT_DATA_RESPONSE CLIPRDR_FORMAT_DATA_RESPONSE;
@ -229,7 +229,7 @@ struct _CLIPRDR_FILE_CONTENTS_RESPONSE
UINT32 streamId;
UINT32 dwFlags;
UINT32 cbRequested;
BYTE* requestedData;
const BYTE* requestedData;
};
typedef struct _CLIPRDR_FILE_CONTENTS_RESPONSE CLIPRDR_FILE_CONTENTS_RESPONSE;

View File

@ -316,6 +316,8 @@ typedef struct _DEVICE DEVICE;
typedef struct _IRP IRP;
typedef struct _DEVMAN DEVMAN;
typedef UINT(*pcCustomComponentRequest)(DEVICE* device, UINT16 component, UINT16 packetId,
wStream* s);
typedef UINT(*pcIRPRequest)(DEVICE* device, IRP* irp);
typedef UINT(*pcInitDevice)(DEVICE* device);
typedef UINT(*pcFreeDevice)(DEVICE* device);
@ -328,6 +330,7 @@ struct _DEVICE
const char* name;
wStream* data;
pcCustomComponentRequest CustomComponentRequest;
pcIRPRequest IRPRequest;
pcInitDevice Init;
pcFreeDevice Free;

View File

@ -96,7 +96,7 @@ FREERDP_API int freerdp_client_settings_write_connection_file(const rdpSettings*
const char* filename, BOOL unicode);
FREERDP_API int freerdp_client_settings_parse_assistance_file(rdpSettings* settings,
const char* filename);
int argc, char* argv[]);
FREERDP_API BOOL client_cli_authenticate(freerdp* instance, char** username, char** password,
char** domain);
@ -107,11 +107,25 @@ FREERDP_API DWORD client_cli_verify_certificate(freerdp* instance, const char* c
const char* subject, const char* issuer,
const char* fingerprint, BOOL host_mismatch);
FREERDP_API DWORD client_cli_verify_certificate_ex(freerdp* instance,
const char* host, UINT16 port,
const char* common_name,
const char* subject, const char* issuer,
const char* fingerprint, DWORD flags);
FREERDP_API DWORD client_cli_verify_changed_certificate(freerdp* instance, const char* common_name,
const char* subject, const char* issuer,
const char* fingerprint,
const char* old_subject, const char* old_issuer,
const char* old_fingerprint);
FREERDP_API DWORD client_cli_verify_changed_certificate_ex(freerdp* instance,
const char* host, UINT16 port,
const char* common_name,
const char* subject, const char* issuer,
const char* fingerprint,
const char* old_subject, const char* old_issuer,
const char* old_fingerprint, DWORD flags);
FREERDP_API BOOL client_auto_reconnect(freerdp* instance);
FREERDP_API BOOL client_auto_reconnect_ex(freerdp* instance,
BOOL(*window_events)(freerdp* instance));

View File

@ -34,26 +34,26 @@
typedef struct _cliprdr_client_context CliprdrClientContext;
typedef UINT (*pcCliprdrServerCapabilities)(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities);
typedef UINT (*pcCliprdrClientCapabilities)(CliprdrClientContext* context, CLIPRDR_CAPABILITIES* capabilities);
typedef UINT (*pcCliprdrMonitorReady)(CliprdrClientContext* context, CLIPRDR_MONITOR_READY* monitorReady);
typedef UINT (*pcCliprdrTempDirectory)(CliprdrClientContext* context, CLIPRDR_TEMP_DIRECTORY* tempDirectory);
typedef UINT (*pcCliprdrClientFormatList)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList);
typedef UINT (*pcCliprdrServerFormatList)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST* formatList);
typedef UINT (*pcCliprdrClientFormatListResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse);
typedef UINT (*pcCliprdrServerFormatListResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse);
typedef UINT (*pcCliprdrClientLockClipboardData)(CliprdrClientContext* context, CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData);
typedef UINT (*pcCliprdrServerLockClipboardData)(CliprdrClientContext* context, CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData);
typedef UINT (*pcCliprdrClientUnlockClipboardData)(CliprdrClientContext* context, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData);
typedef UINT (*pcCliprdrServerUnlockClipboardData)(CliprdrClientContext* context, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData);
typedef UINT (*pcCliprdrClientFormatDataRequest)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest);
typedef UINT (*pcCliprdrServerFormatDataRequest)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest);
typedef UINT (*pcCliprdrClientFormatDataResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse);
typedef UINT (*pcCliprdrServerFormatDataResponse)(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse);
typedef UINT (*pcCliprdrClientFileContentsRequest)(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest);
typedef UINT (*pcCliprdrServerFileContentsRequest)(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest);
typedef UINT (*pcCliprdrClientFileContentsResponse)(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse);
typedef UINT (*pcCliprdrServerFileContentsResponse)(CliprdrClientContext* context, CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse);
typedef UINT (*pcCliprdrServerCapabilities)(CliprdrClientContext* context, const CLIPRDR_CAPABILITIES* capabilities);
typedef UINT (*pcCliprdrClientCapabilities)(CliprdrClientContext* context, const CLIPRDR_CAPABILITIES* capabilities);
typedef UINT (*pcCliprdrMonitorReady)(CliprdrClientContext* context, const CLIPRDR_MONITOR_READY* monitorReady);
typedef UINT (*pcCliprdrTempDirectory)(CliprdrClientContext* context, const CLIPRDR_TEMP_DIRECTORY* tempDirectory);
typedef UINT (*pcCliprdrClientFormatList)(CliprdrClientContext* context, const CLIPRDR_FORMAT_LIST* formatList);
typedef UINT (*pcCliprdrServerFormatList)(CliprdrClientContext* context, const CLIPRDR_FORMAT_LIST* formatList);
typedef UINT (*pcCliprdrClientFormatListResponse)(CliprdrClientContext* context, const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse);
typedef UINT (*pcCliprdrServerFormatListResponse)(CliprdrClientContext* context, const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse);
typedef UINT (*pcCliprdrClientLockClipboardData)(CliprdrClientContext* context, const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData);
typedef UINT (*pcCliprdrServerLockClipboardData)(CliprdrClientContext* context, const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData);
typedef UINT (*pcCliprdrClientUnlockClipboardData)(CliprdrClientContext* context, const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData);
typedef UINT (*pcCliprdrServerUnlockClipboardData)(CliprdrClientContext* context, const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData);
typedef UINT (*pcCliprdrClientFormatDataRequest)(CliprdrClientContext* context, const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest);
typedef UINT (*pcCliprdrServerFormatDataRequest)(CliprdrClientContext* context, const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest);
typedef UINT (*pcCliprdrClientFormatDataResponse)(CliprdrClientContext* context, const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse);
typedef UINT (*pcCliprdrServerFormatDataResponse)(CliprdrClientContext* context, const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse);
typedef UINT (*pcCliprdrClientFileContentsRequest)(CliprdrClientContext* context, const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest);
typedef UINT (*pcCliprdrServerFileContentsRequest)(CliprdrClientContext* context, const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest);
typedef UINT (*pcCliprdrClientFileContentsResponse)(CliprdrClientContext* context, const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse);
typedef UINT (*pcCliprdrServerFileContentsResponse)(CliprdrClientContext* context, const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse);
struct _cliprdr_client_context
{

View File

@ -46,7 +46,7 @@ FREERDP_API BOOL freerdp_client_print_command_line_help_ex(
FREERDP_API BOOL freerdp_parse_username(const char* username, char** user, char** domain);
FREERDP_API BOOL freerdp_parse_hostname(const char* hostname, char** host, int* port);
FREERDP_API BOOL freerdp_set_connection_type(rdpSettings* settings, int type);
FREERDP_API BOOL freerdp_set_connection_type(rdpSettings* settings, UINT32 type);
FREERDP_API BOOL freerdp_client_add_device_channel(rdpSettings* settings, int count, char** params);
FREERDP_API BOOL freerdp_client_add_static_channel(rdpSettings* settings, int count, char** params);

View File

@ -78,13 +78,14 @@ typedef void* (*pcRdpgfxGetCacheSlotData)(RdpgfxClientContext* context,
typedef UINT(*pcRdpgfxUpdateSurfaces)(RdpgfxClientContext* context);
typedef UINT(*pcRdpgfxUpdateSurfaceArea)(RdpgfxClientContext* context, UINT16 surfaceId,
UINT32 nrRects, const RECTANGLE_16* rects);
UINT32 nrRects, const RECTANGLE_16* rects);
struct _rdpgfx_client_context
{
void* handle;
void* custom;
/* Implementations require locking */
pcRdpgfxResetGraphics ResetGraphics;
pcRdpgfxStartFrame StartFrame;
pcRdpgfxEndFrame EndFrame;
@ -108,9 +109,11 @@ struct _rdpgfx_client_context
pcRdpgfxSetCacheSlotData SetCacheSlotData;
pcRdpgfxGetCacheSlotData GetCacheSlotData;
/* No locking required */
pcRdpgfxUpdateSurfaces UpdateSurfaces;
pcRdpgfxUpdateSurfaceArea UpdateSurfaceArea;
CRITICAL_SECTION mux;
PROFILER_DEFINE(SurfaceProfiler)
};

View File

@ -155,6 +155,8 @@ struct _RFX_CONTEXT
/* decoded header blocks */
UINT32 decodedHeaderBlocks;
UINT16 expectedDataBlockType;
RFX_MESSAGE currentMessage;
/* routines */
void (*quantization_decode)(INT16* buffer, const UINT32* quantization_values);

View File

@ -51,35 +51,35 @@ struct rdp_certificate_store
};
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
FREERDP_API rdpCertificateData* certificate_data_new(
char* hostname, UINT16 port, char* subject,
char* issuer, char* fingerprint);
const char* hostname, UINT16 port, const char* subject,
const char* issuer, const char* fingerprint);
FREERDP_API void certificate_data_free(
rdpCertificateData* certificate_data);
rdpCertificateData* certificate_data);
FREERDP_API rdpCertificateStore* certificate_store_new(
rdpSettings* settings);
rdpSettings* settings);
FREERDP_API BOOL certificate_data_replace(
rdpCertificateStore* certificate_store,
rdpCertificateData* certificate_data);
rdpCertificateStore* certificate_store,
rdpCertificateData* certificate_data);
FREERDP_API void certificate_store_free(
rdpCertificateStore* certificate_store);
rdpCertificateStore* certificate_store);
FREERDP_API int certificate_data_match(
rdpCertificateStore* certificate_store,
rdpCertificateData* certificate_data);
rdpCertificateStore* certificate_store,
rdpCertificateData* certificate_data);
FREERDP_API BOOL certificate_data_print(
rdpCertificateStore* certificate_store,
rdpCertificateData* certificate_data);
rdpCertificateStore* certificate_store,
rdpCertificateData* certificate_data);
FREERDP_API BOOL certificate_get_stored_data(
rdpCertificateStore* certificate_store,
rdpCertificateData* certificate_data,
char** subject, char** issuer,
char** fingerprint);
rdpCertificateStore* certificate_store,
rdpCertificateData* certificate_data,
char** subject, char** issuer,
char** fingerprint);
#ifdef __cplusplus
}
}
#endif
#endif /* FREERDP_CRYPTO_CERTIFICATE_H */

View File

@ -72,10 +72,10 @@ Note: email and upn amongst others are also alt_names,
but the old crypto_cert_get_alt_names returned only the dns_names
*/
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_names);
FREERDP_API void crypto_cert_subject_alt_name_free(int count, int* lengths, char** alt_names);
FREERDP_API BOOL x509_verify_certificate(CryptoCert cert, char* certificate_store_path);
FREERDP_API rdpCertificateData* crypto_get_certificate_data(X509* xcert, char* hostname,
FREERDP_API BOOL x509_verify_certificate(CryptoCert cert, const char* certificate_store_path);
FREERDP_API rdpCertificateData* crypto_get_certificate_data(X509* xcert, const char* hostname,
UINT16 port);
FREERDP_API BOOL crypto_cert_get_public_key(CryptoCert cert, BYTE** PublicKey,
DWORD* PublicKeyLength);

View File

@ -96,16 +96,6 @@ FREERDP_API int tls_write_all(rdpTls* tls, const BYTE* data, int length);
FREERDP_API int tls_set_alert_code(rdpTls* tls, int level, int description);
FREERDP_API BOOL tls_match_hostname(char* pattern, int pattern_length, char* hostname);
FREERDP_API int tls_verify_certificate(rdpTls* tls, CryptoCert cert, char* hostname, int port);
FREERDP_API void tls_print_certificate_error(char* hostname, UINT16 port,
char* fingerprint, char* hosts_file);
FREERDP_API void tls_print_certificate_name_mismatch_error(
char* hostname, UINT16 port, char* common_name, char** alt_names,
int alt_names_count);
FREERDP_API BOOL tls_print_error(char* func, SSL* connection, int value);
FREERDP_API rdpTls* tls_new(rdpSettings* settings);
FREERDP_API void tls_free(rdpTls* tls);

View File

@ -45,19 +45,6 @@ extern "C" {
#define ERRINFO_RPC_INITIATED_DISCONNECT_BY_USER 0x0000000B
#define ERRINFO_LOGOFF_BY_USER 0x0000000C
/* Protocol-independent codes generated by the Connection Broker */
#define ERRINFO_CB_DESTINATION_NOT_FOUND 0x0000400
#define ERRINFO_CB_LOADING_DESTINATION 0x0000402
#define ERRINFO_CB_REDIRECTING_TO_DESTINATION 0x0000404
#define ERRINFO_CB_SESSION_ONLINE_VM_WAKE 0x0000405
#define ERRINFO_CB_SESSION_ONLINE_VM_BOOT 0x0000406
#define ERRINFO_CB_SESSION_ONLINE_VM_NO_DNS 0x0000407
#define ERRINFO_CB_DESTINATION_POOL_NOT_FREE 0x0000408
#define ERRINFO_CB_CONNECTION_CANCELLED 0x0000409
#define ERRINFO_CB_CONNECTION_ERROR_INVALID_SETTINGS 0x0000410
#define ERRINFO_CB_SESSION_ONLINE_VM_BOOT_TIMEOUT 0x0000411
#define ERRINFO_CB_SESSION_ONLINE_VM_SESSMON_FAILED 0x0000412
/* Protocol-independent licensing codes */
#define ERRINFO_LICENSE_INTERNAL 0x00000100
#define ERRINFO_LICENSE_NO_LICENSE_SERVER 0x00000101
@ -71,6 +58,19 @@ extern "C" {
#define ERRINFO_LICENSE_CANT_UPGRADE_LICENSE 0x00000109
#define ERRINFO_LICENSE_NO_REMOTE_CONNECTIONS 0x0000010A
/* Protocol-independent codes generated by the Connection Broker */
#define ERRINFO_CB_DESTINATION_NOT_FOUND 0x0000400
#define ERRINFO_CB_LOADING_DESTINATION 0x0000402
#define ERRINFO_CB_REDIRECTING_TO_DESTINATION 0x0000404
#define ERRINFO_CB_SESSION_ONLINE_VM_WAKE 0x0000405
#define ERRINFO_CB_SESSION_ONLINE_VM_BOOT 0x0000406
#define ERRINFO_CB_SESSION_ONLINE_VM_NO_DNS 0x0000407
#define ERRINFO_CB_DESTINATION_POOL_NOT_FREE 0x0000408
#define ERRINFO_CB_CONNECTION_CANCELLED 0x0000409
#define ERRINFO_CB_CONNECTION_ERROR_INVALID_SETTINGS 0x0000410
#define ERRINFO_CB_SESSION_ONLINE_VM_BOOT_TIMEOUT 0x0000411
#define ERRINFO_CB_SESSION_ONLINE_VM_SESSMON_FAILED 0x0000412
/* RDP specific codes */
#define ERRINFO_UNKNOWN_DATA_PDU_TYPE 0x000010C9
#define ERRINFO_UNKNOWN_PDU_TYPE 0x000010CA
@ -134,6 +134,7 @@ extern "C" {
#define ERRINFO_BAD_MONITOR_DATA 0x00001129
#define ERRINFO_VC_DECOMPRESSED_REASSEMBLE_FAILED 0x0000112A
#define ERRINFO_VC_DATA_TOO_LONG 0x0000112B
#define ERRINFO_BAD_FRAME_ACK_DATA 0x0000112C
#define ERRINFO_GRAPHICS_MODE_NOT_SUPPORTED 0x0000112D
#define ERRINFO_GRAPHICS_SUBSYSTEM_RESET_FAILED 0x0000112E
#define ERRINFO_GRAPHICS_SUBSYSTEM_FAILED 0x0000112F
@ -141,6 +142,9 @@ extern "C" {
#define ERRINFO_TIMEZONE_KEY_NAME_LENGTH_TOO_LONG 0x00001131
#define ERRINFO_DYNAMIC_DST_DISABLED_FIELD_MISSING 0x00001132
#define ERRINFO_VC_DECODING_ERROR 0x00001133
#define ERRINFO_VIRTUALDESKTOPTOOLARGE 0x00001134
#define ERRINFO_MONITORGEOMETRYVALIDATIONFAILED 0x00001135
#define ERRINFO_INVALIDMONITORCOUNT 0x00001136
#define ERRINFO_UPDATE_SESSION_KEY_FAILED 0x00001191
#define ERRINFO_DECRYPT_FAILED 0x00001192
#define ERRINFO_ENCRYPT_FAILED 0x00001193

View File

@ -59,6 +59,14 @@ typedef RDP_CLIENT_ENTRY_POINTS_V1 RDP_CLIENT_ENTRY_POINTS;
extern "C" {
#endif
/* Flags used by certificate callbacks */
#define VERIFY_CERT_FLAG_NONE 0x00
#define VERIFY_CERT_FLAG_LEGACY 0x02
#define VERIFY_CERT_FLAG_REDIRECT 0x10
#define VERIFY_CERT_FLAG_GATEWAY 0x20
#define VERIFY_CERT_FLAG_CHANGED 0x40
#define VERIFY_CERT_FLAG_MISMATCH 0x80
typedef BOOL (*pContextNew)(freerdp* instance, rdpContext* context);
typedef void (*pContextFree)(freerdp* instance, rdpContext* context);
@ -71,6 +79,7 @@ typedef BOOL (*pAuthenticate)(freerdp* instance, char** username,
/** @brief Callback used if user interaction is required to accept
* an unknown certificate.
*
* @deprecated Use pVerifyCertificateEx
* @param common_name The certificate registered hostname.
* @param subject The common name of the certificate.
* @param issuer The issuer of the certificate.
@ -88,9 +97,33 @@ typedef DWORD (*pVerifyCertificate)(freerdp* instance,
const char* fingerprint,
BOOL host_mismatch);
/** @brief Callback used if user interaction is required to accept
* an unknown certificate.
*
* @param host The hostname connecting to.
* @param port The port connecting to.
* @param common_name The certificate registered hostname.
* @param subject The common name of the certificate.
* @param issuer The issuer of the certificate.
* @param fingerprint The fingerprint of the certificate.
* @param flags Flags of type VERIFY_CERT_FLAG*
*
* @return 1 to accept and store a certificate, 2 to accept
* a certificate only for this session, 0 otherwise.
*/
typedef DWORD (*pVerifyCertificateEx)(freerdp* instance,
const char* host,
UINT16 port,
const char* common_name,
const char* subject,
const char* issuer,
const char* fingerprint,
DWORD flags);
/** @brief Callback used if user interaction is required to accept
* a changed certificate.
*
* @deprecated Use pVerifyChangedCertificateEx
* @param common_name The certificate registered hostname.
* @param subject The common name of the new certificate.
* @param issuer The issuer of the new certificate.
@ -111,9 +144,53 @@ typedef DWORD (*pVerifyChangedCertificate)(freerdp* instance,
const char* old_subject,
const char* old_issuer,
const char* old_fingerprint);
typedef int (*pVerifyX509Certificate)(freerdp* instance, BYTE* data,
int length, const char* hostname,
int port, DWORD flags);
/** @brief Callback used if user interaction is required to accept
* a changed certificate.
*
* @param host The hostname connecting to.
* @param port The port connecting to.
* @param common_name The certificate registered hostname.
* @param subject The common name of the new certificate.
* @param issuer The issuer of the new certificate.
* @param fingerprint The fingerprint of the new certificate.
* @param old_subject The common name of the old certificate.
* @param old_issuer The issuer of the new certificate.
* @param old_fingerprint The fingerprint of the old certificate.
* @param flags Flags of type VERIFY_CERT_FLAG*
*
* @return 1 to accept and store a certificate, 2 to accept
* a certificate only for this session, 0 otherwise.
*/
typedef DWORD (*pVerifyChangedCertificateEx)(freerdp* instance,
const char* host,
UINT16 port,
const char* common_name,
const char* subject,
const char* issuer,
const char* new_fingerprint,
const char* old_subject,
const char* old_issuer,
const char* old_fingerprint,
DWORD flags);
/** @brief Callback used if user interaction is required to accept
* a certificate.
*
* @param instance Pointer to the freerdp instance.
* @param data Pointer to certificate data in PEM format.
* @param length The length of the certificate data.
* @param hostname The hostname connecting to.
* @param port The port connecting to.
* @param flags Flags of type VERIFY_CERT_FLAG*
*
* @return 1 to accept and store a certificate, 2 to accept
* a certificate only for this session, 0 otherwise.
*/
typedef int (*pVerifyX509Certificate)(freerdp* instance, const BYTE* data,
size_t length, const char* hostname,
UINT16 port, DWORD flags);
typedef int (*pLogonErrorInfo)(freerdp* instance, UINT32 data, UINT32 type);
@ -122,6 +199,9 @@ typedef int (*pSendChannelData)(freerdp* instance, UINT16 channelId, BYTE* data,
typedef int (*pReceiveChannelData)(freerdp* instance, UINT16 channelId,
BYTE* data, int size, int flags, int totalSize);
typedef BOOL (*pPresentGatewayMessage)(freerdp* instance, UINT32 type, BOOL isDisplayMandatory,
BOOL isConsentMandatory, size_t length, const WCHAR* message);
/**
* Defines the context for a given instance of RDP connection.
* It is embedded in the rdp_freerdp structure, and allocated by a call to freerdp_context_new().
@ -274,11 +354,12 @@ struct rdp_freerdp
It is used to get the username/password when it was not provided at connection time. */
ALIGN64 pVerifyCertificate VerifyCertificate; /**< (offset 51)
Callback for certificate validation.
Used to verify that an unknown certificate is trusted. */
Used to verify that an unknown certificate is trusted.
DEPRECATED: Use VerifyChangedCertificateEx*/
ALIGN64 pVerifyChangedCertificate VerifyChangedCertificate; /**< (offset 52)
Callback for changed certificate validation.
Used when a certificate differs from stored fingerprint.
If returns TRUE, the new fingerprint will be trusted and old thrown out. */
DEPRECATED: Use VerifyChangedCertificateEx */
ALIGN64 pVerifyX509Certificate
VerifyX509Certificate; /**< (offset 53) Callback for X509 certificate verification (PEM format) */
@ -294,7 +375,11 @@ struct rdp_freerdp
Callback for gateway authentication.
It is used to get the username/password when it was not provided at connection time. */
UINT64 paddingD[64 - 57]; /* 57 */
ALIGN64 pPresentGatewayMessage PresentGatewayMessage;/**< (offset 57)
Callback for gateway consent messages.
It is used to present consent messages to the user. */
UINT64 paddingD[64 - 58]; /* 58 */
ALIGN64 pSendChannelData SendChannelData; /* (offset 64)
Callback for sending data to a channel.
@ -305,7 +390,13 @@ struct rdp_freerdp
This is called by freerdp_channel_process() (if not NULL).
Clients will typically use a function that calls freerdp_channels_data() to perform the needed tasks. */
UINT64 paddingE[80 - 66]; /* 66 */
ALIGN64 pVerifyCertificateEx VerifyCertificateEx; /**< (offset 66)
Callback for certificate validation.
Used to verify that an unknown certificate is trusted. */
ALIGN64 pVerifyChangedCertificateEx VerifyChangedCertificateEx; /**< (offset 67)
Callback for changed certificate validation.
Used when a certificate differs from stored fingerprint. */
UINT64 paddingE[80 - 68]; /* 68 */
};
struct rdp_channel_handles

View File

@ -27,7 +27,7 @@ struct gdi_gfx_surface
{
UINT16 surfaceId;
rdpCodecs* codecs;
H264_CONTEXT *h264;
H264_CONTEXT* h264;
UINT32 width;
UINT32 height;
BYTE* data;
@ -55,7 +55,7 @@ typedef struct gdi_gfx_cache_entry gdiGfxCacheEntry;
extern "C" {
#endif
FREERDP_API void gdi_graphics_pipeline_init(rdpGdi* gdi, RdpgfxClientContext* gfx);
FREERDP_API BOOL gdi_graphics_pipeline_init(rdpGdi* gdi, RdpgfxClientContext* gfx);
FREERDP_API void gdi_graphics_pipeline_uninit(rdpGdi* gdi, RdpgfxClientContext* gfx);
#ifdef __cplusplus

160
include/freerdp/license.h Normal file
View File

@ -0,0 +1,160 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Licensing API
*
* Copyright 2018 David Fort <contact@hardening-consulting.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_LICENSE_H
#define FREERDP_LICENSE_H
#include <freerdp/api.h>
typedef struct rdp_license rdpLicense;
/** @brief Licensing Packet Types */
enum
{
LICENSE_REQUEST = 0x01,
PLATFORM_CHALLENGE = 0x02,
NEW_LICENSE = 0x03,
UPGRADE_LICENSE = 0x04,
LICENSE_INFO = 0x12,
NEW_LICENSE_REQUEST = 0x13,
PLATFORM_CHALLENGE_RESPONSE = 0x15,
ERROR_ALERT = 0xFF
};
#define LICENSE_PKT_CS_MASK (LICENSE_INFO | NEW_LICENSE_REQUEST | PLATFORM_CHALLENGE_RESPONSE | ERROR_ALERT)
#define LICENSE_PKT_SC_MASK (LICENSE_REQUEST | PLATFORM_CHALLENGE | NEW_LICENSE | UPGRADE_LICENSE | ERROR_ALERT)
#define LICENSE_PKT_MASK (LICENSE_PKT_CS_MASK | LICENSE_PKT_SC_MASK)
#define LICENSE_PREAMBLE_LENGTH 4
/* Cryptographic Lengths */
#define CLIENT_RANDOM_LENGTH 32
#define SERVER_RANDOM_LENGTH 32
#define MASTER_SECRET_LENGTH 48
#define PREMASTER_SECRET_LENGTH 48
#define SESSION_KEY_BLOB_LENGTH 48
#define MAC_SALT_KEY_LENGTH 16
#define LICENSING_ENCRYPTION_KEY_LENGTH 16
#define HWID_PLATFORM_ID_LENGTH 4
#define HWID_UNIQUE_DATA_LENGTH 16
#define HWID_LENGTH 20
#define LICENSING_PADDING_SIZE 8
/* Preamble Flags */
#define PREAMBLE_VERSION_2_0 0x02
#define PREAMBLE_VERSION_3_0 0x03
#define LicenseProtocolVersionMask 0x0F
#define EXTENDED_ERROR_MSG_SUPPORTED 0x80
/** @brief binary Blob Types */
enum
{
BB_ANY_BLOB = 0x0000,
BB_DATA_BLOB = 0x0001,
BB_RANDOM_BLOB = 0x0002,
BB_CERTIFICATE_BLOB = 0x0003,
BB_ERROR_BLOB = 0x0004,
BB_ENCRYPTED_DATA_BLOB = 0x0009,
BB_KEY_EXCHG_ALG_BLOB = 0x000D,
BB_SCOPE_BLOB = 0x000E,
BB_CLIENT_USER_NAME_BLOB = 0x000F,
BB_CLIENT_MACHINE_NAME_BLOB = 0x0010
};
/* License Key Exchange Algorithms */
#define KEY_EXCHANGE_ALG_RSA 0x00000001
/** @brief license Error Codes */
enum
{
ERR_INVALID_SERVER_CERTIFICATE = 0x00000001,
ERR_NO_LICENSE = 0x00000002,
ERR_INVALID_MAC = 0x00000003,
ERR_INVALID_SCOPE = 0x00000004,
ERR_NO_LICENSE_SERVER = 0x00000006,
STATUS_VALID_CLIENT = 0x00000007,
ERR_INVALID_CLIENT = 0x00000008,
ERR_INVALID_PRODUCT_ID = 0x0000000B,
ERR_INVALID_MESSAGE_LENGTH = 0x0000000C
};
/** @brief state Transition Codes */
enum
{
ST_TOTAL_ABORT = 0x00000001,
ST_NO_TRANSITION = 0x00000002,
ST_RESET_PHASE_TO_START = 0x00000003,
ST_RESEND_LAST_MESSAGE = 0x00000004
};
/** @brief Platform Challenge Types */
enum
{
WIN32_PLATFORM_CHALLENGE_TYPE = 0x0100,
WIN16_PLATFORM_CHALLENGE_TYPE = 0x0200,
WINCE_PLATFORM_CHALLENGE_TYPE = 0x0300,
OTHER_PLATFORM_CHALLENGE_TYPE = 0xFF00
};
/** @brief License Detail Levels */
enum
{
LICENSE_DETAIL_SIMPLE = 0x0001,
LICENSE_DETAIL_MODERATE = 0x0002,
LICENSE_DETAIL_DETAIL = 0x0003
};
/*
* PlatformId:
*
* The most significant byte of the PlatformId field contains the operating system version of the client.
* The second most significant byte of the PlatformId field identifies the ISV that provided the client image.
* The remaining two bytes in the PlatformId field are used by the ISV to identify the build number of the operating system.
*
* 0x04010000:
*
* CLIENT_OS_ID_WINNT_POST_52 (0x04000000)
* CLIENT_IMAGE_ID_MICROSOFT (0x00010000)
*/
enum
{
CLIENT_OS_ID_WINNT_351 = 0x01000000,
CLIENT_OS_ID_WINNT_40 = 0x02000000,
CLIENT_OS_ID_WINNT_50 = 0x03000000,
CLIENT_OS_ID_WINNT_POST_52 = 0x04000000,
CLIENT_IMAGE_ID_MICROSOFT = 0x00010000,
CLIENT_IMAGE_ID_CITRIX = 0x00020000,
};
#ifdef __cpluscplus
extern "C" {
#endif
FREERDP_API BOOL license_send_valid_client_error_packet(rdpRdp* rdp);
#ifdef __cpluscplus
}
#endif
#endif /* FREERDP_LICENSE_H */

View File

@ -67,6 +67,17 @@ typedef int (*psPeerVirtualChannelWrite)(freerdp_peer* peer, HANDLE hChannel, BY
typedef void* (*psPeerVirtualChannelGetData)(freerdp_peer* peer, HANDLE hChannel);
typedef int (*psPeerVirtualChannelSetData)(freerdp_peer* peer, HANDLE hChannel, void* data);
/** @brief the result of the license callback */
typedef enum
{
LICENSE_CB_INTERNAL_ERROR, /** an internal error happened in the callback */
LICENSE_CB_ABORT, /** licensing process failed, abort the connection */
LICENSE_CB_IN_PROGRESS, /** incoming packet has been treated, we're waiting for further packets to complete the workflow */
LICENSE_CB_COMPLETED /** the licensing workflow has completed, go to next step */
} LicenseCallbackResult;
typedef LicenseCallbackResult (*psPeerLicenseCallback)(freerdp_peer* peer, wStream* s);
struct rdp_freerdp_peer
{
@ -123,6 +134,7 @@ struct rdp_freerdp_peer
psPeerAdjustMonitorsLayout AdjustMonitorsLayout;
psPeerClientCapabilities ClientCapabilities;
psPeerComputeNtlmHash ComputeNtlmHash;
psPeerLicenseCallback LicenseCallback;
};
#ifdef __cplusplus

View File

@ -44,6 +44,7 @@
#define RAIL_EXEC_FLAG_TRANSLATE_FILES 0x0002
#define RAIL_EXEC_FLAG_FILE 0x0004
#define RAIL_EXEC_FLAG_EXPAND_ARGUMENTS 0x0008
#define RAIL_EXEC_FLAG_APP_USER_MODEL_ID 0x0010
/* Server Execute Result PDU */
#define RAIL_EXEC_S_OK 0x0000

View File

@ -682,6 +682,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_PrivateKeyContent (1417)
#define FreeRDP_RdpKeyContent (1418)
#define FreeRDP_AutoAcceptCertificate (1419)
#define FreeRDP_AutoDenyCertificate (1420)
#define FreeRDP_Workarea (1536)
#define FreeRDP_Fullscreen (1537)
#define FreeRDP_PercentScreen (1538)
@ -709,6 +710,7 @@ typedef struct _RDPDR_PARALLEL RDPDR_PARALLEL;
#define FreeRDP_AuthenticationOnly (1603)
#define FreeRDP_CredentialsFromStdin (1604)
#define FreeRDP_UnmapButtons (1605)
#define FreeRDP_OldLicenseBehaviour (1606)
#define FreeRDP_ComputerName (1664)
#define FreeRDP_ConnectionFile (1728)
#define FreeRDP_AssistanceFile (1729)
@ -1135,7 +1137,8 @@ struct rdp_settings
ALIGN64 char* PrivateKeyContent; /* 1417 */
ALIGN64 char* RdpKeyContent; /* 1418 */
ALIGN64 BOOL AutoAcceptCertificate; /* 1419 */
UINT64 padding1472[1472 - 1420]; /* 1420 */
ALIGN64 BOOL AutoDenyCertificate; /* 1420 */
UINT64 padding1472[1472 - 1421]; /* 1421 */
UINT64 padding1536[1536 - 1472]; /* 1472 */
/**
@ -1518,7 +1521,7 @@ struct rdp_settings
ALIGN64 BYTE*
SettingsModified; /* byte array marking fields that have been modified from their default value */
ALIGN64 char* ActionScript;
ALIGN64 BOOL Floatbar;
ALIGN64 DWORD Floatbar;
};
typedef struct rdp_settings rdpSettings;

View File

@ -139,6 +139,20 @@ enum SURFCMD_FRAMEACTION
SURFACECMD_FRAMEACTION_END = 0x0001
};
/** @brief status code as in 2.2.5.2 Server Status Info PDU */
enum
{
TS_STATUS_FINDING_DESTINATION = 0x00000401,
TS_STATUS_LOADING_DESTINATION = 0x00000402,
TS_STATUS_BRINGING_SESSION_ONLINE = 0x00000403,
TS_STATUS_REDIRECTING_TO_DESTINATION = 0x00000404,
TS_STATUS_VM_LOADING = 0x00000501,
TS_STATUS_VM_WAKING = 0x00000502,
TS_STATUS_VM_STARTING = 0x00000503,
TS_STATUS_VM_STARTING_MONITORING = 0x00000504,
TS_STATUS_VM_RETRYING_MONITORING = 0x00000505
};
struct _SURFACE_FRAME
{
UINT32 frameId;
@ -180,6 +194,7 @@ typedef BOOL (*pSurfaceFrameAcknowledge)(rdpContext* context, UINT32 frameId);
typedef BOOL (*pSaveSessionInfo)(rdpContext* context, UINT32 type, void* data);
typedef BOOL (*pSetKeyboardImeStatus)(rdpContext* context, UINT16 imeId, UINT32 imeState,
UINT32 imeConvMode);
typedef BOOL (*pServerStatusInfo)(rdpContext* context, UINT32 status);
struct rdp_update
{
@ -216,7 +231,8 @@ struct rdp_update
pSurfaceFrameBits SurfaceFrameBits; /* 67 */
pSurfaceFrameAcknowledge SurfaceFrameAcknowledge; /* 68 */
pSaveSessionInfo SaveSessionInfo; /* 69 */
UINT32 paddingE[80 - 70]; /* 70 */
pServerStatusInfo ServerStatusInfo; /* 70 */
UINT32 paddingE[80 - 71]; /* 71 */
/* internal */

View File

@ -206,7 +206,9 @@ endif()
if(WITH_OPENH264)
set(CODEC_SRCS ${CODEC_SRCS} codec/h264_openh264.c)
freerdp_include_directory_add(${OPENH264_INCLUDE_DIR})
freerdp_library_add(${OPENH264_LIBRARIES})
if (NOT WITH_OPENH264_LOADING)
freerdp_library_add(${OPENH264_LIBRARIES})
endif (NOT WITH_OPENH264_LOADING)
endif()
if(WITH_FFMPEG)

View File

@ -796,6 +796,9 @@ CACHE_GLYPH_ORDER* copy_cache_glyph_order(rdpContext* context, const CACHE_GLYPH
if (glyph->unicodeCharacters)
{
if (glyph->cGlyphs == 0)
goto fail;
dst->unicodeCharacters = calloc(glyph->cGlyphs, sizeof(WCHAR));
if (!dst->unicodeCharacters)
@ -855,6 +858,9 @@ CACHE_GLYPH_V2_ORDER* copy_cache_glyph_v2_order(rdpContext* context,
if (glyph->unicodeCharacters)
{
if (glyph->cGlyphs == 0)
goto fail;
dst->unicodeCharacters = calloc(glyph->cGlyphs, sizeof(WCHAR));
if (!dst->unicodeCharacters)

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