mirror of https://github.com/FreeRDP/FreeRDP
Merge branch 'master' of github.com:FreeRDP/FreeRDP
This commit is contained in:
commit
ceefc4b099
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
LIBRARY "cliprdr"
|
||||
EXPORTS
|
||||
VirtualChannelEntry @1
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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) | \
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
LIBRARY "drive"
|
||||
EXPORTS
|
||||
DeviceServiceEntry @1
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -394,6 +394,8 @@ static UINT parallel_free(DEVICE* device)
|
|||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define DeviceServiceEntry parallel_DeviceServiceEntry
|
||||
#else
|
||||
#define DeviceServiceEntry FREERDP_API DeviceServiceEntry
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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_ */
|
|
@ -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")
|
||||
|
|
|
@ -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)))
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -813,6 +813,8 @@ static UINT serial_free(DEVICE* device)
|
|||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define DeviceServiceEntry serial_DeviceServiceEntry
|
||||
#else
|
||||
#define DeviceServiceEntry FREERDP_API DeviceServiceEntry
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
/**
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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, "
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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 */
|
|
@ -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;
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
LIBRARY "freerdp-client"
|
||||
EXPORTS
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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@"
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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__ */
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -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)++;
|
||||
}
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue