Merge branch 'master' of github.com:FreeRDP/FreeRDP

This commit is contained in:
Marc-André Moreau 2016-03-07 10:19:50 -05:00
commit ceefc4b099
248 changed files with 11399 additions and 4700 deletions

View File

@ -122,8 +122,10 @@ if(NOT DEFINED BUILD_SHARED_LIBS)
endif()
endif()
if(NOT DEFINED EXPORT_ALL_SYMBOLS)
set(EXPORT_ALL_SYMBOLS TRUE)
if(BUILD_TESTING)
set(EXPORT_ALL_SYMBOLS TRUE)
elseif(NOT DEFINED EXPORT_ALL_SYMBOLS)
set(EXPORT_ALL_SYMBOLS FALSE)
endif()
# BSD
@ -698,17 +700,17 @@ if (TARGET_ARCH MATCHES "sparc")
endif()
# Path to put FreeRDP data
set(FREERDP_DATA_PATH "${CMAKE_INSTALL_PREFIX}/share/freerdp")
set(FREERDP_DATA_PATH "${CMAKE_INSTALL_PREFIX}/share/freerdp${FREERDP_VERSION_MAJOR}")
# Path to put plugins
set(FREERDP_LIBRARY_PATH "${CMAKE_INSTALL_LIBDIR}")
set(FREERDP_PLUGIN_PATH "${CMAKE_INSTALL_LIBDIR}/freerdp")
set(FREERDP_PLUGIN_PATH "${CMAKE_INSTALL_LIBDIR}/freerdp${FREERDP_VERSION_MAJOR}")
set(FREERDP_ADDIN_PATH "${FREERDP_PLUGIN_PATH}")
# Path to put extensions
set(FREERDP_EXTENSION_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/freerdp/extensions")
set(FREERDP_EXTENSION_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/freerdp${FREERDP_VERSION_MAJOR}/extensions")
# Include directories
include_directories(${CMAKE_CURRENT_BINARY_DIR})
@ -789,6 +791,10 @@ include_directories("${CMAKE_BINARY_DIR}/rdtk/include")
add_subdirectory(rdtk)
if(WAYLAND_FOUND)
add_subdirectory(uwac)
endif()
if(BSD)
if(IS_DIRECTORY /usr/local/include)
include_directories(/usr/local/include)

View File

@ -522,6 +522,8 @@ static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* arg
#ifdef STATIC_CHANNELS
#define freerdp_audin_client_subsystem_entry alsa_freerdp_audin_client_subsystem_entry
#else
#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry
#endif
/**

View File

@ -82,7 +82,7 @@ struct _AUDIN_PLUGIN
/* Parsed plugin data */
UINT16 fixed_format;
UINT16 fixed_channel;
UINT16 fixed_channel;
UINT32 fixed_rate;
char* subsystem;
char* device_name;
@ -93,6 +93,8 @@ struct _AUDIN_PLUGIN
rdpContext* rdpcontext;
};
static BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args);
/**
* Function description
*
@ -639,8 +641,12 @@ static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDI
{
PFREERDP_AUDIN_DEVICE_ENTRY entry;
FREERDP_AUDIN_DEVICE_ENTRY_POINTS entryPoints;
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*)pPlugin;
UINT error;
if (!audin_process_addin_args(audin, args))
return CHANNEL_RC_INITIALIZATION_ERROR;
entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_channel_addin_entry("audin", (LPSTR) name, NULL, 0);
if (entry == NULL)
@ -660,6 +666,7 @@ static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDI
return error;
}
WLog_INFO(TAG, "Loaded %s backend for audin", name);
return CHANNEL_RC_OK;
}
@ -707,18 +714,19 @@ static COMMAND_LINE_ARGUMENT_A audin_args[] =
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
};
static BOOL audin_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args)
BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args)
{
int status;
DWORD flags;
COMMAND_LINE_ARGUMENT_A* arg;
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin;
UINT error;
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON;
flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD;
status = CommandLineParseArgumentsA(args->argc, (const char**) args->argv,
audin_args, flags, audin, NULL, NULL);
if (status != 0)
return FALSE;
arg = audin_args;
@ -771,6 +779,8 @@ static BOOL audin_process_addin_args(IWTSPlugin* pPlugin, ADDIN_ARGV* args)
#ifdef STATIC_CHANNELS
#define DVCPluginEntry audin_DVCPluginEntry
#else
#define DVCPluginEntry FREERDP_API DVCPluginEntry
#endif
/**
@ -786,7 +796,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
char *device;
};
UINT error = CHANNEL_RC_OK;
UINT error = CHANNEL_RC_INITIALIZATION_ERROR;
ADDIN_ARGV* args;
AUDIN_PLUGIN* audin;
struct SubsystemEntry entries[] =
@ -837,31 +847,53 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
args = pEntryPoints->GetPluginData(pEntryPoints);
audin->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings(pEntryPoints))->instance)->context;
while (entry && entry->subsystem && !audin->device)
if (args)
{
if ((error = audin_set_subsystem(audin, entry->subsystem)))
{
WLog_ERR(TAG, "audin_set_subsystem for %s failed with error %lu!",
entry->subsystem, error);
}
else if ((error = audin_set_device_name(audin, entry->device)))
{
WLog_ERR(TAG, "audin_set_device_name for %s failed with error %lu!",
entry->subsystem, error);
}
else if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args)))
if (!audin_process_addin_args(audin, args))
goto out;
}
if (audin->subsystem)
{
if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args)))
{
WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %lu!",
entry->subsystem, error);
audin->subsystem, error);
goto out;
}
}
else
{
while (entry && entry->subsystem && !audin->device)
{
if ((error = audin_set_subsystem(audin, entry->subsystem)))
{
WLog_ERR(TAG, "audin_set_subsystem for %s failed with error %lu!",
entry->subsystem, error);
}
else if ((error = audin_set_device_name(audin, entry->device)))
{
WLog_ERR(TAG, "audin_set_device_name for %s failed with error %lu!",
entry->subsystem, error);
}
else if ((error = audin_load_device_plugin((IWTSPlugin*) audin, audin->subsystem, args)))
{
WLog_ERR(TAG, "audin_load_device_plugin %s failed with error %lu!",
entry->subsystem, error);
}
entry++;
entry++;
}
}
if (audin->device == NULL)
{
WLog_ERR(TAG, "no sound device.");
}
error = CHANNEL_RC_OK;
out:
if (error != CHANNEL_RC_OK)
audin_plugin_terminated((IWTSPlugin*)audin);
return error;
}

View File

@ -405,6 +405,8 @@ static UINT audin_mac_parse_addin_args(AudinMacDevice *device, ADDIN_ARGV *args)
#ifdef STATIC_CHANNELS
#define freerdp_audin_client_subsystem_entry mac_freerdp_audin_client_subsystem_entry
#else
#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry
#endif
UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints)

View File

@ -218,8 +218,6 @@ static BOOL audin_opensles_format_supported(IAudinDevice* device, audinFormat* f
switch (format->wFormatTag)
{
/* TODO: Deactivated, untested */
#if 0
case WAVE_FORMAT_PCM: /* PCM */
if (format->cbSize == 0 &&
(format->nSamplesPerSec <= 48000) &&
@ -229,7 +227,6 @@ static BOOL audin_opensles_format_supported(IAudinDevice* device, audinFormat* f
return TRUE;
}
break;
#endif
/* TODO: Deactivated format, does not work, find out why */
// case WAVE_FORMAT_ADPCM: /* IMA ADPCM */
case WAVE_FORMAT_DVI_ADPCM:
@ -479,6 +476,9 @@ static UINT audin_opensles_parse_addin_args(AudinOpenSLESDevice* device,
#ifdef STATIC_CHANNELS
#define freerdp_audin_client_subsystem_entry \
opensles_freerdp_audin_client_subsystem_entry
#else
#define freerdp_audin_client_subsystem_entry \
FREERDP_API freerdp_audin_client_subsystem_entry
#endif
/**

View File

@ -485,6 +485,8 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args)
#ifdef STATIC_CHANNELS
#define freerdp_audin_client_subsystem_entry oss_freerdp_audin_client_subsystem_entry
#else
#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry
#endif
/**

View File

@ -525,6 +525,8 @@ static UINT audin_pulse_parse_addin_args(AudinPulseDevice* device, ADDIN_ARGV* a
#ifdef STATIC_CHANNELS
#define freerdp_audin_client_subsystem_entry pulse_freerdp_audin_client_subsystem_entry
#else
#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry
#endif
/**

View File

@ -393,6 +393,8 @@ static UINT audin_winmm_parse_addin_args(AudinWinmmDevice* device, ADDIN_ARGV* a
#ifdef STATIC_CHANNELS
#define freerdp_audin_client_subsystem_entry winmm_freerdp_audin_client_subsystem_entry
#else
#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry
#endif
/**

View File

@ -102,16 +102,25 @@ UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data
formats[index].formatName = NULL;
/* According to MS-RDPECLIP 2.2.3.1.1.1 formatName is "a 32-byte block containing
* the *null-terminated* name assigned to the Clipboard Format: (32 ASCII 8 characters
* or 16 Unicode characters)"
* However, both Windows RDSH and mstsc violate this specs as seen in the following
* example of a transferred short format name string: [R.i.c.h. .T.e.x.t. .F.o.r.m.a.t.]
* These are 16 unicode charaters - *without* terminating null !
*/
if (asciiNames)
{
szFormatName = (char*) Stream_Pointer(s);
if (szFormatName[0])
{
/* ensure null termination */
formats[index].formatName = (char*) malloc(32 + 1);
if (!formats[index].formatName)
{
WLog_ERR(TAG, "calloc failed!");
WLog_ERR(TAG, "malloc failed!");
error = CHANNEL_RC_NO_MEMORY;
goto error_out;
}
@ -125,8 +134,16 @@ UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data
if (wszFormatName[0])
{
ConvertFromUnicode(CP_UTF8, 0, wszFormatName,
16, &(formats[index].formatName), 0, NULL, NULL);
/* ConvertFromUnicode always returns a null-terminated
* string on success, even if the source string isn't.
*/
if (ConvertFromUnicode(CP_UTF8, 0, wszFormatName, 16,
&(formats[index].formatName), 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert short clipboard format name");
error = ERROR_INTERNAL_ERROR;
goto error_out;
}
}
}
@ -185,8 +202,13 @@ UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data
if (formatNameLength)
{
ConvertFromUnicode(CP_UTF8, 0, wszFormatName,
-1, &(formats[index].formatName), 0, NULL, NULL);
if (ConvertFromUnicode(CP_UTF8, 0, wszFormatName, -1,
&(formats[index].formatName), 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert long clipboard format name");
error = ERROR_INTERNAL_ERROR;
goto error_out;
}
}
Stream_Seek(s, (formatNameLength + 1) * 2);

View File

@ -1,3 +0,0 @@
LIBRARY "cliprdr"
EXPORTS
VirtualChannelEntry @1

View File

@ -597,8 +597,12 @@ static UINT cliprdr_server_receive_temporary_directory(CliprdrServerContext* con
free(cliprdr->temporaryDirectory);
cliprdr->temporaryDirectory = NULL;
ConvertFromUnicode(CP_UTF8, 0, wszTempDir, -1,
&(cliprdr->temporaryDirectory), 0, NULL, NULL);
if (ConvertFromUnicode(CP_UTF8, 0, wszTempDir, -1,
&(cliprdr->temporaryDirectory), 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert temporary directory name");
return ERROR_INVALID_DATA;
}
length = strlen(cliprdr->temporaryDirectory);
@ -680,12 +684,21 @@ static UINT cliprdr_server_receive_format_list(CliprdrServerContext* context, wS
formats[index].formatName = NULL;
/* According to MS-RDPECLIP 2.2.3.1.1.1 formatName is "a 32-byte block containing
* the *null-terminated* name assigned to the Clipboard Format: (32 ASCII 8 characters
* or 16 Unicode characters)"
* However, both Windows RDSH and mstsc violate this specs as seen in the following
* example of a transferred short format name string: [R.i.c.h. .T.e.x.t. .F.o.r.m.a.t.]
* These are 16 unicode charaters - *without* terminating null !
*/
if (asciiNames)
{
szFormatName = (char*) Stream_Pointer(s);
if (szFormatName[0])
{
/* ensure null termination */
formats[index].formatName = (char*) malloc(32 + 1);
CopyMemory(formats[index].formatName, szFormatName, 32);
formats[index].formatName[32] = '\0';
@ -697,8 +710,16 @@ static UINT cliprdr_server_receive_format_list(CliprdrServerContext* context, wS
if (wszFormatName[0])
{
ConvertFromUnicode(CP_UTF8, 0, wszFormatName,
16, &(formats[index].formatName), 0, NULL, NULL);
/* ConvertFromUnicode always returns a null-terminated
* string on success, even if the source string isn't.
*/
if (ConvertFromUnicode(CP_UTF8, 0, wszFormatName, 16,
&(formats[index].formatName), 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert short clipboard format name");
error = ERROR_INVALID_DATA;
goto out;
}
}
}
@ -757,8 +778,13 @@ static UINT cliprdr_server_receive_format_list(CliprdrServerContext* context, wS
if (formatNameLength)
{
ConvertFromUnicode(CP_UTF8, 0, wszFormatName,
-1, &(formats[index].formatName), 0, NULL, NULL);
if (ConvertFromUnicode(CP_UTF8, 0, wszFormatName, -1,
&(formats[index].formatName), 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert long clipboard format name");
error = ERROR_INVALID_DATA;
goto out;
}
}
Stream_Seek(s, (formatNameLength + 1) * 2);
@ -775,6 +801,7 @@ static UINT cliprdr_server_receive_format_list(CliprdrServerContext* context, wS
if (error)
WLog_ERR(TAG, "ClientFormatList failed with error %lu!", error);
out:
for (index = 0; index < formatList.numFormats; index++)
{
free(formatList.formats[index].formatName);

View File

@ -340,6 +340,8 @@ UINT disp_send_monitor_layout(DispClientContext* context, UINT32 NumMonitors, DI
#ifdef STATIC_CHANNELS
#define DVCPluginEntry disp_DVCPluginEntry
#else
#define DVCPluginEntry FREERDP_API DVCPluginEntry
#endif
/**

View File

@ -958,8 +958,8 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int c
Stream_Write_UINT8(data_out, 0x10 | cbChId);
Stream_SetPosition(s, 1);
Stream_Copy(data_out, s, pos - 1);
Stream_Copy(s, data_out, pos - 1);
if (channel_status == CHANNEL_RC_OK)
{
WLog_DBG(TAG, "channel created");

View File

@ -286,7 +286,7 @@ static struct dirent *readdir(DIR *dirp)
return NULL;
}
if (FindNextFileA (dirp->search_handle, &dirp->find_data) == FALSE) {
/* the very last entry has been processed or an error occured */
/* the very last entry has been processed or an error occurred */
FindClose (dirp->search_handle);
dirp->search_handle = INVALID_HANDLE_VALUE;
return NULL;

View File

@ -7,6 +7,8 @@
* Copyright 2012 Gerald Richter
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
* Copyright 2016 Inuvika Inc.
* Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -59,6 +61,8 @@
#ifdef _WIN32
#pragma comment(lib, "Shlwapi.lib")
#include <Shlwapi.h>
#else
#include <winpr/path.h>
#endif
#include "drive_file.h"
@ -507,18 +511,23 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
{
char* s = NULL;
mode_t m;
UINT64 size;
INT64 size;
int status;
char* fullpath;
struct STAT st;
#if defined(__linux__) && !defined(ANDROID) || defined(sun)
struct timespec tv[2];
#else
struct timeval tv[2];
#endif
UINT64 LastWriteTime;
ULARGE_INTEGER liCreationTime;
ULARGE_INTEGER liLastAccessTime;
ULARGE_INTEGER liLastWriteTime;
ULARGE_INTEGER liChangeTime;
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
FILETIME* pftCreationTime = NULL;
FILETIME* pftLastAccessTime = NULL;
FILETIME* pftLastWriteTime = NULL;
UINT32 FileAttributes;
UINT32 FileNameLength;
HANDLE hFd;
LARGE_INTEGER liSize;
m = 0;
@ -526,55 +535,73 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
{
case FileBasicInformation:
/* http://msdn.microsoft.com/en-us/library/cc232094.aspx */
Stream_Seek_UINT64(input); /* CreationTime */
Stream_Seek_UINT64(input); /* LastAccessTime */
Stream_Read_UINT64(input, LastWriteTime);
Stream_Seek_UINT64(input); /* ChangeTime */
Stream_Read_UINT64(input, liCreationTime.QuadPart);
Stream_Read_UINT64(input, liLastAccessTime.QuadPart);
Stream_Read_UINT64(input, liLastWriteTime.QuadPart);
Stream_Read_UINT64(input, liChangeTime.QuadPart);
Stream_Read_UINT32(input, FileAttributes);
if (FSTAT(file->fd, &st) != 0)
if (!PathFileExistsA(file->fullpath))
return FALSE;
tv[0].tv_sec = st.st_atime;
tv[1].tv_sec = (LastWriteTime > 0 ? FILE_TIME_RDP_TO_SYSTEM(LastWriteTime) : st.st_mtime);
#ifndef WIN32
/* TODO on win32 */
#ifdef ANDROID
tv[0].tv_usec = 0;
tv[1].tv_usec = 0;
utimes(file->fullpath, tv);
#elif defined (__linux__) || defined (sun)
tv[0].tv_nsec = 0;
tv[1].tv_nsec = 0;
futimens(file->fd, tv);
#else
tv[0].tv_usec = 0;
tv[1].tv_usec = 0;
futimes(file->fd, tv);
#endif
if (FileAttributes > 0)
hFd = CreateFileA(file->fullpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFd == INVALID_HANDLE_VALUE)
{
m = st.st_mode;
if ((FileAttributes & FILE_ATTRIBUTE_READONLY) == 0)
m |= S_IWUSR;
else
m &= ~S_IWUSR;
if (m != st.st_mode)
fchmod(file->fd, st.st_mode);
WLog_ERR(TAG, "Unable to set file time %s to %d", file->fullpath);
return FALSE;
}
#endif
if (liCreationTime.QuadPart != 0)
{
ftCreationTime.dwHighDateTime = liCreationTime.HighPart;
ftCreationTime.dwLowDateTime = liCreationTime.LowPart;
pftCreationTime = &ftCreationTime;
}
if (liLastAccessTime.QuadPart != 0)
{
ftLastAccessTime.dwHighDateTime = liLastAccessTime.HighPart;
ftLastAccessTime.dwLowDateTime = liLastAccessTime.LowPart;
pftLastAccessTime = &ftLastAccessTime;
}
if (liLastWriteTime.QuadPart != 0)
{
ftLastWriteTime.dwHighDateTime = liLastWriteTime.HighPart;
ftLastWriteTime.dwLowDateTime = liLastWriteTime.LowPart;
pftLastWriteTime = &ftLastWriteTime;
}
if (liChangeTime.QuadPart != 0 && liChangeTime.QuadPart > liLastWriteTime.QuadPart)
{
ftLastWriteTime.dwHighDateTime = liChangeTime.HighPart;
ftLastWriteTime.dwLowDateTime = liChangeTime.LowPart;
pftLastWriteTime = &ftLastWriteTime;
}
if (!SetFileTime(hFd, pftCreationTime, pftLastAccessTime, pftLastWriteTime))
{
WLog_ERR(TAG, "Unable to set file time %s to %d", file->fullpath);
CloseHandle(hFd);
return FALSE;
}
CloseHandle(hFd);
break;
case FileEndOfFileInformation:
/* http://msdn.microsoft.com/en-us/library/cc232067.aspx */
case FileAllocationInformation:
/* http://msdn.microsoft.com/en-us/library/cc232076.aspx */
Stream_Read_UINT64(input, size);
#ifndef _WIN32
if (ftruncate(file->fd, size) != 0)
Stream_Read_INT64(input, size);
hFd = CreateFileA(file->fullpath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFd == INVALID_HANDLE_VALUE)
{
WLog_ERR(TAG, "Unable to truncate %s to %d", file->fullpath, size);
return FALSE;
#endif
}
liSize.QuadPart = size;
if (SetFilePointerEx(hFd, liSize, NULL, FILE_BEGIN) == 0)
{
WLog_ERR(TAG, "Unable to truncate %s to %d", file->fullpath, size);
CloseHandle(hFd);
return FALSE;
}
CloseHandle(hFd);
break;
case FileDispositionInformation:

View File

@ -7,6 +7,8 @@
* Copyright 2012 Gerald Richter
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
* Copyright 2016 Inuvika Inc.
* Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -84,8 +86,6 @@ typedef UINT32 mode_t;
#define FILE_TIME_SYSTEM_TO_RDP(_t) \
(((UINT64)(_t) + EPOCH_DIFF) * 10000000LL)
#define FILE_TIME_RDP_TO_SYSTEM(_t) \
(((_t) == 0LL || (_t) == (UINT64)(-1LL)) ? 0 : (time_t)((_t) / 10000000LL - EPOCH_DIFF))
#define FILE_ATTR_SYSTEM_TO_RDP(_f, _st) ( \
(S_ISDIR(_st.st_mode) ? FILE_ATTRIBUTE_DIRECTORY : 0) | \

View File

@ -859,6 +859,8 @@ out_error:
#ifdef STATIC_CHANNELS
#define DeviceServiceEntry drive_DeviceServiceEntry
#else
#define DeviceServiceEntry FREERDP_API DeviceServiceEntry
#endif
UINT sys_code_page = 0;

View File

@ -1,3 +0,0 @@
LIBRARY "drive"
EXPORTS
DeviceServiceEntry @1

View File

@ -3,6 +3,8 @@
* statvfs emulation for Windows
*
* Copyright 2012 Gerald Richter
* Copyright 2016 Inuvika Inc.
* Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -29,17 +31,18 @@ int statvfs(const char *path, struct statvfs *buf)
{
BOOL res;
int len;
LPWSTR unicodestr;
LPWSTR unicodestr = NULL;
DWORD lpSectorsPerCluster;
DWORD lpBytesPerSector;
DWORD lpNumberOfFreeClusters;
DWORD lpTotalNumberOfClusters;
len = MultiByteToWideChar(CP_ACP, 0, path, -1, NULL, 0);
unicodestr = (LPWSTR) malloc(len);
MultiByteToWideChar(CP_ACP, 0, path, -1, unicodestr, len);
len = ConvertToUnicode(CP_ACP, 0, path, -1, &unicodestr, 0);
if (len <= 0)
return -1;
res = GetDiskFreeSpace(unicodestr, &lpSectorsPerCluster, &lpBytesPerSector, &lpNumberOfFreeClusters, &lpTotalNumberOfClusters);
res = GetDiskFreeSpaceW(unicodestr, &lpSectorsPerCluster, &lpBytesPerSector, &lpNumberOfFreeClusters, &lpTotalNumberOfClusters);
free(unicodestr);
buf->f_bsize = lpBytesPerSector; /* file system block size */
buf->f_frsize = 0; /* fragment size */

View File

@ -162,6 +162,8 @@ static UINT echo_plugin_terminated(IWTSPlugin* pPlugin)
#ifdef STATIC_CHANNELS
#define DVCPluginEntry echo_DVCPluginEntry
#else
#define DVCPluginEntry FREERDP_API DVCPluginEntry
#endif
/**

View File

@ -116,12 +116,15 @@ static void* echo_server_thread_func(void* arg)
DWORD BytesReturned = 0;
echo_server* echo = (echo_server*) arg;
UINT error;
DWORD status;
DWORD status;
if ((error = echo_server_open_channel(echo)))
{
IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED);
UINT error2 = 0;
WLog_ERR(TAG, "echo_server_open_channel failed with error %lu!", error);
IFCALLRET(echo->context.OpenResult, error2, &echo->context, ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED);
if (error2)
WLog_ERR(TAG, "echo server's OpenResult callback failed with error %lu", error2);
goto out;
}
@ -145,14 +148,14 @@ static void* echo_server_thread_func(void* arg)
while (1)
{
status = WaitForMultipleObjects(nCount, events, FALSE, 100);
status = WaitForMultipleObjects(nCount, events, FALSE, 100);
if (status == WAIT_FAILED)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
break;
}
if (status == WAIT_FAILED)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %lu", error);
break;
}
if (status == WAIT_OBJECT_0)
{

View File

@ -394,6 +394,8 @@ static UINT parallel_free(DEVICE* device)
#ifdef STATIC_CHANNELS
#define DeviceServiceEntry parallel_DeviceServiceEntry
#else
#define DeviceServiceEntry FREERDP_API DeviceServiceEntry
#endif
/**

View File

@ -5,6 +5,7 @@
* Copyright 2010-2011 Vic Lee
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
* Copyright 2016 Armin Novak <armin.novak@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -229,10 +230,12 @@ static void printer_cups_free_printer(rdpPrinter* printer)
cups_printer->printjob->printjob.Close((rdpPrintJob*) cups_printer->printjob);
free(printer->name);
free(printer->driver);
free(printer);
}
static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver, const char* name, BOOL is_default)
static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver,
const char* name, const char* driverName, BOOL is_default)
{
rdpCupsPrinter* cups_printer;
@ -247,8 +250,17 @@ static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver, c
free(cups_printer);
return NULL;
}
/* This is a generic PostScript printer driver developed by MS, so it should be good in most cases */
cups_printer->printer.driver = "MS Publisher Imagesetter";
if (driverName)
cups_printer->printer.driver = _strdup(driverName);
else
cups_printer->printer.driver = _strdup("MS Publisher Imagesetter");
if (!cups_printer->printer.driver)
{
free(cups_printer->printer.name);
free(cups_printer);
return NULL;
}
cups_printer->printer.is_default = is_default;
cups_printer->printer.CreatePrintJob = printer_cups_create_printjob;
@ -279,7 +291,7 @@ static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver)
if (dest->instance == NULL)
{
printers[num_printers++] = printer_cups_new_printer((rdpCupsPrinterDriver*) driver,
dest->name, dest->is_default);
dest->name, NULL, dest->is_default);
}
}
cupsFreeDests(num_dests, dests);
@ -287,11 +299,13 @@ static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver)
return printers;
}
static rdpPrinter* printer_cups_get_printer(rdpPrinterDriver* driver, const char* name)
static rdpPrinter* printer_cups_get_printer(rdpPrinterDriver* driver,
const char* name, const char* driverName)
{
rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*) driver;
return printer_cups_new_printer(cups_driver, name, cups_driver->id_sequence == 1 ? TRUE : FALSE);
return printer_cups_new_printer(cups_driver, name, driverName,
cups_driver->id_sequence == 1 ? TRUE : FALSE);
}
static rdpCupsPrinterDriver* cups_driver = NULL;

View File

@ -5,6 +5,7 @@
* Copyright 2010-2011 Vic Lee
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
* Copyright 2016 Armin Novak <armin.novak@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -36,6 +37,8 @@
#include <freerdp/channels/rdpdr.h>
#include "../printer.h"
#ifdef WITH_CUPS
#include "printer_cups.h"
#endif
@ -449,6 +452,8 @@ error_out:
#ifdef STATIC_CHANNELS
#define DeviceServiceEntry printer_DeviceServiceEntry
#else
#define DeviceServiceEntry FREERDP_API DeviceServiceEntry
#endif
/**
@ -487,7 +492,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
if (name && name[0])
{
printer = driver->GetPrinter(driver, name);
printer = driver->GetPrinter(driver, name, driver_name);
if (!printer)
{
@ -495,9 +500,6 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints)
return CHANNEL_RC_INITIALIZATION_ERROR;
}
if (driver_name && driver_name[0])
printer->driver = driver_name;
if ((error = printer_register(pEntryPoints, printer)))
{
WLog_ERR(TAG, "printer_register failed with error %lu!", error);

View File

@ -5,6 +5,7 @@
* Copyright 2010-2011 Vic Lee
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
* Copyright 2016 Armin Novak <armin.novak@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -24,25 +25,12 @@
#include <freerdp/channels/rdpdr.h>
/* SERVER_PRINTER_CACHE_EVENT.cachedata */
#define RDPDR_ADD_PRINTER_EVENT 0x00000001
#define RDPDR_UPDATE_PRINTER_EVENT 0x00000002
#define RDPDR_DELETE_PRINTER_EVENT 0x00000003
#define RDPDR_RENAME_PRINTER_EVENT 0x00000004
/* DR_PRN_DEVICE_ANNOUNCE.Flags */
#define RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII 0x00000001
#define RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER 0x00000002
#define RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER 0x00000004
#define RDPDR_PRINTER_ANNOUNCE_FLAG_TSPRINTER 0x00000008
#define RDPDR_PRINTER_ANNOUNCE_FLAG_XPSFORMAT 0x00000010
typedef struct rdp_printer_driver rdpPrinterDriver;
typedef struct rdp_printer rdpPrinter;
typedef struct rdp_print_job rdpPrintJob;
typedef rdpPrinter** (*pcEnumPrinters) (rdpPrinterDriver* driver);
typedef rdpPrinter* (*pcGetPrinter) (rdpPrinterDriver* driver, const char* name);
typedef rdpPrinter* (*pcGetPrinter) (rdpPrinterDriver* driver, const char* name, const char* driverName);
struct rdp_printer_driver
{

View File

@ -5,6 +5,7 @@
* Copyright 2012 Gerald Richter
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
* Copyright 2016 Armin Novak <armin.novak@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -175,10 +176,12 @@ static void printer_win_free_printer(rdpPrinter* printer)
win_printer->printjob->printjob.Close((rdpPrintJob*) win_printer->printjob);
free(printer->name);
free(printer->driver);
free(printer);
}
static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, const char* name, const wchar_t* drivername, BOOL is_default)
static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver,
const char* name, const WCHAR* drivername, BOOL is_default)
{
rdpWinPrinter* win_printer;
wchar_t wname[256];
@ -216,7 +219,10 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, cons
}
GetPrinter(win_printer->hPrinter, 2, (LPBYTE) prninfo, needed, &needed);
win_printer->printer.driver = malloc(1000);
if (drivername)
win_printer->printer.driver = _wcsdup(drivername);
else
win_printer->printer.driver = _wcsdup(prninfo->pDriverName);
if (!win_printer->printer.driver)
{
GlobalFree(prninfo);
@ -224,7 +230,6 @@ static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, cons
free(win_printer);
return NULL;
}
wcstombs_s(&charsConverted, win_printer->printer.driver, 1000, prninfo->pDriverName, _TRUNCATE);
return (rdpPrinter*)win_printer;
}
@ -274,13 +279,24 @@ static rdpPrinter** printer_win_enum_printers(rdpPrinterDriver* driver)
return printers;
}
static rdpPrinter* printer_win_get_printer(rdpPrinterDriver* driver, const char* name)
static rdpPrinter* printer_win_get_printer(rdpPrinterDriver* driver,
const char* name, const char* driverName)
{
WCHAR* driverNameW = NULL;
rdpWinPrinterDriver* win_driver = (rdpWinPrinterDriver*)driver;
rdpPrinter *myPrinter = NULL;
myPrinter = printer_win_new_printer(win_driver, name, L"", win_driver->id_sequence == 1 ? TRUE : FALSE);
if (driverName)
{
ConvertToUnicode(CP_UTF8, 0, driverName, -1, &driverNameW, 0);
if (!driverNameW)
return NULL;
}
myPrinter = printer_win_new_printer(win_driver, name, driverNameW,
win_driver->id_sequence == 1 ? TRUE : FALSE);
free(driverNameW);
return myPrinter;
}

View File

@ -0,0 +1,37 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Definition for the printer channel
*
* Copyright 2016 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 __CHANNELS_PRINTER_PRINTER_H_
#define __CHANNELS_PRINTER_PRINTER_H_
/* SERVER_PRINTER_CACHE_EVENT.cachedata */
#define RDPDR_ADD_PRINTER_EVENT 0x00000001
#define RDPDR_UPDATE_PRINTER_EVENT 0x00000002
#define RDPDR_DELETE_PRINTER_EVENT 0x00000003
#define RDPDR_RENAME_PRINTER_EVENT 0x00000004
/* DR_PRN_DEVICE_ANNOUNCE.Flags */
#define RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII 0x00000001
#define RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER 0x00000002
#define RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER 0x00000004
#define RDPDR_PRINTER_ANNOUNCE_FLAG_TSPRINTER 0x00000008
#define RDPDR_PRINTER_ANNOUNCE_FLAG_XPSFORMAT 0x00000010
#endif /* __CHANNELS_PRINTER_PRINTER_H_ */

View File

@ -2,6 +2,8 @@
# FreeRDP cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
# Copyright 2016 Inuvika Inc.
# Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -32,6 +34,10 @@ add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE
target_link_libraries(${MODULE_NAME} winpr freerdp)
if(APPLE AND (NOT IOS))
find_library(CORESERVICES_LIBRARY CoreServices)
target_link_libraries(${MODULE_NAME} ${CORESERVICES_LIBRARY})
endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client")

View File

@ -46,6 +46,15 @@
#include <fcntl.h>
#endif
#ifdef __MACOSX__
#include <CoreFoundation/CoreFoundation.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@ -103,6 +112,45 @@ static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 cou
#ifdef _WIN32
BOOL check_path(char* path)
{
UINT type = GetDriveTypeA(path);
if (!(type == DRIVE_REMOVABLE || type == DRIVE_CDROM || type == DRIVE_REMOTE))
return FALSE;
return GetVolumeInformationA(path, NULL, 0, NULL, NULL, NULL, NULL, 0);
}
void first_hotplug(rdpdrPlugin *rdpdr)
{
int i;
char drive_path[5] = { 'c', ':', '\\', '\0' };
DWORD unitmask = GetLogicalDrives();
for (i = 0; i < 26; i++)
{
if (unitmask & 0x01)
{
RDPDR_DRIVE* drive;
drive_path[0] = 'A' + i;
drive_path[1] = ':';
if (check_path(drive_path))
{
drive = (RDPDR_DRIVE*)malloc(sizeof(RDPDR_DRIVE));
ZeroMemory(drive, sizeof(RDPDR_DRIVE));
drive->Type = RDPDR_DTYP_FILESYSTEM;
drive->Path = _strdup(drive_path);
drive_path[1] = '\0';
drive->Name = _strdup(drive_path);
devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext);
}
}
unitmask = unitmask >> 1;
}
}
LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
rdpdrPlugin *rdpdr;
@ -131,17 +179,21 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
RDPDR_DRIVE* drive;
drive_path[0] = 'A' + i;
drive_path[1] = ':';
drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE));
ZeroMemory(drive, sizeof(RDPDR_DRIVE));
if (check_path(drive_path))
{
drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE));
ZeroMemory(drive, sizeof(RDPDR_DRIVE));
drive->Type = RDPDR_DTYP_FILESYSTEM;
drive->Type = RDPDR_DTYP_FILESYSTEM;
drive->Path = _strdup(drive_path);
drive_path[1] = '\0';
drive->Name = _strdup(drive_path);
devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext);
rdpdr_send_device_list_announce_request(rdpdr, TRUE);
drive->Path = _strdup(drive_path);
drive_path[1] = '\0';
drive->Name = _strdup(drive_path);
devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext);
rdpdr_send_device_list_announce_request(rdpdr, TRUE);
}
}
unitmask = unitmask >> 1;
}
@ -275,6 +327,242 @@ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr)
return error;
}
#elif __MACOSX__
#define MAX_USB_DEVICES 100
typedef struct _hotplug_dev
{
char* path;
BOOL to_add;
} hotplug_dev;
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT handle_hotplug(rdpdrPlugin* rdpdr)
{
struct dirent *pDirent;
DIR *pDir;
char fullpath[PATH_MAX];
char* szdir = (char*)"/Volumes";
struct stat buf;
hotplug_dev dev_array[MAX_USB_DEVICES];
int count;
DEVICE_DRIVE_EXT *device_ext;
ULONG_PTR *keys;
int i, j;
int size = 0;
UINT error;
UINT32 ids[1];
pDir = opendir (szdir);
if (pDir == NULL)
{
printf ("Cannot open directory\n");
return ERROR_OPEN_FAILED;
}
while ((pDirent = readdir(pDir)) != NULL)
{
if (pDirent->d_name[0] != '.')
{
sprintf(fullpath, "%s/%s", szdir, pDirent->d_name);
lstat(fullpath, &buf);
if(S_ISDIR(buf.st_mode))
{
dev_array[size].path = _strdup(fullpath);
if (!dev_array[size].path)
{
closedir (pDir);
error = CHANNEL_RC_NO_MEMORY;
goto cleanup;
}
dev_array[size++].to_add = TRUE;
}
}
}
closedir (pDir);
/* delete removed devices */
count = ListDictionary_GetKeys(rdpdr->devman->devices, &keys);
for (j = 0; j < count; j++)
{
BOOL dev_found = FALSE;
device_ext = (DEVICE_DRIVE_EXT *)ListDictionary_GetItemValue(rdpdr->devman->devices, (void *)keys[j]);
if (!device_ext)
continue;
if (device_ext->path == NULL)
continue;
/* not plugable device */
if (strstr(device_ext->path, "/Volumes/") == NULL)
continue;
for (i = 0; i < size; i++)
{
if (strstr(device_ext->path, dev_array[i].path) != NULL)
{
dev_found = TRUE;
dev_array[i].to_add = FALSE;
break;
}
}
if (!dev_found)
{
devman_unregister_device(rdpdr->devman, (void *)keys[j]);
ids[0] = keys[j];
if ((error = rdpdr_send_device_list_remove_request(rdpdr, 1, ids)))
{
WLog_ERR(TAG, "rdpdr_send_device_list_remove_request failed with error %lu!", error);
goto cleanup;
}
}
}
/* add new devices */
for (i = 0; i < size; i++)
{
RDPDR_DRIVE* drive;
if (dev_array[i].to_add)
{
char* name;
drive = (RDPDR_DRIVE*) calloc(1, sizeof(RDPDR_DRIVE));
if (!drive)
{
WLog_ERR(TAG, "calloc failed!");
error = CHANNEL_RC_NO_MEMORY;
goto cleanup;
}
drive->Type = RDPDR_DTYP_FILESYSTEM;
drive->Path = dev_array[i].path;
dev_array[i].path = NULL;
name = strrchr(drive->Path, '/') + 1;
drive->Name = _strdup(name);
if (!drive->Name)
{
WLog_ERR(TAG, "_strdup failed!");
free(drive->Path);
free(drive);
error = CHANNEL_RC_NO_MEMORY;
goto cleanup;
}
if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext)))
{
WLog_ERR(TAG, "devman_load_device_service failed!");
free(drive->Path);
free(drive->Name);
free(drive);
error = CHANNEL_RC_NO_MEMORY;
goto cleanup;
}
}
}
cleanup:
for (i = 0; i < size; i++)
free (dev_array[i].path);
return error;
}
static void drive_hotplug_fsevent_callback(ConstFSEventStreamRef streamRef, void *clientCallBackInfo,
size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[])
{
rdpdrPlugin* rdpdr;
int i;
UINT error;
char **paths = (char**)eventPaths;
rdpdr = (rdpdrPlugin*) clientCallBackInfo;
for (i=0; i<numEvents; i++)
{
if (strcmp(paths[i], "/Volumes/") == 0)
{
if ((error = handle_hotplug(rdpdr)))
{
WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error);
}
else
rdpdr_send_device_list_announce_request(rdpdr, TRUE);
return;
}
}
}
void first_hotplug(rdpdrPlugin *rdpdr)
{
UINT error;
if ((error = handle_hotplug(rdpdr)))
{
WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error);
}
}
static void* drive_hotplug_thread_func(void* arg)
{
rdpdrPlugin* rdpdr;
FSEventStreamRef fsev;
UINT error;
rdpdr = (rdpdrPlugin*) arg;
CFStringRef path = CFSTR("/Volumes/");
CFArrayRef pathsToWatch = CFArrayCreate(kCFAllocatorMalloc, (const void**)&path, 1, NULL);
FSEventStreamContext ctx;
ZeroMemory(&ctx, sizeof(ctx));
ctx.info = arg;
fsev = FSEventStreamCreate(kCFAllocatorMalloc, drive_hotplug_fsevent_callback, &ctx, pathsToWatch, kFSEventStreamEventIdSinceNow, 1, kFSEventStreamCreateFlagNone);
rdpdr->runLoop = CFRunLoopGetCurrent();
FSEventStreamScheduleWithRunLoop(fsev, rdpdr->runLoop, kCFRunLoopDefaultMode);
FSEventStreamStart(fsev);
CFRunLoopRun();
FSEventStreamStop(fsev);
FSEventStreamRelease(fsev);
ExitThread(CHANNEL_RC_OK);
return NULL;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr)
{
UINT error;
if (rdpdr->hotplugThread)
{
CFRunLoopStop(rdpdr->runLoop);
if (WaitForSingleObject(rdpdr->hotplugThread, INFINITE) == WAIT_FAILED)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
return error;
}
rdpdr->hotplugThread = NULL;
}
return CHANNEL_RC_OK;
}
#else
#define MAX_USB_DEVICES 100
@ -506,7 +794,16 @@ cleanup:
for (i = 0; i < size; i++)
free (dev_array[i].path);
return error ? error : rdpdr_send_device_list_announce_request(rdpdr, TRUE);
return error;
}
void first_hotplug(rdpdrPlugin *rdpdr)
{
UINT error;
if ((error = handle_hotplug(rdpdr)))
{
WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error);
}
}
static void* drive_hotplug_thread_func(void* arg)
@ -516,7 +813,7 @@ static void* drive_hotplug_thread_func(void* arg)
fd_set rfds;
struct timeval tv;
int rv;
UINT error;
UINT error = 0;
DWORD status;
rdpdr = (rdpdrPlugin*) arg;
@ -542,12 +839,6 @@ static void* drive_hotplug_thread_func(void* arg)
tv.tv_sec = 1;
tv.tv_usec = 0;
if ((error = handle_hotplug(rdpdr)))
{
WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error);
goto out;
}
while ((rv = select(mfd+1, NULL, NULL, &rfds, &tv)) >= 0)
{
status = WaitForSingleObject(rdpdr->stopEvent, 0);
@ -568,6 +859,8 @@ static void* drive_hotplug_thread_func(void* arg)
WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error);
goto out;
}
else
rdpdr_send_device_list_announce_request(rdpdr, TRUE);
}
FD_ZERO(&rfds);
@ -643,6 +936,7 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr)
if (device->Name && (strcmp(device->Name, "*") == 0))
{
first_hotplug(rdpdr);
if (!(rdpdr->hotplugThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) drive_hotplug_thread_func, rdpdr, 0, NULL)))
{

View File

@ -6,6 +6,8 @@
* Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
* Copyright 2016 Inuvika Inc.
* Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -36,6 +38,10 @@
#include <freerdp/channels/rdpdr.h>
#include <freerdp/channels/log.h>
#ifdef __MACOSX__
#include <CoreServices/CoreServices.h>
#endif
#define TAG CHANNELS_TAG("rdpdr.client")
typedef struct rdpdr_plugin rdpdrPlugin;
@ -64,6 +70,8 @@ struct rdpdr_plugin
HANDLE hotplugThread;
#ifdef _WIN32
HWND hotplug_wnd;
#elif __MACOSX__
CFRunLoopRef runLoop;
#else
HANDLE stopEvent;
#endif

View File

@ -152,9 +152,10 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context
Stream_Seek_UINT32(s); /* CodePage (4 bytes), MUST be set to zero */
Stream_Read_UINT32(s, ComputerNameLen); /* ComputerNameLen (4 bytes) */
if (Stream_GetRemainingLength(s) < ComputerNameLen)
if (UnicodeFlag > 1) /* must be 0x00000000 or 0x00000001 */
{
WLog_ERR(TAG, "not enough data in stream!");
WLog_ERR(TAG, "invalid UnicodeFlag value: 0x%08X", UnicodeFlag);
return ERROR_INVALID_DATA;
}
@ -164,6 +165,39 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context
* not in characters, including the NULL terminator!
*/
if (UnicodeFlag)
{
if ((ComputerNameLen % 2) || ComputerNameLen > 512 || ComputerNameLen < 2)
{
WLog_ERR(TAG, "invalid unicode computer name length: %u", ComputerNameLen);
return ERROR_INVALID_DATA;
}
}
else
{
if (ComputerNameLen > 256 || ComputerNameLen < 1)
{
WLog_ERR(TAG, "invalid ascii computer name length: %u", ComputerNameLen);
return ERROR_INVALID_DATA;
}
}
if (Stream_GetRemainingLength(s) < ComputerNameLen)
{
WLog_ERR(TAG, "not enough data in stream!");
return ERROR_INVALID_DATA;
}
/* ComputerName must be null terminated, check if it really is */
if (Stream_Pointer(s)[ComputerNameLen-1] ||
(UnicodeFlag && Stream_Pointer(s)[ComputerNameLen-2]))
{
WLog_ERR(TAG, "computer name must be null terminated");
return ERROR_INVALID_DATA;
}
if (context->priv->ClientComputerName)
{
free(context->priv->ClientComputerName);
@ -172,12 +206,21 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context
if (UnicodeFlag)
{
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s),
-1, &(context->priv->ClientComputerName), 0, NULL, NULL);
if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), -1,
&(context->priv->ClientComputerName), 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert client computer name");
return ERROR_INVALID_DATA;
}
}
else
{
context->priv->ClientComputerName = _strdup((char*) Stream_Pointer(s));
if (!context->priv->ClientComputerName)
{
WLog_ERR(TAG, "failed to duplicate client computer name");
return CHANNEL_RC_NO_MEMORY;
}
}
Stream_Seek(s, ComputerNameLen);

View File

@ -957,6 +957,8 @@ UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y,
#ifdef STATIC_CHANNELS
#define DVCPluginEntry rdpei_DVCPluginEntry
#else
#define DVCPluginEntry FREERDP_API DVCPluginEntry
#endif
/**

View File

@ -1515,6 +1515,8 @@ void* rdpgfx_get_cache_slot_data(RdpgfxClientContext* context, UINT16 cacheSlot)
#ifdef STATIC_CHANNELS
#define DVCPluginEntry rdpgfx_DVCPluginEntry
#else
#define DVCPluginEntry FREERDP_API DVCPluginEntry
#endif
/**

View File

@ -649,6 +649,8 @@ static UINT rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV*
#ifdef STATIC_CHANNELS
#define freerdp_rdpsnd_client_subsystem_entry alsa_freerdp_rdpsnd_client_subsystem_entry
#else
#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry
#endif
/**

View File

@ -281,6 +281,8 @@ static void rdpsnd_ios_free(rdpsndDevicePlugin* device)
#ifdef STATIC_CHANNELS
#define freerdp_rdpsnd_client_subsystem_entry ios_freerdp_rdpsnd_client_subsystem_entry
#else
#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry
#endif
/**

View File

@ -348,6 +348,8 @@ static void rdpsnd_mac_waveplay(rdpsndDevicePlugin* device, RDPSND_WAVE* wave)
#ifdef STATIC_CHANNELS
#define freerdp_rdpsnd_client_subsystem_entry mac_freerdp_rdpsnd_client_subsystem_entry
#else
#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry
#endif
/**

View File

@ -407,6 +407,9 @@ static int rdpsnd_opensles_parse_addin_args(rdpsndDevicePlugin* device,
#ifdef STATIC_CHANNELS
#define freerdp_rdpsnd_client_subsystem_entry \
opensles_freerdp_rdpsnd_client_subsystem_entry
#else
#define freerdp_rdpsnd_client_subsystem_entry \
FREERDP_API freerdp_rdpsnd_client_subsystem_entry
#endif
/**

View File

@ -477,6 +477,8 @@ static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* a
#ifdef STATIC_CHANNELS
#define freerdp_rdpsnd_client_subsystem_entry oss_freerdp_rdpsnd_client_subsystem_entry
#else
#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry
#endif
/**

View File

@ -636,6 +636,8 @@ static UINT rdpsnd_pulse_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV
#ifdef STATIC_CHANNELS
#define freerdp_rdpsnd_client_subsystem_entry pulse_freerdp_rdpsnd_client_subsystem_entry
#else
#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry
#endif
/**

View File

@ -346,6 +346,8 @@ static void rdpsnd_winmm_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV
#ifdef STATIC_CHANNELS
#define freerdp_rdpsnd_client_subsystem_entry winmm_freerdp_rdpsnd_client_subsystem_entry
#else
#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry
#endif
/**

View File

@ -813,6 +813,8 @@ static UINT serial_free(DEVICE* device)
#ifdef STATIC_CHANNELS
#define DeviceServiceEntry serial_DeviceServiceEntry
#else
#define DeviceServiceEntry FREERDP_API DeviceServiceEntry
#endif
/**

View File

@ -707,7 +707,12 @@ void smartcard_trace_list_readers_return(SMARTCARD_DEVICE* smartcard, ListReader
if (unicode)
{
length = ret->cBytes / 2;
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) ret->msz, (int)length, &mszA, 0, NULL, NULL);
if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) ret->msz, (int)length,
&mszA, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "ConvertFromUnicode failed");
return;
}
}
else
{
@ -1767,7 +1772,12 @@ void smartcard_trace_status_return(SMARTCARD_DEVICE* smartcard, Status_Return* r
if (unicode)
{
length = ret->cBytes / 2;
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) ret->mszReaderNames, (int)length, &mszReaderNamesA, 0, NULL, NULL);
if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) ret->mszReaderNames, (int)length,
&mszReaderNamesA, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "ConvertFromUnicode failed");
return;
}
}
else
{

View File

@ -233,6 +233,8 @@ static void tsmf_alsa_free(ITSMFAudioDevice *audio)
#ifdef STATIC_CHANNELS
#define freerdp_tsmf_client_audio_subsystem_entry alsa_freerdp_tsmf_client_audio_subsystem_entry
#else
#define freerdp_tsmf_client_audio_subsystem_entry FREERDP_API freerdp_tsmf_client_audio_subsystem_entry
#endif
ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void)

View File

@ -543,6 +543,8 @@ static BOOL initialized = FALSE;
#ifdef STATIC_CHANNELS
#define freerdp_tsmf_client_subsystem_entry ffmpeg_freerdp_tsmf_client_decoder_subsystem_entry
#else
#define freerdp_tsmf_client_subsystem_entry FREERDP_API freerdp_tsmf_client_decoder_subsystem_entry
#endif
ITSMFDecoder* freerdp_tsmf_client_subsystem_entry(void)

View File

@ -1012,6 +1012,8 @@ BOOL tsmf_gstreamer_sync(ITSMFDecoder* decoder, void (*cb)(void *), void *stream
#ifdef STATIC_CHANNELS
#define freerdp_tsmf_client_subsystem_entry gstreamer_freerdp_tsmf_client_decoder_subsystem_entry
#else
#define freerdp_tsmf_client_subsystem_entry FREERDP_API freerdp_tsmf_client_decoder_subsystem_entry
#endif
ITSMFDecoder* freerdp_tsmf_client_subsystem_entry(void)

View File

@ -238,6 +238,8 @@ static void tsmf_oss_free(ITSMFAudioDevice* audio)
#ifdef STATIC_CHANNELS
#define freerdp_tsmf_client_audio_subsystem_entry oss_freerdp_tsmf_client_audio_subsystem_entry
#else
#define freerdp_tsmf_client_audio_subsystem_entry FREERDP_API freerdp_tsmf_client_audio_subsystem_entry
#endif
ITSMFAudioDevice* freerdp_tsmf_client_audio_subsystem_entry(void)

View File

@ -360,6 +360,8 @@ static void tsmf_pulse_free(ITSMFAudioDevice *audio)
#ifdef STATIC_CHANNELS
#define freerdp_tsmf_client_audio_subsystem_entry pulse_freerdp_tsmf_client_audio_subsystem_entry
#else
#define freerdp_tsmf_client_audio_subsystem_entry FREERDP_API freerdp_tsmf_client_audio_subsystem_entry
#endif
ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void)

View File

@ -79,7 +79,7 @@ UINT tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
if (!Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4))
return ERROR_OUTOFMEMORY;
pos = Stream_GetPosition(ifman->output);
Stream_Copy(ifman->output, ifman->input, ifman->input_size);
Stream_Copy(ifman->input, ifman->output, ifman->input_size);
Stream_SetPosition(ifman->output, pos);
if (Stream_GetRemainingLength(ifman->output) < 4)

View File

@ -527,6 +527,8 @@ static UINT tsmf_process_addin_args(IWTSPlugin *pPlugin, ADDIN_ARGV *args)
#ifdef STATIC_CHANNELS
#define DVCPluginEntry tsmf_DVCPluginEntry
#else
#define DVCPluginEntry FREERDP_API DVCPluginEntry
#endif
/**

View File

@ -579,6 +579,8 @@ static void urbdrc_udevman_parse_addin_args(UDEVMAN* udevman, ADDIN_ARGV* args)
#ifdef STATIC_CHANNELS
#define freerdp_urbdrc_client_subsystem_entry libusb_freerdp_urbdrc_client_subsystem_entry
#else
#define freerdp_urbdrc_client_subsystem_entry FREERDP_API freerdp_urbdrc_client_subsystem_entry
#endif
int freerdp_urbdrc_client_subsystem_entry(PFREERDP_URBDRC_SERVICE_ENTRY_POINTS pEntryPoints)

View File

@ -1026,7 +1026,7 @@ static void* urbdrc_search_usb_device(void* arg)
}
else
{
WLog_ERR(TAG, "No Device from receive_device(). An error occured.");
WLog_ERR(TAG, "No Device from receive_device(). An error occurred.");
}
}
}
@ -1541,6 +1541,8 @@ static UINT urbdrc_process_addin_args(URBDRC_PLUGIN* urbdrc, ADDIN_ARGV* args)
#ifdef STATIC_CHANNELS
#define DVCPluginEntry urbdrc_DVCPluginEntry
#else
#define DVCPluginEntry FREERDP_API DVCPluginEntry
#endif
/**

View File

@ -1,3 +1,4 @@
message("PRELOADING windows cache")
set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
set(WITH_SERVER "ON" CACHE BOOL "Build server binaries")
#set (BUILD_TESTING ON CACHE BOOL "build testing")

View File

@ -16,7 +16,6 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<supports-screens

View File

@ -575,7 +575,7 @@ public class BookmarkActivity extends PreferenceActivity implements
if (!verifyFailed && sharedPreferences.getInt("bookmark.port", -1) <= 0)
verifyFailed = true;
// if an error occured - display toast and return false
// if an error occurred - display toast and return false
return (!verifyFailed);
}

View File

@ -1066,12 +1066,10 @@ public class SessionActivity extends ActionBarActivity implements
}
@Override
public boolean OnVerifiyCertificate(String subject, String issuer,
String fingerprint) {
public int OnVerifiyCertificate(String commonName, String subject, String issuer, String fingerprint, boolean mismatch) {
// see if global settings says accept all
if (GlobalSettings.getAcceptAllCertificates())
return true;
return 0;
// this is where the return code of our dialog will be stored
callbackDialogResult = false;
@ -1095,7 +1093,38 @@ public class SessionActivity extends ActionBarActivity implements
} catch (InterruptedException e) {
}
return callbackDialogResult;
return callbackDialogResult ? 1 : 0;
}
@Override
public int OnVerifiyChangedCertificate(String commonName, String subject, String issuer, String fingerprint, String oldSubject, String oldIssuer, String oldFingerprint) {
// see if global settings says accept all
if (GlobalSettings.getAcceptAllCertificates())
return 0;
// this is where the return code of our dialog will be stored
callbackDialogResult = false;
// set message
String msg = getResources().getString(
R.string.dlg_msg_verify_certificate);
msg = msg + "\n\nSubject: " + subject + "\nIssuer: " + issuer
+ "\nFingerprint: " + fingerprint;
dlgVerifyCertificate.setMessage(msg);
// start dialog in UI thread
uiHandler.sendMessage(Message.obtain(null, UIHandler.SHOW_DIALOG,
dlgVerifyCertificate));
// wait for result
try {
synchronized (dlgVerifyCertificate) {
dlgVerifyCertificate.wait();
}
} catch (InterruptedException e) {
}
return callbackDialogResult ? 1 : 0;
}
@Override

View File

@ -76,8 +76,8 @@ public class BookmarkDB extends SQLiteOpenHelper {
String sqlInsertDefaultPerfFlags =
"INSERT INTO tbl_performance_flags ("
+ "perf_remotefx, "
+ "perf_gfx"
+ "perf_gfx_h264"
+ "perf_gfx, "
+ "perf_gfx_h264, "
+ "perf_wallpaper, "
+ "perf_theming, "
+ "perf_full_window_drag, "

View File

@ -89,7 +89,12 @@ public class LibFreeRDP {
boolean OnAuthenticate(StringBuilder username, StringBuilder domain, StringBuilder password);
boolean OnVerifiyCertificate(String subject, String issuer, String fingerprint);
int OnVerifiyCertificate(String commonName, String subject,
String issuer, String fingerprint, boolean mismatch);
int OnVerifiyChangedCertificate(String commonName, String subject,
String issuer, String fingerprint, String oldSubject,
String oldIssuer, String oldFingerprint);
void OnGraphicsUpdate(int x, int y, int width, int height);
@ -252,10 +257,13 @@ public class LibFreeRDP {
}
}
/* 0 ... disable
1 ... local
2 ... remote */
/* 0 ... local
1 ... remote
2 ... disable */
args.add("/audio-mode:" + String.valueOf(advanced.getRedirectSound()));
if (advanced.getRedirectSound() == 0) {
args.add("/sound");
}
if (advanced.getRedirectMicrophone()) {
args.add("/microphone");
@ -330,14 +338,30 @@ public class LibFreeRDP {
return false;
}
private static boolean OnVerifyCertificate(int inst, String subject, String issuer, String fingerprint) {
private static int OnVerifyCertificate(int inst, String commonName, String subject,
String issuer, String fingerprint, boolean
hostMismatch) {
SessionState s = GlobalApp.getSession(inst);
if (s == null)
return false;
return 0;
UIEventListener uiEventListener = s.getUIEventListener();
if (uiEventListener != null)
return uiEventListener.OnVerifiyCertificate(subject, issuer, fingerprint);
return false;
return uiEventListener.OnVerifiyCertificate(commonName, subject, issuer, fingerprint,
hostMismatch);
return 0;
}
private static int OnVerifyCertificate(int inst, String commonName, String subject,
String issuer, String fingerprint, String oldSubject,
String oldIssuer, String oldFingerprint) {
SessionState s = GlobalApp.getSession(inst);
if (s == null)
return 0;
UIEventListener uiEventListener = s.getUIEventListener();
if (uiEventListener != null)
return uiEventListener.OnVerifiyChangedCertificate(commonName, subject, issuer,
fingerprint, oldSubject, oldIssuer, oldFingerprint);
return 0;
}
private static void OnGraphicsUpdate(int inst, int x, int y, int width, int height) {

View File

@ -119,9 +119,9 @@
<item>Auf Client abspielen</item>
</string-array>
<string-array name="redirect_sound_values_array">
<item>0</item>
<item>1</item>
<item>2</item>
<item>1</item>
<item>0</item>
</string-array>
<string name="settings_redirect_microphone">Mikrophon umleiten</string>
<string name="settings_security">Sicherheit</string>

View File

@ -122,9 +122,9 @@
<item>Play on Device</item>
</string-array>
<string-array name="redirect_sound_values_array">
<item>0</item>
<item>1</item>
<item>2</item>
<item>1</item>
<item>0</item>
</string-array>
<string name="settings_redirect_microphone">Redirect Microphone</string>
<string name="settings_security">Seguridad</string>

View File

@ -121,9 +121,9 @@
<item>Play on Device</item>
</string-array>
<string-array name="redirect_sound_values_array">
<item>0</item>
<item>1</item>
<item>2</item>
<item>1</item>
<item>0</item>
</string-array>
<string name="settings_redirect_microphone">Redirect Microphone</string>
<string name="settings_security">"Securité"</string>

View File

@ -122,9 +122,9 @@
<item>Play on Device</item>
</string-array>
<string-array name="redirect_sound_values_array">
<item>0</item>
<item>1</item>
<item>2</item>
<item>1</item>
<item>0</item>
</string-array>
<string name="settings_redirect_microphone">Redirect Microphone</string>
<string name="settings_security">Beveiliging</string>

View File

@ -119,9 +119,9 @@
<item>在此设备上播放</item>
</string-array>
<string-array name="redirect_sound_values_array">
<item>0</item>
<item>1</item>
<item>2</item>
<item>1</item>
<item>0</item>
</string-array>
<string name="settings_redirect_microphone">麦克风重定向</string>
<string name="settings_security">连接协议</string>

View File

@ -122,9 +122,9 @@
<item>Play on Device</item>
</string-array>
<string-array name="redirect_sound_values_array">
<item>0</item>
<item>1</item>
<item>2</item>
<item>1</item>
<item>0</item>
</string-array>
<string name="settings_redirect_microphone">Redirect Microphone</string>
<string name="settings_security">Security</string>

View File

@ -417,37 +417,64 @@ static BOOL android_authenticate(freerdp* instance, char** username,
return ((res == JNI_TRUE) ? TRUE : FALSE);
}
static BOOL android_verify_certificate(freerdp* instance, char* subject,
char* issuer, char* fingerprint)
static DWORD android_verify_certificate(
freerdp* instance, const char* common_name,
const char* subject, const char* issuer,
const char* fingerprint, BOOL host_mismatch)
{
JNIEnv* env;
jboolean attached = jni_attach_thread(&env);
jstring jstr1 = (*env)->NewStringUTF(env, subject);
jstring jstr2 = (*env)->NewStringUTF(env, issuer);
jstring jstr3 = (*env)->NewStringUTF(env, fingerprint);
jboolean res;
WLog_DBG(TAG, "Certificate details:");
WLog_DBG(TAG, "\tSubject: %s", subject);
WLog_DBG(TAG, "\tIssuer: %s", issuer);
WLog_DBG(TAG, "\tThumbprint: %s", fingerprint);
WLog_DBG(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 documentation on how to create local certificate store for a private CA.\n");
res = freerdp_callback_bool_result(
"OnVerifyCertificate",
"(ILjava/lang/String;"
"Ljava/lang/String;"
"Ljava/lang/String;)Z",
instance, jstr1, jstr2, jstr3);
JNIEnv* env;
jboolean attached = jni_attach_thread(&env);
jstring jstr0 = (*env)->NewStringUTF(env, common_name);
jstring jstr1 = (*env)->NewStringUTF(env, subject);
jstring jstr2 = (*env)->NewStringUTF(env, issuer);
jstring jstr3 = (*env)->NewStringUTF(env, fingerprint);
if (attached == JNI_TRUE)
jni_detach_thread();
jint res = freerdp_callback_int_result("OnVerifyCertificate",
"(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Z)I",
instance, jstr0, jstr1, jstr2, jstr3, host_mismatch);
return ((res == JNI_TRUE) ? TRUE : FALSE);
if (attached == JNI_TRUE)
jni_detach_thread();
return res;
}
static BOOL android_verify_changed_certificate(
freerdp* instance, char* subject, char* issuer,
char* new_fingerprint, char* old_subject,
char* old_issuer, char* old_fingerprint)
static DWORD android_verify_changed_certificate(freerdp* instance,
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)
{
return android_verify_certificate(
instance, subject, issuer,
new_fingerprint);
JNIEnv* env;
jboolean attached = jni_attach_thread(&env);
jstring jstr0 = (*env)->NewStringUTF(env, common_name);
jstring jstr1 = (*env)->NewStringUTF(env, subject);
jstring jstr2 = (*env)->NewStringUTF(env, issuer);
jstring jstr3 = (*env)->NewStringUTF(env, new_fingerprint);
jstring jstr4 = (*env)->NewStringUTF(env, old_subject);
jstring jstr5 = (*env)->NewStringUTF(env, old_issuer);
jstring jstr6 = (*env)->NewStringUTF(env, old_fingerprint);
jint res = freerdp_callback_int_result("OnVerifyChangedCertificate",
"(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;"
"Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I",
instance, jstr0, jstr1, jstr2, jstr3, jstr4, jstr5, jstr6);
if (attached == JNI_TRUE)
jni_detach_thread();
return res;
}
static void* jni_input_thread(void* arg)

View File

@ -172,6 +172,45 @@ finish:
return res;
}
/* callback with int result */
jint java_callback_int(jobject obj, const char * callback, const char* signature, va_list args)
{
jclass jObjClass;
jmethodID jCallback;
jboolean attached;
jint res = -1;
JNIEnv *env;
WLog_DBG(TAG, "java_callback: %s (%s)", callback, signature);
attached = jni_attach_thread(&env);
jObjClass = (*env)->GetObjectClass(env, obj);
if (!jObjClass)
{
WLog_ERR(TAG, "android_java_callback: failed to get class reference");
goto finish;
}
jCallback = (*env)->GetStaticMethodID(env, jObjClass, callback, signature);
if (!jCallback)
{
WLog_ERR(TAG, "android_java_callback: failed to get method id");
goto finish;
}
res = (*env)->CallStaticIntMethodV(env, jObjClass, jCallback, args);
finish:
if(attached == JNI_TRUE)
jni_detach_thread();
return res;
}
/* callback to freerdp class */
void freerdp_callback(const char * callback, const char * signature, ...)
{
@ -189,3 +228,12 @@ jboolean freerdp_callback_bool_result(const char * callback, const char * signat
va_end(vl);
return res;
}
jint freerdp_callback_int_result(const char * callback, const char * signature, ...)
{
va_list vl;
va_start(vl, signature);
jint res = java_callback_int(jLibFreeRDPObject, callback, signature, vl);
va_end(vl);
return res;
}

View File

@ -21,6 +21,7 @@ jboolean jni_attach_thread(JNIEnv** env);
void jni_detach_thread(void);
void freerdp_callback(const char * callback, const char * signature, ...);
jboolean freerdp_callback_bool_result(const char * callback, const char * signature, ...);
jint freerdp_callback_int_result(const char * callback, const char * signature, ...);
#endif /* FREERDP_ANDROID_JNI_CALLBACK_H */

View File

@ -2,6 +2,7 @@
# FreeRDP Wayland Client cmake build script
#
# Copyright 2014 Manuel Bachmann <tarnyko@tarnyko.net>
# Copyright 2015 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.
@ -18,22 +19,20 @@
set(MODULE_NAME "wlfreerdp")
set(MODULE_PREFIX "FREERDP_CLIENT_WAYLAND")
include_directories(${WAYLAND_INCLUDE_DIRS})
include_directories(${WAYLAND_INCLUDE_DIR})
include_directories(${CMAKE_SOURCE_DIR}/uwac/include)
set(${MODULE_PREFIX}_SRCS
wlf_display.c
wlf_display.h
wlf_window.c
wlf_window.h
wlfreerdp.c
wlfreerdp.h
wlf_input.c
wlf_input.h
wlfreerdp.c
wlfreerdp.h)
)
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${CMAKE_DL_LIBS})
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${WAYLAND_LIBRARIES} freerdp-client freerdp)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp-client freerdp uwac)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)

View File

@ -1,112 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Wayland Displays
*
* Copyright 2014 Manuel Bachmann <tarnyko@tarnyko.net>
*
* 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 <stdio.h>
#include <stdlib.h>
#include "wlf_display.h"
static void wl_registry_handle_global(void* data, struct wl_registry* registry, uint32_t id, const char *interface, uint32_t version)
{
wlfDisplay* display = data;
if (strcmp(interface, "wl_compositor") == 0)
display->compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1);
else if (strcmp(interface, "wl_shell") == 0)
display->shell = wl_registry_bind(registry, id, &wl_shell_interface, 1);
else if (strcmp(interface, "wl_shm") == 0)
display->shm = wl_registry_bind(registry, id, &wl_shm_interface, 1);
else if (strcmp(interface, "wl_seat") == 0)
display->seat = wl_registry_bind(registry, id, &wl_seat_interface, 1);
}
static void wl_registry_handle_global_remove(void* data, struct wl_registry* registry, uint32_t name)
{
}
static const struct wl_registry_listener wl_registry_listener =
{
wl_registry_handle_global,
wl_registry_handle_global_remove
};
wlfDisplay* wlf_CreateDisplay(void)
{
wlfDisplay* display;
display = (wlfDisplay*) calloc(1, sizeof(wlfDisplay));
if (display)
{
display->display = wl_display_connect(NULL);
if (!display->display)
{
WLog_ERR(TAG, "wl_pre_connect: failed to connect to Wayland compositor");
WLog_ERR(TAG, "Please check that the XDG_RUNTIME_DIR environment variable is properly set.");
free(display);
return NULL;
}
display->registry = wl_display_get_registry(display->display);
wl_registry_add_listener(display->registry, &wl_registry_listener, display);
wl_display_roundtrip(display->display);
if (!display->compositor || !display->shell || !display->shm)
{
WLog_ERR(TAG, "wl_pre_connect: failed to find needed compositor interfaces");
free(display);
return NULL;
}
}
return display;
}
BOOL wlf_RefreshDisplay(wlfDisplay* display)
{
if (wl_display_dispatch(display->display) == -1)
return FALSE;
return TRUE;
}
void wlf_DestroyDisplay(wlfContext* wlfc, wlfDisplay* display)
{
if (display == NULL)
return;
if (wlfc->display == display)
wlfc->display = NULL;
if (display->seat)
wl_seat_destroy(display->seat);
if (display->shm)
wl_shm_destroy(display->shm);
if (display->shell)
wl_shell_destroy(display->shell);
if (display->compositor)
wl_compositor_destroy(display->compositor);
if (display->registry)
wl_registry_destroy(display->registry);
wl_display_disconnect(display->display);
free(display);
}

View File

@ -1,43 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Wayland Displays
*
* Copyright 2014 Manuel Bachmann <tarnyko@tarnyko.net>
*
* 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 __WLF_DISPLAY_H
#define __WLF_DISPLAY_H
#include <wayland-client.h>
typedef struct wlf_display wlfDisplay;
#include "wlfreerdp.h"
struct wlf_display
{
struct wl_display* display;
struct wl_registry* registry;
struct wl_compositor* compositor;
struct wl_shell* shell;
struct wl_shm* shm;
struct wl_seat* seat;
};
wlfDisplay* wlf_CreateDisplay(void);
BOOL wlf_RefreshDisplay(wlfDisplay* display);
void wlf_DestroyDisplay(wlfContext* wlfc, wlfDisplay* display);
#endif /* __WLF_DISPLAY_H */

View File

@ -3,6 +3,7 @@
* Wayland Input
*
* Copyright 2014 Manuel Bachmann <tarnyko@tarnyko.net>
* Copyright 2015 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.
@ -24,50 +25,30 @@
#include "wlf_input.h"
static void wl_pointer_enter(void* data, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surface, wl_fixed_t sx_w, wl_fixed_t sy_w)
{
BOOL wlf_handle_pointer_enter(freerdp *instance, UwacPointerEnterLeaveEvent *ev) {
rdpInput* input = instance->input;
return input->MouseEvent(input, PTR_FLAGS_MOVE, ev->x, ev->y);
}
static void wl_pointer_leave(void* data, struct wl_pointer* pointer, uint32_t serial, struct wl_surface* surface)
{
BOOL wlf_handle_pointer_motion(freerdp *instance, UwacPointerMotionEvent *ev) {
rdpInput* input = instance->input;
return input->MouseEvent(input, PTR_FLAGS_MOVE, ev->x, ev->y);
}
static void wl_pointer_motion(void* data, struct wl_pointer* pointer, uint32_t time, wl_fixed_t sx_w, wl_fixed_t sy_w)
{
wlfInput* input_w = data;
BOOL wlf_handle_pointer_buttons(freerdp *instance, UwacPointerButtonEvent *ev) {
rdpInput* input;
UINT16 x;
UINT16 y;
input = input_w->input;
x = (UINT16) wl_fixed_to_int(sx_w);
y = (UINT16) wl_fixed_to_int(sy_w);
input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
input_w->last_x = x;
input_w->last_y = y;
}
static void wl_pointer_button(void* data, struct wl_pointer* pointer, uint32_t serial, uint32_t time, uint32_t button, uint32_t state)
{
wlfInput* input_w = data;
rdpInput* input;
UINT16 x;
UINT16 y;
UINT16 flags;
input = input_w->input;
input = instance->input;
if (state == WL_POINTER_BUTTON_STATE_PRESSED)
if (ev->state == WL_POINTER_BUTTON_STATE_PRESSED)
flags = PTR_FLAGS_DOWN;
else
flags = 0;
switch (button)
switch (ev->button)
{
case BTN_LEFT:
flags |= PTR_FLAGS_BUTTON1;
@ -79,175 +60,50 @@ static void wl_pointer_button(void* data, struct wl_pointer* pointer, uint32_t s
flags |= PTR_FLAGS_BUTTON3;
break;
default:
return;
return TRUE;
}
x = input_w->last_x;
y = input_w->last_y;
input->MouseEvent(input, flags, x, y);
return input->MouseEvent(input, flags, ev->x, ev->y);
}
static void wl_pointer_axis(void* data, struct wl_pointer* pointer, uint32_t time, uint32_t axis, wl_fixed_t value)
{
wlfInput* input_w = data;
BOOL wlf_handle_pointer_axis(freerdp *instance, UwacPointerAxisEvent *ev) {
rdpInput* input;
UINT16 flags;
int direction;
input = input_w->input;
input = instance->input;
flags = PTR_FLAGS_WHEEL;
if (axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
if (ev->axis == WL_POINTER_AXIS_VERTICAL_SCROLL)
{
direction = wl_fixed_to_int(value);
direction = wl_fixed_to_int(ev->value);
if (direction < 0)
flags |= 0x0078;
else
flags |= PTR_FLAGS_WHEEL_NEGATIVE | 0x0088;
}
input->MouseEvent(input, flags, 0, 0);
return input->MouseEvent(input, flags, ev->x, ev->y);
}
static const struct wl_pointer_listener wl_pointer_listener =
{
wl_pointer_enter,
wl_pointer_leave,
wl_pointer_motion,
wl_pointer_button,
wl_pointer_axis
};
static void wl_keyboard_keymap(void* data, struct wl_keyboard* keyboard, uint32_t format, int fd, uint32_t size)
{
}
static void wl_keyboard_enter(void* data, struct wl_keyboard* keyboard, uint32_t serial, struct wl_surface* surface, struct wl_array* keys)
{
wlfInput* input_w = data;
rdpInput* input;
UINT16 x;
UINT16 y;
input = input_w->input;
x = input_w->last_x;
y = input_w->last_y;
input->FocusInEvent(input, 0);
input->MouseEvent(input, PTR_FLAGS_MOVE, x, y);
}
static void wl_keyboard_leave(void* data, struct wl_keyboard* keyboard, uint32_t serial, struct wl_surface* surface)
{
}
static void wl_keyboard_key(void* data, struct wl_keyboard* keyboard, uint32_t serial, uint32_t time, uint32_t key, uint32_t state)
{
wlfInput* input_w = data;
rdpInput* input;
BOOL key_down;
BOOL wlf_handle_key(freerdp *instance, UwacKeyEvent *ev) {
rdpInput* input = instance->input;
DWORD rdp_scancode;
input = input_w->input;
if (state == WL_KEYBOARD_KEY_STATE_PRESSED)
key_down = TRUE;
else
key_down = FALSE;
rdp_scancode = (DWORD) key;
rdp_scancode = (DWORD) ev->raw_key;
if (rdp_scancode == RDP_SCANCODE_UNKNOWN)
return;
return TRUE;
freerdp_input_send_keyboard_event_ex(input, key_down, rdp_scancode);
return freerdp_input_send_keyboard_event_ex(input, ev->pressed, rdp_scancode);
}
static void wl_keyboard_modifiers(void* data, struct wl_keyboard* keyboard, uint32_t serial, uint32_t mods_depr, uint32_t mods_latch, uint32_t mods_lock, uint32_t group)
{
BOOL wlf_keyboard_enter(freerdp *instance, UwacKeyboardEnterLeaveEvent *ev) {
rdpInput* input = instance->input;
return input->FocusInEvent(input, 0) &&
input->MouseEvent(input, PTR_FLAGS_MOVE, 0, 0);
}
static const struct wl_keyboard_listener wl_keyboard_listener =
{
wl_keyboard_keymap,
wl_keyboard_enter,
wl_keyboard_leave,
wl_keyboard_key,
wl_keyboard_modifiers
};
static void wl_seat_handle_capabilities(void* data, struct wl_seat* seat, enum wl_seat_capability capabilities)
{
wlfInput* input = data;
struct wl_pointer* pointer;
struct wl_keyboard* keyboard;
if (capabilities & WL_SEAT_CAPABILITY_POINTER)
{
pointer = wl_seat_get_pointer(seat);
input->pointer = pointer;
wl_pointer_add_listener(pointer, &wl_pointer_listener, input);
}
if (capabilities & WL_SEAT_CAPABILITY_KEYBOARD)
{
keyboard = wl_seat_get_keyboard(seat);
input->keyboard = keyboard;
wl_keyboard_add_listener(keyboard, &wl_keyboard_listener, input);
}
}
static const struct wl_seat_listener wl_seat_listener = {
wl_seat_handle_capabilities
};
wlfInput* wlf_CreateInput(wlfContext* wlfc)
{
wlfInput* input;
struct wl_seat* seat;
if (!wlfc->display)
return NULL;
if (!wlfc->display->seat)
return NULL;
seat = wlfc->display->seat;
input = (wlfInput*) calloc(1, sizeof(wlfInput));
if (input)
{
input->input = wlfc->context.input;
input->last_x = 0;
input->last_y = 0;
wl_seat_add_listener(seat, &wl_seat_listener, input);
}
return input;
}
void wlf_DestroyInput(wlfContext* wlfc, wlfInput* input)
{
if (input == NULL)
return;
if (wlfc->input == input)
wlfc->input = NULL;
if (input->pointer)
wl_pointer_release(input->pointer);
if (input->keyboard)
wl_keyboard_release(input->keyboard);
free(input);
}

View File

@ -3,6 +3,7 @@
* Wayland Input
*
* Copyright 2014 Manuel Bachmann <tarnyko@tarnyko.net>
* Copyright 2015 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.
@ -20,23 +21,15 @@
#ifndef __WLF_INPUT_H
#define __WLF_INPUT_H
#include <wayland-client.h>
#include <freerdp/freerdp.h>
#include <uwac/uwac.h>
typedef struct wlf_input wlfInput;
BOOL wlf_handle_pointer_enter(freerdp* instance, UwacPointerEnterLeaveEvent *ev);
BOOL wlf_handle_pointer_motion(freerdp* instance, UwacPointerMotionEvent *ev);
BOOL wlf_handle_pointer_buttons(freerdp* instance, UwacPointerButtonEvent *ev);
BOOL wlf_handle_pointer_axis(freerdp* instance, UwacPointerAxisEvent *ev);
#include "wlfreerdp.h"
struct wlf_input
{
rdpInput* input;
UINT16 last_x;
UINT16 last_y;
struct wl_pointer* pointer;
struct wl_keyboard* keyboard;
};
wlfInput* wlf_CreateInput(wlfContext* wlfc);
void wlf_DestroyInput(wlfContext* wlfc, wlfInput* input);
BOOL wlf_handle_key(freerdp* instance, UwacKeyEvent *ev);
BOOL wlf_keyboard_enter(freerdp *instance, UwacKeyboardEnterLeaveEvent *ev);
#endif /* __WLF_INPUT_H */

View File

@ -1,220 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Wayland Windows
*
* Copyright 2014 Manuel Bachmann <tarnyko@tarnyko.net>
*
* 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 <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>
#include "wlf_window.h"
static void wl_shell_surface_handle_ping(void* data, struct wl_shell_surface* shell_surface, uint32_t serial)
{
wl_shell_surface_pong(shell_surface, serial);
}
static void wl_shell_surface_handle_configure(void* data, struct wl_shell_surface* shell_surface, unsigned int edges, int32_t width, int32_t height)
{
wlfWindow* window = data;
window->width = width;
window->height = height;
}
static const struct wl_shell_surface_listener wl_shell_surface_listener =
{
wl_shell_surface_handle_ping,
wl_shell_surface_handle_configure,
NULL
};
static void wl_buffer_release(void* data, struct wl_buffer* wl_buffer)
{
wlfBuffer* buffer = data;
buffer->busy = FALSE;
}
static const struct wl_buffer_listener wl_buffer_listener =
{
wl_buffer_release
};
static const struct wl_callback_listener wl_callback_listener;
static void wl_callback_done(void* data, struct wl_callback* callback, uint32_t time)
{
wlfWindow* window = data;
wlfBuffer* buffer;
struct wl_shm_pool* shm_pool;
void* shm_data;
void* free_data;
int fd;
int fdt;
if (!window->buffers[0].busy)
buffer = &window->buffers[0];
else if (!window->buffers[1].busy)
buffer = &window->buffers[1];
else
return;
if (!buffer->buffer) {
fd = shm_open("/wlfreerdp_shm", O_CREAT | O_RDWR, 0666);
fdt = ftruncate(fd, window->width * window->height * 4);
if (fdt != 0)
{
WLog_ERR(TAG, "window_redraw: could not allocate memory");
close(fd);
return;
}
shm_data = mmap(NULL, window->width * window->height * 4, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (shm_data == MAP_FAILED)
{
WLog_ERR(TAG, "window_redraw: failed to memory map buffer");
close(fd);
return;
}
shm_pool = wl_shm_create_pool(window->display->shm, fd, window->width * window->height * 4);
buffer->buffer = wl_shm_pool_create_buffer(shm_pool, 0, window->width, window->height, window->width* 4, WL_SHM_FORMAT_XRGB8888);
wl_buffer_add_listener(buffer->buffer, &wl_buffer_listener, buffer);
wl_shm_pool_destroy(shm_pool);
shm_unlink("/wlfreerdp_shm");
close(fd);
free_data = buffer->shm_data;
buffer->shm_data = shm_data;
munmap(free_data, window->width * window->height * 4);
}
/* this is the real surface data */
memcpy(buffer->shm_data, (void*) window->data, window->width * window->height * 4);
wl_surface_attach(window->surface, buffer->buffer, 0, 0);
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
if (callback) wl_callback_destroy(callback);
window->callback = wl_surface_frame(window->surface);
wl_callback_add_listener(window->callback, &wl_callback_listener, window);
wl_surface_commit(window->surface);
buffer->busy = TRUE;
}
static const struct wl_callback_listener wl_callback_listener =
{
wl_callback_done
};
wlfWindow* wlf_CreateDesktopWindow(wlfContext* wlfc, char* name, int width, int height, BOOL decorations)
{
wlfWindow* window;
window = (wlfWindow*) calloc(1, sizeof(wlfWindow));
if (window)
{
window->width = width;
window->height = height;
window->fullscreen = FALSE;
window->buffers[0].busy = FALSE;
window->buffers[1].busy = FALSE;
window->callback = NULL;
window->display = wlfc->display;
window->surface = wl_compositor_create_surface(window->display->compositor);
window->shell_surface = wl_shell_get_shell_surface(window->display->shell, window->surface);
wl_shell_surface_add_listener(window->shell_surface, &wl_shell_surface_listener, window);
wl_shell_surface_set_toplevel(window->shell_surface);
wlf_ResizeDesktopWindow(wlfc, window, width, height);
wl_surface_damage(window->surface, 0, 0, window->width, window->height);
wlf_SetWindowText(wlfc, window, name);
}
return window;
}
void wlf_ResizeDesktopWindow(wlfContext* wlfc, wlfWindow* window, int width, int height)
{
window->width = width;
window->height = height;
}
void wlf_SetWindowText(wlfContext* wlfc, wlfWindow* window, char* name)
{
wl_shell_surface_set_title(window->shell_surface, name);
}
void wlf_SetWindowFullscreen(wlfContext* wlfc, wlfWindow* window, BOOL fullscreen)
{
if (fullscreen)
{
wl_shell_surface_set_fullscreen(window->shell_surface, WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT, 0, NULL);
window->fullscreen = TRUE;
}
}
void wlf_ShowWindow(wlfContext* wlfc, wlfWindow* window, BYTE state)
{
switch (state)
{
case WINDOW_HIDE:
case WINDOW_SHOW_MINIMIZED:
/* xdg_surface_set_minimized(window->xdg_surface); */
break;
case WINDOW_SHOW_MAXIMIZED:
wl_shell_surface_set_maximized(window->shell_surface, NULL);
break;
case WINDOW_SHOW:
wl_shell_surface_set_toplevel(window->shell_surface);
break;
}
}
void wlf_UpdateWindowArea(wlfContext* wlfc, wlfWindow* window, int x, int y, int width, int height)
{
wl_callback_done(window, NULL, 0);
}
void wlf_DestroyWindow(wlfContext* wlfc, wlfWindow* window)
{
if (window == NULL)
return;
if (wlfc->window == window)
wlfc->window = NULL;
if (window->buffers[0].buffer)
wl_buffer_destroy(window->buffers[0].buffer);
if (window->buffers[1].buffer)
wl_buffer_destroy(window->buffers[1].buffer);
if (window->shell_surface)
wl_shell_surface_destroy(window->shell_surface);
if (window->surface)
wl_surface_destroy(window->surface);
free(window->data);
free(window);
}

View File

@ -1,58 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Wayland Windows
*
* Copyright 2014 Manuel Bachmann <tarnyko@tarnyko.net>
*
* 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 __WLF_WINDOW_H
#define __WLF_WINDOW_H
#include <wayland-client.h>
typedef struct wlf_window wlfWindow;
#include "wlfreerdp.h"
struct wlf_buffer
{
struct wl_buffer* buffer;
void* shm_data;
BOOL busy;
};
typedef struct wlf_buffer wlfBuffer;
struct wlf_window
{
int width;
int height;
struct wl_surface* surface;
struct wl_shell_surface* shell_surface;
struct wl_callback* callback;
wlfBuffer buffers[2];
wlfDisplay* display;
void* data;
BOOL fullscreen;
};
wlfWindow* wlf_CreateDesktopWindow(wlfContext* wlfc, char* name, int width, int height, BOOL decorations);
void wlf_ResizeDesktopWindow(wlfContext* wlfc, wlfWindow* window, int width, int height);
void wlf_SetWindowText(wlfContext* wlfc, wlfWindow* window, char* name);
void wlf_SetWindowFullscreen(wlfContext* wlfc, wlfWindow* window, BOOL fullscree);
void wlf_ShowWindow(wlfContext* wlfc, wlfWindow* window, BYTE state);
void wlf_UpdateWindowArea(wlfContext* wlfc, wlfWindow* window, int x, int y, int width, int height);
void wlf_DestroyWindow(wlfContext* wlfc, wlfWindow* window);
#endif /* __WLF_WINDOW_H */

View File

@ -23,8 +23,13 @@
#include <freerdp/client/cmdline.h>
#include <freerdp/channels/channels.h>
#include <freerdp/gdi/gdi.h>
#include <linux/input.h>
#include "wlfreerdp.h"
#include "wlf_input.h"
UwacDisplay *g_display;
HANDLE g_displayHandle;
static BOOL wl_context_new(freerdp* instance, rdpContext* context)
{
@ -44,6 +49,18 @@ static void wl_context_free(freerdp* instance, rdpContext* context)
}
}
BOOL wl_update_content(wlfContext *context_w)
{
if (!context_w->waitingFrameDone && context_w->haveDamage)
{
UwacWindowSubmitBuffer(context_w->window, true);
context_w->waitingFrameDone = TRUE;
context_w->haveDamage = FALSE;
}
return TRUE;
}
static BOOL wl_begin_paint(rdpContext* context)
{
rdpGdi* gdi;
@ -53,12 +70,12 @@ static BOOL wl_begin_paint(rdpContext* context)
return TRUE;
}
static BOOL wl_end_paint(rdpContext* context)
{
rdpGdi* gdi;
wlfDisplay* display;
wlfWindow* window;
wlfContext* context_w;
char *data;
wlfContext *context_w;
INT32 x, y;
UINT32 w, h;
int i;
@ -73,21 +90,28 @@ static BOOL wl_end_paint(rdpContext* context)
h = gdi->primary->hdc->hwnd->invalid->h;
context_w = (wlfContext*) context;
display = context_w->display;
window = context_w->window;
data = UwacWindowGetDrawingBuffer(context_w->window);
if (!data)
return FALSE;
for (i = 0; i < h; i++)
memcpy(window->data + ((i+y)*(gdi->width*4)) + x*4,
{
memcpy(data + ((i+y)*(gdi->width*4)) + x*4,
gdi->primary_buffer + ((i+y)*(gdi->width*4)) + x*4,
w*4);
}
return wlf_RefreshDisplay(display);
if (UwacWindowAddDamage(context_w->window, x, y, w, h) != UWAC_SUCCESS)
return FALSE;
context_w->haveDamage = TRUE;
return wl_update_content(context_w);
}
static BOOL wl_pre_connect(freerdp* instance)
{
wlfDisplay* display;
wlfInput* input;
wlfContext* context;
if (freerdp_channels_pre_connect(instance->context->channels, instance))
@ -97,17 +121,7 @@ static BOOL wl_pre_connect(freerdp* instance)
if (!context)
return FALSE;
display = wlf_CreateDisplay();
if (!display)
return FALSE;
context->display = display;
input = wlf_CreateInput(context);
if (!input)
return FALSE;
context->input = input;
context->display = g_display;
return TRUE;
}
@ -115,7 +129,7 @@ static BOOL wl_pre_connect(freerdp* instance)
static BOOL wl_post_connect(freerdp* instance)
{
rdpGdi* gdi;
wlfWindow* window;
UwacWindow* window;
wlfContext* context;
if (!gdi_init(instance, CLRCONV_ALPHA | CLRBUF_32BPP, NULL))
@ -126,28 +140,23 @@ static BOOL wl_post_connect(freerdp* instance)
return FALSE;
context = (wlfContext*) instance->context;
window = wlf_CreateDesktopWindow(context, "FreeRDP", gdi->width, gdi->height, FALSE);
context->window = window = UwacCreateWindowShm(context->display, gdi->width, gdi->height, WL_SHM_FORMAT_XRGB8888);
if (!window)
return FALSE;
/* fill buffer with first image here */
window->data = malloc (gdi->width * gdi->height *4);
if (!window->data)
return FALSE;
UwacWindowSetTitle(window, "FreeRDP");
memcpy(window->data, (void*) gdi->primary_buffer, gdi->width * gdi->height * 4);
instance->update->BeginPaint = wl_begin_paint;
instance->update->EndPaint = wl_end_paint;
/* put Wayland data in the context here */
context->window = window;
if (freerdp_channels_post_connect(instance->context->channels, instance) < 0)
return FALSE;
wlf_UpdateWindowArea(context, window, 0, 0, gdi->width, gdi->height);
return TRUE;
memcpy(UwacWindowGetDrawingBuffer(context->window), gdi->primary_buffer, gdi->width * gdi->height * 4);
UwacWindowAddDamage(context->window, 0, 0, gdi->width, gdi->height);
context->haveDamage = TRUE;
return wl_update_content(context);
}
static void wl_post_disconnect(freerdp* instance)
@ -161,55 +170,67 @@ static void wl_post_disconnect(freerdp* instance)
context = (wlfContext*) instance->context;
if (context->display)
wlf_DestroyDisplay(context, context->display);
if (context->input)
wlf_DestroyInput(context, context->input);
gdi_free(instance);
if (context->window)
wlf_DestroyWindow(context, context->window);
UwacDestroyWindow(&context->window);
if (context->display)
UwacCloseDisplay(&context->display);
}
static BOOL wl_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint)
{
char answer;
static BOOL handle_uwac_events(freerdp* instance, UwacDisplay *display) {
UwacEvent event;
wlfContext *context;
printf("Certificate details:\n");
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 "
"the CA certificate in your certificate store, or the certificate has expired. "
"Please look at the documentation on how to create local certificate store for a private CA.\n");
if (UwacDisplayDispatch(display, 1) < 0)
return FALSE;
while (1)
while (UwacHasEvent(display))
{
printf("Do you trust the above certificate? (Y/N) ");
answer = fgetc(stdin);
if (feof(stdin))
{
printf("\nError: Could not read answer from stdin.");
if (instance->settings->CredentialsFromStdin)
printf(" - Run without parameter \"--from-stdin\" to set trust.");
printf("\n");
if (UwacNextEvent(display, &event) != UWAC_SUCCESS)
return FALSE;
}
if (answer == 'y' || answer == 'Y')
{
return TRUE;
}
else if (answer == 'n' || answer == 'N')
{
/*printf("UWAC event type %d\n", event.type);*/
switch (event.type) {
case UWAC_EVENT_FRAME_DONE:
if (!instance)
continue;
context = (wlfContext *)instance->context;
context->waitingFrameDone = FALSE;
if (context->haveDamage && !wl_end_paint(instance->context))
return FALSE;
break;
case UWAC_EVENT_POINTER_ENTER:
if (!wlf_handle_pointer_enter(instance, &event.mouse_enter_leave))
return FALSE;
break;
case UWAC_EVENT_POINTER_MOTION:
if (!wlf_handle_pointer_motion(instance, &event.mouse_motion))
return FALSE;
break;
case UWAC_EVENT_POINTER_BUTTONS:
if (!wlf_handle_pointer_buttons(instance, &event.mouse_button))
return FALSE;
break;
case UWAC_EVENT_POINTER_AXIS:
if (!wlf_handle_pointer_axis(instance, &event.mouse_axis))
return FALSE;
break;
case UWAC_EVENT_KEY:
if (!wlf_handle_key(instance, &event.key))
return FALSE;
break;
case UWAC_EVENT_KEYBOARD_ENTER:
if (!wlf_keyboard_enter(instance, &event.keyboard_enter_leave))
return FALSE;
break;
default:
break;
}
printf("\n");
}
return FALSE;
return TRUE;
}
static int wlfreerdp_run(freerdp* instance)
@ -224,27 +245,39 @@ static int wlfreerdp_run(freerdp* instance)
return -1;
}
handle_uwac_events(instance, g_display);
while (!freerdp_shall_disconnect(instance))
{
count = freerdp_get_event_handles(instance->context, handles, 64);
handles[0] = g_displayHandle;
count = freerdp_get_event_handles(instance->context, &handles[1], 63);
if (!count)
{
printf("Failed to get FreeRDP file descriptor\n");
break;
}
status = WaitForMultipleObjects(count, handles, FALSE, INFINITE);
status = WaitForMultipleObjects(count+1, handles, FALSE, INFINITE);
if (WAIT_FAILED == status)
{
printf("%s: WaitForMultipleObjects failed\n", __FUNCTION__);
break;
}
if (freerdp_check_event_handles(instance->context) != TRUE)
{
printf("Failed to check FreeRDP file descriptor\n");
if (!handle_uwac_events(instance, g_display)) {
printf("error handling UWAC events\n");
break;
}
//if (WaitForMultipleObjects(count, &handles[1], FALSE, INFINITE)) {
if (freerdp_check_event_handles(instance->context) != TRUE)
{
printf("Failed to check FreeRDP file descriptor\n");
break;
}
//}
}
freerdp_channels_disconnect(instance->context->channels, instance);
@ -255,14 +288,28 @@ static int wlfreerdp_run(freerdp* instance)
int main(int argc, char* argv[])
{
int status;
UwacReturnCode status;
freerdp* instance;
g_display = UwacOpenDisplay(NULL, &status);
if (!g_display)
exit(1);
g_displayHandle = CreateFileDescriptorEvent(NULL, FALSE, FALSE, UwacDisplayGetFd(g_display), WINPR_FD_READ);
if (!g_displayHandle)
exit(1);
//if (!handle_uwac_events(NULL, g_display))
// exit(1);
instance = freerdp_new();
instance->PreConnect = wl_pre_connect;
instance->PostConnect = wl_post_connect;
instance->PostDisconnect = wl_post_disconnect;
instance->VerifyCertificate = wl_verify_certificate;
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->ContextSize = sizeof(wlfContext);
instance->ContextNew = wl_context_new;

View File

@ -23,22 +23,22 @@
#include <freerdp/freerdp.h>
#include <freerdp/log.h>
#include <winpr/wtypes.h>
#include <uwac/uwac.h>
#define TAG CLIENT_TAG("wayland")
typedef struct wlf_context wlfContext;
#include "wlf_display.h"
#include "wlf_window.h"
#include "wlf_input.h"
struct wlf_context
{
rdpContext context;
wlfDisplay* display;
wlfWindow* window;
wlfInput* input;
UwacDisplay *display;
UwacWindow *window;
BOOL waitingFrameDone;
BOOL haveDamage;
};
#endif /* __WLFREERDP_H */

View File

@ -40,9 +40,10 @@
#include "wf_client.h"
#include <shellapi.h>
INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
int index;
int status;
HANDLE thread;
wfContext* wfc;
@ -50,7 +51,11 @@ INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
rdpContext* context;
rdpSettings* settings;
RDP_CLIENT_ENTRY_POINTS clientEntryPoints;
int ret = 0;
int ret = 1;
int argc = 0, i;
LPWSTR* args;
LPWSTR cmd;
char** argv;
ZeroMemory(&clientEntryPoints, sizeof(RDP_CLIENT_ENTRY_POINTS));
clientEntryPoints.Size = sizeof(RDP_CLIENT_ENTRY_POINTS);
@ -59,56 +64,71 @@ INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
RdpClientEntry(&clientEntryPoints);
context = freerdp_client_context_new(&clientEntryPoints);
if (!context)
return -1;
cmd = GetCommandLineW();
if (!cmd)
goto out;
args = CommandLineToArgvW(cmd, &argc);
if (!args)
goto out;
argv = calloc(argc, sizeof(char*));
if (!argv)
goto out;
for (i=0; i<argc; i++)
{
int size = WideCharToMultiByte(CP_UTF8, 0, args[i], -1, NULL, 0, NULL, NULL);
argv[i] = calloc(size, sizeof(char));
if (!argv[i])
goto out;
if (WideCharToMultiByte(CP_UTF8, 0, args[i], -1, argv[i], size, NULL, NULL) != size)
goto out;
}
settings = context->settings;
wfc = (wfContext*) context;
settings->SoftwareGdi = TRUE;
context->argc = __argc;
context->argv = (char**) malloc(sizeof(char*) * __argc);
if (!context->argv)
{
ret = 1;
if (!settings || !wfc)
goto out;
}
for (index = 0; index < context->argc; index++)
{
context->argv[index] = _strdup(__argv[index]);
if (!context->argv[index])
{
ret = 1;
for (--index; index >= 0; --index)
free(context->argv[index]);
free(context->argv);
context->argv = NULL;
goto out;
}
}
status = freerdp_client_settings_parse_command_line(settings, context->argc, context->argv, FALSE);
status = freerdp_client_settings_command_line_status_print(settings, status, context->argc, context->argv);
status = freerdp_client_settings_parse_command_line(settings, argc, argv, FALSE);
if (status)
{
freerdp_client_context_free(context);
return 0;
}
{
freerdp_client_settings_command_line_status_print(settings, status, argc, argv);
goto out;
}
freerdp_client_start(context);
if (freerdp_client_start(context) != 0)
goto out;
thread = freerdp_client_get_thread(context);
if (thread)
{
if (WaitForSingleObject(thread, INFINITE) == WAIT_OBJECT_0)
{
GetExitCodeThread(thread, &dwExitCode);
ret = dwExitCode;
}
}
WaitForSingleObject(thread, INFINITE);
if (freerdp_client_stop(context) != 0)
goto out;
GetExitCodeThread(thread, &dwExitCode);
freerdp_client_stop(context);
out:
freerdp_client_context_free(context);
if (argv)
{
for (i=0; i<argc; i++)
free(argv[i]);
free (argv);
}
LocalFree(args);
return ret;
}

View File

@ -608,6 +608,31 @@ BOOL wf_verify_certificate(freerdp* instance, char* subject, char* issuer, char*
return TRUE;
}
static DWORD wf_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)
{
char answer;
WLog_ERR(TAG, "!!! Certificate has changed !!!");
WLog_ERR(TAG, "New Certificate details:");
WLog_ERR(TAG, "\tSubject: %s", subject);
WLog_ERR(TAG, "\tIssuer: %s", issuer);
WLog_ERR(TAG, "\tThumbprint: %s", fingerprint);
WLog_ERR(TAG, "Old Certificate details:");
WLog_ERR(TAG, "\tSubject: %s", old_subject);
WLog_ERR(TAG, "\tIssuer: %s", old_issuer);
WLog_ERR(TAG, "\tThumbprint: %s", old_fingerprint);
WLog_ERR(TAG, "The above X.509 certificate does not match the certificate used for previous connections. "
"This may indicate that the certificate has been tampered with."
"Please contact the administrator of the RDP server and clarify.");
return 0;
}
static BOOL wf_auto_reconnect(freerdp* instance)
{
wfContext* wfc = (wfContext *)instance->context;
@ -1081,6 +1106,7 @@ BOOL wfreerdp_client_new(freerdp* instance, rdpContext* context)
instance->Authenticate = wf_authenticate;
instance->GatewayAuthenticate = wf_gw_authenticate;
instance->VerifyCertificate = wf_verify_certificate;
instance->VerifyChangedCertificate = wf_verify_changed_certificate;
wfc->instance = instance;
wfc->settings = instance->settings;

View File

@ -456,14 +456,33 @@ static BOOL wf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
{
char* title = NULL;
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string,
windowState->titleInfo.length / 2, &title, 0, NULL, NULL);
if (windowState->titleInfo.length == 0)
{
if (!(title = _strdup("")))
{
WLog_ERR(TAG, "failed to duplicate empty window title string");
/* error handled below */
}
}
else if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string,
windowState->titleInfo.length / 2, &title, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert window title");
/* error handled below */
}
railWindow->title = title;
}
else
{
railWindow->title = _strdup("RdpRailWindow");
if (!(railWindow->title = _strdup("RdpRailWindow")))
WLog_ERR(TAG, "failed to duplicate default window title string");
}
if (!railWindow->title)
{
free(railWindow);
return FALSE;
}
ConvertToUnicode(CP_UTF8, 0, railWindow->title, -1, &titleW, 0);
@ -569,8 +588,20 @@ static BOOL wf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
char* title = NULL;
WCHAR* titleW = NULL;
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string,
windowState->titleInfo.length / 2, &title, 0, NULL, NULL);
if (windowState->titleInfo.length == 0)
{
if (!(title = _strdup("")))
{
WLog_ERR(TAG, "failed to duplicate empty window title string");
return FALSE;
}
}
else if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string,
windowState->titleInfo.length / 2, &title, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert window title");
return FALSE;
}
free(railWindow->title);
railWindow->title = title;

View File

@ -102,8 +102,6 @@
#include <freerdp/log.h>
#define TAG CLIENT_TAG("x11")
static const size_t password_size = 512;
static int (*_def_error_handler)(Display*, XErrorEvent*);
static int _xf_error_handler(Display* d, XErrorEvent* ev);
static void xf_check_extensions(xfContext* context);
@ -1357,158 +1355,6 @@ static void xf_post_disconnect(freerdp* instance)
xf_keyboard_free(xfc);
}
/** Callback set in the rdp_freerdp structure, and used to get the user's password,
* if required to establish the connection.
* This function is actually called in credssp_ntlmssp_client_init()
* @see rdp_server_accept_nego() and rdp_check_fds()
* @param instance - pointer to the rdp_freerdp structure that contains the connection settings
* @param username - unused
* @param password - on return: pointer to a character string that will be filled by the password entered by the user.
* Note that this character string will be allocated inside the function, and needs to be deallocated by the caller
* using free(), even in case this function fails.
* @param domain - unused
* @return TRUE if a password was successfully entered. See freerdp_passphrase_read() for more details.
*/
static BOOL xf_authenticate_raw(freerdp* instance, BOOL gateway, char** username,
char** password, char** domain)
{
const char* auth[] =
{
"Username: ",
"Domain: ",
"Password: "
};
const char* gw[] =
{
"GatewayUsername: ",
"GatewayDomain: ",
"GatewayPassword: "
};
const char** prompt = (gateway) ? gw : auth;
if (!username || !password || !domain)
return FALSE;
if (!*username)
{
size_t username_size = 0;
printf("%s", prompt[0]);
if (getline(username, &username_size, stdin) < 0)
{
WLog_ERR(TAG, "getline returned %s [%d]", strerror(errno), errno);
goto fail;
}
if (*username)
{
*username = StrSep(username, "\r");
*username = StrSep(username, "\n");
}
}
if (!*domain)
{
size_t domain_size = 0;
printf("%s", prompt[1]);
if (getline(domain, &domain_size, stdin) < 0)
{
WLog_ERR(TAG, "getline returned %s [%d]", strerror(errno), errno);
goto fail;
}
if (*domain)
{
*domain = StrSep(domain, "\r");
*domain = StrSep(domain, "\n");
}
}
if (!*password)
{
*password = calloc(password_size, sizeof(char));
if (!*password)
goto fail;
if (freerdp_passphrase_read(prompt[2], *password, password_size,
instance->settings->CredentialsFromStdin) == NULL)
goto fail;
}
return TRUE;
fail:
free(*username);
free(*domain);
free(*password);
*username = NULL;
*domain = NULL;
*password = NULL;
return FALSE;
}
static BOOL xf_authenticate(freerdp* instance, char** username, char** password, char** domain)
{
return xf_authenticate_raw(instance, FALSE, username, password, domain);
}
static BOOL xf_gw_authenticate(freerdp* instance, char** username, char** password, char** domain)
{
return xf_authenticate_raw(instance, TRUE, username, password, domain);
}
/** 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 subject
* @param issuer
* @param fingerprint
* @return TRUE if the certificate is trusted. FALSE otherwise.
*/
BOOL xf_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 documentation on how to create local certificate store for a private CA.");
while (1)
{
WLog_INFO(TAG, "Do you trust the above certificate? (Y/N) ");
answer = fgetc(stdin);
if (feof(stdin))
{
WLog_INFO(TAG, "Error: Could not read answer from stdin.");
if (instance->settings->CredentialsFromStdin)
WLog_INFO(TAG, " - Run without parameter \"--from-stdin\" to set trust.");
WLog_INFO(TAG, "");
return FALSE;
}
if (answer == 'y' || answer == 'Y')
{
return TRUE;
}
else if (answer == 'n' || answer == 'N')
{
break;
}
WLog_INFO(TAG, "");
}
return FALSE;
}
int xf_logon_error_info(freerdp* instance, UINT32 data, UINT32 type)
{
xfContext* xfc = (xfContext*) instance->context;
@ -1956,9 +1802,10 @@ static BOOL xfreerdp_client_new(freerdp* instance, rdpContext* context)
instance->PreConnect = xf_pre_connect;
instance->PostConnect = xf_post_connect;
instance->PostDisconnect = xf_post_disconnect;
instance->Authenticate = xf_authenticate;
instance->GatewayAuthenticate = xf_gw_authenticate;
instance->VerifyCertificate = xf_verify_certificate;
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->LogonErrorInfo = xf_logon_error_info;
settings = instance->settings;

View File

@ -44,6 +44,8 @@
#define TAG CLIENT_TAG("x11")
#define MAX_CLIPBOARD_FORMATS 255
struct xf_cliprdr_format
{
Atom atom;
@ -64,6 +66,9 @@ struct xf_clipboard
Atom clipboard_atom;
Atom property_atom;
Atom raw_transfer_atom;
Atom raw_format_list_atom;
int numClientFormats;
xfCliprdrFormat clientFormats[20];
@ -76,8 +81,9 @@ struct xf_clipboard
int requestedFormatId;
BYTE* data;
UINT32 data_format;
UINT32 data_alt_format;
BOOL data_raw_format;
UINT32 data_format_id;
const char* data_format_name;
int data_length;
XEvent* respond;
@ -122,9 +128,70 @@ static BOOL xf_cliprdr_is_self_owned(xfClipboard* clipboard)
return XGetSelectionOwner(xfc->display, clipboard->clipboard_atom) == xfc->drawable;
}
static xfCliprdrFormat* xf_cliprdr_get_format_by_id(xfClipboard* clipboard, UINT32 formatId)
static void xf_cliprdr_set_raw_transfer_enabled(xfClipboard* clipboard, BOOL enabled)
{
UINT32 index;
UINT32 data = enabled;
xfContext* xfc = clipboard->xfc;
XChangeProperty(xfc->display, xfc->drawable, clipboard->raw_transfer_atom,
XA_INTEGER, 32, PropModeReplace, (BYTE*) &data, 1);
}
static BOOL xf_cliprdr_is_raw_transfer_available(xfClipboard* clipboard)
{
Atom type;
int format;
int result = 0;
unsigned long length;
unsigned long bytes_left;
UINT32* data = NULL;
UINT32 is_enabled = 0;
Window owner = None;
xfContext* xfc = clipboard->xfc;
owner = XGetSelectionOwner(xfc->display, clipboard->clipboard_atom);
if (owner != None)
{
result = XGetWindowProperty(xfc->display, owner,
clipboard->raw_transfer_atom, 0, 4, 0, XA_INTEGER,
&type, &format, &length, &bytes_left, (BYTE**) &data);
}
if (data)
{
is_enabled = *data;
XFree(data);
}
if ((owner == None) || (owner == xfc->drawable))
return FALSE;
if (result != Success)
return FALSE;
return is_enabled ? TRUE : FALSE;
}
static BOOL xf_cliprdr_formats_equal(const CLIPRDR_FORMAT* server, const xfCliprdrFormat* client)
{
if (server->formatName && client->formatName)
{
/* The server may be using short format names while we store them in full form. */
return (0 == strncmp(server->formatName, client->formatName, strlen(server->formatName)));
}
if (!server->formatName && !client->formatName)
{
return (server->formatId == client->formatId);
}
return FALSE;
}
static xfCliprdrFormat* xf_cliprdr_get_client_format_by_id(xfClipboard* clipboard, UINT32 formatId)
{
int index;
xfCliprdrFormat* format;
for (index = 0; index < clipboard->numClientFormats; index++)
@ -138,25 +205,41 @@ static xfCliprdrFormat* xf_cliprdr_get_format_by_id(xfClipboard* clipboard, UINT
return NULL;
}
static xfCliprdrFormat* xf_cliprdr_get_format_by_atom(xfClipboard* clipboard, Atom atom)
static xfCliprdrFormat* xf_cliprdr_get_client_format_by_atom(xfClipboard* clipboard, Atom atom)
{
int i, j;
int i;
xfCliprdrFormat* format;
for (i = 0; i < clipboard->numClientFormats; i++)
{
format = &(clipboard->clientFormats[i]);
if (format->atom != atom)
continue;
if (format->formatId == 0)
if (format->atom == atom)
return format;
}
for (j = 0; j < clipboard->numServerFormats; j++)
return NULL;
}
static CLIPRDR_FORMAT* xf_cliprdr_get_server_format_by_atom(xfClipboard* clipboard, Atom atom)
{
int i, j;
xfCliprdrFormat* client_format;
CLIPRDR_FORMAT* server_format;
for (i = 0; i < clipboard->numClientFormats; i++)
{
client_format = &(clipboard->clientFormats[i]);
if (client_format->atom == atom)
{
if (clipboard->serverFormats[j].formatId == format->formatId)
return format;
for (j = 0; j < clipboard->numServerFormats; j++)
{
server_format = &(clipboard->serverFormats[j]);
if (xf_cliprdr_formats_equal(server_format, client_format))
return server_format;
}
}
}
@ -190,14 +273,170 @@ static UINT xf_cliprdr_send_data_response(xfClipboard* clipboard, BYTE* data, in
ZeroMemory(&response, sizeof(CLIPRDR_FORMAT_DATA_RESPONSE));
response.msgFlags = CB_RESPONSE_OK;
response.msgFlags = (data) ? CB_RESPONSE_OK : CB_RESPONSE_FAIL;
response.dataLen = size;
response.requestedFormatData = data;
return clipboard->context->ClientFormatDataResponse(clipboard->context, &response);
}
static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard)
static wStream* xf_cliprdr_serialize_server_format_list(xfClipboard* clipboard)
{
UINT32 i;
UINT32 formatCount;
wStream* s = NULL;
/* Typical MS Word format list is about 80 bytes long. */
if (!(s = Stream_New(NULL, 128)))
{
WLog_ERR(TAG, "failed to allocate serialized format list");
goto error;
}
/* If present, the last format is always synthetic CF_RAW. Do not include it. */
formatCount = (clipboard->numServerFormats > 0) ? clipboard->numServerFormats - 1 : 0;
Stream_Write_UINT32(s, formatCount);
for (i = 0; i < formatCount; i++)
{
CLIPRDR_FORMAT* format = &clipboard->serverFormats[i];
size_t name_length = format->formatName ? strlen(format->formatName) : 0;
if (!Stream_EnsureRemainingCapacity(s, sizeof(UINT32) + name_length + 1))
{
WLog_ERR(TAG, "failed to expand serialized format list");
goto error;
}
Stream_Write_UINT32(s, format->formatId);
Stream_Write(s, format->formatName, name_length);
Stream_Write_UINT8(s, '\0');
}
Stream_SealLength(s);
return s;
error:
Stream_Free(s, TRUE);
return NULL;
}
static CLIPRDR_FORMAT* xf_cliprdr_parse_server_format_list(BYTE* data, size_t length, UINT32* numFormats)
{
UINT32 i;
wStream* s = NULL;
CLIPRDR_FORMAT* formats = NULL;
if (!(s = Stream_New(data, length)))
{
WLog_ERR(TAG, "failed to allocate stream for parsing serialized format list");
goto error;
}
if (Stream_GetRemainingLength(s) < sizeof(UINT32))
{
WLog_ERR(TAG, "too short serialized format list");
goto error;
}
Stream_Read_UINT32(s, *numFormats);
if (*numFormats > MAX_CLIPBOARD_FORMATS)
{
WLog_ERR(TAG, "unexpectedly large number of formats: %u", *numFormats);
goto error;
}
if (!(formats = (CLIPRDR_FORMAT*) calloc(*numFormats, sizeof(CLIPRDR_FORMAT))))
{
WLog_ERR(TAG, "failed to allocate format list");
goto error;
}
for (i = 0; i < *numFormats; i++)
{
const char* formatName = NULL;
size_t formatNameLength = 0;
if (Stream_GetRemainingLength(s) < sizeof(UINT32))
{
WLog_ERR(TAG, "unexpected end of serialized format list");
goto error;
}
Stream_Read_UINT32(s, formats[i].formatId);
formatName = (const char*) Stream_Pointer(s);
formatNameLength = strnlen(formatName, Stream_GetRemainingLength(s));
if (formatNameLength == Stream_GetRemainingLength(s))
{
WLog_ERR(TAG, "missing terminating null byte, %zu bytes left to read", formatNameLength);
goto error;
}
formats[i].formatName = strndup(formatName, formatNameLength);
Stream_Seek(s, formatNameLength + 1);
}
Stream_Free(s, FALSE);
return formats;
error:
Stream_Free(s, FALSE);
free(formats);
*numFormats = 0;
return NULL;
}
static void xf_cliprdr_free_formats(CLIPRDR_FORMAT* formats, UINT32 numFormats)
{
UINT32 i;
for (i = 0; i < numFormats; i++)
{
free(formats[i].formatName);
}
free(formats);
}
static CLIPRDR_FORMAT* xf_cliprdr_get_raw_server_formats(xfClipboard* clipboard, UINT32* numFormats)
{
Atom type = None;
int format = 0;
unsigned long length = 0;
unsigned long remaining;
BYTE* data = NULL;
CLIPRDR_FORMAT* formats = NULL;
xfContext* xfc = clipboard->xfc;
*numFormats = 0;
XGetWindowProperty(xfc->display, clipboard->owner, clipboard->raw_format_list_atom,
0, 4096, False, clipboard->raw_format_list_atom, &type, &format,
&length, &remaining, &data);
if (data && length > 0 && format == 8 && type == clipboard->raw_format_list_atom)
{
formats = xf_cliprdr_parse_server_format_list(data, length, numFormats);
}
else
{
WLog_ERR(TAG, "failed to retrieve raw format list: data=%p, length=%lu, format=%d, type=%d (expected=%d)",
data, length, format, type, clipboard->raw_format_list_atom);
}
if (data)
XFree(data);
return formats;
}
static CLIPRDR_FORMAT* xf_cliprdr_get_formats_from_targets(xfClipboard* clipboard, UINT32* numFormats)
{
int i;
Atom atom;
@ -205,14 +444,11 @@ static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard)
int format_property;
unsigned long length;
unsigned long bytes_left;
UINT32 numFormats = 0;
CLIPRDR_FORMAT_LIST formatList;
xfCliprdrFormat* format = NULL;
CLIPRDR_FORMAT* formats = NULL;
xfContext* xfc = clipboard->xfc;
if (!clipboard->numServerFormats)
return; /* server format list was not yet received */
*numFormats = 0;
XGetWindowProperty(xfc->display, xfc->drawable, clipboard->property_atom,
0, 200, 0, XA_ATOM, &atom, &format_property, &length, &bytes_left, &data);
@ -235,16 +471,73 @@ static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard)
{
atom = ((Atom*) data)[i];
format = xf_cliprdr_get_format_by_atom(clipboard, atom);
format = xf_cliprdr_get_client_format_by_atom(clipboard, atom);
if (format)
{
formats[numFormats].formatId = format->formatId;
formats[numFormats].formatName = format->formatName;
numFormats++;
formats[*numFormats].formatId = format->formatId;
formats[*numFormats].formatName = _strdup(format->formatName);
*numFormats += 1;
}
}
out:
if (data)
XFree(data);
return formats;
}
static CLIPRDR_FORMAT* xf_cliprdr_get_client_formats(xfClipboard* clipboard, UINT32* numFormats)
{
CLIPRDR_FORMAT* formats = NULL;
*numFormats = 0;
if (xf_cliprdr_is_raw_transfer_available(clipboard))
{
formats = xf_cliprdr_get_raw_server_formats(clipboard, numFormats);
}
if (*numFormats == 0)
{
xf_cliprdr_free_formats(formats, *numFormats);
formats = xf_cliprdr_get_formats_from_targets(clipboard, numFormats);
}
return formats;
}
static void xf_cliprdr_provide_server_format_list(xfClipboard* clipboard)
{
wStream* formats = NULL;
xfContext* xfc = clipboard->xfc;
formats = xf_cliprdr_serialize_server_format_list(clipboard);
if (formats)
{
XChangeProperty(xfc->display, xfc->drawable, clipboard->raw_format_list_atom,
clipboard->raw_format_list_atom, 8, PropModeReplace,
Stream_Buffer(formats), Stream_Length(formats));
}
else
{
XDeleteProperty(xfc->display, xfc->drawable, clipboard->raw_format_list_atom);
}
Stream_Free(formats, TRUE);
}
static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard)
{
UINT32 numFormats = 0;
CLIPRDR_FORMAT* formats = NULL;
CLIPRDR_FORMAT_LIST formatList;
formats = xf_cliprdr_get_client_formats(clipboard, &numFormats);
ZeroMemory(&formatList, sizeof(CLIPRDR_FORMAT_LIST));
formatList.msgFlags = CB_RESPONSE_OK;
@ -253,10 +546,7 @@ static void xf_cliprdr_get_requested_targets(xfClipboard* clipboard)
clipboard->context->ClientFormatList(clipboard->context, &formatList);
out:
if (data)
XFree(data);
free(formats);
xf_cliprdr_free_formats(formats, numFormats);
}
static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasData, BYTE* data, int size)
@ -264,8 +554,8 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
BOOL bSuccess;
UINT32 SrcSize;
UINT32 DstSize;
UINT32 formatId;
UINT32 altFormatId;
UINT32 srcFormatId;
UINT32 dstFormatId;
BYTE* pSrcData = NULL;
BYTE* pDstData = NULL;
xfCliprdrFormat* format;
@ -273,7 +563,7 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
if (clipboard->incr_starts && hasData)
return;
format = xf_cliprdr_get_format_by_id(clipboard, clipboard->requestedFormatId);
format = xf_cliprdr_get_client_format_by_id(clipboard, clipboard->requestedFormatId);
if (!hasData || !data || !format)
{
@ -281,25 +571,29 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
return;
}
formatId = 0;
altFormatId = 0;
srcFormatId = 0;
dstFormatId = 0;
switch (format->formatId)
{
case CF_RAW:
srcFormatId = CF_RAW;
break;
case CF_TEXT:
case CF_OEMTEXT:
case CF_UNICODETEXT:
size = strlen((char*) data) + 1;
formatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
srcFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
break;
case CF_DIB:
formatId = ClipboardGetFormatId(clipboard->system, "image/bmp");
srcFormatId = ClipboardGetFormatId(clipboard->system, "image/bmp");
break;
case CB_FORMAT_HTML:
size = strlen((char*) data) + 1;
formatId = ClipboardGetFormatId(clipboard->system, "text/html");
srcFormatId = ClipboardGetFormatId(clipboard->system, "text/html");
break;
}
@ -311,17 +605,24 @@ static void xf_cliprdr_process_requested_data(xfClipboard* clipboard, BOOL hasDa
CopyMemory(pSrcData, data, SrcSize);
bSuccess = ClipboardSetData(clipboard->system, formatId, (void*) pSrcData, SrcSize);
bSuccess = ClipboardSetData(clipboard->system, srcFormatId, (void*) pSrcData, SrcSize);
if (!bSuccess)
free(pSrcData);
altFormatId = clipboard->requestedFormatId;
if (format->formatName)
{
dstFormatId = ClipboardGetFormatId(clipboard->system, format->formatName);
}
else
{
dstFormatId = format->formatId;
}
if (bSuccess && altFormatId)
if (bSuccess)
{
DstSize = 0;
pDstData = (BYTE*) ClipboardGetData(clipboard->system, altFormatId, &DstSize);
pDstData = (BYTE*) ClipboardGetData(clipboard->system, dstFormatId, &DstSize);
}
if (!pDstData)
@ -346,7 +647,7 @@ static BOOL xf_cliprdr_get_requested_data(xfClipboard* clipboard, Atom target)
xfCliprdrFormat* format;
xfContext* xfc = clipboard->xfc;
format = xf_cliprdr_get_format_by_id(clipboard, clipboard->requestedFormatId);
format = xf_cliprdr_get_client_format_by_id(clipboard, clipboard->requestedFormatId);
if (!format || (format->atom != target))
{
@ -495,13 +796,14 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent*
int fmt;
Atom type;
UINT32 formatId;
const char* formatName;
XEvent* respond;
UINT32 altFormatId;
BYTE* data = NULL;
BOOL delayRespond;
BOOL rawTransfer;
unsigned long length;
unsigned long bytes_left;
xfCliprdrFormat* format;
CLIPRDR_FORMAT* format;
xfContext* xfc = clipboard->xfc;
if (xevent->xselectionrequest.owner != xfc->drawable)
@ -535,14 +837,15 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent*
}
else
{
format = xf_cliprdr_get_format_by_atom(clipboard, xevent->xselectionrequest.target);
format = xf_cliprdr_get_server_format_by_atom(clipboard, xevent->xselectionrequest.target);
if (format && (xevent->xselectionrequest.requestor != xfc->drawable))
{
formatId = format->formatId;
altFormatId = formatId;
formatName = format->formatName;
rawTransfer = FALSE;
if (formatId == 0)
if (formatId == CF_RAW)
{
if (XGetWindowProperty(xfc->display, xevent->xselectionrequest.requestor,
clipboard->property_atom, 0, 4, 0, XA_INTEGER,
@ -553,12 +856,13 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent*
if (data)
{
CopyMemory(&altFormatId, data, 4);
rawTransfer = TRUE;
CopyMemory(&formatId, data, 4);
XFree(data);
}
}
if ((clipboard->data != 0) && (formatId == clipboard->data_format) && (altFormatId == clipboard->data_alt_format))
if ((clipboard->data != 0) && (formatId == clipboard->data_format_id) && (formatName == clipboard->data_format_name))
{
/* Cached clipboard data available. Send it now */
respond->xselection.property = xevent->xselectionrequest.property;
@ -582,11 +886,12 @@ static BOOL xf_cliprdr_process_selection_request(xfClipboard* clipboard, XEvent*
respond->xselection.property = xevent->xselectionrequest.property;
clipboard->respond = respond;
clipboard->data_format = formatId;
clipboard->data_alt_format = altFormatId;
clipboard->data_format_id = formatId;
clipboard->data_format_name = formatName;
clipboard->data_raw_format = rawTransfer;
delayRespond = TRUE;
xf_cliprdr_send_data_request(clipboard, altFormatId);
xf_cliprdr_send_data_request(clipboard, formatId);
}
}
}
@ -631,7 +936,7 @@ static BOOL xf_cliprdr_process_property_notify(xfClipboard* clipboard, XEvent* x
else if ((xevent->xproperty.window == xfc->drawable) &&
(xevent->xproperty.state == PropertyNewValue) && clipboard->incr_starts)
{
format = xf_cliprdr_get_format_by_id(clipboard, clipboard->requestedFormatId);
format = xf_cliprdr_get_client_format_by_id(clipboard, clipboard->requestedFormatId);
if (format)
xf_cliprdr_get_requested_data(clipboard, format->atom);
@ -787,24 +1092,6 @@ UINT xf_cliprdr_send_client_format_list_response(xfClipboard* clipboard, BOOL st
return clipboard->context->ClientFormatListResponse(clipboard->context, &formatListResponse);
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
int xf_cliprdr_send_client_format_data_request(xfClipboard* clipboard, UINT32 formatId)
{
CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest;
formatDataRequest.msgType = CB_FORMAT_DATA_REQUEST;
formatDataRequest.msgFlags = CB_RESPONSE_OK;
formatDataRequest.requestedFormatId = formatId;
clipboard->requestedFormatId = formatId;
return clipboard->context->ClientFormatDataRequest(clipboard->context, &formatDataRequest);
}
/**
* Function description
*
@ -856,6 +1143,9 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR
clipboard->data = NULL;
}
clipboard->data_format_id = -1;
clipboard->data_format_name = NULL;
if (clipboard->serverFormats)
{
for (i = 0; i < clipboard->numServerFormats; i++)
@ -867,14 +1157,11 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR
clipboard->numServerFormats = 0;
}
clipboard->numServerFormats = formatList->numFormats;
clipboard->numServerFormats = formatList->numFormats + 1; /* +1 for CF_RAW */
if (clipboard->numServerFormats)
{
if (!(clipboard->serverFormats = (CLIPRDR_FORMAT*) calloc(clipboard->numServerFormats, sizeof(CLIPRDR_FORMAT)))) {
WLog_ERR(TAG, "failed to allocate %d CLIPRDR_FORMAT structs", clipboard->numServerFormats);
return CHANNEL_RC_NO_MEMORY;
}
if (!(clipboard->serverFormats = (CLIPRDR_FORMAT*) calloc(clipboard->numServerFormats, sizeof(CLIPRDR_FORMAT)))) {
WLog_ERR(TAG, "failed to allocate %d CLIPRDR_FORMAT structs", clipboard->numServerFormats);
return CHANNEL_RC_NO_MEMORY;
}
for (i = 0; i < formatList->numFormats; i++)
@ -897,6 +1184,13 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR
}
}
/* CF_RAW is always implicitly supported by the server */
format = &clipboard->serverFormats[formatList->numFormats];
format->formatId = CF_RAW;
format->formatName = NULL;
xf_cliprdr_provide_server_format_list(clipboard);
clipboard->numTargets = 2;
for (i = 0; i < formatList->numFormats; i++)
@ -905,7 +1199,7 @@ static UINT xf_cliprdr_server_format_list(CliprdrClientContext* context, CLIPRDR
for (j = 0; j < clipboard->numClientFormats; j++)
{
if (format->formatId == clipboard->clientFormats[j].formatId)
if (xf_cliprdr_formats_equal(format, &clipboard->clientFormats[j]))
{
xf_cliprdr_append_target(clipboard, clipboard->clientFormats[j].atom);
}
@ -940,25 +1234,28 @@ static UINT xf_cliprdr_server_format_list_response(CliprdrClientContext* context
*/
static UINT xf_cliprdr_server_format_data_request(CliprdrClientContext* context, CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
{
BOOL rawTransfer;
xfCliprdrFormat* format = NULL;
UINT32 formatId = formatDataRequest->requestedFormatId;
xfClipboard* clipboard = (xfClipboard*) context->custom;
xfContext* xfc = clipboard->xfc;
if (xf_cliprdr_is_self_owned(clipboard))
rawTransfer = xf_cliprdr_is_raw_transfer_available(clipboard);
if (rawTransfer)
{
format = xf_cliprdr_get_format_by_id(clipboard, 0);
format = xf_cliprdr_get_client_format_by_id(clipboard, CF_RAW);
XChangeProperty(xfc->display, xfc->drawable, clipboard->property_atom,
XA_INTEGER, 32, PropModeReplace, (BYTE*) &formatId, 1);
}
else
format = xf_cliprdr_get_format_by_id(clipboard, formatId);
format = xf_cliprdr_get_client_format_by_id(clipboard, formatId);
if (!format)
return xf_cliprdr_send_data_response(clipboard, NULL, 0);
clipboard->requestedFormatId = formatId;
clipboard->requestedFormatId = rawTransfer ? CF_RAW : formatId;
XConvertSelection(xfc->display, clipboard->clipboard_atom,
format->atom, clipboard->property_atom, xfc->drawable, CurrentTime);
@ -982,9 +1279,8 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context
BYTE* pDstData;
UINT32 DstSize;
UINT32 SrcSize;
UINT32 formatId;
UINT32 altFormatId;
xfCliprdrFormat* format;
UINT32 srcFormatId;
UINT32 dstFormatId;
BOOL nullTerminated = FALSE;
UINT32 size = formatDataResponse->dataLen;
BYTE* data = formatDataResponse->requestedFormatData;
@ -994,8 +1290,6 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context
if (!clipboard->respond)
return CHANNEL_RC_OK;
format = xf_cliprdr_get_format_by_id(clipboard, clipboard->requestedFormatId);
if (clipboard->data)
{
free(clipboard->data);
@ -1005,39 +1299,50 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context
pDstData = NULL;
DstSize = 0;
formatId = 0;
altFormatId = 0;
srcFormatId = 0;
dstFormatId = 0;
switch (clipboard->data_format)
if (clipboard->data_raw_format)
{
srcFormatId = CF_RAW;
dstFormatId = CF_RAW;
}
else if (clipboard->data_format_name)
{
if (strcmp(clipboard->data_format_name, "HTML Format") == 0)
{
srcFormatId = ClipboardGetFormatId(clipboard->system, "HTML Format");
dstFormatId = ClipboardGetFormatId(clipboard->system, "text/html");
nullTerminated = TRUE;
}
}
else
{
switch (clipboard->data_format_id)
{
case CF_TEXT:
formatId = CF_TEXT;
altFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
srcFormatId = CF_TEXT;
dstFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
nullTerminated = TRUE;
break;
case CF_OEMTEXT:
formatId = CF_OEMTEXT;
altFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
srcFormatId = CF_OEMTEXT;
dstFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
nullTerminated = TRUE;
break;
case CF_UNICODETEXT:
formatId = CF_UNICODETEXT;
altFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
srcFormatId = CF_UNICODETEXT;
dstFormatId = ClipboardGetFormatId(clipboard->system, "UTF8_STRING");
nullTerminated = TRUE;
break;
case CF_DIB:
formatId = CF_DIB;
altFormatId = ClipboardGetFormatId(clipboard->system, "image/bmp");
break;
case CB_FORMAT_HTML:
formatId = ClipboardGetFormatId(clipboard->system, "HTML Format");
altFormatId = ClipboardGetFormatId(clipboard->system, "text/html");
nullTerminated = TRUE;
srcFormatId = CF_DIB;
dstFormatId = ClipboardGetFormatId(clipboard->system, "image/bmp");
break;
}
}
SrcSize = (UINT32) size;
@ -1048,18 +1353,21 @@ static UINT xf_cliprdr_server_format_data_response(CliprdrClientContext* context
CopyMemory(pSrcData, data, SrcSize);
bSuccess = ClipboardSetData(clipboard->system, formatId, (void*) pSrcData, SrcSize);
bSuccess = ClipboardSetData(clipboard->system, srcFormatId, (void*) pSrcData, SrcSize);
if (!bSuccess)
free (pSrcData);
if (bSuccess && altFormatId)
if (bSuccess)
{
DstSize = 0;
pDstData = (BYTE*) ClipboardGetData(clipboard->system, altFormatId, &DstSize);
pDstData = (BYTE*) ClipboardGetData(clipboard->system, dstFormatId, &DstSize);
if ((DstSize > 1) && nullTerminated)
DstSize--;
if (nullTerminated)
{
while (DstSize > 0 && pDstData[DstSize - 1] == '\0')
DstSize--;
}
}
clipboard->data = pDstData;
@ -1111,6 +1419,11 @@ xfClipboard* xf_clipboard_new(xfContext* xfc)
clipboard->property_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR", FALSE);
clipboard->raw_transfer_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR_RAW", FALSE);
clipboard->raw_format_list_atom = XInternAtom(xfc->display, "_FREERDP_CLIPRDR_FORMATS", FALSE);
xf_cliprdr_set_raw_transfer_enabled(clipboard, TRUE);
XSelectInput(xfc->display, clipboard->root_window, PropertyChangeMask);
#ifdef WITH_XFIXES
@ -1140,7 +1453,7 @@ xfClipboard* xf_clipboard_new(xfContext* xfc)
n = 0;
clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "_FREERDP_RAW", False);
clipboard->clientFormats[n].formatId = 0;
clipboard->clientFormats[n].formatId = CF_RAW;
n++;
clipboard->clientFormats[n].atom = XInternAtom(xfc->display, "UTF8_STRING", False);

View File

@ -290,15 +290,29 @@ static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
{
char* title = NULL;
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string,
windowState->titleInfo.length / 2, &title, 0, NULL, NULL);
if (windowState->titleInfo.length == 0)
{
if (!(title = _strdup("")))
{
WLog_ERR(TAG, "failed to duplicate empty window title string");
/* error handled below */
}
}
else if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string,
windowState->titleInfo.length / 2, &title, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert window title");
/* error handled below */
}
appWindow->title = title;
}
else
{
appWindow->title = _strdup("RdpRailWindow");
if (!(appWindow->title = _strdup("RdpRailWindow")))
WLog_ERR(TAG, "failed to duplicate default window title string");
}
if (!appWindow->title)
{
free(appWindow);
@ -365,9 +379,20 @@ static BOOL xf_rail_window_common(rdpContext* context, WINDOW_ORDER_INFO* orderI
{
char* title = NULL;
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string,
windowState->titleInfo.length / 2, &title, 0, NULL, NULL);
if (windowState->titleInfo.length == 0)
{
if (!(title = _strdup("")))
{
WLog_ERR(TAG, "failed to duplicate empty window title string");
return FALSE;
}
}
else if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) windowState->titleInfo.string,
windowState->titleInfo.length / 2, &title, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert window title");
return FALSE;
}
free(appWindow->title);
appWindow->title = title;
}

View File

@ -39,7 +39,7 @@ foreach(FREERDP_CHANNELS_CLIENT_SRC ${FREERDP_CHANNELS_CLIENT_SRCS})
endforeach()
if(MSVC)
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} module.def)
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS})
endif()
# On windows create dll version information.

View File

@ -21,14 +21,21 @@
#include "config.h"
#endif
#include <string.h>
#include <errno.h>
#include <freerdp/client.h>
#include <freerdp/addin.h>
#include <freerdp/assistance.h>
#include <freerdp/client/file.h>
#include <freerdp/utils/passphrase.h>
#include <freerdp/client/cmdline.h>
#include <freerdp/client/channels.h>
#include <freerdp/log.h>
#define TAG CLIENT_TAG("common")
static BOOL freerdp_client_common_new(freerdp* instance, rdpContext* context)
{
RDP_CLIENT_ENTRY_POINTS* pEntryPoints = instance->pClientEntryPoints;
@ -296,3 +303,213 @@ int freerdp_client_settings_parse_assistance_file(rdpSettings* settings, const c
return 0;
}
/** Callback set in the rdp_freerdp structure, and used to get the user's password,
* if required to establish the connection.
* This function is actually called in credssp_ntlmssp_client_init()
* @see rdp_server_accept_nego() and rdp_check_fds()
* @param instance - pointer to the rdp_freerdp structure that contains the connection settings
* @param username - unused
* @param password - on return: pointer to a character string that will be filled by the password entered by the user.
* Note that this character string will be allocated inside the function, and needs to be deallocated by the caller
* using free(), even in case this function fails.
* @param domain - unused
* @return TRUE if a password was successfully entered. See freerdp_passphrase_read() for more details.
*/
static BOOL client_cli_authenticate_raw(freerdp* instance, BOOL gateway, char** username,
char** password, char** domain)
{
static const size_t password_size = 512;
const char* auth[] =
{
"Username: ",
"Domain: ",
"Password: "
};
const char* gw[] =
{
"GatewayUsername: ",
"GatewayDomain: ",
"GatewayPassword: "
};
const char** prompt = (gateway) ? gw : auth;
if (!username || !password || !domain)
return FALSE;
if (!*username)
{
size_t username_size = 0;
printf("%s", prompt[0]);
if (GetLine(username, &username_size, stdin) < 0)
{
WLog_ERR(TAG, "GetLine returned %s [%d]", strerror(errno), errno);
goto fail;
}
if (*username)
{
*username = StrSep(username, "\r");
*username = StrSep(username, "\n");
}
}
if (!*domain)
{
size_t domain_size = 0;
printf("%s", prompt[1]);
if (GetLine(domain, &domain_size, stdin) < 0)
{
WLog_ERR(TAG, "GetLine returned %s [%d]", strerror(errno), errno);
goto fail;
}
if (*domain)
{
*domain = StrSep(domain, "\r");
*domain = StrSep(domain, "\n");
}
}
if (!*password)
{
*password = calloc(password_size, sizeof(char));
if (!*password)
goto fail;
if (freerdp_passphrase_read(prompt[2], *password, password_size,
instance->settings->CredentialsFromStdin) == NULL)
goto fail;
}
return TRUE;
fail:
free(*username);
free(*domain);
free(*password);
*username = NULL;
*domain = NULL;
*password = NULL;
return FALSE;
}
BOOL client_cli_authenticate(freerdp* instance, char** username, char** password, char** domain)
{
return client_cli_authenticate_raw(instance, FALSE, username, password, domain);
}
BOOL client_cli_gw_authenticate(freerdp* instance, char** username, char** password, char** domain)
{
return client_cli_authenticate_raw(instance, TRUE, username, password, domain);
}
static DWORD client_cli_accept_certificate(rdpSettings* settings)
{
char answer;
if (settings->CredentialsFromStdin)
return 0;
while (1)
{
printf("Do you trust the above certificate? (Y/T/N) ");
answer = fgetc(stdin);
if (feof(stdin))
{
printf("\nError: Could not read answer from stdin.");
if (settings->CredentialsFromStdin)
printf(" - Run without parameter \"--from-stdin\" to set trust.");
printf("\n");
return 0;
}
switch(answer)
{
case 'y':
case 'Y':
return 1;
case 't':
case 'T':
return 2;
case 'n':
case 'N':
return 0;
default:
break;
}
printf("\n");
}
return 0;
}
/** 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 common_name
* @param subject
* @param issuer
* @param fingerprint
* @param host_mismatch Indicates the certificate host does not match.
* @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise.
*/
DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name,
const char* subject, const char* issuer,
const char* fingerprint, BOOL host_mismatch)
{
printf("Certificate details:\n");
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 documentation on how to create local certificate store for a private CA.\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()
* @param instance - pointer to the rdp_freerdp structure that contains the connection settings
* @param common_name
* @param subject
* @param issuer
* @param fingerprint
* @param old_subject
* @param old_issuer
* @param old_fingerprint
* @return 1 if the certificate is trusted, 2 if temporary trusted, 0 otherwise.
*/
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)
{
printf("!!! Certificate has changed !!!\n");
printf("\n");
printf("New Certificate details:\n");
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);
}

View File

@ -4,6 +4,7 @@
*
* Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2014 Norbert Federa <norbert.federa@thincast.com>
* Copyright 2016 Armin Novak <armin.novak@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -175,6 +176,12 @@ static COMMAND_LINE_ARGUMENT_A args[] =
{ "buildconfig", COMMAND_LINE_VALUE_FLAG | COMMAND_LINE_PRINT_BUILDCONFIG, NULL, NULL, NULL, -1, NULL, "print the build configuration" },
{ "log-level", COMMAND_LINE_VALUE_REQUIRED, "[OFF|FATAL|ERROR|WARN|INFO|DEBUG|TRACE]", NULL, NULL, -1, NULL, "Set the default log level" },
{ "log-filters", COMMAND_LINE_VALUE_REQUIRED, "<logger tag>:<log level>[, <logger tag>:<log level>][, ...]]", NULL, NULL, -1, NULL, "Set logger filters" },
{ "pwidth", COMMAND_LINE_VALUE_REQUIRED, "<physical width (mm)>", NULL, NULL, -1, NULL, "Physical width of display (in millimeters)" },
{ "pheight", COMMAND_LINE_VALUE_REQUIRED, "<physical height (mm)>", NULL, NULL, -1, NULL, "Physical height of display (in millimeters)" },
{ "orientation", COMMAND_LINE_VALUE_REQUIRED, "<orientation>", NULL, NULL, -1, NULL, "Orientation of display in degrees (0, 90, 180, 270)" },
{ "scale", COMMAND_LINE_VALUE_REQUIRED, "<scale amount (%%)>", "100", NULL, -1, NULL, "Scaling factor of the display (value of 100, 140, or 180)" },
{ "scale-desktop", COMMAND_LINE_VALUE_REQUIRED, "<scale amount (%%)>", "100", NULL, -1, NULL, "Scaling factor for desktop applications (value between 100 and 500)" },
{ "scale-device", COMMAND_LINE_VALUE_REQUIRED, "<scale amount (%%)>", "100", NULL, -1, NULL, "Scaling factor for app store applications (100, 140, or 180)" },
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL }
};
@ -1305,7 +1312,7 @@ int freerdp_detect_posix_style_command_line_syntax(int argc, char** argv,
}
static BOOL freerdp_client_detect_command_line(int argc, char** argv,
DWORD* flags, BOOL ignoreUnknown)
DWORD* flags, BOOL ignoreUnknown)
{
int old_cli_status;
int old_cli_count;
@ -1678,7 +1685,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
{
id = (unsigned long int) freerdp_map_keyboard_layout_name_to_id(arg->Value);
if (id == -1)
WLog_ERR(TAG, "A problem occured while mapping the layout name to id");
WLog_ERR(TAG, "A problem occurred while mapping the layout name to id");
else if (id == 0)
{
WLog_ERR(TAG, "Could not identify keyboard layout: %s", arg->Value);
@ -2289,6 +2296,55 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
if (!(settings->RemoteAssistancePassword = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
CommandLineSwitchCase(arg, "pwidth")
{
settings->DesktopPhysicalWidth = atoi(arg->Value);
}
CommandLineSwitchCase(arg, "pheight")
{
settings->DesktopPhysicalHeight = atoi(arg->Value);
}
CommandLineSwitchCase(arg, "orientation")
{
settings->DesktopOrientation = atoi(arg->Value);
}
CommandLineSwitchCase(arg, "scale")
{
int scaleFactor = atoi(arg->Value);
if (scaleFactor == 100 || scaleFactor == 140 || scaleFactor == 180) {
settings->DesktopScaleFactor = scaleFactor;
settings->DeviceScaleFactor = scaleFactor;
} else {
WLog_ERR(TAG, "scale: invalid scale factor (%d)", scaleFactor);
return COMMAND_LINE_ERROR;
}
}
CommandLineSwitchCase(arg, "scale-desktop")
{
int desktopScaleFactor = atoi(arg->Value);
if (desktopScaleFactor >= 100 && desktopScaleFactor <= 500)
{
settings->DesktopScaleFactor = desktopScaleFactor;
}
else
{
WLog_ERR(TAG, "scale: invalid desktop scale factor (%d)", desktopScaleFactor);
return COMMAND_LINE_ERROR;
}
}
CommandLineSwitchCase(arg, "scale-device")
{
int deviceScaleFactor = atoi(arg->Value);
if (deviceScaleFactor == 100 || deviceScaleFactor == 140 || deviceScaleFactor == 180)
{
settings->DeviceScaleFactor = deviceScaleFactor;
}
else
{
WLog_ERR(TAG, "scale: invalid device scale factor (%d)", deviceScaleFactor);
return COMMAND_LINE_ERROR;
}
}
CommandLineSwitchDefault(arg)
{
}
@ -2453,28 +2509,34 @@ BOOL freerdp_client_load_addins(rdpChannels* channels, rdpSettings* settings)
{
RDPDR_SMARTCARD* smartcard;
smartcard = (RDPDR_SMARTCARD*) calloc(1, sizeof(RDPDR_SMARTCARD));
if (!freerdp_device_collection_find_type(settings, RDPDR_DTYP_SMARTCARD))
{
smartcard = (RDPDR_SMARTCARD*) calloc(1, sizeof(RDPDR_SMARTCARD));
if (!smartcard)
return FALSE;
if (!smartcard)
return FALSE;
smartcard->Type = RDPDR_DTYP_SMARTCARD;
if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*) smartcard))
return FALSE;
smartcard->Type = RDPDR_DTYP_SMARTCARD;
if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*) smartcard))
return FALSE;
}
}
if (settings->RedirectPrinters)
{
RDPDR_PRINTER* printer;
printer = (RDPDR_PRINTER*) calloc(1, sizeof(RDPDR_PRINTER));
if (!freerdp_device_collection_find_type(settings, RDPDR_DTYP_PRINT))
{
printer = (RDPDR_PRINTER*) calloc(1, sizeof(RDPDR_PRINTER));
if (!printer)
return FALSE;
if (!printer)
return FALSE;
printer->Type = RDPDR_DTYP_PRINT;
if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*) printer))
return FALSE;
printer->Type = RDPDR_DTYP_PRINT;
if (!freerdp_device_collection_add(settings, (RDPDR_DEVICE*) printer))
return FALSE;
}
}
if (settings->RedirectClipboard)

View File

@ -1,3 +0,0 @@
LIBRARY "freerdp-client"
EXPORTS

View File

@ -14,8 +14,15 @@ BOOL ios_ui_end_paint(rdpContext * context);
BOOL ios_ui_resize_window(rdpContext * context);
BOOL ios_ui_authenticate(freerdp * instance, char** username, char** password, char** domain);
BOOL ios_ui_check_certificate(freerdp * instance, char * subject, char * issuer, char * fingerprint);
BOOL ios_ui_check_changed_certificate(freerdp * instance, char * subject, char * issuer, char * new_fingerprint, char * old_fingerprint);
DWORD ios_ui_check_certificate(freerdp * instance, const char* common_name,
const char * subject, const char * issuer,
const char * fingerprint, BOOL host_mismatch);
DWORD ios_ui_check_changed_certificate(freerdp * instance,
const char* common_name,
const char * subject,
const char * issuer,
const char * new_fingerprint,
const char * old_fingerprint);
void ios_allocate_display_buffer(mfInfo* mfi);
void ios_resize_display_buffer(mfInfo* mfi);

View File

@ -63,39 +63,47 @@ BOOL ios_ui_authenticate(freerdp * instance, char** username, char** password, c
return TRUE;
}
BOOL ios_ui_check_certificate(freerdp * instance, char * subject, char * issuer, char * fingerprint)
DWORD ios_ui_check_certificate(freerdp * instance, const char* common_name,
const char * subject, const char * issuer,
const char * fingerprint, BOOL host_mismatch)
{
// check whether we accept all certificates
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"security.accept_certificates"] == YES)
return TRUE;
// check whether we accept all certificates
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"security.accept_certificates"] == YES)
return 2;
mfInfo* mfi = MFI_FROM_INSTANCE(instance);
NSMutableDictionary* params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
(subject) ? [NSString stringWithUTF8String:subject] : @"", @"subject",
(issuer) ? [NSString stringWithUTF8String:issuer] : @"", @"issuer",
(fingerprint) ? [NSString stringWithUTF8String:subject] : @"", @"fingerprint",
nil];
// request certificate verification UI
[mfi->session performSelectorOnMainThread:@selector(sessionVerifyCertificateWithParams:) withObject:params waitUntilDone:YES];
// wait for UI request to be completed
[[mfi->session uiRequestCompleted] lock];
[[mfi->session uiRequestCompleted] wait];
[[mfi->session uiRequestCompleted] unlock];
(subject) ? [NSString stringWithUTF8String:subject] : @"", @"subject",
(issuer) ? [NSString stringWithUTF8String:issuer] : @"", @"issuer",
(fingerprint) ? [NSString stringWithUTF8String:subject] : @"", @"fingerprint",
nil];
// request certificate verification UI
[mfi->session performSelectorOnMainThread:@selector(sessionVerifyCertificateWithParams:) withObject:params waitUntilDone:YES];
// wait for UI request to be completed
[[mfi->session uiRequestCompleted] lock];
[[mfi->session uiRequestCompleted] wait];
[[mfi->session uiRequestCompleted] unlock];
if (![[params valueForKey:@"result"] boolValue])
{
mfi->unwanted = YES;
return FALSE;
return 0;
}
return TRUE;
return 1;
}
BOOL ios_ui_check_changed_certificate(freerdp * instance, char * subject, char * issuer, char * new_fingerprint, char * old_fingerprint)
DWORD ios_ui_check_changed_certificate(freerdp * instance,
const char * common_name,
const char * subject,
const char * issuer,
const char * new_fingerprint,
const char * old_fingerprint)
{
return ios_ui_check_certificate(instance, subject, issuer, new_fingerprint);
return ios_ui_check_certificate(instance, common_name, subject, issuer,
new_fingerprint, FALSE);
}

View File

@ -1,19 +1,16 @@
# - Find Wayland
# Find the Wayland libraries
# - Finds Wayland
# Find the Wayland libraries that are needed for UWAC
#
# This module defines the following variables:
# WAYLAND_FOUND - true if WAYLAND_INCLUDE_DIR & WAYLAND_LIBRARY are found
# WAYLAND_LIBRARIES - Set when WAYLAND_LIBRARY is found
# WAYLAND_INCLUDE_DIRS - Set when WAYLAND_INCLUDE_DIR is found
#
# WAYLAND_INCLUDE_DIR - where to find wayland-client.h, etc.
# WAYLAND_LIBRARY - the Wayland client library
# WAYLAND_VERSION - wayland client version if found and pkg-config was used
# WAYLAND_FOUND - true if UWAC has been found
# WAYLAND_LIBS - Set to the full path to wayland client libraries
# WAYLAND_INCLUDE_DIR - Set to the include directories for wayland
# XKBCOMMON_LIBS - Set to the full path to xkbcommon libraries
# XKBCOMMON_INCLUDE_DIR - Set to the include directories for xkbcommon
#
#=============================================================================
# Copyright 2014 Manuel Bachmann <tarnyko@tarnyko.net>
# Copyright 2015 Bernhard Miklautz <bernhard.miklautz@shacknet.at>
# Copyright 2015 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.
@ -28,38 +25,35 @@
# limitations under the License.
#=============================================================================
set(REQUIRED_WAYLAND_CLIENT_VERSION 1.3.0)
include(FindPkgConfig)
if(PKG_CONFIG_FOUND)
pkg_check_modules(WAYLAND wayland-client)
pkg_check_modules(WAYLAND_SCANNER_PC wayland-scanner)
pkg_check_modules(WAYLAND_CLIENT_PC wayland-client)
pkg_check_modules(XKBCOMMON_PC xkbcommon)
endif()
find_path(WAYLAND_INCLUDE_DIR NAMES wayland-client.h
PATHS ${WAYLAND_INCLUDE_DIRS}
DOC "The Wayland include directory"
find_program(WAYLAND_SCANNER wayland-scanner
HINTS "${WAYLAND_SCANNER_PC_PREFIX}/bin"
)
find_library(WAYLAND_LIBRARY NAMES wayland-client
PATHS ${WAYLAND_LIBRARY_DIRS}
DOC "The Wayland client library"
find_path(WAYLAND_INCLUDE_DIR wayland-client.h
HINTS ${WAYLAND_CLIENT_PC_INCLUDE_DIRS}
)
find_library(WAYLAND_LIBS
NAMES "wayland-client"
HINTS "${WAYLAND_CLIENT_PC_LIBRARY_DIRS}"
)
find_path(XKBCOMMON_INCLUDE_DIR xkbcommon/xkbcommon.h
HINTS ${XKBCOMMON_PC_INCLUDE_DIRS}
)
find_library(XKBCOMMON_LIBS
NAMES xkbcommon
HINTS "${XKBCOMMON_PC_LIBRARY_DIRS}"
)
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_LIBRARY WAYLAND_INCLUDE_DIR)
if(WAYLAND_VERSION)
if (${WAYLAND_VERSION} VERSION_LESS ${REQUIRED_WAYLAND_CLIENT_VERSION})
message(WARNING "Installed wayland version ${WAYLAND_VERSION} is too old - minimum required version ${REQUIRED_WAYLAND_CLIENT_VERSION}")
set(WAYLAND_FOUND FALSE)
endif()
else()
message(WARNING "Couldn't detect wayland version - no version check is done")
endif()
if(WAYLAND_FOUND)
set(WAYLAND_LIBRARIES ${WAYLAND_LIBRARY})
set(WAYLAND_INCLUDE_DIRS ${WAYLAND_INCLUDE_DIR})
endif()
mark_as_advanced(WAYLAND_INCLUDE_DIR WAYLAND_LIBRARY WAYLAND_VERSION)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(WAYLAND DEFAULT_MSG WAYLAND_SCANNER WAYLAND_INCLUDE_DIR WAYLAND_LIBS XKBCOMMON_INCLUDE_DIR XKBCOMMON_LIBS)

View File

@ -19,7 +19,7 @@ BEGIN
BEGIN
VALUE "CompanyName", "@RC_VERSION_VENDOR@"
VALUE "FileDescription", "@RC_VERSION_DESCRIPTION@"
VALUE "FileVersion", "@RC_VERSION_MAJOR@,@RC_VERSION_MINOR@,@RC_VERSION_BUILD@,@RC_VERSION_PATCH@"
VALUE "FileVersion", "@RC_VERSION_MAJOR@,@RC_VERSION_MINOR@,@RC_VERSION_PATCH@,@RC_VERSION_BUILD@"
VALUE "InternalName", "@RC_VERSION_FILE@"
VALUE "LegalCopyright", "Copyright (C) 2011-@RC_VERSION_YEAR@"
VALUE "OriginalFilename", "@RC_VERSION_FILE@"

View File

@ -94,6 +94,18 @@ FREERDP_API int freerdp_client_settings_write_connection_file(const rdpSettings*
FREERDP_API int freerdp_client_settings_parse_assistance_file(rdpSettings* settings, const char* filename);
FREERDP_API BOOL client_cli_authenticate(freerdp* instance, char** username, char** password, char** domain);
FREERDP_API BOOL client_cli_gw_authenticate(freerdp* instance, char** username, char** password, char** domain);
FREERDP_API DWORD client_cli_verify_certificate(freerdp* instance, const char* common_name,
const char* subject, const char* issuer,
const char* fingerprint, BOOL host_mismatch);
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);
#ifdef __cplusplus
}
#endif

View File

@ -73,10 +73,10 @@ FREERDP_API void region16_init(REGION16 *region);
/** @return the number of rectangles of this region16 */
FREERDP_API int region16_n_rects(const REGION16 *region);
/** returns a pointer on rectangles and the number of rectangles in this region.
* nbRect can be set to NULL if not interested by the numnber of rectangles.
/** returns a pointer to rectangles and the number of rectangles in this region.
* nbRects can be set to NULL if not interested in the number of rectangles.
* @param region the input region
* @param nbRects a pointer that will be filled with the number of rectangles
* @param nbRects if non-NULL returns the number of rectangles
* @return a pointer on the rectangles
*/
FREERDP_API const RECTANGLE_16 *region16_rects(const REGION16 *region, int *nbRects);

View File

@ -25,13 +25,8 @@
#include <openssl/ssl.h>
#include <openssl/err.h>
#include <openssl/rc4.h>
#include <openssl/md5.h>
#include <openssl/sha.h>
#include <openssl/hmac.h>
#include <openssl/bn.h>
#include <openssl/x509v3.h>
#include <openssl/rand.h>
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090800f)
#define D2I_X509_CONST const
@ -43,31 +38,7 @@
#include <freerdp/api.h>
#include <freerdp/freerdp.h>
struct crypto_sha1_struct
{
SHA_CTX sha_ctx;
};
struct crypto_md5_struct
{
MD5_CTX md5_ctx;
};
struct crypto_rc4_struct
{
RC4_KEY rc4_key;
};
struct crypto_des3_struct
{
EVP_CIPHER_CTX des3_ctx;
};
struct crypto_hmac_struct
{
HMAC_CTX hmac_ctx;
};
#include <freerdp/crypto/certificate.h>
struct crypto_cert_struct
{
@ -79,47 +50,8 @@ struct crypto_cert_struct
extern "C" {
#endif
#define CRYPTO_SHA1_DIGEST_LENGTH SHA_DIGEST_LENGTH
typedef struct crypto_sha1_struct* CryptoSha1;
FREERDP_API CryptoSha1 crypto_sha1_init(void);
FREERDP_API void crypto_sha1_update(CryptoSha1 sha1, const BYTE* data, UINT32 length);
FREERDP_API void crypto_sha1_final(CryptoSha1 sha1, BYTE* out_data);
#define CRYPTO_MD5_DIGEST_LENGTH MD5_DIGEST_LENGTH
typedef struct crypto_md5_struct* CryptoMd5;
FREERDP_API CryptoMd5 crypto_md5_init(void);
FREERDP_API void crypto_md5_update(CryptoMd5 md5, const BYTE* data, UINT32 length);
FREERDP_API void crypto_md5_final(CryptoMd5 md5, BYTE* out_data);
typedef struct crypto_rc4_struct* CryptoRc4;
FREERDP_API CryptoRc4 crypto_rc4_init(const BYTE* key, UINT32 length);
FREERDP_API void crypto_rc4(CryptoRc4 rc4, UINT32 length, const BYTE* in_data, BYTE* out_data);
FREERDP_API void crypto_rc4_free(CryptoRc4 rc4);
typedef struct crypto_des3_struct* CryptoDes3;
FREERDP_API CryptoDes3 crypto_des3_encrypt_init(const BYTE* key, const BYTE* ivec);
FREERDP_API CryptoDes3 crypto_des3_decrypt_init(const BYTE* key, const BYTE* ivec);
FREERDP_API BOOL crypto_des3_encrypt(CryptoDes3 des3, UINT32 length, const BYTE *in_data, BYTE *out_data);
FREERDP_API BOOL crypto_des3_decrypt(CryptoDes3 des3, UINT32 length, const BYTE *in_data, BYTE* out_data);
FREERDP_API void crypto_des3_free(CryptoDes3 des3);
typedef struct crypto_hmac_struct* CryptoHmac;
FREERDP_API CryptoHmac crypto_hmac_new(void);
FREERDP_API BOOL crypto_hmac_sha1_init(CryptoHmac hmac, const BYTE *data, UINT32 length);
FREERDP_API BOOL crypto_hmac_md5_init(CryptoHmac hmac, const BYTE *data, UINT32 length);
FREERDP_API void crypto_hmac_update(CryptoHmac hmac, const BYTE *data, UINT32 length);
FREERDP_API void crypto_hmac_final(CryptoHmac hmac, BYTE *out_data, UINT32 length);
FREERDP_API void crypto_hmac_free(CryptoHmac hmac);
typedef struct crypto_cert_struct* CryptoCert;
#include <freerdp/crypto/certificate.h>
FREERDP_API CryptoCert crypto_cert_read(BYTE* data, UINT32 length);
FREERDP_API char* crypto_cert_fingerprint(X509* xcert);
FREERDP_API char* crypto_cert_subject(X509* xcert);
@ -146,7 +78,6 @@ FREERDP_API int crypto_rsa_public_decrypt(const BYTE* input, int length, UINT32
FREERDP_API int crypto_rsa_private_encrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output);
FREERDP_API int crypto_rsa_private_decrypt(const BYTE* input, int length, UINT32 key_length, const BYTE* modulus, const BYTE* private_exponent, BYTE* output);
FREERDP_API void crypto_reverse(BYTE* data, int length);
FREERDP_API void crypto_nonce(BYTE* nonce, int size);
FREERDP_API char* crypto_base64_encode(const BYTE* data, int length);
FREERDP_API void crypto_base64_decode(const char* enc_data, int length, BYTE** dec_data, int* res_length);

View File

@ -65,13 +65,55 @@ typedef void (*pContextFree)(freerdp* instance, rdpContext* context);
typedef BOOL (*pPreConnect)(freerdp* instance);
typedef BOOL (*pPostConnect)(freerdp* instance);
typedef void (*pPostDisconnect)(freerdp* instance);
typedef BOOL (*pAuthenticate)(freerdp* instance, char** username, char** password, char** domain);
typedef BOOL (*pVerifyCertificate)(freerdp* instance, char* subject, char* issuer, char* fingerprint);
typedef BOOL (*pVerifyChangedCertificate)(freerdp* instance, char* subject,
char* issuer, char* new_fingerprint,
char* old_subject, char* old_issuer,
char* old_fingerprint);
typedef int (*pVerifyX509Certificate)(freerdp* instance, BYTE* data, int length, const char* hostname, int port, DWORD flags);
typedef BOOL (*pAuthenticate)(freerdp* instance, char** username,
char** password, char** domain);
/** @brief Callback used if user interaction is required to accept
* an unknown certificate.
*
* @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 host_mismatch A flag indicating the certificate
* subject does not match the host connecting to.
*
* @return 1 to accept and store a certificate, 2 to accept
* a certificate only for this session, 0 otherwise.
*/
typedef DWORD (*pVerifyCertificate)(freerdp* instance,
const char* common_name,
const char* subject,
const char* issuer,
const char* fingerprint,
BOOL host_mismatch);
/** @brief Callback used if user interaction is required to accept
* a changed certificate.
*
* @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.
*
* @return 1 to accept and store a certificate, 2 to accept
* a certificate only for this session, 0 otherwise.
*/
typedef DWORD (*pVerifyChangedCertificate)(freerdp* instance,
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);
typedef int (*pVerifyX509Certificate)(freerdp* instance, BYTE* data,
int length, const char* hostname,
int port, DWORD flags);
typedef int (*pLogonErrorInfo)(freerdp* instance, UINT32 data, UINT32 type);

View File

@ -1,37 +0,0 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Time Zone Redirection
*
* 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.
*/
#ifndef FREERDP_LOCALE_TIMEZONE_H
#define FREERDP_LOCALE_TIMEZONE_H
#include <freerdp/api.h>
#include <freerdp/types.h>
#include <freerdp/settings.h>
#ifdef __cplusplus
extern "C" {
#endif
FREERDP_API void freerdp_time_zone_detect(TIME_ZONE_INFO* clientTimeZone);
#ifdef __cplusplus
}
#endif
#endif /* FREERDP_LOCALE_TIMEZONE_H */

View File

@ -277,7 +277,9 @@ typedef struct _SHADOW_MSG_OUT_AUDIO_OUT_VOLUME SHADOW_MSG_OUT_AUDIO_OUT_VOLUME;
extern "C" {
#endif
FREERDP_API void shadow_subsystem_set_entry_builtin(const char* name);
FREERDP_API void shadow_subsystem_set_entry(pfnShadowSubsystemEntry pEntry);
FREERDP_API int shadow_subsystem_pointer_convert_alpha_pointer_data(BYTE* pixels, BOOL premultiplied,
UINT32 width, UINT32 height, SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* pointerColor);

48
include/freerdp/session.h Normal file
View File

@ -0,0 +1,48 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Client Session Info
*
* Copyright 2016 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_SESSION_H__
#define __FREERDP_SESSION_H__
#include <winpr/wtypes.h>
/* Logon Information Types */
#define INFO_TYPE_LOGON 0x00000000
#define INFO_TYPE_LOGON_LONG 0x00000001
#define INFO_TYPE_LOGON_PLAIN_NOTIFY 0x00000002
#define INFO_TYPE_LOGON_EXTENDED_INF 0x00000003
struct rdp_logon_info {
UINT32 sessionId;
char *username;
char *domain;
};
typedef struct rdp_logon_info logon_info;
struct rdp_logon_info_ex {
BOOL haveCookie;
UINT32 LogonId;
BYTE ArcRandomBits[16];
BOOL haveErrorInfo;
UINT32 ErrorNotificationType;
UINT32 ErrorNotificationData;
};
typedef struct rdp_logon_info_ex logon_info_ex;
#endif /* __FREERDP_SESSION_H__ */

View File

@ -4,6 +4,7 @@
*
* Copyright 2009-2011 Jay Sorg
* Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2016 Armin Novak <armin.novak@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -21,6 +22,8 @@
#ifndef FREERDP_SETTINGS_H
#define FREERDP_SETTINGS_H
#include <winpr/timezone.h>
#include <freerdp/api.h>
#include <freerdp/types.h>
@ -269,32 +272,6 @@ typedef struct _TARGET_NET_ADDRESS TARGET_NET_ADDRESS;
#define ORIENTATION_LANDSCAPE_FLIPPED 180
#define ORIENTATION_PORTRAIT_FLIPPED 270
/* SYSTEM_TIME */
typedef struct
{
UINT16 wYear;
UINT16 wMonth;
UINT16 wDayOfWeek;
UINT16 wDay;
UINT16 wHour;
UINT16 wMinute;
UINT16 wSecond;
UINT16 wMilliseconds;
} SYSTEM_TIME;
/* TIME_ZONE_INFORMATION */
struct _TIME_ZONE_INFO
{
UINT32 bias;
char standardName[32];
SYSTEM_TIME standardDate;
UINT32 standardBias;
char daylightName[32];
SYSTEM_TIME daylightDate;
UINT32 daylightBias;
};
typedef struct _TIME_ZONE_INFO TIME_ZONE_INFO;
/* ARC_CS_PRIVATE_PACKET */
typedef struct
{
@ -977,7 +954,7 @@ struct rdp_settings
UINT64 padding0896[896 - 837]; /* 837 */
/* Client Info (Time Zone) */
ALIGN64 TIME_ZONE_INFO* ClientTimeZone; /* 896 */
ALIGN64 LPTIME_ZONE_INFORMATION ClientTimeZone; /* 896 */
ALIGN64 char* DynamicDSTTimeZoneKeyName; /* 897 */
ALIGN64 BOOL DynamicDaylightTimeDisabled; /* 898 */
UINT64 padding0960[960 - 899]; /* 899 */
@ -1459,6 +1436,7 @@ FREERDP_API int freerdp_addin_replace_argument_value(ADDIN_ARGV* args, char* pre
FREERDP_API BOOL freerdp_device_collection_add(rdpSettings* settings, RDPDR_DEVICE* device);
FREERDP_API RDPDR_DEVICE* freerdp_device_collection_find(rdpSettings* settings, const char* name);
FREERDP_API RDPDR_DEVICE* freerdp_device_collection_find_type(rdpSettings* settings, UINT32 type);
FREERDP_API RDPDR_DEVICE* freerdp_device_clone(RDPDR_DEVICE* device);
FREERDP_API void freerdp_device_collection_free(rdpSettings* settings);

View File

@ -156,6 +156,8 @@ typedef BOOL (*pSurfaceFrameMarker)(rdpContext* context, SURFACE_FRAME_MARKER* s
typedef BOOL (*pSurfaceFrameBits)(rdpContext* context, SURFACE_BITS_COMMAND* cmd, BOOL first, BOOL last, UINT32 frameId);
typedef BOOL (*pSurfaceFrameAcknowledge)(rdpContext* context, UINT32 frameId);
typedef BOOL (*pSaveSessionInfo)(rdpContext *context, UINT32 type, void *data);
struct rdp_update
{
rdpContext* context; /* 0 */
@ -189,7 +191,8 @@ struct rdp_update
pSurfaceFrameMarker SurfaceFrameMarker; /* 66 */
pSurfaceFrameBits SurfaceFrameBits; /* 67 */
pSurfaceFrameAcknowledge SurfaceFrameAcknowledge; /* 68 */
UINT32 paddingE[80 - 69]; /* 69 */
pSaveSessionInfo SaveSessionInfo; /* 69 */
UINT32 paddingE[80 - 70]; /* 70 */
/* internal */

View File

@ -57,7 +57,7 @@ void update_process_glyph(rdpContext* context, BYTE* data, int* index,
if (offset & 0x80)
{
offset = data[*index + 1] | ((int)((char)data[*index + 2]) << 8);
offset = data[*index + 1] | ((int)((signed char)data[*index + 2]) << 8);
(*index)++;
(*index)++;
}

View File

@ -94,17 +94,17 @@ const RECTANGLE_16 *region16_rects(const REGION16 *region, int *nbRects)
REGION16_DATA *data;
assert(region);
assert(region->data);
data = region->data;
if (!data)
{
if (nbRects)
*nbRects = 0;
return 0;
return NULL;
}
*nbRects = data->nbRects;
if (nbRects)
*nbRects = data->nbRects;
return (RECTANGLE_16 *)(data + 1);
}

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