Imported Upstream version 2.0.0~git75ae3f5

This commit is contained in:
Bernhard Miklautz 2016-03-17 10:45:51 +00:00
parent 9a34f3e181
commit 7878df420c
136 changed files with 5802 additions and 2078 deletions

View File

@ -217,10 +217,6 @@ if(CMAKE_COMPILER_IS_GNUCC)
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set(CMAKE_C_FLAGS_RELEASE "-DNDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "-DNDEBUG")
if(NOT OPENBSD)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O2")
endif()
CHECK_C_COMPILER_FLAG (-Wno-builtin-macro-redefined Wno-builtin-macro-redefined)
if(Wno-builtin-macro-redefined)
@ -700,17 +696,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})

518
ChangeLog
View File

@ -1,7 +1,472 @@
2016-03-17 11:06:39 +0100 akallabeth (75ae3f5)
* Merge pull request #3243 from hardening/typofix (HEAD,
origin/master, origin/HEAD, master)
2016-03-17 11:02:51 +0100 Bernhard Miklautz (14daecf)
* Merge pull request #3240 from akallabeth/drive_fixes
2016-03-17 10:44:11 +0100 David FORT (2cb3717)
* Fixed a typo in debug messages
2016-03-17 09:34:24 +0100 Armin Novak (43b13ff)
* Replace SetFilePointerEx with SetFilePointer.
2016-03-17 09:33:39 +0100 Armin Novak (f45be8d)
* Print device name when loading channel.
2016-03-16 15:19:11 +0100 Martin Fleisz (80cd647)
* Merge pull request #3164 from akallabeth/windows_UnixChangeFileMode
2016-03-16 14:05:55 +0100 Bernhard Miklautz (eb5e303)
* Merge pull request #3215 from akallabeth/avc_444
2016-03-16 13:56:39 +0100 Bernhard Miklautz (90b3bf4)
* Merge pull request #3204 from akallabeth/rdp_file_preference_fix
2016-03-16 13:46:47 +0100 Armin Novak (7faff04)
* Assume the update rectangle is inclusive.
2016-03-14 09:01:57 +0100 Armin Novak (dfdc4c3)
* Fixed comments.
2016-03-14 08:57:00 +0100 Armin Novak (9ab3532)
* Renamed GFX defines to conform to spec.
2016-03-02 15:16:49 +0100 Armin Novak (5bc333c)
* Implemented GFX AVC444 support.
2016-03-02 14:53:55 +0100 Armin Novak (3309bf8)
* Implemented YUV444 related primitives.
2016-03-02 14:39:36 +0100 Armin Novak (3a3ec85)
* Unified RDPGFX_RECT16 and RECTANGLE_16
2016-03-16 13:32:51 +0100 akallabeth (0c99d6a)
* Merge pull request #3226 from rjcorrig/#3198
2016-03-16 13:32:29 +0100 akallabeth (2ea56c6)
* Merge pull request #3234 from bmiklautz/rdkt_version
2016-03-16 08:29:21 -0400 Robert Corrigan (a4f0089)
* winpr_detect_windows_time_zone should have void argument
2016-03-16 13:15:39 +0100 Armin Novak (fd26624)
* Parse RDP and assistance files in parser.
2016-03-16 13:05:00 +0100 Armin Novak (fb44b68)
* Removed windows extra handling for RDP files.
2016-03-16 13:15:24 +0100 Bernhard Miklautz (babbc4b)
* Increase rdtk version to 2.0.0
2016-03-16 13:08:06 +0100 Armin Novak (3d23a77)
* Updated ConvertToUnicode return check.
2016-03-16 13:03:33 +0100 Bernhard Miklautz (228f6b1)
* Merge pull request #3207 from akallabeth/mic_crash_fix
2016-03-16 12:39:36 +0100 Armin Novak (059c754)
* Fixed double free.
2016-03-16 11:58:31 +0100 Bernhard Miklautz (1b15636)
* Merge pull request #3214 from hardening/fix_systemd_appender
2016-03-15 09:25:50 +0100 akallabeth (b35f306)
* Merge pull request #3225 from mfleisz/fix_set_err_info
2016-03-10 15:10:49 -0500 Robert Corrigan (16796b9)
* winpr: Updates time zones and fixes bias values
2016-03-14 15:28:56 +0100 Bernhard Miklautz (c5fd49c)
* Merge pull request #3223 from comicfans/wayland_fix
2016-03-14 15:27:15 +0100 Martin Fleisz (b2d24a4)
* freerdp: Fix possible crash when setting error info in server-mode
2016-03-14 15:13:52 +0100 Bernhard Miklautz (05bcec4)
* Merge pull request #3224 from mfleisz/win32_bld_fix
2016-03-14 14:08:48 +0100 Martin Fleisz (0249b09)
* winpr: Fix definition of PathFileExists on Win32
2016-03-14 12:51:50 +0000 comicfans44 (6603039)
* only compile wayland client when WAYLAND_FOUND
2016-03-14 13:19:08 +0100 Armin Novak (2dbc1a0)
* Reverted WTS API changes.
2016-03-08 13:19:40 +0100 Armin Novak (d06723e)
* Fixed return value for failed malloc.
2016-03-07 12:54:49 +0100 Armin Novak (36cbf1b)
* Fixed error handling for channel load failures.
2016-03-14 13:00:52 +0100 Bernhard Miklautz (6ebf452)
* Merge pull request #3209 from akallabeth/android_translation_fix
2016-03-14 10:08:25 +0100 akallabeth (4ad3428)
* Merge pull request #3221 from bmiklautz/fix_nightlies
2016-03-14 09:57:33 +0100 Bernhard Miklautz (e13a327)
* Merge pull request #3212 from realjiangms/fix_default_audin
2016-03-14 09:53:45 +0100 Armin Novak (77d82f1)
* Removed untranslatable strings from translated files.
2016-03-14 09:38:35 +0100 Bernhard Miklautz (3bae203)
* pkg/deb: adapt channel paths
2016-03-14 09:20:30 +0100 Martin Fleisz (9554177)
* Merge pull request #3213 from akallabeth/android_build_fixes
2016-03-11 11:22:59 +0100 Martin Fleisz (66ae3f2)
* Merge pull request #3177 from akallabeth/codec_reset_fix
2016-03-10 23:41:12 +0100 Hardening (19494bd)
* Make systemd appender honor layout and log off
2016-03-10 22:07:30 +0100 Armin Novak (f60b8d5)
* Replaced version patch with make argument.
2016-03-10 21:54:11 +0100 Armin Novak (4a7816d)
* Updated OpenSSL version in script.
2016-03-10 21:52:40 +0100 Armin Novak (382626f)
* Fixed settings load/store.
2016-03-10 21:18:19 +0100 Armin Novak (cabcf7c)
* Fixed paralell building issue.
2016-03-11 01:52:18 +0800 zihao.jiang (40ea6e9)
* audin: Fixed default sys argument for audin PR #3173 fixed argument
parsing. However it breaks the usage without specifying
subsystem: "/microphone" In particular, aFreerdp
microphone redirect is broken as it exactly uses
"/microphone" This PR fixes the regression. Fix: We should
not call CommandLineParseArgumentsA if argc is only 1
(same case as rdpsnd_main.c)
2016-03-10 08:22:30 +0100 Martin Fleisz (1feb03d)
* Merge pull request #3210 from hardening/env_fix
2016-03-09 14:10:31 +0100 David FORT (b3c0478)
* Don't require HOME env var to be set for server-side code
2016-03-08 20:34:19 +0100 Armin Novak (15498ea)
* Marked non translatable strings as such.
2016-03-08 16:27:51 +0100 Armin Novak (1d4fd05)
* Reverted translation of internal VALUE arrays.
2016-03-08 20:50:30 +0100 akallabeth (ff1eb25)
* Merge pull request #3172 from
realjiangms/android_launch_by_scheme_2720
2016-02-27 18:31:43 +0800 zihao.jiang (0927114)
* android: Allow freerdp mobile version to be launched from URI
(freerdp://) It would be good if we have a easy way to
call aFreeRDP in another Android APP (Requirement also
mentioned in #2720) We can define a scheme (freerdp://) as
unified way to launch FreeRDP from another APP or browser
and connect to compatible RDP server 1. Define scheme
freerdp:// 2. General form could be
freerdp://user@hostname:port/connect?key1=value&key2=-&key3=%2b&key4=
3. [user] part would be translated to /u: 4.
[hostname:port] would be translated to /v: 5. The
[user@hostname:port] part would be used as app title,
currently it's just the progress dialog title 6. query
parameters would be translated to command line arguments.
Later same arguments will overwrite the formers: a.
key1=value: => /key1:value b. key2=-:
=> -key2 c. key3=%2b => +key3
(%2b is url encoded +) d. key4=
=> /key4 e. Especially, drive=sdcard will be properly
handled with local sdcard path. On my device it will be
translated to /drive:sdcard,/storage/emulated/0
2016-03-08 10:05:57 +0100 Martin Fleisz (30325f1)
* Merge pull request #3181 from akallabeth/wlog_filter_fix
2016-03-07 15:39:59 +0100 Bernhard Miklautz (9f8baf3)
* Merge pull request #3206 from akallabeth/openssl_unification
2016-03-07 13:12:38 +0100 Armin Novak (bb3448f)
* Set variable to NULL to prevent double free.
2016-03-07 11:51:13 +0100 Armin Novak (2208a84)
* Moved assistance to winpr crypto.
2016-03-07 10:55:51 +0100 akallabeth (52f1e6b)
* Merge pull request #3086 from DavBfr/fix-rdpdr
2016-03-07 10:50:35 +0100 akallabeth (ece552d)
* Merge pull request #3200 from dwmw2/master
2016-03-07 09:43:35 +0100 Armin Novak (83ef642)
* Use common command line parser.
2016-03-07 09:43:53 +0100 Armin Novak (4bb33e9)
* Reparse command line after RDP or assistance file.
2016-03-07 09:44:07 +0100 Armin Novak (36241ed)
* Fix memory leaks if parsed multiple times.
2016-03-07 09:24:44 +0100 Martin Fleisz (f0cc927)
* Merge pull request #3202 from akallabeth/file_bsd_fix
2016-03-04 09:25:04 +0100 Armin Novak (34b1236)
* Fixed FreeBSD support for filetime settings.
2016-03-04 13:22:58 +0000 David Woodhouse (701f54e)
* winpr: Bump API version to 2.0
2016-03-04 11:19:00 +0100 Hardening (fb63dd2)
* Merge pull request #3194 from
nfedera/fix-convertfromunicode-hardening
2016-03-04 11:17:42 +0100 Bernhard Miklautz (9fa85ae)
* Merge pull request #1726 from grpomega/patch-3
2016-03-04 00:45:26 +0100 Norbert Federa (de4adef)
* fix logon info processing
2016-03-03 20:39:31 +0100 Bernhard Miklautz (120bd2d)
* Merge pull request #3173 from akallabeth/audin_arg_fix
2016-03-03 17:34:57 +0100 Martin Fleisz (151f435)
* Merge pull request #3196 from akallabeth/exported_symbols_fix
2016-03-03 17:11:26 +0100 Armin Novak (fb88ad0)
* Fixed symbol export for sound plugins.
2016-03-03 16:21:12 +0100 Norbert Federa (ef4b29e)
* ConvertFromUnicode fixes and misc hardening
2016-03-03 13:58:42 +0100 Bernhard Miklautz (167fd47)
* Merge pull request #3192 from akallabeth/plugin_path_fix
2016-03-03 12:07:10 +0100 Armin Novak (ee2839f)
* Caching log filter after first use.
2016-03-03 12:12:21 +0100 Martin Fleisz (f150575)
* Merge pull request #3191 from hardening/saveInfoPdu_fix
2016-03-03 11:45:12 +0100 David FORT (f5ce5e7)
* Fix parsing of saveSessionInfo PDU
2016-03-03 11:36:26 +0100 Armin Novak (767e6bb)
* Updated freerdp plugin path to use major version.
2016-03-03 11:06:24 +0100 Martin Fleisz (2710ebf)
* Merge pull request #3187 from akallabeth/client_name_fix
2016-03-03 09:08:30 +0100 Armin Novak (7dcba9a)
* Removed additional '\0' from TUNNEL_AUTH message.
2016-03-02 20:53:19 +0100 Hardening (9afa928)
* Merge pull request #3184 from xhaakon/fix-ubuntu-gcc-build
2016-02-23 15:27:33 +0100 Jakub Adam (bc750e9)
* Fix build on older 32-bit Ubuntu releases
2016-03-02 19:02:01 +0100 Armin Novak (0ea7aea)
* Remember filter log level.
2016-03-01 17:10:22 -0800 David PHAM-VAN (40504c5)
* Fix Uninitialized Variable
2016-03-02 19:03:46 +0100 akallabeth (e71369d)
* Merge pull request #3183 from bmiklautz/timezone_regression
2016-02-26 10:32:54 -0800 David PHAM-VAN (f4eb278)
* Mount only removable devices and network drives in Windows; Adds
consistency with Linux and Mac
2016-02-26 10:31:14 -0800 David PHAM-VAN (31d9599)
* Move first_hotplug call to parent thread to avoid parallel access
to devman dictionary
2016-02-26 10:19:21 -0800 David PHAM-VAN (2f28b6c)
* Improve code using more winpr functions
2015-09-07 12:16:03 +0200 David PHAM-VAN (2e1e6a4)
* Add hotplug support for MacOS
2016-01-07 11:04:10 -0800 David PHAM-VAN (a20950f)
* Implement FileAllocationInformation
2016-03-02 12:37:48 -0500 Bernhard Miklautz (7075353)
* winpr: fix regression in timezone detection
2016-03-02 10:33:41 -0500 Bernhard Miklautz (ee40be2)
* Merge pull request #3182 from xhaakon/shadow-pkg-config
2016-03-02 10:20:12 +0100 Jakub Adam (9f0b14f)
* shadow/subsystem: fix pkgconfig file
2016-03-01 17:30:08 +0100 Armin Novak (5bb68a0)
* Fixed broken resource cleanup.
2016-03-01 17:14:35 +0100 Armin Novak (ce8f3f2)
* Fixed context reset of sample server.
2016-03-01 16:56:36 +0100 Armin Novak (09e957f)
* Fixed broken check.
2016-03-01 16:39:53 +0100 Armin Novak (8997c6c)
* Added log messages for unsupported surface commands.
2016-03-01 16:17:28 +0100 Armin Novak (2e110c7)
* Fixed codec reset, now resetting resolution too.
2016-03-02 14:11:15 +0100 Armin Novak (41fdac2)
* Respecting filter in WLog_GetLogLevel
2016-03-02 09:43:46 +0100 Martin Fleisz (857c373)
* Merge pull request #3163 from akallabeth/set_file_time
2016-03-02 09:43:24 +0100 Martin Fleisz (cfe5923)
* Merge pull request #3179 from akallabeth/minor_fixes
2016-02-26 12:53:23 +0100 Armin Novak (c74e37d)
* Implemented UnixChangeFileMode for windows.
2016-03-02 09:16:59 +0100 Armin Novak (65cddbc)
* Removed obsolete log message.
2016-03-02 09:16:49 +0100 Armin Novak (227ecc4)
* Fixed uninitialized variable.
2016-03-01 23:34:57 +0100 Hardening (49a0a9c)
* Merge pull request #3178 from hendwolt/master
2016-03-01 21:49:21 +0100 Hendrik Woltersdorf (a5bb05b)
* fix wayland-client.h not found
2016-03-01 16:44:19 +0100 Bernhard Miklautz (e02af82)
* Merge pull request #3160 from akallabeth/stream_fixes
2016-03-01 11:40:11 +0100 Armin Novak (a79072a)
* Added tests for remaining stream functions.
2016-03-01 11:39:21 +0100 Armin Novak (e7814d5)
* Fixed stream API for Stream_Copy.
2016-03-01 10:29:51 +0100 Armin Novak (a98e0f9)
* Reverted opaque structures.
2016-02-29 17:39:18 +0100 Norbert Federa (b4b8239)
* Merge pull request #3176 from bmiklautz/shadow_subsystem (HEAD,
origin/master, origin/HEAD, master)
* Merge pull request #3176 from bmiklautz/shadow_subsystem
2016-02-29 17:10:53 +0100 Bernhard Miklautz (014f31d)
@ -48,6 +513,18 @@
* Fixed crypto tests.
2016-02-29 12:54:31 +0100 Armin Novak (b690470)
* Replaced stream manipulation with EnsureCapacity.
2016-02-29 12:51:54 +0100 Armin Novak (46fa7ec)
* Fixed invalid stream copy length.
2016-02-29 12:34:53 +0100 Armin Novak (8482fbf)
* Fixed formatting.
2016-02-29 11:12:32 +0100 Armin Novak (19568c6)
* Fixed indentation.
@ -64,6 +541,10 @@
* Refactored crypto *_New functions.
2016-02-28 19:56:57 +0100 Armin Novak (71bea3e)
* Fixed argument parsing for audin.
2016-02-28 11:12:17 +0100 Armin Novak (92c1578)
* Updated RC4 API, fixed crashing bug.
@ -101,6 +582,10 @@
* Removed crypto_nonce.
2016-02-27 22:16:41 +0100 Armin Novak (4929844)
* Fixed const argument for Stream_Write.
2016-02-27 22:13:59 +0100 Armin Novak (86436bc)
* Added API export for uwac.
@ -129,6 +614,19 @@
* Fixed duplicate loading of smartcard and printers.
2016-02-26 12:13:02 +0100 Armin Novak (98d4a93)
* Added support for android SetFileTime. Deactivated libjpeg support
for android.
2016-02-26 11:22:56 +0100 Armin Novak (5537230)
* Fixed missing iOS UTIME_OMIT.
2016-02-26 10:48:53 +0100 Armin Novak (436be24)
* Implemented SetFileTime
2016-02-26 09:57:35 +0100 Martin Fleisz (4f22682)
* Merge pull request #3151 from akallabeth/timezone_refactor
@ -165,6 +663,18 @@
* cmake/FindWayland: cleanup
2016-02-25 20:13:56 +0100 Armin Novak (cf9543e)
* Converted Stream defines to inline functions.
2016-02-25 20:01:12 +0100 Armin Novak (e79eee2)
* Fixed Stream API misuse.
2016-02-25 19:37:20 +0100 Armin Novak (b61ab5e)
* Fixed stream copy in update_message_SurfaceCommand
2016-02-25 16:57:48 +0100 akallabeth (16ba8f3)
* Merge pull request #3159 from bmiklautz/disable_mipsel
@ -15949,6 +16459,10 @@
* libwinpr-crt: add byteswap macros
2014-03-06 10:04:53 -0600 grpomega (c005e81)
* Need Week instead of Day for TZ transistion
2014-03-05 18:03:39 -0500 Marc-André Moreau (95127d5)
* libfreerdp-codec: start testing MPPC against large buffer

View File

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

View File

@ -82,7 +82,7 @@ struct _AUDIN_PLUGIN
/* Parsed plugin data */
UINT16 fixed_format;
UINT16 fixed_channel;
UINT16 fixed_channel;
UINT32 fixed_rate;
char* subsystem;
char* device_name;
@ -93,6 +93,8 @@ struct _AUDIN_PLUGIN
rdpContext* rdpcontext;
};
static BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args);
/**
* Function description
*
@ -639,8 +641,12 @@ static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDI
{
PFREERDP_AUDIN_DEVICE_ENTRY entry;
FREERDP_AUDIN_DEVICE_ENTRY_POINTS entryPoints;
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*)pPlugin;
UINT error;
if (!audin_process_addin_args(audin, args))
return CHANNEL_RC_INITIALIZATION_ERROR;
entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_channel_addin_entry("audin", (LPSTR) name, NULL, 0);
if (entry == NULL)
@ -660,6 +666,7 @@ static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDI
return error;
}
WLog_INFO(TAG, "Loaded %s backend for audin", name);
return CHANNEL_RC_OK;
}
@ -707,18 +714,24 @@ 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;
if (args->argc == 1)
{
return TRUE;
}
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;
@ -788,7 +801,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[] =
@ -819,51 +832,71 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints)
assert(pEntryPoints->GetPlugin);
audin = (AUDIN_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "audin");
if (audin == NULL)
if (audin != NULL)
return CHANNEL_RC_ALREADY_INITIALIZED;
audin = (AUDIN_PLUGIN*) calloc(1, sizeof(AUDIN_PLUGIN));
if (!audin)
{
audin = (AUDIN_PLUGIN*) calloc(1, sizeof(AUDIN_PLUGIN));
if (!audin)
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
audin->iface.Initialize = audin_plugin_initialize;
audin->iface.Connected = NULL;
audin->iface.Disconnected = NULL;
audin->iface.Terminated = audin_plugin_terminated;
error = pEntryPoints->RegisterPlugin(pEntryPoints, "audin", (IWTSPlugin*) audin);
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
audin->iface.Initialize = audin_plugin_initialize;
audin->iface.Connected = NULL;
audin->iface.Disconnected = NULL;
audin->iface.Terminated = audin_plugin_terminated;
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 = pEntryPoints->RegisterPlugin(pEntryPoints, "audin", (IWTSPlugin*) audin);
out:
if (error != CHANNEL_RC_OK)
audin_plugin_terminated((IWTSPlugin*)audin);
return error;
}

View File

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

View File

@ -476,6 +476,9 @@ static UINT audin_opensles_parse_addin_args(AudinOpenSLESDevice* device,
#ifdef STATIC_CHANNELS
#define freerdp_audin_client_subsystem_entry \
opensles_freerdp_audin_client_subsystem_entry
#else
#define freerdp_audin_client_subsystem_entry \
FREERDP_API freerdp_audin_client_subsystem_entry
#endif
/**

View File

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

View File

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

View File

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

View File

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

View File

@ -159,10 +159,10 @@ static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream*
WLog_ERR(TAG, "cliprdr_get_client_interface failed!");
return ERROR_INTERNAL_ERROR;
}
Stream_Read_UINT32(s, version); /* version (4 bytes) */
Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */
DEBUG_CLIPRDR("Version: %d", version);
#ifdef WITH_DEBUG_CLIPRDR
cliprdr_print_general_capability_flags(generalFlags);
@ -179,7 +179,7 @@ static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream*
if (cliprdr->canLockClipData)
cliprdr->canLockClipData = (generalFlags & CB_CAN_LOCK_CLIPDATA) ? TRUE : FALSE;
cliprdr->capabilitiesReceived = TRUE;
if (!context->custom)
@ -187,7 +187,7 @@ static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream*
WLog_ERR(TAG, "context->custom not set!");
return ERROR_INTERNAL_ERROR;
}
capabilities.cCapabilitiesSets = 1;
capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &(generalCapabilitySet);
generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
@ -215,7 +215,7 @@ static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16
UINT16 cCapabilitiesSets;
UINT16 capabilitySetType;
UINT error = CHANNEL_RC_OK;
Stream_Read_UINT16(s, cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */
Stream_Seek_UINT16(s); /* pad1 (2 bytes) */
@ -235,7 +235,7 @@ static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT16
return error;
}
break;
default:
WLog_ERR(TAG, "unknown cliprdr capability set: %d", capabilitySetType);
return CHANNEL_RC_BAD_PROC;
@ -273,13 +273,13 @@ static UINT cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, UI
* When the server capabilities pdu is not used, default capabilities
* corresponding to a generalFlags field set to zero are assumed.
*/
cliprdr->useLongFormatNames = FALSE;
cliprdr->streamFileClipEnabled = FALSE;
cliprdr->fileClipNoFilePaths = TRUE;
cliprdr->canLockClipData = FALSE;
}
monitorReady.msgType = CB_MONITOR_READY;
monitorReady.msgFlags = flags;
monitorReady.dataLen = length;
@ -354,7 +354,7 @@ static UINT cliprdr_process_filecontents_response(cliprdrPlugin* cliprdr, wStrea
WLog_ERR(TAG, "context->custom not set!");
return ERROR_INTERNAL_ERROR;
}
if (Stream_GetRemainingLength(s) < 4)
{
WLog_ERR(TAG, "not enought remaining data");
@ -366,7 +366,7 @@ static UINT cliprdr_process_filecontents_response(cliprdrPlugin* cliprdr, wStrea
response.dataLen = length;
Stream_Read_UINT32(s, response.streamId); /* streamId (4 bytes) */
response.cbRequested = length - 4;
response.requestedData = Stream_Pointer(s); /* requestedFileContentsData */
@ -434,7 +434,7 @@ static UINT cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s,
WLog_ERR(TAG, "context->custom not set!");
return ERROR_INTERNAL_ERROR;
}
if (Stream_GetRemainingLength(s) < 4)
{
WLog_ERR(TAG, "not enought remaining data");
@ -637,7 +637,7 @@ UINT cliprdr_client_format_list(CliprdrClientContext* context, CLIPRDR_FORMAT_LI
if (!cliprdr->useLongFormatNames)
{
length = formatList->numFormats * 36;
s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length);
if (!s)
@ -649,40 +649,40 @@ UINT cliprdr_client_format_list(CliprdrClientContext* context, CLIPRDR_FORMAT_LI
for (index = 0; index < formatList->numFormats; index++)
{
format = (CLIPRDR_FORMAT*) &(formatList->formats[index]);
Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */
formatNameSize = 0;
formatNameLength = 0;
szFormatName = format->formatName;
if (asciiNames)
{
if (szFormatName)
formatNameLength = strlen(szFormatName);
if (formatNameLength > 31)
formatNameLength = 31;
Stream_Write(s, szFormatName, formatNameLength);
Stream_Zero(s, 32 - formatNameLength);
}
else
{
wszFormatName = NULL;
if (szFormatName)
formatNameSize = ConvertToUnicode(CP_UTF8, 0, szFormatName, -1, &wszFormatName, 0);
if (formatNameSize > 15)
formatNameSize = 15;
if (wszFormatName)
if (wszFormatName)
Stream_Write(s, wszFormatName, formatNameSize * 2);
Stream_Zero(s, 32 - (formatNameSize * 2));
free(wszFormatName);
}
}
@ -1218,9 +1218,9 @@ static UINT cliprdr_virtual_channel_event_disconnected(cliprdrPlugin* cliprdr)
if (MessageQueue_PostQuit(cliprdr->queue, 0) && (WaitForSingleObject(cliprdr->thread, INFINITE) == WAIT_FAILED))
{
rc = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
return rc;
rc = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
return rc;
}
MessageQueue_Free(cliprdr->queue);
@ -1257,7 +1257,9 @@ static UINT cliprdr_virtual_channel_event_terminated(cliprdrPlugin* cliprdr)
return CHANNEL_RC_OK;
}
static VOID VCAPITYPE cliprdr_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
static VOID VCAPITYPE cliprdr_virtual_channel_init_event(LPVOID pInitHandle,
UINT event, LPVOID pData,
UINT dataLength)
{
cliprdrPlugin* cliprdr;
UINT error = CHANNEL_RC_OK;
@ -1289,8 +1291,6 @@ static VOID VCAPITYPE cliprdr_virtual_channel_init_event(LPVOID pInitHandle, UIN
}
if (error && cliprdr->context->rdpcontext)
setChannelError(cliprdr->context->rdpcontext, error, "cliprdr_virtual_channel_init_event reported an error");
return;
}
/* cliprdr is always built-in */
@ -1358,14 +1358,14 @@ BOOL VCAPITYPE VirtualChannelEntry(PCHANNEL_ENTRY_POINTS pEntryPoints)
cliprdr->streamFileClipEnabled = FALSE;
cliprdr->fileClipNoFilePaths = TRUE;
cliprdr->canLockClipData = FALSE;
WLog_Print(cliprdr->log, WLOG_DEBUG, "VirtualChannelEntry");
CopyMemory(&(cliprdr->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP));
rc = cliprdr->channelEntryPoints.pVirtualChannelInit(&cliprdr->InitHandle,
&cliprdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, cliprdr_virtual_channel_init_event);
if (CHANNEL_RC_OK != rc)
{
WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08X]",

View File

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

View File

@ -241,7 +241,7 @@ IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin)
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args, rdpSettings* settings)
static UINT dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args, rdpSettings* settings)
{
DVCMAN_ENTRY_POINTS entryPoints;
PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL;
@ -261,7 +261,7 @@ UINT dvcman_load_addin(IWTSVirtualChannelManager* pChannelMgr, ADDIN_ARGV* args,
entryPoints.args = args;
entryPoints.settings = settings;
pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*) &entryPoints);
return pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*) &entryPoints);
}
return CHANNEL_RC_OK;
@ -478,8 +478,8 @@ UINT dvcman_create_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 Channe
context = dvcman->drdynvc->context;
IFCALLRET(context->OnChannelConnected, error, context, ChannelName, listener->iface.pInterface);
if (error)
WLog_ERR(TAG, "context.ReceiveSamples failed with error %lu", error);
if (error)
WLog_ERR(TAG, "context.ReceiveSamples failed with error %lu", error);
return error;
}
@ -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");
@ -1056,7 +1056,7 @@ static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cb
WLog_ERR(TAG, "dvcman_close_channel failed with error %lu!", error);
return error;
}
data_out = Stream_New(NULL, 4);
if (!data_out)
@ -1214,6 +1214,10 @@ void* drdynvc_get_open_handle_data(DWORD openHandle)
void drdynvc_remove_open_handle_data(DWORD openHandle)
{
void* pOpenHandle = (void*) (size_t) openHandle;
if (!g_OpenHandles)
return;
ListDictionary_Remove(g_OpenHandles, pOpenHandle);
if (ListDictionary_Count(g_OpenHandles) < 1)
@ -1411,7 +1415,9 @@ static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO
for (index = 0; index < settings->DynamicChannelCount; index++)
{
args = settings->DynamicChannelArray[index];
dvcman_load_addin(drdynvc->channel_mgr, args, settings);
error = dvcman_load_addin(drdynvc->channel_mgr, args, settings);
if (CHANNEL_RC_OK != error)
goto error;
}
if ((error = dvcman_init(drdynvc->channel_mgr)))
@ -1434,8 +1440,6 @@ static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO
error:
drdynvc_remove_open_handle_data(drdynvc->OpenHandle);
MessageQueue_Free(drdynvc->queue);
drdynvc->queue = NULL;
return error;
}
@ -1449,11 +1453,11 @@ static UINT drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc)
UINT status;
if (MessageQueue_PostQuit(drdynvc->queue, 0) && (WaitForSingleObject(drdynvc->thread, INFINITE) == WAIT_FAILED))
{
status = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", status);
return status;
}
{
status = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", status);
return status;
}
MessageQueue_Free(drdynvc->queue);
CloseHandle(drdynvc->thread);
@ -1497,7 +1501,9 @@ static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc)
return CHANNEL_RC_OK;
}
static void VCAPITYPE drdynvc_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
static VOID VCAPITYPE drdynvc_virtual_channel_init_event(LPVOID pInitHandle,
UINT event, LPVOID pData,
UINT dataLength)
{
drdynvcPlugin* drdynvc;
UINT error = CHANNEL_RC_OK;
@ -1529,7 +1535,6 @@ static void VCAPITYPE drdynvc_virtual_channel_init_event(LPVOID pInitHandle, UIN
}
if (error && drdynvc->rdpcontext)
setChannelError(drdynvc->rdpcontext, error, "drdynvc_virtual_channel_init_event reported an error");
}
/**

View File

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

View File

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

View File

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

View File

@ -1217,9 +1217,9 @@ static UINT encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp)
if (MessageQueue_PostQuit(encomsp->queue, 0) && (WaitForSingleObject(encomsp->thread, INFINITE) == WAIT_FAILED))
{
rc = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
return rc;
rc = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
return rc;
}
MessageQueue_Free(encomsp->queue);
@ -1259,7 +1259,9 @@ static UINT encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp)
return CHANNEL_RC_OK;
}
static void VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
static VOID VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle,
UINT event, LPVOID pData,
UINT dataLength)
{
encomspPlugin* encomsp;
UINT error = CHANNEL_RC_OK;
@ -1293,8 +1295,6 @@ static void VCAPITYPE encomsp_virtual_channel_init_event(LPVOID pInitHandle, UIN
if (error && encomsp->rdpcontext)
setChannelError(encomsp->rdpcontext, error, "encomsp_virtual_channel_init_event reported an error");
return;
}
/* encomsp is always built-in */

View File

@ -741,9 +741,9 @@ static UINT rail_virtual_channel_event_disconnected(railPlugin* rail)
UINT rc;
if (MessageQueue_PostQuit(rail->queue, 0) && (WaitForSingleObject(rail->thread, INFINITE) == WAIT_FAILED))
{
rc = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
return rc;
rc = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
return rc;
}
MessageQueue_Free(rail->queue);
@ -757,7 +757,7 @@ static UINT rail_virtual_channel_event_disconnected(railPlugin* rail)
{
WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08X]",
WTSErrorToString(rc), rc);
return rc;
return rc;
}
if (rail->data_in)
@ -798,7 +798,7 @@ static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle, UINT e
case CHANNEL_EVENT_DISCONNECTED:
if ((error = rail_virtual_channel_event_disconnected(rail)))
WLog_ERR(TAG, "rail_virtual_channel_event_disconnected failed with error %lu!", error);
WLog_ERR(TAG, "rail_virtual_channel_event_disconnected failed with error %lu!", error);
break;
case CHANNEL_EVENT_TERMINATED:
@ -808,8 +808,6 @@ static VOID VCAPITYPE rail_virtual_channel_init_event(LPVOID pInitHandle, UINT e
if(error && rail->rdpcontext)
setChannelError(rail->rdpcontext, error, "rail_virtual_channel_init_event reported an error");
return;
}
/* rail is always built-in */

View File

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

View File

@ -173,7 +173,10 @@ UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext
return ERROR_INVALID_NAME;
}
WLog_INFO(TAG, "Loading device service %s (static)", ServiceName);
if (device->Name)
WLog_INFO(TAG, "Loading device service %s [%s] (static)", ServiceName, device->Name);
else
WLog_INFO(TAG, "Loading device service %s (static)", ServiceName);
entry = (PDEVICE_SERVICE_ENTRY) freerdp_load_channel_addin_entry(ServiceName, NULL, "DeviceServiceEntry", 0);
if (!entry)

View File

@ -46,6 +46,15 @@
#include <fcntl.h>
#endif
#ifdef __MACOSX__
#include <CoreFoundation/CoreFoundation.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
@ -103,6 +112,45 @@ static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 cou
#ifdef _WIN32
BOOL check_path(char* path)
{
UINT type = GetDriveTypeA(path);
if (!(type == DRIVE_REMOVABLE || type == DRIVE_CDROM || type == DRIVE_REMOTE))
return FALSE;
return GetVolumeInformationA(path, NULL, 0, NULL, NULL, NULL, NULL, 0);
}
void first_hotplug(rdpdrPlugin *rdpdr)
{
int i;
char drive_path[5] = { 'c', ':', '\\', '\0' };
DWORD unitmask = GetLogicalDrives();
for (i = 0; i < 26; i++)
{
if (unitmask & 0x01)
{
RDPDR_DRIVE* drive;
drive_path[0] = 'A' + i;
drive_path[1] = ':';
if (check_path(drive_path))
{
drive = (RDPDR_DRIVE*)malloc(sizeof(RDPDR_DRIVE));
ZeroMemory(drive, sizeof(RDPDR_DRIVE));
drive->Type = RDPDR_DTYP_FILESYSTEM;
drive->Path = _strdup(drive_path);
drive_path[1] = '\0';
drive->Name = _strdup(drive_path);
devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext);
}
}
unitmask = unitmask >> 1;
}
}
LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
{
rdpdrPlugin *rdpdr;
@ -131,17 +179,21 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam)
RDPDR_DRIVE* drive;
drive_path[0] = 'A' + i;
drive_path[1] = ':';
drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE));
ZeroMemory(drive, sizeof(RDPDR_DRIVE));
if (check_path(drive_path))
{
drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE));
ZeroMemory(drive, sizeof(RDPDR_DRIVE));
drive->Type = RDPDR_DTYP_FILESYSTEM;
drive->Type = RDPDR_DTYP_FILESYSTEM;
drive->Path = _strdup(drive_path);
drive_path[1] = '\0';
drive->Name = _strdup(drive_path);
devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext);
rdpdr_send_device_list_announce_request(rdpdr, TRUE);
drive->Path = _strdup(drive_path);
drive_path[1] = '\0';
drive->Name = _strdup(drive_path);
devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext);
rdpdr_send_device_list_announce_request(rdpdr, TRUE);
}
}
unitmask = unitmask >> 1;
}
@ -275,6 +327,242 @@ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr)
return error;
}
#elif __MACOSX__
#define MAX_USB_DEVICES 100
typedef struct _hotplug_dev
{
char* path;
BOOL to_add;
} hotplug_dev;
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT handle_hotplug(rdpdrPlugin* rdpdr)
{
struct dirent *pDirent;
DIR *pDir;
char fullpath[PATH_MAX];
char* szdir = (char*)"/Volumes";
struct stat buf;
hotplug_dev dev_array[MAX_USB_DEVICES];
int count;
DEVICE_DRIVE_EXT *device_ext;
ULONG_PTR *keys;
int i, j;
int size = 0;
UINT error;
UINT32 ids[1];
pDir = opendir (szdir);
if (pDir == NULL)
{
printf ("Cannot open directory\n");
return ERROR_OPEN_FAILED;
}
while ((pDirent = readdir(pDir)) != NULL)
{
if (pDirent->d_name[0] != '.')
{
sprintf(fullpath, "%s/%s", szdir, pDirent->d_name);
lstat(fullpath, &buf);
if(S_ISDIR(buf.st_mode))
{
dev_array[size].path = _strdup(fullpath);
if (!dev_array[size].path)
{
closedir (pDir);
error = CHANNEL_RC_NO_MEMORY;
goto cleanup;
}
dev_array[size++].to_add = TRUE;
}
}
}
closedir (pDir);
/* delete removed devices */
count = ListDictionary_GetKeys(rdpdr->devman->devices, &keys);
for (j = 0; j < count; j++)
{
BOOL dev_found = FALSE;
device_ext = (DEVICE_DRIVE_EXT *)ListDictionary_GetItemValue(rdpdr->devman->devices, (void *)keys[j]);
if (!device_ext)
continue;
if (device_ext->path == NULL)
continue;
/* not plugable device */
if (strstr(device_ext->path, "/Volumes/") == NULL)
continue;
for (i = 0; i < size; i++)
{
if (strstr(device_ext->path, dev_array[i].path) != NULL)
{
dev_found = TRUE;
dev_array[i].to_add = FALSE;
break;
}
}
if (!dev_found)
{
devman_unregister_device(rdpdr->devman, (void *)keys[j]);
ids[0] = keys[j];
if ((error = rdpdr_send_device_list_remove_request(rdpdr, 1, ids)))
{
WLog_ERR(TAG, "rdpdr_send_device_list_remove_request failed with error %lu!", error);
goto cleanup;
}
}
}
/* add new devices */
for (i = 0; i < size; i++)
{
RDPDR_DRIVE* drive;
if (dev_array[i].to_add)
{
char* name;
drive = (RDPDR_DRIVE*) calloc(1, sizeof(RDPDR_DRIVE));
if (!drive)
{
WLog_ERR(TAG, "calloc failed!");
error = CHANNEL_RC_NO_MEMORY;
goto cleanup;
}
drive->Type = RDPDR_DTYP_FILESYSTEM;
drive->Path = dev_array[i].path;
dev_array[i].path = NULL;
name = strrchr(drive->Path, '/') + 1;
drive->Name = _strdup(name);
if (!drive->Name)
{
WLog_ERR(TAG, "_strdup failed!");
free(drive->Path);
free(drive);
error = CHANNEL_RC_NO_MEMORY;
goto cleanup;
}
if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE *)drive, rdpdr->rdpcontext)))
{
WLog_ERR(TAG, "devman_load_device_service failed!");
free(drive->Path);
free(drive->Name);
free(drive);
error = CHANNEL_RC_NO_MEMORY;
goto cleanup;
}
}
}
cleanup:
for (i = 0; i < size; i++)
free (dev_array[i].path);
return error;
}
static void drive_hotplug_fsevent_callback(ConstFSEventStreamRef streamRef, void *clientCallBackInfo,
size_t numEvents, void *eventPaths, const FSEventStreamEventFlags eventFlags[],
const FSEventStreamEventId eventIds[])
{
rdpdrPlugin* rdpdr;
int i;
UINT error;
char **paths = (char**)eventPaths;
rdpdr = (rdpdrPlugin*) clientCallBackInfo;
for (i=0; i<numEvents; i++)
{
if (strcmp(paths[i], "/Volumes/") == 0)
{
if ((error = handle_hotplug(rdpdr)))
{
WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error);
}
else
rdpdr_send_device_list_announce_request(rdpdr, TRUE);
return;
}
}
}
void first_hotplug(rdpdrPlugin *rdpdr)
{
UINT error;
if ((error = handle_hotplug(rdpdr)))
{
WLog_ERR(TAG, "handle_hotplug failed with error %lu!", error);
}
}
static void* drive_hotplug_thread_func(void* arg)
{
rdpdrPlugin* rdpdr;
FSEventStreamRef fsev;
UINT error;
rdpdr = (rdpdrPlugin*) arg;
CFStringRef path = CFSTR("/Volumes/");
CFArrayRef pathsToWatch = CFArrayCreate(kCFAllocatorMalloc, (const void**)&path, 1, NULL);
FSEventStreamContext ctx;
ZeroMemory(&ctx, sizeof(ctx));
ctx.info = arg;
fsev = FSEventStreamCreate(kCFAllocatorMalloc, drive_hotplug_fsevent_callback, &ctx, pathsToWatch, kFSEventStreamEventIdSinceNow, 1, kFSEventStreamCreateFlagNone);
rdpdr->runLoop = CFRunLoopGetCurrent();
FSEventStreamScheduleWithRunLoop(fsev, rdpdr->runLoop, kCFRunLoopDefaultMode);
FSEventStreamStart(fsev);
CFRunLoopRun();
FSEventStreamStop(fsev);
FSEventStreamRelease(fsev);
ExitThread(CHANNEL_RC_OK);
return NULL;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr)
{
UINT error;
if (rdpdr->hotplugThread)
{
CFRunLoopStop(rdpdr->runLoop);
if (WaitForSingleObject(rdpdr->hotplugThread, INFINITE) == WAIT_FAILED)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
return error;
}
rdpdr->hotplugThread = NULL;
}
return CHANNEL_RC_OK;
}
#else
#define MAX_USB_DEVICES 100
@ -361,13 +649,13 @@ static char* get_word(char* str, unsigned int* offset)
(*offset)++;
word = malloc(wlen + 1);
if (word != NULL)
{
CopyMemory(word, p, wlen);
word[wlen] = '\0';
}
return word;
}
@ -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)))
{
@ -1426,7 +1720,8 @@ static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr)
free(rdpdr);
}
static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle, UINT event,
LPVOID pData, UINT dataLength)
{
rdpdrPlugin* rdpdr;
UINT error = CHANNEL_RC_OK;
@ -1464,7 +1759,6 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event(LPVOID pInitHandle, UINT
if (error && rdpdr->rdpcontext)
setChannelError(rdpdr->rdpcontext, error, "rdpdr_virtual_channel_init_event reported an error");
return;
}
/* rdpdr is always built-in */

View File

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

View File

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

View File

@ -38,10 +38,11 @@
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, RDPGFX_H264_METABLOCK* meta)
static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s,
RDPGFX_H264_METABLOCK* meta)
{
UINT32 index;
RDPGFX_RECT16* regionRect;
RECTANGLE_16* regionRect;
RDPGFX_H264_QUANT_QUALITY* quantQualityVal;
UINT error = ERROR_INVALID_DATA;
@ -56,13 +57,13 @@ static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, RDPGFX_H2
Stream_Read_UINT32(s, meta->numRegionRects); /* numRegionRects (4 bytes) */
if (Stream_GetRemainingLength(s) < (meta->numRegionRects * 8))
if (Stream_GetRemainingLength(s) < (meta->numRegionRects * sizeof(RECTANGLE_16)))
{
WLog_ERR(TAG, "not enough data!");
goto error_out;
}
meta->regionRects = (RDPGFX_RECT16*) malloc(meta->numRegionRects * sizeof(RDPGFX_RECT16));
meta->regionRects = (RECTANGLE_16*) malloc(meta->numRegionRects * sizeof(RECTANGLE_16));
if (!meta->regionRects)
{
@ -128,11 +129,11 @@ error_out:
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT rdpgfx_decode_h264(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
static UINT rdpgfx_decode_AVC420(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
{
UINT error;
wStream* s;
RDPGFX_H264_BITMAP_STREAM h264;
RDPGFX_AVC420_BITMAP_STREAM h264;
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
s = Stream_New(cmd->data, cmd->length);
@ -169,6 +170,91 @@ static UINT rdpgfx_decode_h264(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
return error;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
{
UINT error;
UINT32 tmp;
size_t pos1, pos2;
wStream* s;
RDPGFX_AVC444_BITMAP_STREAM h264;
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
s = Stream_New(cmd->data, cmd->length);
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, tmp);
h264.cbAvc420EncodedBitstream1 = tmp & 0x3FFFFFFFUL;
h264.LC = (tmp >> 30UL) & 0x03UL;
if (h264.LC == 0x03)
return ERROR_INVALID_DATA;
pos1 = Stream_GetPosition(s);
if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.bitstream[0].meta))))
{
WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %lu!", error);
return error;
}
pos2 = Stream_GetPosition(s);
h264.bitstream[0].data = Stream_Pointer(s);
if (h264.LC == 0)
{
tmp = h264.cbAvc420EncodedBitstream1 - pos2 + pos1;
if (Stream_GetRemainingLength(s) < tmp)
return ERROR_INVALID_DATA;
h264.bitstream[0].length = tmp;
Stream_Seek(s, tmp);
if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.bitstream[1].meta))))
{
WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %lu!", error);
return error;
}
h264.bitstream[1].data = Stream_Pointer(s);
h264.bitstream[1].length = Stream_GetRemainingLength(s);
}
else
{
h264.bitstream[0].length = Stream_GetRemainingLength(s);
memset(&h264.bitstream[1], 0, sizeof(h264.bitstream[1]));
}
Stream_Free(s, FALSE);
cmd->extra = (void*) &h264;
if (context)
{
IFCALLRET(context->SurfaceCommand, error, context, cmd);
if (error)
WLog_ERR(TAG, "context->SurfaceCommand failed with error %lu", error);
}
free(h264.bitstream[0].meta.regionRects);
free(h264.bitstream[0].meta.quantQualityVals);
free(h264.bitstream[1].meta.regionRects);
free(h264.bitstream[1].meta.quantQualityVals);
return error;
}
/**
* Function description
*
@ -181,10 +267,18 @@ UINT rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd)
switch (cmd->codecId)
{
case RDPGFX_CODECID_H264:
if ((error = rdpgfx_decode_h264(gfx, cmd)))
case RDPGFX_CODECID_AVC420:
if ((error = rdpgfx_decode_AVC420(gfx, cmd)))
{
WLog_ERR(TAG, "rdpgfx_decode_h264 failed with error %lu", error);
WLog_ERR(TAG, "rdpgfx_decode_AVC420 failed with error %lu", error);
return error;
}
break;
case RDPGFX_CODECID_AVC444:
if ((error = rdpgfx_decode_AVC444(gfx, cmd)))
{
WLog_ERR(TAG, "rdpgfx_decode_AVC444 failed with error %lu", error);
return error;
}
break;

View File

@ -77,8 +77,10 @@ const char* rdpgfx_get_codec_id_string(UINT16 codecId)
return "RDPGFX_CODECID_CLEARCODEC";
case RDPGFX_CODECID_PLANAR:
return "RDPGFX_CODECID_PLANAR";
case RDPGFX_CODECID_H264:
return "RDPGFX_CODECID_H264";
case RDPGFX_CODECID_AVC420:
return "RDPGFX_CODECID_AVC420";
case RDPGFX_CODECID_AVC444:
return "RDPGFX_CODECID_AVC444";
case RDPGFX_CODECID_ALPHA:
return "RDPGFX_CODECID_ALPHA";
case RDPGFX_CODECID_CAPROGRESSIVE:
@ -161,7 +163,7 @@ UINT rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16)
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16)
UINT rdpgfx_read_rect16(wStream* s, RECTANGLE_16* rect16)
{
if (Stream_GetRemainingLength(s) < 8)
{
@ -182,7 +184,7 @@ UINT rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16)
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16)
UINT rdpgfx_write_rect16(wStream* s, RECTANGLE_16* rect16)
{
Stream_Write_UINT16(s, rect16->left); /* left (2 bytes) */
Stream_Write_UINT16(s, rect16->top); /* top (2 bytes) */

View File

@ -36,8 +36,8 @@ UINT rdpgfx_write_header(wStream* s, RDPGFX_HEADER* header);
UINT rdpgfx_read_point16(wStream* s, RDPGFX_POINT16* pt16);
UINT rdpgfx_write_point16(wStream* s, RDPGFX_POINT16* point16);
UINT rdpgfx_read_rect16(wStream* s, RDPGFX_RECT16* rect16);
UINT rdpgfx_write_rect16(wStream* s, RDPGFX_RECT16* rect16);
UINT rdpgfx_read_rect16(wStream* s, RECTANGLE_16* rect16);
UINT rdpgfx_write_rect16(wStream* s, RECTANGLE_16* rect16);
UINT rdpgfx_read_color32(wStream* s, RDPGFX_COLOR32* color32);
UINT rdpgfx_write_color32(wStream* s, RDPGFX_COLOR32* color32);

View File

@ -58,7 +58,7 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
RDPGFX_PLUGIN* gfx;
RDPGFX_HEADER header;
RDPGFX_CAPSET* capsSet;
RDPGFX_CAPSET capsSets[2];
RDPGFX_CAPSET capsSets[3];
RDPGFX_CAPS_ADVERTISE_PDU pdu;
gfx = (RDPGFX_PLUGIN*) callback->plugin;
@ -90,7 +90,17 @@ static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback)
capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;
if (gfx->H264)
capsSet->flags |= RDPGFX_CAPS_FLAG_H264ENABLED;
capsSet->flags |= RDPGFX_CAPS_FLAG_AVC420_ENABLED;
capsSet = &capsSets[pdu.capsSetCount++];
capsSet->version = RDPGFX_CAPVERSION_10;
capsSet->flags = 0;
if (gfx->SmallCache)
capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE;
if (!gfx->H264)
capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED;
header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount * RDPGFX_CAPSET_SIZE);
@ -688,7 +698,7 @@ static UINT rdpgfx_recv_delete_encoding_context_pdu(RDPGFX_CHANNEL_CALLBACK* cal
UINT rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
{
UINT16 index;
RDPGFX_RECT16* fillRect;
RECTANGLE_16* fillRect;
RDPGFX_SOLID_FILL_PDU pdu;
RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin;
RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface;
@ -714,7 +724,7 @@ UINT rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
return ERROR_INVALID_DATA;
}
pdu.fillRects = (RDPGFX_RECT16*) calloc(pdu.fillRectCount, sizeof(RDPGFX_RECT16));
pdu.fillRects = (RECTANGLE_16*) calloc(pdu.fillRectCount, sizeof(RECTANGLE_16));
if (!pdu.fillRects)
{
@ -742,7 +752,7 @@ UINT rdpgfx_recv_solid_fill_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s)
if (error)
WLog_ERR(TAG, "context->SolidFill failed with error %lu", error);
}
free(pdu.fillRects);
return error;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -116,39 +116,39 @@ static void* rdpsnd_schedule_thread(void* arg)
while (1)
{
status = WaitForMultipleObjects(2, events, FALSE, INFINITE);
status = WaitForMultipleObjects(2, events, FALSE, INFINITE);
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;
}
status = WaitForSingleObject(rdpsnd->stopEvent, 0);
status = WaitForSingleObject(rdpsnd->stopEvent, 0);
if (status == WAIT_FAILED)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
break;
}
if (status == WAIT_FAILED)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
break;
}
if (status == WAIT_OBJECT_0)
break;
if (status == WAIT_OBJECT_0)
break;
status = WaitForSingleObject(events[0], 0);
status = WaitForSingleObject(events[0], 0);
if (status == WAIT_FAILED)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
break;
}
if (status == WAIT_FAILED)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
break;
}
if (!MessageQueue_Peek(rdpsnd->MsgPipe->Out, &message, TRUE))
if (!MessageQueue_Peek(rdpsnd->MsgPipe->Out, &message, TRUE))
{
WLog_ERR(TAG, "MessageQueue_Peek failed!");
error = ERROR_INTERNAL_ERROR;
@ -811,6 +811,7 @@ static UINT rdpsnd_load_device_plugin(rdpsndPlugin* rdpsnd, const char* name, AD
if ((error = entry(&entryPoints)))
WLog_ERR(TAG, "%s entry returns error %lu", name, error);
WLog_INFO(TAG, "Loaded %s backend for rdpsnd", name);
return error;
}
@ -828,7 +829,7 @@ BOOL rdpsnd_set_device_name(rdpsndPlugin* rdpsnd, const char* device_name)
return (rdpsnd->device_name != NULL);
}
COMMAND_LINE_ARGUMENT_A rdpsnd_args[] =
static COMMAND_LINE_ARGUMENT_A rdpsnd_args[] =
{
{ "sys", COMMAND_LINE_VALUE_REQUIRED, "<subsystem>", NULL, NULL, -1, NULL, "subsystem" },
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "device" },
@ -1078,10 +1079,10 @@ static void rdpsnd_process_disconnect(rdpsndPlugin* rdpsnd)
{
SetEvent(rdpsnd->stopEvent);
if (WaitForSingleObject(rdpsnd->ScheduleThread, INFINITE) == WAIT_FAILED)
{
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError());
return;
}
{
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", GetLastError());
return;
}
CloseHandle(rdpsnd->ScheduleThread);
CloseHandle(rdpsnd->stopEvent);
}
@ -1386,9 +1387,9 @@ static UINT rdpsnd_virtual_channel_event_disconnected(rdpsndPlugin* rdpsnd)
MessagePipe_PostQuit(rdpsnd->MsgPipe, 0);
if (WaitForSingleObject(rdpsnd->thread, INFINITE) == WAIT_FAILED)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
return error;
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu!", error);
return error;
}
CloseHandle(rdpsnd->thread);

View File

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

View File

@ -1030,11 +1030,11 @@ static UINT remdesk_virtual_channel_event_disconnected(remdeskPlugin* remdesk)
UINT rc;
if (MessageQueue_PostQuit(remdesk->queue, 0) && (WaitForSingleObject(remdesk->thread, INFINITE) == WAIT_FAILED))
{
rc = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
return rc;
}
{
rc = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %lu", rc);
return rc;
}
MessageQueue_Free(remdesk->queue);
CloseHandle(remdesk->thread);
@ -1066,7 +1066,9 @@ static void remdesk_virtual_channel_event_terminated(remdeskPlugin* remdesk)
free(remdesk);
}
static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle, UINT event, LPVOID pData, UINT dataLength)
static VOID VCAPITYPE remdesk_virtual_channel_init_event(LPVOID pInitHandle,
UINT event, LPVOID pData,
UINT dataLength)
{
remdeskPlugin* remdesk;
UINT error = CHANNEL_RC_OK;

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -36,7 +36,7 @@ if(FREERDP_VENDOR AND WITH_CLIENT)
add_subdirectory(X11)
endif()
if(WITH_WAYLAND)
if(WITH_WAYLAND AND WAYLAND_FOUND)
add_subdirectory(Wayland)
endif()

View File

@ -177,7 +177,8 @@ BOOL df_pre_connect(freerdp* instance)
dfi->clrconv->palette = (rdpPalette*) malloc(sizeof(rdpPalette));
ZeroMemory(dfi->clrconv->palette, sizeof(rdpPalette));
freerdp_channels_pre_connect(instance->context->channels, instance);
if (freerdp_channels_pre_connect(instance->context->channels, instance) != CHANNEL_RC_OK)
return FALSE;
return (instance->context->cache = cache_new(instance->settings)) != NULL;
}
@ -235,7 +236,7 @@ BOOL df_post_connect(freerdp* instance)
pointer_cache_register_callbacks(instance->update);
df_register_graphics(instance->context->graphics);
return freerdp_channels_post_connect(instance->context->channels, instance) >= 0;
return freerdp_channels_post_connect(instance->context->channels, instance) == CHANNEL_RC_OK;
}
BOOL df_verify_certificate(freerdp* instance, char* subject, char* issuer, char* fingerprint)
@ -487,7 +488,8 @@ int main(int argc, char* argv[])
if (status < 0)
exit(0);
freerdp_client_load_addins(instance->context->channels, instance->settings);
if (!freerdp_client_load_addins(instance->context->channels, instance->settings))
exit(-1);
data = (struct thread_data*) malloc(sizeof(struct thread_data));
ZeroMemory(data, sizeof(sizeof(struct thread_data)));

View File

@ -109,7 +109,8 @@ static BOOL tf_pre_connect(freerdp* instance)
settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = TRUE;
settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = TRUE;
freerdp_channels_pre_connect(instance->context->channels, instance);
if (freerdp_channels_pre_connect(instance->context->channels, instance) != CHANNEL_RC_OK)
return FALSE;
return TRUE;
}
@ -122,7 +123,7 @@ static BOOL tf_post_connect(freerdp* instance)
instance->update->BeginPaint = tf_begin_paint;
instance->update->EndPaint = tf_end_paint;
return (freerdp_channels_post_connect(instance->context->channels, instance) >= 0);
return (freerdp_channels_post_connect(instance->context->channels, instance) == CHANNEL_RC_OK);
}
static void* tf_client_thread_proc(freerdp* instance)
@ -200,7 +201,8 @@ int main(int argc, char* argv[])
exit(0);
}
freerdp_client_load_addins(instance->context->channels, instance->settings);
if (!freerdp_client_load_addins(instance->context->channels, instance->settings))
exit (-1);
if (!(thread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)
tf_client_thread_proc, instance, 0, NULL)))

View File

@ -19,6 +19,7 @@
set(MODULE_NAME "wlfreerdp")
set(MODULE_PREFIX "FREERDP_CLIENT_WAYLAND")
include_directories(${WAYLAND_INCLUDE_DIR})
include_directories(${CMAKE_SOURCE_DIR}/uwac/include)
set(${MODULE_PREFIX}_SRCS

View File

@ -114,7 +114,7 @@ static BOOL wl_pre_connect(freerdp* instance)
{
wlfContext* context;
if (freerdp_channels_pre_connect(instance->context->channels, instance))
if (freerdp_channels_pre_connect(instance->context->channels, instance) != CHANNEL_RC_OK)
return FALSE;
context = (wlfContext*) instance->context;
@ -149,7 +149,7 @@ static BOOL wl_post_connect(freerdp* instance)
instance->update->BeginPaint = wl_begin_paint;
instance->update->EndPaint = wl_end_paint;
if (freerdp_channels_post_connect(instance->context->channels, instance) < 0)
if (freerdp_channels_post_connect(instance->context->channels, instance) != CHANNEL_RC_OK)
return FALSE;
@ -317,14 +317,15 @@ int main(int argc, char* argv[])
freerdp_context_new(instance);
status = freerdp_client_settings_parse_command_line_arguments(instance->settings, argc, argv, FALSE);
status = freerdp_client_settings_parse_command_line(instance->settings, argc, argv, FALSE);
status = freerdp_client_settings_command_line_status_print(instance->settings, status, argc, argv);
if (status)
exit(0);
freerdp_client_load_addins(instance->context->channels, instance->settings);
if (!freerdp_client_load_addins(instance->context->channels, instance->settings))
exit(-1);
wlfreerdp_run(instance);

View File

@ -1127,8 +1127,11 @@ BOOL xf_pre_connect(freerdp* instance)
PubSub_SubscribeChannelDisconnected(instance->context->pubSub,
(pChannelDisconnectedEventHandler) xf_OnChannelDisconnectedEventHandler);
freerdp_client_load_addins(channels, instance->settings);
freerdp_channels_pre_connect(channels, instance);
if (!freerdp_client_load_addins(channels, instance->settings))
return FALSE;
if (freerdp_channels_pre_connect(channels, instance) != CHANNEL_RC_OK)
return FALSE;
if (!settings->Username && !settings->CredentialsFromStdin)
{
@ -1312,7 +1315,7 @@ BOOL xf_post_connect(freerdp* instance)
if (!(xfc->clipboard = xf_clipboard_new(xfc)))
return FALSE;
if (freerdp_channels_post_connect(channels, instance) < 0)
if (freerdp_channels_post_connect(channels, instance) != CHANNEL_RC_OK)
return FALSE;
EventArgsInit(&e, "xfreerdp");

View File

@ -31,7 +31,7 @@
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics)
static UINT xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* resetGraphics)
{
int index;
UINT16 count;
@ -48,21 +48,29 @@ UINT xf_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU* r
if (!surface || !surface->outputMapped)
continue;
freerdp_client_codecs_reset(surface->codecs, FREERDP_CODEC_ALL);
if (!freerdp_client_codecs_reset(surface->codecs, FREERDP_CODEC_ALL,
surface->width, surface->height))
{
free(pSurfaceIds);
return ERROR_INTERNAL_ERROR;
}
region16_clear(&surface->invalidRegion);
}
free(pSurfaceIds);
freerdp_client_codecs_reset(xfc->codecs, FREERDP_CODEC_ALL);
if (!freerdp_client_codecs_reset(xfc->codecs, FREERDP_CODEC_ALL,
xfc->settings->DesktopWidth,
xfc->settings->DesktopHeight))
return ERROR_INTERNAL_ERROR;
xfc->graphicsReset = TRUE;
return CHANNEL_RC_OK;
}
int xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface)
static int xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface)
{
UINT16 width, height;
UINT32 surfaceX, surfaceY;
@ -124,7 +132,7 @@ int xf_OutputUpdate(xfContext* xfc, xfGfxSurface* surface)
return 1;
}
int xf_UpdateSurfaces(xfContext* xfc)
static int xf_UpdateSurfaces(xfContext* xfc)
{
UINT16 count;
int index;
@ -212,7 +220,7 @@ int xf_OutputExpose(xfContext* xfc, int x, int y, int width, int height)
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_StartFrame(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFrame)
static UINT xf_StartFrame(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFrame)
{
xfContext* xfc = (xfContext*) context->custom;
@ -226,7 +234,7 @@ UINT xf_StartFrame(RdpgfxClientContext* context, RDPGFX_START_FRAME_PDU* startFr
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame)
static UINT xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame)
{
xfContext* xfc = (xfContext*) context->custom;
@ -242,7 +250,7 @@ UINT xf_EndFrame(RdpgfxClientContext* context, RDPGFX_END_FRAME_PDU* endFrame)
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
static UINT xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
xfGfxSurface* surface;
RECTANGLE_16 invalidRect;
@ -273,7 +281,7 @@ UINT xf_SurfaceCommand_Uncompressed(xfContext* xfc, RdpgfxClientContext* context
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
static UINT xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
int j;
UINT16 i;
@ -363,7 +371,7 @@ UINT xf_SurfaceCommand_RemoteFX(xfContext* xfc, RdpgfxClientContext* context, RD
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
static UINT xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
int status;
BYTE* DstData = NULL;
@ -407,7 +415,7 @@ UINT xf_SurfaceCommand_ClearCodec(xfContext* xfc, RdpgfxClientContext* context,
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
static UINT xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
int status;
BYTE* DstData = NULL;
@ -445,45 +453,46 @@ UINT xf_SurfaceCommand_Planar(xfContext* xfc, RdpgfxClientContext* context, RDPG
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_SurfaceCommand_H264(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
static UINT xf_SurfaceCommand_AVC420(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
int status;
UINT32 i;
BYTE* DstData = NULL;
xfGfxSurface* surface;
RDPGFX_H264_METABLOCK* meta;
RDPGFX_H264_BITMAP_STREAM* bs;
RDPGFX_AVC420_BITMAP_STREAM* bs;
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
if (!surface)
return ERROR_INTERNAL_ERROR;
if (!freerdp_client_codecs_prepare(surface->codecs, FREERDP_CODEC_H264))
if (!freerdp_client_codecs_prepare(surface->codecs, FREERDP_CODEC_AVC420))
return ERROR_INTERNAL_ERROR;
bs = (RDPGFX_H264_BITMAP_STREAM*) cmd->extra;
bs = (RDPGFX_AVC420_BITMAP_STREAM*) cmd->extra;
if (!bs)
return ERROR_INTERNAL_ERROR;
meta = &(bs->meta);
DstData = surface->data;
status = h264_decompress(surface->codecs->h264, bs->data, bs->length, &DstData,
surface->format, surface->scanline , surface->width,
surface->height, meta->regionRects, meta->numRegionRects);
status = avc420_decompress(surface->codecs->h264, bs->data, bs->length,
surface->data, surface->format,
surface->scanline , surface->width,
surface->height, meta->regionRects,
meta->numRegionRects);
if (status < 0)
{
WLog_WARN(TAG, "h264_decompress failure: %d, ignoring update.", status);
WLog_WARN(TAG, "avc420_decompress failure: %d, ignoring update.", status);
return CHANNEL_RC_OK;
}
for (i = 0; i < meta->numRegionRects; i++)
{
region16_union_rect(&surface->invalidRegion, &surface->invalidRegion, (RECTANGLE_16*) &(meta->regionRects[i]));
region16_union_rect(&surface->invalidRegion,
&surface->invalidRegion,
&(meta->regionRects[i]));
}
if (!xfc->inGfxFrame)
@ -497,7 +506,77 @@ UINT xf_SurfaceCommand_H264(xfContext* xfc, RdpgfxClientContext* context, RDPGFX
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_SurfaceCommand_Alpha(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
static UINT xf_SurfaceCommand_AVC444(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
int status;
UINT32 i;
xfGfxSurface* surface;
RDPGFX_AVC444_BITMAP_STREAM* bs;
RDPGFX_AVC420_BITMAP_STREAM* avc1;
RDPGFX_AVC420_BITMAP_STREAM* avc2;
RDPGFX_H264_METABLOCK* meta1;
RDPGFX_H264_METABLOCK* meta2;
RECTANGLE_16* regionRects = NULL;
surface = (xfGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
if (!surface)
return ERROR_INTERNAL_ERROR;
if (!freerdp_client_codecs_prepare(surface->codecs, FREERDP_CODEC_AVC444))
return ERROR_INTERNAL_ERROR;
bs = (RDPGFX_AVC444_BITMAP_STREAM*) cmd->extra;
if (!bs)
return ERROR_INTERNAL_ERROR;
avc1 = &bs->bitstream[0];
avc2 = &bs->bitstream[1];
meta1 = &avc1->meta;
meta2 = &avc2->meta;
status = avc444_decompress(surface->codecs->h264, bs->LC,
meta1->regionRects, meta1->numRegionRects,
avc1->data, avc1->length,
meta2->regionRects, meta2->numRegionRects,
avc2->data, avc2->length, surface->data,
surface->format, surface->scanline,
surface->width, surface->height);
if (status < 0)
{
WLog_WARN(TAG, "avc444_decompress failure: %d, ignoring update.", status);
return CHANNEL_RC_OK;
}
for (i = 0; i < meta1->numRegionRects; i++)
{
region16_union_rect(&surface->invalidRegion,
&surface->invalidRegion,
&(meta1->regionRects[i]));
}
for (i = 0; i < meta2->numRegionRects; i++)
{
region16_union_rect(&surface->invalidRegion,
&surface->invalidRegion,
&(meta2->regionRects[i]));
}
if (!xfc->inGfxFrame)
xf_UpdateSurfaces(xfc);
free (regionRects);
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT xf_SurfaceCommand_Alpha(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
int status = 0;
xfGfxSurface* surface;
@ -535,7 +614,7 @@ UINT xf_SurfaceCommand_Alpha(xfContext* xfc, RdpgfxClientContext* context, RDPGF
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
static UINT xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
int i, j;
int status;
@ -637,7 +716,7 @@ UINT xf_SurfaceCommand_Progressive(xfContext* xfc, RdpgfxClientContext* context,
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
static UINT xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
UINT status = CHANNEL_RC_OK;
xfContext* xfc = (xfContext*) context->custom;
@ -660,8 +739,12 @@ UINT xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd
status = xf_SurfaceCommand_Planar(xfc, context, cmd);
break;
case RDPGFX_CODECID_H264:
status = xf_SurfaceCommand_H264(xfc, context, cmd);
case RDPGFX_CODECID_AVC420:
status = xf_SurfaceCommand_AVC420(xfc, context, cmd);
break;
case RDPGFX_CODECID_AVC444:
status = xf_SurfaceCommand_AVC444(xfc, context, cmd);
break;
case RDPGFX_CODECID_ALPHA:
@ -673,6 +756,11 @@ UINT xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd
break;
case RDPGFX_CODECID_CAPROGRESSIVE_V2:
WLog_WARN(TAG, "SurfaceCommand %08X not implemented", cmd->codecId);
break;
default:
WLog_WARN(TAG, "Invalid SurfaceCommand %08X", cmd->codecId);
break;
}
@ -684,7 +772,7 @@ UINT xf_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext)
static UINT xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODING_CONTEXT_PDU* deleteEncodingContext)
{
return CHANNEL_RC_OK;
}
@ -694,7 +782,7 @@ UINT xf_DeleteEncodingContext(RdpgfxClientContext* context, RDPGFX_DELETE_ENCODI
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface)
static UINT xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* createSurface)
{
size_t size;
UINT32 bytesPerPixel;
@ -714,6 +802,13 @@ UINT xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* c
return CHANNEL_RC_NO_MEMORY;
}
if (!freerdp_client_codecs_reset(surface->codecs, FREERDP_CODEC_ALL,
createSurface->width, createSurface->height))
{
free (surface);
return ERROR_INTERNAL_ERROR;
}
surface->surfaceId = createSurface->surfaceId;
surface->width = (UINT32) createSurface->width;
surface->height = (UINT32) createSurface->height;
@ -775,7 +870,7 @@ UINT xf_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU* c
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface)
static UINT xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* deleteSurface)
{
rdpCodecs* codecs = NULL;
xfGfxSurface* surface = NULL;
@ -807,13 +902,13 @@ UINT xf_DeleteSurface(RdpgfxClientContext* context, RDPGFX_DELETE_SURFACE_PDU* d
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill)
static UINT xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill)
{
UINT16 index;
UINT32 color;
BYTE a, r, g, b;
int nWidth, nHeight;
RDPGFX_RECT16* rect;
RECTANGLE_16* rect;
xfGfxSurface* surface;
RECTANGLE_16 invalidRect;
xfContext* xfc = (xfContext*) context->custom;
@ -859,12 +954,12 @@ UINT xf_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFill
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface)
static UINT xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE_PDU* surfaceToSurface)
{
UINT16 index;
BOOL sameSurface;
int nWidth, nHeight;
RDPGFX_RECT16* rectSrc;
RECTANGLE_16* rectSrc;
RDPGFX_POINT16* destPt;
RECTANGLE_16 invalidRect;
xfGfxSurface* surfaceSrc;
@ -924,10 +1019,10 @@ UINT xf_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFACE
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache)
static UINT xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache)
{
size_t size;
RDPGFX_RECT16* rect;
RECTANGLE_16* rect;
xfGfxSurface* surface;
xfGfxCacheEntry* cacheEntry;
xfContext* xfc = (xfContext*) context->custom;
@ -977,7 +1072,7 @@ UINT xf_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface)
static UINT xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU* cacheToSurface)
{
UINT16 index;
RDPGFX_POINT16* destPt;
@ -1019,7 +1114,7 @@ UINT xf_CacheToSurface(RdpgfxClientContext* context, RDPGFX_CACHE_TO_SURFACE_PDU
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_CacheImportReply(RdpgfxClientContext* context, RDPGFX_CACHE_IMPORT_REPLY_PDU* cacheImportReply)
static UINT xf_CacheImportReply(RdpgfxClientContext* context, RDPGFX_CACHE_IMPORT_REPLY_PDU* cacheImportReply)
{
return CHANNEL_RC_OK;
}
@ -1029,7 +1124,7 @@ UINT xf_CacheImportReply(RdpgfxClientContext* context, RDPGFX_CACHE_IMPORT_REPLY
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_EvictCacheEntry(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry)
static UINT xf_EvictCacheEntry(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_PDU* evictCacheEntry)
{
xfGfxCacheEntry* cacheEntry;
@ -1051,7 +1146,7 @@ UINT xf_EvictCacheEntry(RdpgfxClientContext* context, RDPGFX_EVICT_CACHE_ENTRY_P
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_MapSurfaceToOutput(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput)
static UINT xf_MapSurfaceToOutput(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_OUTPUT_PDU* surfaceToOutput)
{
xfGfxSurface* surface;
@ -1074,7 +1169,7 @@ UINT xf_MapSurfaceToOutput(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_O
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT xf_MapSurfaceToWindow(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow)
static UINT xf_MapSurfaceToWindow(RdpgfxClientContext* context, RDPGFX_MAP_SURFACE_TO_WINDOW_PDU* surfaceToWindow)
{
return CHANNEL_RC_OK;
}

View File

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

View File

@ -195,17 +195,6 @@ int freerdp_client_settings_parse_command_line(rdpSettings* settings, int argc,
status = freerdp_client_settings_parse_command_line_arguments(settings, argc, argv, allowUnknown);
if (settings->ConnectionFile)
{
status = freerdp_client_settings_parse_connection_file(settings, settings->ConnectionFile);
}
if (settings->AssistanceFile)
{
status = freerdp_client_settings_parse_assistance_file(settings, settings->AssistanceFile);
}
/* Only call post processing if no status/error was returned*/
if (status < 0)
return status;

View File

@ -321,6 +321,9 @@ static int freerdp_client_command_line_pre_filter(void* context, int index, int
if (!(settings->ConnectionFile = _strdup(argv[index])))
return COMMAND_LINE_ERROR_MEMORY;
if (freerdp_client_settings_parse_connection_file(settings, settings->ConnectionFile))
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
return 1;
}
}
@ -333,6 +336,9 @@ static int freerdp_client_command_line_pre_filter(void* context, int index, int
if (!(settings->AssistanceFile = _strdup(argv[index])))
return COMMAND_LINE_ERROR_MEMORY;
if (freerdp_client_settings_parse_assistance_file(settings, settings->AssistanceFile) < 0)
return COMMAND_LINE_ERROR_UNEXPECTED_VALUE;
return 1;
}
}
@ -1474,6 +1480,9 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
CommandLineSwitchCase(arg, "v")
{
free (settings->ServerHostname);
settings->ServerHostname = NULL;
p = strchr(arg->Value, '[');
/* ipv4 */
if (!p)
@ -1515,6 +1524,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
CommandLineSwitchCase(arg, "spn-class")
{
free (settings->AuthenticationServiceClass);
if (!(settings->AuthenticationServiceClass = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
@ -1531,6 +1541,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
{
settings->SendPreconnectionPdu = TRUE;
free (settings->PreconnectionBlob);
if (!(settings->PreconnectionBlob = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
@ -1622,6 +1633,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
CommandLineSwitchCase(arg, "t")
{
free (settings->WindowTitle);
if (!(settings->WindowTitle = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
@ -1663,11 +1675,13 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
{
settings->ConsoleSession = TRUE;
settings->RestrictedAdminModeRequired = TRUE;
free (settings->PasswordHash);
if (!(settings->PasswordHash = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
CommandLineSwitchCase(arg, "client-hostname")
{
free (settings->ClientHostname);
if (!(settings->ClientHostname = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
@ -1715,16 +1729,19 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
CommandLineSwitchCase(arg, "d")
{
free (settings->Domain);
if (!(settings->Domain = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
CommandLineSwitchCase(arg, "p")
{
free (settings->Password);
if (!(settings->Password = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
CommandLineSwitchCase(arg, "g")
{
free (settings->GatewayHostname);
if (arg->Flags & COMMAND_LINE_VALUE_PRESENT)
{
p = strchr(arg->Value, ':');
@ -1764,12 +1781,14 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
CommandLineSwitchCase(arg, "gd")
{
free (settings->GatewayDomain);
if (!(settings->GatewayDomain = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
settings->GatewayUseSameCredentials = FALSE;
}
CommandLineSwitchCase(arg, "gp")
{
free (settings->GatewayPassword);
if (!(settings->GatewayPassword = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
settings->GatewayUseSameCredentials = FALSE;
@ -1815,6 +1834,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
CommandLineSwitchCase(arg, "app")
{
free (settings->RemoteApplicationProgram);
if (!(settings->RemoteApplicationProgram = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
@ -1826,33 +1846,39 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
CommandLineSwitchCase(arg, "load-balance-info")
{
free (settings->LoadBalanceInfo);
if (!(settings->LoadBalanceInfo = (BYTE*) _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
settings->LoadBalanceInfoLength = (UINT32) strlen((char*) settings->LoadBalanceInfo);
}
CommandLineSwitchCase(arg, "app-name")
{
free (settings->RemoteApplicationName);
if (!(settings->RemoteApplicationName = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
CommandLineSwitchCase(arg, "app-icon")
{
free (settings->RemoteApplicationIcon);
if (!(settings->RemoteApplicationIcon = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
CommandLineSwitchCase(arg, "app-cmd")
{
free (settings->RemoteApplicationCmdLine);
if (!(settings->RemoteApplicationCmdLine = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
CommandLineSwitchCase(arg, "app-file")
{
free (settings->RemoteApplicationFile);
if (!(settings->RemoteApplicationFile = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
CommandLineSwitchCase(arg, "app-guid")
{
free (settings->RemoteApplicationGuid);
if (!(settings->RemoteApplicationGuid = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
@ -1878,11 +1904,13 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
CommandLineSwitchCase(arg, "shell")
{
free (settings->AlternateShell);
if (!(settings->AlternateShell = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
CommandLineSwitchCase(arg, "shell-dir")
{
free (settings->ShellWorkingDirectory);
if (!(settings->ShellWorkingDirectory = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
@ -2037,6 +2065,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
CommandLineSwitchCase(arg, "pcb")
{
settings->SendPreconnectionPdu = TRUE;
free (settings->PreconnectionBlob);
if (!(settings->PreconnectionBlob = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
@ -2141,6 +2170,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
CommandLineSwitchCase(arg, "tls-ciphers")
{
free (settings->AllowedTlsCiphers);
if (strcmp(arg->Value, "netmon") == 0)
{
if (!(settings->AllowedTlsCiphers = _strdup("ALL:!ECDH")))
@ -2159,6 +2189,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
CommandLineSwitchCase(arg, "cert-name")
{
free (settings->CertificateName);
if (!(settings->CertificateName = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
@ -2253,11 +2284,13 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
CommandLineSwitchCase(arg, "wm-class")
{
free (settings->WmClass);
if (!(settings->WmClass = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
CommandLineSwitchCase(arg, "play-rfx")
{
free (settings->PlayRemoteFxFile);
if (!(settings->PlayRemoteFxFile = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
settings->PlayRemoteFx = TRUE;
@ -2293,6 +2326,7 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
CommandLineSwitchCase(arg, "assistance")
{
settings->RemoteAssistanceMode = TRUE;
free (settings->RemoteAssistancePassword);
if (!(settings->RemoteAssistancePassword = _strdup(arg->Value)))
return COMMAND_LINE_ERROR_MEMORY;
}
@ -2353,9 +2387,12 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
}
while ((arg = CommandLineFindNextArgumentA(arg)) != NULL);
free (settings->Username);
if (!settings->Domain && user)
{
BOOL ret;
free (settings->Domain);
ret = freerdp_parse_username(user, &settings->Username, &settings->Domain);
free(user);
if (!ret)
@ -2364,9 +2401,11 @@ int freerdp_client_settings_parse_command_line_arguments(rdpSettings* settings,
else
settings->Username = user;
free (settings->GatewayUsername);
if (!settings->GatewayDomain && gwUser)
{
BOOL ret;
free (settings->GatewayDomain);
ret = freerdp_parse_username(gwUser, &settings->GatewayUsername,
&settings->GatewayDomain);
free(gwUser);

View File

@ -38,9 +38,9 @@ FREERDP_API int freerdp_channels_client_load(rdpChannels* channels, rdpSettings*
PVIRTUALCHANNELENTRY entry, void* data);
FREERDP_API int freerdp_channels_load_plugin(rdpChannels* channels, rdpSettings* settings,
const char* name, void* data);
FREERDP_API int freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance);
FREERDP_API int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance);
FREERDP_API int freerdp_channels_disconnect(rdpChannels* channels, freerdp* instance);
FREERDP_API UINT freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance);
FREERDP_API UINT freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance);
FREERDP_API UINT freerdp_channels_disconnect(rdpChannels* channels, freerdp* instance);
FREERDP_API BOOL freerdp_channels_get_fds(rdpChannels* channels, freerdp* instance, void** read_fds,
int* read_count, void** write_fds, int* write_count);
FREERDP_API BOOL freerdp_channels_check_fds(rdpChannels* channels, freerdp* instance);

View File

@ -37,15 +37,6 @@ struct _RDPGFX_POINT16
};
typedef struct _RDPGFX_POINT16 RDPGFX_POINT16;
struct _RDPGFX_RECT16
{
UINT16 left;
UINT16 top;
UINT16 right;
UINT16 bottom;
};
typedef struct _RDPGFX_RECT16 RDPGFX_RECT16;
struct _RDPGFX_COLOR32
{
BYTE B;
@ -99,6 +90,7 @@ typedef struct _RDPGFX_HEADER RDPGFX_HEADER;
#define RDPGFX_CAPVERSION_8 0x00080004
#define RDPGFX_CAPVERSION_81 0x00080105
#define RDPGFX_CAPVERSION_10 0x000A0002
#define RDPGFX_CAPSET_SIZE 12
@ -111,7 +103,8 @@ typedef struct _RDPGFX_CAPSET RDPGFX_CAPSET;
#define RDPGFX_CAPS_FLAG_THINCLIENT 0x00000001 /* 8.0+ */
#define RDPGFX_CAPS_FLAG_SMALL_CACHE 0x00000002 /* 8.0+ */
#define RDPGFX_CAPS_FLAG_H264ENABLED 0x00000010 /* 8.1+ */
#define RDPGFX_CAPS_FLAG_AVC420_ENABLED 0x00000010 /* 8.1+ */
#define RDPGFX_CAPS_FLAG_AVC_DISABLED 0x00000020 /* 10.0+ */
struct _RDPGFX_CAPSET_VERSION8
{
@ -129,6 +122,14 @@ struct _RDPGFX_CAPSET_VERSION81
};
typedef struct _RDPGFX_CAPSET_VERSION81 RDPGFX_CAPSET_VERSION81;
struct _RDPGFX_CAPSET_VERSION10
{
UINT32 version;
UINT32 capsDataLength;
UINT32 flags;
};
typedef struct _RDPGFX_CAPSET_VERSION10 RDPGFX_CAPSET_VERSION10;
/**
* Graphics Messages
*/
@ -137,15 +138,16 @@ typedef struct _RDPGFX_CAPSET_VERSION81 RDPGFX_CAPSET_VERSION81;
#define RDPGFX_CODECID_CAVIDEO 0x0003
#define RDPGFX_CODECID_CLEARCODEC 0x0008
#define RDPGFX_CODECID_PLANAR 0x000A
#define RDPGFX_CODECID_H264 0x000B
#define RDPGFX_CODECID_AVC420 0x000B
#define RDPGFX_CODECID_ALPHA 0x000C
#define RDPGFX_CODECID_AVC444 0x000E
struct _RDPGFX_WIRE_TO_SURFACE_PDU_1
{
UINT16 surfaceId;
UINT16 codecId;
RDPGFX_PIXELFORMAT pixelFormat;
RDPGFX_RECT16 destRect;
RECTANGLE_16 destRect;
UINT32 bitmapDataLength;
BYTE* bitmapData;
};
@ -195,7 +197,7 @@ struct _RDPGFX_SOLID_FILL_PDU
UINT16 surfaceId;
RDPGFX_COLOR32 fillPixel;
UINT16 fillRectCount;
RDPGFX_RECT16* fillRects;
RECTANGLE_16* fillRects;
};
typedef struct _RDPGFX_SOLID_FILL_PDU RDPGFX_SOLID_FILL_PDU;
@ -203,7 +205,7 @@ struct _RDPGFX_SURFACE_TO_SURFACE_PDU
{
UINT16 surfaceIdSrc;
UINT16 surfaceIdDest;
RDPGFX_RECT16 rectSrc;
RECTANGLE_16 rectSrc;
UINT16 destPtsCount;
RDPGFX_POINT16* destPts;
};
@ -214,7 +216,7 @@ struct _RDPGFX_SURFACE_TO_CACHE_PDU
UINT16 surfaceId;
UINT64 cacheKey;
UINT16 cacheSlot;
RDPGFX_RECT16 rectSrc;
RECTANGLE_16 rectSrc;
};
typedef struct _RDPGFX_SURFACE_TO_CACHE_PDU RDPGFX_SURFACE_TO_CACHE_PDU;
@ -349,18 +351,27 @@ typedef struct _RDPGFX_H264_QUANT_QUALITY RDPGFX_H264_QUANT_QUALITY;
struct _RDPGFX_H264_METABLOCK
{
UINT32 numRegionRects;
RDPGFX_RECT16* regionRects;
RECTANGLE_16* regionRects;
RDPGFX_H264_QUANT_QUALITY* quantQualityVals;
};
typedef struct _RDPGFX_H264_METABLOCK RDPGFX_H264_METABLOCK;
struct _RDPGFX_H264_BITMAP_STREAM
struct _RDPGFX_AVC420_BITMAP_STREAM
{
RDPGFX_H264_METABLOCK meta;
UINT32 length;
BYTE* data;
};
typedef struct _RDPGFX_H264_BITMAP_STREAM RDPGFX_H264_BITMAP_STREAM;
typedef struct _RDPGFX_AVC420_BITMAP_STREAM RDPGFX_AVC420_BITMAP_STREAM;
struct _RDPGFX_AVC444_BITMAP_STREAM
{
UINT32 cbAvc420EncodedBitstream1;
BYTE LC;
RDPGFX_AVC420_BITMAP_STREAM bitstream[2];
};
typedef struct _RDPGFX_AVC444_BITMAP_STREAM RDPGFX_AVC444_BITMAP_STREAM;
#endif /* FREERDP_CHANNEL_RDPGFX_H */

View File

@ -71,7 +71,7 @@ FREERDP_API int clear_compress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcS
FREERDP_API int clear_decompress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize,
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nXDst, int nYDst, int nWidth, int nHeight);
FREERDP_API int clear_context_reset(CLEAR_CONTEXT* clear);
FREERDP_API BOOL clear_context_reset(CLEAR_CONTEXT* clear);
FREERDP_API CLEAR_CONTEXT* clear_context_new(BOOL Compressor);
FREERDP_API void clear_context_free(CLEAR_CONTEXT* clear);
@ -81,4 +81,4 @@ FREERDP_API void clear_context_free(CLEAR_CONTEXT* clear);
#endif
#endif /* FREERDP_CODEC_CLEAR_H */

View File

@ -29,8 +29,10 @@ typedef struct _H264_CONTEXT H264_CONTEXT;
typedef BOOL (*pfnH264SubsystemInit)(H264_CONTEXT* h264);
typedef void (*pfnH264SubsystemUninit)(H264_CONTEXT* h264);
typedef int (*pfnH264SubsystemDecompress)(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize);
typedef int (*pfnH264SubsystemCompress)(H264_CONTEXT* h264, BYTE** ppDstData, UINT32* pDstSize);
typedef int (*pfnH264SubsystemDecompress)(H264_CONTEXT* h264, BYTE* pSrcData,
UINT32 SrcSize, UINT32 plane);
typedef int (*pfnH264SubsystemCompress)(H264_CONTEXT* h264, BYTE** ppDstData,
UINT32* pDstSize, UINT32 plane);
struct _H264_CONTEXT_SUBSYSTEM
{
@ -61,10 +63,15 @@ struct _H264_CONTEXT
FLOAT FrameRate;
UINT32 QP;
UINT32 NumberOfThreads;
int iStride[3];
BYTE* pYUVData[3];
UINT32 iStride[2][3];
BYTE* pYUVData[2][3];
UINT32 iYUV444Size[3];
UINT32 iYUV444Stride[3];
BYTE* pYUV444Data[3];
UINT32 numSystemData;
void* pSystemData;
H264_CONTEXT_SUBSYSTEM* subsystem;
};
@ -73,14 +80,32 @@ struct _H264_CONTEXT
extern "C" {
#endif
FREERDP_API int h264_compress(H264_CONTEXT* h264, BYTE* pSrcData, DWORD SrcFormat,
int nSrcStep, int nSrcWidth, int nSrcHeight, BYTE** ppDstData, UINT32* pDstSize);
FREERDP_API INT32 avc420_compress(H264_CONTEXT* h264, BYTE* pSrcData,
DWORD SrcFormat, UINT32 nSrcStep,
UINT32 nSrcWidth, UINT32 nSrcHeight,
BYTE** ppDstData, UINT32* pDstSize);
FREERDP_API int h264_decompress(H264_CONTEXT* h264, BYTE* pSrcData, UINT32 SrcSize,
BYTE** ppDstData, DWORD DstFormat, int nDstStep, int nDstWidth, int nDstHeight,
RDPGFX_RECT16* regionRects, int numRegionRect);
FREERDP_API INT32 avc420_decompress(H264_CONTEXT* h264, BYTE* pSrcData,
UINT32 SrcSize, BYTE* pDstData,
DWORD DstFormat, UINT32 nDstStep,
UINT32 nDstWidth, UINT32 nDstHeight,
RECTANGLE_16* regionRects, UINT32 numRegionRect);
FREERDP_API int h264_context_reset(H264_CONTEXT* h264);
FREERDP_API INT32 avc444_compress(H264_CONTEXT* h264, BYTE* pSrcData, DWORD SrcFormat,
UINT32 nSrcStep, UINT32 nSrcWidth, UINT32 nSrcHeight,
BYTE* op,
BYTE** pDstData, UINT32* pDstSize,
BYTE** pAuxDstData, UINT32* pAuxDstSize);
FREERDP_API INT32 avc444_decompress(H264_CONTEXT* h264, BYTE op,
RECTANGLE_16* regionRects, UINT32 numRegionRect,
BYTE* pSrcData, UINT32 SrcSize,
RECTANGLE_16* auxRegionRects, UINT32 numAuxRegionRect,
BYTE* pAuxSrcData, UINT32 AuxSrcSize,
BYTE* pDstData, DWORD DstFormat,
UINT32 nDstStep, UINT32 nDstWidth, UINT32 nDstHeight);
FREERDP_API BOOL h264_context_reset(H264_CONTEXT* h264, UINT32 width, UINT32 height);
FREERDP_API H264_CONTEXT* h264_context_new(BOOL Compressor);
FREERDP_API void h264_context_free(H264_CONTEXT* h264);

View File

@ -48,7 +48,7 @@ FREERDP_API int interleaved_decompress(BITMAP_INTERLEAVED_CONTEXT* interleaved,
FREERDP_API int interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pDstData, UINT32* pDstSize,
int nWidth, int nHeight, BYTE* pSrcData, DWORD SrcFormat, int nSrcStep, int nXSrc, int nYSrc, BYTE* palette, int bpp);
FREERDP_API int bitmap_interleaved_context_reset(BITMAP_INTERLEAVED_CONTEXT* interleaved);
FREERDP_API BOOL bitmap_interleaved_context_reset(BITMAP_INTERLEAVED_CONTEXT* interleaved);
FREERDP_API BITMAP_INTERLEAVED_CONTEXT* bitmap_interleaved_context_new(BOOL Compressor);
FREERDP_API void bitmap_interleaved_context_free(BITMAP_INTERLEAVED_CONTEXT* interleaved);

View File

@ -93,7 +93,7 @@ FREERDP_API NSC_MESSAGE* nsc_encode_messages(NSC_CONTEXT* context, BYTE* data, i
FREERDP_API int nsc_write_message(NSC_CONTEXT* context, wStream* s, NSC_MESSAGE* message);
FREERDP_API int nsc_message_free(NSC_CONTEXT* context, NSC_MESSAGE* message);
FREERDP_API int nsc_context_reset(NSC_CONTEXT* context);
FREERDP_API BOOL nsc_context_reset(NSC_CONTEXT* context, UINT32 width, UINT32 height);
FREERDP_API NSC_CONTEXT* nsc_context_new(void);
FREERDP_API void nsc_context_free(NSC_CONTEXT* context);

View File

@ -109,7 +109,7 @@ FREERDP_API BOOL freerdp_bitmap_planar_delta_encode_planes(BYTE* inPlanes[4], in
FREERDP_API BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data, UINT32 format,
int width, int height, int scanline, BYTE* dstData, int* pDstSize);
FREERDP_API int freerdp_bitmap_planar_context_reset(BITMAP_PLANAR_CONTEXT* context);
FREERDP_API BOOL freerdp_bitmap_planar_context_reset(BITMAP_PLANAR_CONTEXT* context);
FREERDP_API BITMAP_PLANAR_CONTEXT* freerdp_bitmap_planar_context_new(DWORD flags, int maxWidth, int maxHeight);
FREERDP_API void freerdp_bitmap_planar_context_free(BITMAP_PLANAR_CONTEXT* context);

View File

@ -242,7 +242,7 @@ FREERDP_API int progressive_decompress(PROGRESSIVE_CONTEXT* progressive, BYTE* p
FREERDP_API int progressive_create_surface_context(PROGRESSIVE_CONTEXT* progressive, UINT16 surfaceId, UINT32 width, UINT32 height);
FREERDP_API int progressive_delete_surface_context(PROGRESSIVE_CONTEXT* progressive, UINT16 surfaceId);
FREERDP_API int progressive_context_reset(PROGRESSIVE_CONTEXT* progressive);
FREERDP_API BOOL progressive_context_reset(PROGRESSIVE_CONTEXT* progressive);
FREERDP_API PROGRESSIVE_CONTEXT* progressive_context_new(BOOL Compressor);
FREERDP_API void progressive_context_free(PROGRESSIVE_CONTEXT* progressive);
@ -252,4 +252,4 @@ FREERDP_API void progressive_context_free(PROGRESSIVE_CONTEXT* progressive);
#endif
#endif /* FREERDP_CODEC_PROGRESSIVE_H */

View File

@ -183,7 +183,7 @@ FREERDP_API RFX_MESSAGE* rfx_encode_messages(RFX_CONTEXT* context, const RFX_REC
BYTE* data, int width, int height, int scanline, int* numMessages, int maxDataSize);
FREERDP_API BOOL rfx_write_message(RFX_CONTEXT* context, wStream* s, RFX_MESSAGE* message);
FREERDP_API void rfx_context_reset(RFX_CONTEXT* context);
FREERDP_API BOOL rfx_context_reset(RFX_CONTEXT* context, UINT32 width, UINT32 height);
FREERDP_API RFX_CONTEXT* rfx_context_new(BOOL encoder);
FREERDP_API void rfx_context_free(RFX_CONTEXT* context);

View File

@ -39,7 +39,8 @@
#define FREERDP_CODEC_CLEARCODEC 0x00000010
#define FREERDP_CODEC_ALPHACODEC 0x00000020
#define FREERDP_CODEC_PROGRESSIVE 0x00000040
#define FREERDP_CODEC_H264 0x00000080
#define FREERDP_CODEC_AVC420 0x00000080
#define FREERDP_CODEC_AVC444 0x00000100
#define FREERDP_CODEC_ALL 0xFFFFFFFF
struct rdp_codecs
@ -60,7 +61,8 @@ struct rdp_codecs
#endif
FREERDP_API BOOL freerdp_client_codecs_prepare(rdpCodecs* codecs, UINT32 flags);
FREERDP_API BOOL freerdp_client_codecs_reset(rdpCodecs* codecs, UINT32 flags);
FREERDP_API BOOL freerdp_client_codecs_reset(rdpCodecs* codecs, UINT32 flags,
UINT32 width, UINT32 height);
FREERDP_API rdpCodecs* codecs_new(rdpContext* context);
FREERDP_API void codecs_free(rdpCodecs* codecs);

View File

@ -58,8 +58,8 @@ typedef INT32 pstatus_t; /* match IppStatus. */
/* Structures compatible with IPP */
typedef struct
{
INT32 width;
INT32 height;
UINT32 width;
UINT32 height;
} prim_size_t; /* like IppiSize */
/* Function prototypes for all of the supported primitives. */
@ -74,7 +74,7 @@ typedef pstatus_t (*__copy_8u_t)(
typedef pstatus_t (*__copy_8u_AC4r_t)(
const BYTE *pSrc,
INT32 srcStep, /* bytes */
BYTE *pDst,
BYTE *pDst,
INT32 dstStep, /* bytes */
INT32 width, INT32 height); /* pixels */
typedef pstatus_t (*__set_8u_t)(
@ -169,13 +169,31 @@ typedef pstatus_t (*__RGB565ToARGB_16u32u_C3C4_t)(
UINT32 width, UINT32 height,
BOOL alpha, BOOL invert);
typedef pstatus_t (*__YUV420ToRGB_8u_P3AC4R_t)(
const BYTE* pSrc[3], INT32 srcStep[3],
BYTE* pDst, INT32 dstStep,
const BYTE* pSrc[3], const UINT32 srcStep[3],
BYTE* pDst, UINT32 dstStep,
const prim_size_t* roi);
typedef pstatus_t (*__YUV444ToRGB_8u_P3AC4R_t)(
const BYTE* pSrc[3], const UINT32 srcStep[3],
BYTE* pDst, UINT32 dstStep,
const prim_size_t* roi);
typedef pstatus_t (*__RGBToYUV420_8u_P3AC4R_t)(
const BYTE* pSrc, INT32 srcStep,
BYTE* pDst[3], INT32 dstStep[3],
const BYTE* pSrc, UINT32 srcStep,
BYTE* pDst[3], UINT32 dstStep[3],
const prim_size_t* roi);
typedef pstatus_t (*__RGBToYUV444_8u_P3AC4R_t)(
const BYTE* pSrc, UINT32 srcStep,
BYTE* pDst[3], UINT32 dstStep[3],
const prim_size_t* roi);
typedef pstatus_t (*__YUV420CombineToYUV444_t)(
const BYTE* pMainSrc[3], const UINT32 srcMainStep[3],
const BYTE* pAuxSrc[3], const UINT32 srcAuxStep[3],
BYTE* pDst[3], const UINT32 dstStep[3],
const prim_size_t* roi);
typedef pstatus_t (*__YUV444SplitToYUV420_t)(
const BYTE* pSrc[3], const UINT32 srcStep[3],
BYTE* pMainDst[3], const UINT32 dstMainStep[3],
BYTE* pAuxDst[3], const UINT32 srcAuxStep[3],
const prim_size_t* roi);
typedef pstatus_t (*__andC_32u_t)(
const UINT32 *pSrc,
UINT32 val,
@ -224,6 +242,10 @@ typedef struct
__RGB565ToARGB_16u32u_C3C4_t RGB565ToARGB_16u32u_C3C4;
__YUV420ToRGB_8u_P3AC4R_t YUV420ToRGB_8u_P3AC4R;
__RGBToYUV420_8u_P3AC4R_t RGBToYUV420_8u_P3AC4R;
__RGBToYUV444_8u_P3AC4R_t RGBToYUV444_8u_P3AC4R;
__YUV420CombineToYUV444_t YUV420CombineToYUV444;
__YUV444SplitToYUV420_t YUV444SplitToYUV420;
__YUV420ToRGB_8u_P3AC4R_t YUV444ToRGB_8u_P3AC4R;
} primitives_t;
#ifdef __cplusplus

View File

@ -234,7 +234,7 @@ endif()
if(WITH_SSE2)
if(CMAKE_COMPILER_IS_GNUCC)
set(OPTIMIZATION "${OPTIMIZATION} -msse2 -mssse3 -O2 -Wdeclaration-after-statement")
set(OPTIMIZATION "${OPTIMIZATION} -msse2 -mssse3 -Wdeclaration-after-statement")
endif()
if(MSVC)
@ -251,12 +251,6 @@ if(DEFINED OPTIMIZATION)
set_source_files_properties(${PRIMITIVES_OPT_SRCS} PROPERTIES COMPILE_FLAGS ${OPTIMIZATION})
endif()
# always compile with optimization
if(CMAKE_COMPILER_IS_GNUCC)
set_source_files_properties(${PRIMITIVES_SRCS} PROPERTIES COMPILE_FLAGS "-O2")
endif()
set(PRIMITIVES_SRCS ${PRIMITIVES_SRCS} ${PRIMITIVES_OPT_SRCS})
freerdp_module_add(${PRIMITIVES_SRCS})

View File

@ -830,12 +830,16 @@ int clear_compress(CLEAR_CONTEXT* clear, BYTE* pSrcData, UINT32 SrcSize, BYTE**
return 1;
}
int clear_context_reset(CLEAR_CONTEXT* clear)
BOOL clear_context_reset(CLEAR_CONTEXT* clear)
{
if (!clear)
return FALSE;
clear->seqNumber = 0;
clear->VBarStorageCursor = 0;
clear->ShortVBarStorageCursor = 0;
return 1;
return TRUE;
}
CLEAR_CONTEXT* clear_context_new(BOOL Compressor)

File diff suppressed because it is too large Load Diff

View File

@ -413,9 +413,12 @@ int interleaved_compress(BITMAP_INTERLEAVED_CONTEXT* interleaved, BYTE* pDstData
return status;
}
int bitmap_interleaved_context_reset(BITMAP_INTERLEAVED_CONTEXT* interleaved)
BOOL bitmap_interleaved_context_reset(BITMAP_INTERLEAVED_CONTEXT* interleaved)
{
return 1;
if (!interleaved)
return FALSE;
return TRUE;
}
BITMAP_INTERLEAVED_CONTEXT* bitmap_interleaved_context_new(BOOL Compressor)

View File

@ -266,9 +266,15 @@ static void nsc_profiler_print(NSC_CONTEXT* context)
PROFILER_PRINT_FOOTER;
}
int nsc_context_reset(NSC_CONTEXT* context)
BOOL nsc_context_reset(NSC_CONTEXT* context, UINT32 width, UINT32 height)
{
return 1;
if (!context)
return FALSE;
context->width = width;
context->height = height;
return TRUE;
}
NSC_CONTEXT* nsc_context_new(void)

View File

@ -1160,9 +1160,12 @@ BYTE* freerdp_bitmap_compress_planar(BITMAP_PLANAR_CONTEXT* context, BYTE* data,
return dstData;
}
int freerdp_bitmap_planar_context_reset(BITMAP_PLANAR_CONTEXT* context)
BOOL freerdp_bitmap_planar_context_reset(BITMAP_PLANAR_CONTEXT* context)
{
return 1;
if (!context)
return FALSE;
return TRUE;
}
BITMAP_PLANAR_CONTEXT* freerdp_bitmap_planar_context_new(DWORD flags, int maxWidth, int maxHeight)

View File

@ -1880,9 +1880,12 @@ int progressive_compress(PROGRESSIVE_CONTEXT* progressive, BYTE* pSrcData, UINT3
return 1;
}
int progressive_context_reset(PROGRESSIVE_CONTEXT* progressive)
BOOL progressive_context_reset(PROGRESSIVE_CONTEXT* progressive)
{
return 1;
if (!progressive)
return FALSE;
return TRUE;
}
PROGRESSIVE_CONTEXT* progressive_context_new(BOOL Compressor)

View File

@ -357,6 +357,9 @@ void rfx_context_free(RFX_CONTEXT* context)
{
RFX_CONTEXT_PRIV *priv;
if (!context)
return;
assert(NULL != context);
assert(NULL != context->priv);
assert(NULL != context->priv->TilePool);
@ -419,10 +422,17 @@ void rfx_context_set_pixel_format(RFX_CONTEXT* context, RDP_PIXEL_FORMAT pixel_f
}
}
void rfx_context_reset(RFX_CONTEXT* context)
BOOL rfx_context_reset(RFX_CONTEXT* context, UINT32 width, UINT32 height)
{
if (!context)
return FALSE;
context->width = width;
context->height = height;
context->state = RFX_STATE_SEND_HEADERS;
context->frameIdx = 0;
return TRUE;
}
static BOOL rfx_process_message_sync(RFX_CONTEXT* context, wStream* s)

View File

@ -25,10 +25,9 @@ set(${MODULE_PREFIX}_SRCS
freerdp_module_add(${${MODULE_PREFIX}_SRCS})
freerdp_include_directory_add(${OPENSSL_INCLUDE_DIR})
freerdp_include_directory_add(${ZLIB_INCLUDE_DIRS})
freerdp_library_add(${OPENSSL_LIBRARIES} ${ZLIB_LIBRARIES})
freerdp_library_add(${ZLIB_LIBRARIES})
if(BUILD_TESTING)
add_subdirectory(test)

View File

@ -26,11 +26,6 @@
#include <winpr/print.h>
#include <winpr/windows.h>
#include <openssl/ssl.h>
#include <openssl/evp.h>
#include <openssl/aes.h>
#include <openssl/engine.h>
#include <freerdp/log.h>
#include <freerdp/client/file.h>
#include <freerdp/client/cmdline.h>
@ -77,11 +72,12 @@
int freerdp_assistance_crypt_derive_key_sha1(BYTE* hash, int hashLength, BYTE* key, int keyLength)
{
int rc = -1;
int i;
BYTE* buffer;
BYTE pad1[64];
BYTE pad2[64];
SHA_CTX hashCtx;
WINPR_SHA1_CTX hashCtx;
memset(pad1, 0x36, 64);
memset(pad2, 0x5C, 64);
@ -95,21 +91,29 @@ int freerdp_assistance_crypt_derive_key_sha1(BYTE* hash, int hashLength, BYTE* k
buffer = (BYTE*) calloc(1, hashLength * 2);
if (!buffer)
return -1;
goto fail;
SHA1_Init(&hashCtx);
SHA1_Update(&hashCtx, pad1, 64);
SHA1_Final((void*) buffer, &hashCtx);
if (!winpr_SHA1_Init(&hashCtx))
goto fail;
if (!winpr_SHA1_Update(&hashCtx, pad1, 64))
goto fail;
if (!winpr_SHA1_Final(&hashCtx, buffer, hashLength))
goto fail;
SHA1_Init(&hashCtx);
SHA1_Update(&hashCtx, pad2, 64);
SHA1_Final((void*) &buffer[hashLength], &hashCtx);
if (!winpr_SHA1_Init(&hashCtx))
goto fail;
if (!winpr_SHA1_Update(&hashCtx, pad2, 64))
goto fail;
if (!winpr_SHA1_Final(&hashCtx, &buffer[hashLength], hashLength))
goto fail;
CopyMemory(key, buffer, keyLength);
rc = 1;
fail:
free(buffer);
return 1;
return rc;
}
int freerdp_assistance_parse_address_list(rdpAssistanceFile* file, char* list)
@ -543,15 +547,16 @@ char* freerdp_assistance_generate_pass_stub(DWORD flags)
BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* passStub, int* pEncryptedSize)
{
BOOL rc;
int status;
WINPR_MD5_CTX md5Ctx;
int cbPasswordW;
int cbPassStubW;
int EncryptedSize;
BYTE PasswordHash[WINPR_MD5_DIGEST_LENGTH];
EVP_CIPHER_CTX rc4Ctx;
WINPR_CIPHER_CTX* rc4Ctx;
BYTE* pbIn, *pbOut;
int cbOut, cbIn, cbFinal;
size_t cbOut, cbIn, cbFinal;
WCHAR* PasswordW = NULL;
WCHAR* PassStubW = NULL;
@ -617,21 +622,9 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas
free(PasswordW);
free(PassStubW);
EVP_CIPHER_CTX_init(&rc4Ctx);
status = EVP_EncryptInit_ex(&rc4Ctx, EVP_rc4(), NULL, NULL, NULL);
if (!status)
{
WLog_ERR(TAG, "EVP_CipherInit_ex failure");
free (pbOut);
free (pbIn);
return NULL;
}
status = EVP_EncryptInit_ex(&rc4Ctx, NULL, NULL, PasswordHash, NULL);
if (!status)
rc4Ctx = winpr_Cipher_New(WINPR_CIPHER_ARC4_128, WINPR_ENCRYPT,
PasswordHash, NULL);
if (!rc4Ctx)
{
WLog_ERR(TAG, "EVP_CipherInit_ex failure");
free (pbOut);
@ -642,26 +635,26 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas
cbOut = cbFinal = 0;
cbIn = EncryptedSize;
status = EVP_EncryptUpdate(&rc4Ctx, pbOut, &cbOut, pbIn, cbIn);
rc = winpr_Cipher_Update(rc4Ctx, pbIn, cbIn, pbOut, &cbOut);
free(pbIn);
if (!status)
if (!rc)
{
WLog_ERR(TAG, "EVP_CipherUpdate failure");
winpr_Cipher_Free(rc4Ctx);
free (pbOut);
return NULL;
}
status = EVP_EncryptFinal_ex(&rc4Ctx, pbOut + cbOut, &cbFinal);
if (!status)
if (!winpr_Cipher_Final(rc4Ctx, pbOut + cbOut, &cbFinal))
{
WLog_ERR(TAG, "EVP_CipherFinal_ex failure");
winpr_Cipher_Free(rc4Ctx);
free (pbOut);
return NULL;
}
EVP_CIPHER_CTX_cleanup(&rc4Ctx);
winpr_Cipher_Free(rc4Ctx);
*pEncryptedSize = EncryptedSize;
@ -671,17 +664,17 @@ BYTE* freerdp_assistance_encrypt_pass_stub(const char* password, const char* pas
int freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password)
{
int status;
SHA_CTX shaCtx;
WINPR_SHA1_CTX shaCtx;
int cbPasswordW;
int cchOutW = 0;
WCHAR* pbOutW = NULL;
EVP_CIPHER_CTX aesDec;
WINPR_CIPHER_CTX* aesDec;
WCHAR* PasswordW = NULL;
BYTE* pbIn, *pbOut;
int cbOut, cbIn, cbFinal;
BYTE DerivedKey[AES_BLOCK_SIZE];
BYTE InitializationVector[AES_BLOCK_SIZE];
BYTE PasswordHash[SHA_DIGEST_LENGTH];
size_t cbOut, cbIn, cbFinal;
BYTE DerivedKey[WINPR_AES_BLOCK_SIZE];
BYTE InitializationVector[WINPR_AES_BLOCK_SIZE];
BYTE PasswordHash[WINPR_SHA1_DIGEST_LENGTH];
status = ConvertToUnicode(CP_UTF8, 0, password, -1, &PasswordW, 0);
@ -690,9 +683,13 @@ int freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password)
cbPasswordW = (status - 1) * 2;
SHA1_Init(&shaCtx);
SHA1_Update(&shaCtx, PasswordW, cbPasswordW);
SHA1_Final((void*) PasswordHash, &shaCtx);
if (!winpr_SHA1_Init(&shaCtx) ||
!winpr_SHA1_Update(&shaCtx, (BYTE*)PasswordW, cbPasswordW) ||
!winpr_SHA1_Final(&shaCtx, PasswordHash, sizeof(PasswordHash)))
{
free (PasswordW);
return -1;
}
status = freerdp_assistance_crypt_derive_key_sha1(PasswordHash, sizeof(PasswordHash),
DerivedKey, sizeof(DerivedKey));
@ -705,22 +702,9 @@ int freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password)
ZeroMemory(InitializationVector, sizeof(InitializationVector));
EVP_CIPHER_CTX_init(&aesDec);
status = EVP_DecryptInit_ex(&aesDec, EVP_aes_128_cbc(), NULL, NULL, NULL);
if (status != 1)
{
free(PasswordW);
return -1;
}
EVP_CIPHER_CTX_set_key_length(&aesDec, (128 / 8));
EVP_CIPHER_CTX_set_padding(&aesDec, 0);
status = EVP_DecryptInit_ex(&aesDec, EVP_aes_128_cbc(), NULL, DerivedKey, InitializationVector);
if (status != 1)
aesDec = winpr_Cipher_New(WINPR_CIPHER_AES_128_CBC, WINPR_DECRYPT,
DerivedKey, InitializationVector);
if (!aesDec)
{
free(PasswordW);
return -1;
@ -729,34 +713,33 @@ int freerdp_assistance_decrypt2(rdpAssistanceFile* file, const char* password)
cbOut = cbFinal = 0;
cbIn = file->EncryptedLHTicketLength;
pbIn = (BYTE*) file->EncryptedLHTicket;
pbOut = (BYTE*) calloc(1, cbIn + AES_BLOCK_SIZE + 2);
pbOut = (BYTE*) calloc(1, cbIn + WINPR_AES_BLOCK_SIZE + 2);
if (!pbOut)
{
winpr_Cipher_Free(aesDec);
free(PasswordW);
return -1;
}
status = EVP_DecryptUpdate(&aesDec, pbOut, &cbOut, pbIn, cbIn);
if (status != 1)
if (!winpr_Cipher_Update(aesDec, pbIn, cbIn, pbOut, &cbOut))
{
winpr_Cipher_Free(aesDec);
free(PasswordW);
free(pbOut);
return -1;
}
status = EVP_DecryptFinal_ex(&aesDec, pbOut + cbOut, &cbFinal);
if (status != 1)
if (!winpr_Cipher_Final(aesDec, pbOut + cbOut, &cbFinal))
{
WLog_ERR(TAG, "EVP_DecryptFinal_ex failure");
winpr_Cipher_Free(aesDec);
free(PasswordW);
free(pbOut);
return -1;
}
EVP_CIPHER_CTX_cleanup(&aesDec);
winpr_Cipher_Free(aesDec);
cbOut += cbFinal;
cbFinal = 0;

View File

@ -3392,10 +3392,10 @@ BOOL rdp_print_capability_sets(wStream* s, UINT16 numberCapabilities, BOOL recei
break;
}
if (s->pointer != em)
if (Stream_Pointer(s) != em)
{
WLog_ERR(TAG, "incorrect offset, type:0x%02X actual:%d expected:%d",
type, (int)(s->pointer - bm), (int)(em - bm));
type, (int)(Stream_Pointer(s) - bm), (int)(em - bm));
}
Stream_SetPointer(s, em);
@ -3617,10 +3617,10 @@ BOOL rdp_read_capability_sets(wStream* s, rdpSettings* settings, UINT16 numberCa
}
}
if (s->pointer != em)
if (Stream_Pointer(s) != em)
{
WLog_ERR(TAG, "incorrect offset, type:0x%02X actual:%d expected:%d",
type, (int)(s->pointer - bm), (int)(em - bm));
type, (int)(Stream_Pointer(s) - bm), (int)(em - bm));
}
Stream_SetPointer(s, em);

View File

@ -200,8 +200,9 @@ UINT freerdp_drdynvc_on_channel_disconnected(DrdynvcClientContext* context, cons
* go through and inform all the libraries that we are initialized
* called only from main thread
*/
int freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance)
UINT freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance)
{
UINT error = CHANNEL_RC_OK;
int index;
CHANNEL_CLIENT_DATA* pChannelClientData;
@ -212,10 +213,14 @@ int freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance)
pChannelClientData = &channels->clientDataList[index];
if (pChannelClientData->pChannelInitEventProc)
pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle, CHANNEL_EVENT_INITIALIZED, 0, 0);
pChannelClientData->pChannelInitEventProc(
pChannelClientData->pInitHandle,
CHANNEL_EVENT_INITIALIZED, 0, 0);
if (CHANNEL_RC_OK != getChannelError(instance->context))
break;
}
return 0;
return error;
}
/**
@ -223,10 +228,11 @@ int freerdp_channels_pre_connect(rdpChannels* channels, freerdp* instance)
* this will tell the libraries that its ok to call MyVirtualChannelOpen
* called only from main thread
*/
int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance)
UINT freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance)
{
UINT error = CHANNEL_RC_OK;
int index;
char* name;
char* name = NULL;
char* hostname;
int hostnameLength;
CHANNEL_CLIENT_DATA* pChannelClientData;
@ -246,11 +252,17 @@ int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance)
pChannelOpenData = &channels->openDataList[index];
pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle, CHANNEL_EVENT_CONNECTED, hostname, hostnameLength);
pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle,
CHANNEL_EVENT_CONNECTED, hostname, hostnameLength);
if (getChannelError(instance->context) != CHANNEL_RC_OK)
goto fail;
name = (char*) malloc(9);
if (!name)
return -1;
{
error = CHANNEL_RC_NO_MEMORY;
goto fail;
}
CopyMemory(name, pChannelOpenData->name, 8);
name[8] = '\0';
@ -260,6 +272,7 @@ int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance)
PubSub_OnChannelConnected(instance->context->pubSub, instance->context, &e);
free(name);
name = NULL;
}
}
@ -272,7 +285,9 @@ int freerdp_channels_post_connect(rdpChannels* channels, freerdp* instance)
channels->drdynvc->OnChannelDisconnected = freerdp_drdynvc_on_channel_disconnected;
}
return 0;
fail:
free (name);
return error;
}
int freerdp_channels_data(freerdp* instance, UINT16 channelId, BYTE* data, int dataSize, int flags, int totalSize)
@ -437,8 +452,9 @@ BOOL freerdp_channels_check_fds(rdpChannels* channels, freerdp* instance)
return TRUE;
}
int freerdp_channels_disconnect(rdpChannels* channels, freerdp* instance)
UINT freerdp_channels_disconnect(rdpChannels* channels, freerdp* instance)
{
UINT error = CHANNEL_RC_OK;
int index;
char* name;
CHANNEL_OPEN_DATA* pChannelOpenData;
@ -458,7 +474,11 @@ int freerdp_channels_disconnect(rdpChannels* channels, freerdp* instance)
pChannelClientData = &channels->clientDataList[index];
if (pChannelClientData->pChannelInitEventProc)
pChannelClientData->pChannelInitEventProc(pChannelClientData->pInitHandle, CHANNEL_EVENT_DISCONNECTED, 0, 0);
pChannelClientData->pChannelInitEventProc(
pChannelClientData->pInitHandle,
CHANNEL_EVENT_DISCONNECTED, 0, 0);
if (getChannelError(instance->context) != CHANNEL_RC_OK)
goto fail;
pChannelOpenData = &channels->openDataList[index];
@ -476,7 +496,8 @@ int freerdp_channels_disconnect(rdpChannels* channels, freerdp* instance)
free(name);
}
return 0;
fail:
return error;
}
void freerdp_channels_close(rdpChannels* channels, freerdp* instance)

View File

@ -88,7 +88,7 @@ BOOL freerdp_client_codecs_prepare(rdpCodecs* codecs, UINT32 flags)
}
}
if ((flags & FREERDP_CODEC_H264) && !codecs->h264)
if ((flags & (FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444)) && !codecs->h264)
{
if (!(codecs->h264 = h264_context_new(FALSE)))
{
@ -100,13 +100,19 @@ BOOL freerdp_client_codecs_prepare(rdpCodecs* codecs, UINT32 flags)
return TRUE;
}
BOOL freerdp_client_codecs_reset(rdpCodecs* codecs, UINT32 flags)
BOOL freerdp_client_codecs_reset(rdpCodecs* codecs, UINT32 flags,
UINT32 width, UINT32 height)
{
BOOL rc = TRUE;
if (!freerdp_client_codecs_prepare(codecs, flags))
return FALSE;
if (flags & FREERDP_CODEC_INTERLEAVED)
{
if (codecs->interleaved)
{
bitmap_interleaved_context_reset(codecs->interleaved);
rc &= bitmap_interleaved_context_reset(codecs->interleaved);
}
}
@ -114,7 +120,7 @@ BOOL freerdp_client_codecs_reset(rdpCodecs* codecs, UINT32 flags)
{
if (codecs->planar)
{
freerdp_bitmap_planar_context_reset(codecs->planar);
rc &= freerdp_bitmap_planar_context_reset(codecs->planar);
}
}
@ -122,7 +128,7 @@ BOOL freerdp_client_codecs_reset(rdpCodecs* codecs, UINT32 flags)
{
if (codecs->nsc)
{
nsc_context_reset(codecs->nsc);
rc &= nsc_context_reset(codecs->nsc, width, height);
}
}
@ -130,7 +136,7 @@ BOOL freerdp_client_codecs_reset(rdpCodecs* codecs, UINT32 flags)
{
if (codecs->rfx)
{
rfx_context_reset(codecs->rfx);
rc &= rfx_context_reset(codecs->rfx, width, height);
}
}
@ -138,7 +144,7 @@ BOOL freerdp_client_codecs_reset(rdpCodecs* codecs, UINT32 flags)
{
if (codecs->clear)
{
clear_context_reset(codecs->clear);
rc &= clear_context_reset(codecs->clear);
}
}
@ -151,19 +157,19 @@ BOOL freerdp_client_codecs_reset(rdpCodecs* codecs, UINT32 flags)
{
if (codecs->progressive)
{
progressive_context_reset(codecs->progressive);
rc &= progressive_context_reset(codecs->progressive);
}
}
if (flags & FREERDP_CODEC_H264)
if (flags & (FREERDP_CODEC_AVC420 | FREERDP_CODEC_AVC444))
{
if (codecs->h264)
{
h264_context_reset(codecs->h264);
rc &= h264_context_reset(codecs->h264, width, height);
}
}
return TRUE;
return rc;
}
rdpCodecs* codecs_new(rdpContext* context)
@ -173,9 +179,7 @@ rdpCodecs* codecs_new(rdpContext* context)
codecs = (rdpCodecs*) calloc(1, sizeof(rdpCodecs));
if (codecs)
{
codecs->context = context;
}
return codecs;
}

View File

@ -400,7 +400,7 @@ BOOL rdp_client_reconnect(rdpRdp* rdp)
status = rdp_client_connect(rdp);
if (status)
status = (freerdp_channels_post_connect(channels, context->instance) >= 0);
status = (freerdp_channels_post_connect(channels, context->instance) == CHANNEL_RC_OK);
return status;
}

View File

@ -45,7 +45,7 @@
* Fast-Path packet format is defined in [MS-RDPBCGR] 2.2.9.1.2, which revises
* server output packets from the first byte with the goal of improving
* bandwidth.
*
*
* Slow-Path packet always starts with TPKT header, which has the first
* byte 0x03, while Fast-Path packet starts with 2 zero bits in the first
* two less significant bits of the first byte.
@ -282,7 +282,7 @@ static int fastpath_recv_update(rdpFastPath* fastpath, BYTE updateCode, UINT32 s
if (!fastpath_recv_update_synchronize(fastpath, s))
WLog_ERR(TAG, "fastpath_recv_update_synchronize failure but we continue");
else
IFCALL(update->Synchronize, context);
IFCALL(update->Synchronize, context);
break;
case FASTPATH_UPDATETYPE_SURFCMDS:
@ -463,7 +463,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
Stream_SetPosition(fastpath->updateData, 0);
Stream_Copy(fastpath->updateData, cs, size);
Stream_Copy(cs, fastpath->updateData, size);
}
else if (fragmentation == FASTPATH_FRAGMENT_NEXT)
{
@ -491,7 +491,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
goto out_fail;
}
Stream_Copy(fastpath->updateData, cs, size);
Stream_Copy(cs, fastpath->updateData, size);
}
else if (fragmentation == FASTPATH_FRAGMENT_LAST)
{
@ -519,7 +519,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
goto out_fail;
}
Stream_Copy(fastpath->updateData, cs, size);
Stream_Copy(cs, fastpath->updateData, size);
Stream_SealLength(fastpath->updateData);
Stream_SetPosition(fastpath->updateData, 0);
@ -546,7 +546,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, wStream* s)
out_fail:
if (cs != s) {
Stream_Release(cs);
Stream_Release(cs);
}
return -1;

View File

@ -627,7 +627,11 @@ UINT32 freerdp_error_info(freerdp* instance)
return instance->context->rdp->errorInfo;
}
void freerdp_set_error_info(rdpRdp* rdp, UINT32 error) {
void freerdp_set_error_info(rdpRdp* rdp, UINT32 error)
{
if (!rdp)
return;
rdp_set_error_info(rdp, error);
}

View File

@ -407,7 +407,7 @@ wStream* http_request_write(HttpContext* context, HttpRequest* request)
free(lines);
Stream_Write(s, "\0", 1); /* append null terminator */
Stream_Rewind(s, 1); /* don't include null terminator in length */
Stream_Length(s) = Stream_GetPosition(s);
Stream_SetLength(s, Stream_GetPosition(s));
return s;
out_free:

View File

@ -206,7 +206,7 @@ BOOL rdg_send_tunnel_authorization(rdpRdg* rdg)
if (!clientName)
return FALSE;
packetSize = 12 + clientNameLen * 2 + sizeof(WCHAR);
packetSize = 12 + clientNameLen * sizeof(WCHAR);
s = Stream_New(NULL, packetSize);
if (!s)
@ -225,8 +225,6 @@ BOOL rdg_send_tunnel_authorization(rdpRdg* rdg)
for (i = 0; i < clientNameLen; i++)
Stream_Write_UINT16(s, clientName[i]);
Stream_Write_UINT16(s, 0);
Stream_SealLength(s);
status = rdg_write_packet(rdg, s);

View File

@ -226,7 +226,7 @@ void gcc_write_conference_create_request(wStream* s, wStream* userData)
per_write_octet_string(s, h221_cs_key, 4, 4); /* h221NonStandard, client-to-server H.221 key, "Duca" */
/* userData::value (OCTET_STRING) */
per_write_octet_string(s, userData->buffer, Stream_GetPosition(userData), 0); /* array of client data blocks */
per_write_octet_string(s, Stream_Buffer(userData), Stream_GetPosition(userData), 0); /* array of client data blocks */
}
BOOL gcc_read_conference_create_response(wStream* s, rdpMcs* mcs)
@ -320,7 +320,7 @@ void gcc_write_conference_create_response(wStream* s, wStream* userData)
per_write_octet_string(s, h221_sc_key, 4, 4); /* h221NonStandard, server-to-client H.221 key, "McDn" */
/* userData (OCTET_STRING) */
per_write_octet_string(s, userData->buffer, Stream_GetPosition(userData), 0); /* array of server data blocks */
per_write_octet_string(s, Stream_Buffer(userData), Stream_GetPosition(userData), 0); /* array of server data blocks */
}
BOOL gcc_read_client_data_blocks(wStream* s, rdpMcs* mcs, int length)
@ -509,7 +509,7 @@ BOOL gcc_read_server_data_blocks(wStream* s, rdpMcs* mcs, int length)
break;
}
offset += blockLength;
Stream_Pointer(s) = holdp + blockLength;
Stream_SetPointer(s, holdp + blockLength);
}
return TRUE;
@ -590,7 +590,12 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
Stream_Read_UINT32(s, settings->ClientBuild); /* ClientBuild (4 bytes) */
/* clientName (32 bytes, null-terminated unicode, truncated to 15 characters) */
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 32 / 2, &str, 0, NULL, NULL);
if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 32 / 2,
&str, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert client host name");
return FALSE;
}
Stream_Seek(s, 32);
free(settings->ClientHostname);
settings->ClientHostname = str;
@ -644,10 +649,17 @@ BOOL gcc_read_client_core_data(wStream* s, rdpMcs* mcs, UINT16 blockLength)
settings->EarlyCapabilityFlags = (UINT32) earlyCapabilityFlags;
blockLength -= 2;
/* clientDigProductId (64 bytes): Contains a value that uniquely identifies the client */
if (blockLength < 64)
break;
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2, &str, 0, NULL, NULL);
if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), 64 / 2,
&str, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert the client product identifier");
return FALSE;
}
Stream_Seek(s, 64); /* clientDigProductId (64 bytes) */
free(settings->ClientProductId);
settings->ClientProductId = str;

View File

@ -199,6 +199,7 @@ BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s)
UINT16 cbClientDir;
UINT16 cbAutoReconnectLen;
rdpSettings* settings = rdp->settings;
WCHAR* wstr;
if (Stream_GetRemainingLength(s) < 4)
return FALSE;
@ -206,6 +207,17 @@ BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s)
Stream_Read_UINT16(s, clientAddressFamily); /* clientAddressFamily (2 bytes) */
Stream_Read_UINT16(s, cbClientAddress); /* cbClientAddress (2 bytes) */
/* cbClientAddress is the size in bytes of the character data in the clientAddress field.
* This size includes the length of the mandatory null terminator.
* The maximum allowed value is 80 bytes
*/
if ((cbClientAddress % 2) || cbClientAddress < 2 || cbClientAddress > 80)
{
WLog_ERR(TAG, "protocol error: invalid cbClientAddress value: %u", cbClientAddress);
return FALSE;
}
settings->IPv6Enabled = (clientAddressFamily == ADDRESS_FAMILY_INET6 ? TRUE : FALSE);
if (Stream_GetRemainingLength(s) < cbClientAddress)
@ -217,7 +229,17 @@ BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s)
settings->ClientAddress = NULL;
}
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbClientAddress / 2, &settings->ClientAddress, 0, NULL, NULL);
wstr = (WCHAR*) Stream_Pointer(s);
if (wstr[cbClientAddress / 2 - 1])
{
WLog_ERR(TAG, "protocol error: clientAddress must be null terminated");
return FALSE;
}
if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &settings->ClientAddress, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert client address");
return FALSE;
}
Stream_Seek(s, cbClientAddress);
if (Stream_GetRemainingLength(s) < 2)
@ -225,6 +247,17 @@ BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s)
Stream_Read_UINT16(s, cbClientDir); /* cbClientDir (2 bytes) */
/* cbClientDir is the size in bytes of the character data in the clientDir field.
* This size includes the length of the mandatory null terminator.
* The maximum allowed value is 512 bytes
*/
if ((cbClientDir % 2) || cbClientDir < 2 || cbClientDir > 512)
{
WLog_ERR(TAG, "protocol error: invalid cbClientDir value: %u", cbClientDir);
return FALSE;
}
if (Stream_GetRemainingLength(s) < cbClientDir)
return FALSE;
@ -234,7 +267,17 @@ BOOL rdp_read_extended_info_packet(rdpRdp* rdp, wStream* s)
settings->ClientDir = NULL;
}
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbClientDir / 2, &settings->ClientDir, 0, NULL, NULL);
wstr = (WCHAR*) Stream_Pointer(s);
if (wstr[cbClientDir / 2 - 1])
{
WLog_ERR(TAG, "protocol error: clientDir must be null terminated");
return FALSE;
}
if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), -1, &settings->ClientDir, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert client directory");
return FALSE;
}
Stream_Seek(s, cbClientDir);
if (!rdp_read_client_time_zone(s, settings))
@ -337,6 +380,7 @@ BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s)
UINT16 cbWorkingDir;
UINT32 CompressionLevel;
rdpSettings* settings = rdp->settings;
WCHAR* wstr;
if (Stream_GetRemainingLength(s) < 18)
return FALSE;
@ -357,6 +401,12 @@ BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s)
settings->CompressionLevel = CompressionLevel;
}
if (!(flags & INFO_UNICODE))
{
WLog_ERR(TAG, "Client without INFO_UNICODE flag: this is currently not supported");
return FALSE;
}
Stream_Read_UINT16(s, cbDomain); /* cbDomain (2 bytes) */
Stream_Read_UINT16(s, cbUserName); /* cbUserName (2 bytes) */
Stream_Read_UINT16(s, cbPassword); /* cbPassword (2 bytes) */
@ -368,7 +418,26 @@ BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s)
if (cbDomain > 0)
{
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbDomain / 2, &settings->Domain, 0, NULL, NULL);
/* cbDomain is the size in bytes of the character data in the Domain field.
* This size excludes (!) the length of the mandatory null terminator.
* Maximum value including the mandatory null terminator: 512
*/
if ((cbDomain % 2) || cbDomain > 512)
{
WLog_ERR(TAG, "protocol error: invalid cbDomain value: %u", cbDomain);
return FALSE;
}
wstr = (WCHAR*) Stream_Pointer(s);
if (wstr[cbDomain / 2])
{
WLog_ERR(TAG, "protocol error: Domain must be null terminated");
return FALSE;
}
if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &settings->Domain, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert Domain string");
return FALSE;
}
Stream_Seek(s, cbDomain);
}
Stream_Seek(s, 2);
@ -378,7 +447,26 @@ BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s)
if (cbUserName > 0)
{
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbUserName / 2, &settings->Username, 0, NULL, NULL);
/* cbUserName is the size in bytes of the character data in the UserName field.
* This size excludes (!) the length of the mandatory null terminator.
* Maximum value including the mandatory null terminator: 512
*/
if ((cbUserName % 2) || cbUserName > 512)
{
WLog_ERR(TAG, "protocol error: invalid cbUserName value: %u", cbUserName);
return FALSE;
}
wstr = (WCHAR*) Stream_Pointer(s);
if (wstr[cbUserName / 2])
{
WLog_ERR(TAG, "protocol error: UserName must be null terminated");
return FALSE;
}
if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &settings->Username, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert UserName string");
return FALSE;
}
Stream_Seek(s, cbUserName);
}
Stream_Seek(s, 2);
@ -388,7 +476,26 @@ BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s)
if (cbPassword > 0)
{
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbPassword / 2, &settings->Password, 0, NULL, NULL);
/* cbPassword is the size in bytes of the character data in the Password field.
* This size excludes (!) the length of the mandatory null terminator.
* Maximum value including the mandatory null terminator: 512
*/
if ((cbPassword % 2) || cbPassword > 512)
{
WLog_ERR(TAG, "protocol error: invalid cbPassword value: %u", cbPassword);
return FALSE;
}
wstr = (WCHAR*) Stream_Pointer(s);
if (wstr[cbPassword / 2])
{
WLog_ERR(TAG, "protocol error: Password must be null terminated");
return FALSE;
}
if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &settings->Password, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert Password string");
return FALSE;
}
Stream_Seek(s, cbPassword);
}
Stream_Seek(s, 2);
@ -398,7 +505,26 @@ BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s)
if (cbAlternateShell > 0)
{
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbAlternateShell / 2, &settings->AlternateShell, 0, NULL, NULL);
/* cbAlternateShell is the size in bytes of the character data in the AlternateShell field.
* This size excludes (!) the length of the mandatory null terminator.
* Maximum value including the mandatory null terminator: 512
*/
if ((cbAlternateShell % 2) || cbAlternateShell > 512)
{
WLog_ERR(TAG, "protocol error: invalid cbAlternateShell value: %u", cbAlternateShell);
return FALSE;
}
wstr = (WCHAR*) Stream_Pointer(s);
if (wstr[cbAlternateShell / 2])
{
WLog_ERR(TAG, "protocol error: AlternateShell must be null terminated");
return FALSE;
}
if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &settings->AlternateShell, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert AlternateShell string");
return FALSE;
}
Stream_Seek(s, cbAlternateShell);
}
Stream_Seek(s, 2);
@ -408,7 +534,26 @@ BOOL rdp_read_info_packet(rdpRdp* rdp, wStream* s)
if (cbWorkingDir > 0)
{
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbWorkingDir / 2, &settings->ShellWorkingDirectory, 0, NULL, NULL);
/* cbWorkingDir is the size in bytes of the character data in the WorkingDir field.
* This size excludes (!) the length of the mandatory null terminator.
* Maximum value including the mandatory null terminator: 512
*/
if ((cbWorkingDir % 2) || cbWorkingDir > 512)
{
WLog_ERR(TAG, "protocol error: invalid cbWorkingDir value: %u", cbWorkingDir);
return FALSE;
}
wstr = (WCHAR*) Stream_Pointer(s);
if (wstr[cbWorkingDir / 2])
{
WLog_ERR(TAG, "protocol error: WorkingDir must be null terminated");
return FALSE;
}
if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &settings->ShellWorkingDirectory, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "failed to convert AlternateShell string");
return FALSE;
}
Stream_Seek(s, cbWorkingDir);
}
Stream_Seek(s, 2);
@ -664,33 +809,76 @@ BOOL rdp_recv_logon_info_v1(rdpRdp* rdp, wStream* s, logon_info *info)
{
UINT32 cbDomain;
UINT32 cbUserName;
WCHAR* wstr;
ZeroMemory(info, sizeof(*info));
if (Stream_GetRemainingLength(s) < 576)
return FALSE;
Stream_Read_UINT32(s, cbDomain); /* cbDomain (4 bytes) */
if (cbDomain > 52)
return FALSE;
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbDomain, &info->domain, 0, NULL, FALSE);
if (!info->domain)
return FALSE;
/* cbDomain is the size of the Unicode character data (including the mandatory
* null terminator) in bytes present in the fixed-length (52 bytes) Domain field
*/
if (cbDomain)
{
if ((cbDomain % 2) || cbDomain > 52)
{
WLog_ERR(TAG, "protocol error: invalid cbDomain value: %lu", cbDomain);
goto fail;
}
wstr = (WCHAR*) Stream_Pointer(s);
if (wstr[cbDomain / 2 - 1])
{
WLog_ERR(TAG, "protocol error: Domain must be null terminated");
goto fail;
}
if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &info->domain, 0, NULL, FALSE) < 1)
{
WLog_ERR(TAG, "failed to convert the Domain string");
goto fail;
}
}
Stream_Seek(s, 52); /* domain (52 bytes) */
Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */
if (cbUserName > 512)
goto error_username;
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbUserName, &info->username, 0, NULL, FALSE);
if (!info->username)
goto error_username;
/* cbUserName is the size of the Unicode character data (including the mandatory
* null terminator) in bytes present in the fixed-length (512 bytes) UserName field.
*/
if (cbUserName)
{
if ((cbUserName % 2) || cbUserName > 512)
{
WLog_ERR(TAG, "protocol error: invalid cbUserName value: %lu", cbUserName);
goto fail;
}
wstr = (WCHAR*) Stream_Pointer(s);
if (wstr[cbUserName / 2 - 1])
{
WLog_ERR(TAG, "protocol error: UserName must be null terminated");
goto fail;
}
if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &info->username, 0, NULL, FALSE) < 1)
{
WLog_ERR(TAG, "failed to convert the UserName string");
goto fail;
}
}
Stream_Seek(s, 512); /* userName (512 bytes) */
Stream_Read_UINT32(s, info->sessionId); /* SessionId (4 bytes) */
WLog_DBG(TAG, "LogonInfoV1: SessionId: 0x%04X", info->sessionId);
WLog_DBG(TAG, "LogonInfoV1: SessionId: 0x%04X UserName: [%s] Domain: [%s]",
info->sessionId, info->username, info->domain);
return TRUE;
error_username:
fail:
free(info->username);
info->username = NULL;
free(info->domain);
info->domain = NULL;
return FALSE;
@ -702,6 +890,9 @@ BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info *info)
UINT32 Size;
UINT32 cbDomain;
UINT32 cbUserName;
WCHAR* wstr;
ZeroMemory(info, sizeof(*info));
if (Stream_GetRemainingLength(s) < 576)
return FALSE;
@ -713,26 +904,82 @@ BOOL rdp_recv_logon_info_v2(rdpRdp* rdp, wStream* s, logon_info *info)
Stream_Read_UINT32(s, cbUserName); /* cbUserName (4 bytes) */
Stream_Seek(s, 558); /* pad (558 bytes) */
if (Stream_GetRemainingLength(s) < (cbDomain + cbUserName))
return FALSE;
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbDomain, &info->domain, 0, NULL, FALSE);
if (!info->domain)
return FALSE;
/* cbDomain is the size in bytes of the Unicode character data in the Domain field.
* The size of the mandatory null terminator is include in this value.
* Note: Since MS-RDPBCGR 2.2.10.1.1.2 does not mention any size limits we assume
* that the maximum value is 52 bytes, according to the fixed size of the
* Domain field in the Logon Info Version 1 (TS_LOGON_INFO) structure.
*/
if (cbDomain)
{
if ((cbDomain % 2) || cbDomain > 52)
{
WLog_ERR(TAG, "protocol error: invalid cbDomain value: %lu", cbDomain);
goto fail;
}
if (Stream_GetRemainingLength(s) < (size_t) cbDomain)
{
WLog_ERR(TAG, "insufficient remaining stream length");
goto fail;
}
wstr = (WCHAR*) Stream_Pointer(s);
if (wstr[cbDomain / 2 - 1])
{
WLog_ERR(TAG, "protocol error: Domain field must be null terminated");
goto fail;
}
if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &info->domain, 0, NULL, FALSE) < 1)
{
WLog_ERR(TAG, "failed to convert the Domain string");
goto fail;
}
}
Stream_Seek(s, cbDomain); /* domain */
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), cbUserName, &info->username, 0, NULL, FALSE);
if (!info->username)
/* cbUserName is the size in bytes of the Unicode character data in the UserName field.
* The size of the mandatory null terminator is include in this value.
* Note: Since MS-RDPBCGR 2.2.10.1.1.2 does not mention any size limits we assume
* that the maximum value is 512 bytes, according to the fixed size of the
* Username field in the Logon Info Version 1 (TS_LOGON_INFO) structure.
*/
if (cbUserName)
{
free(info->domain);
info->domain = NULL;
return FALSE;
if ((cbUserName % 2) || cbUserName < 2 || cbUserName > 512)
{
WLog_ERR(TAG, "protocol error: invalid cbUserName value: %lu", cbUserName);
goto fail;
}
if (Stream_GetRemainingLength(s) < (size_t) cbUserName)
{
WLog_ERR(TAG, "insufficient remaining stream length");
goto fail;
}
wstr = (WCHAR*) Stream_Pointer(s);
if (wstr[cbUserName / 2 - 1])
{
WLog_ERR(TAG, "protocol error: UserName field must be null terminated");
goto fail;
}
if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &info->username, 0, NULL, FALSE) < 1)
{
WLog_ERR(TAG, "failed to convert the Domain string");
goto fail;
}
}
Stream_Seek(s, cbUserName); /* userName */
WLog_DBG(TAG, "LogonInfoV2: SessionId: 0x%04X", info->sessionId);
WLog_DBG(TAG, "LogonInfoV2: SessionId: 0x%04X UserName: [%s] Domain: [%s]",
info->sessionId, info->username, info->domain);
return TRUE;
fail:
free(info->username);
info->username = NULL;
free(info->domain);
info->domain = NULL;
return FALSE;
}
BOOL rdp_recv_logon_plain_notify(rdpRdp* rdp, wStream* s)

View File

@ -571,7 +571,7 @@ BOOL mcs_write_connect_initial(wStream* s, rdpMcs* mcs, wStream* userData)
goto out;
/* userData (OCTET_STRING) */
ber_write_octet_string(tmps, userData->buffer, Stream_GetPosition(userData));
ber_write_octet_string(tmps, Stream_Buffer(userData), Stream_GetPosition(userData));
length = Stream_GetPosition(tmps);
/* Connect-Initial (APPLICATION 101, IMPLICIT SEQUENCE) */
@ -608,7 +608,7 @@ BOOL mcs_write_connect_response(wStream* s, rdpMcs* mcs, wStream* userData)
if (!mcs_write_domain_parameters(tmps, &(mcs->domainParameters)))
goto out;
/* userData (OCTET_STRING) */
ber_write_octet_string(tmps, userData->buffer, Stream_GetPosition(userData));
ber_write_octet_string(tmps, Stream_Buffer(userData), Stream_GetPosition(userData));
length = Stream_GetPosition(tmps);
ber_write_application_tag(s, MCS_TYPE_CONNECT_RESPONSE, length);

View File

@ -188,19 +188,12 @@ static BOOL update_message_SurfaceCommand(rdpContext* context, wStream* s)
{
wStream* wParam;
wParam = (wStream*) malloc(sizeof(wStream));
wParam = Stream_New(NULL, Stream_GetRemainingLength(s));
if (!wParam)
return FALSE;
wParam->capacity = Stream_Capacity(s);
wParam->buffer = (BYTE*) malloc(wParam->capacity);
if (!wParam->buffer)
{
free(wParam);
return FALSE;
}
wParam->pointer = wParam->buffer;
Stream_Copy(s, wParam, Stream_GetRemainingLength(s));
Stream_SetPosition(wParam, 0);
return MessageQueue_Post(context->update->queue, (void*) context,
MakeMessageId(Update, SurfaceCommand), (void*) wParam, NULL);
@ -2058,7 +2051,7 @@ int update_message_free_pointer_update_class(wMessage* msg, int type)
free(wParam);
}
break;
case PointerUpdate_PointerNew:
{
POINTER_NEW_UPDATE* wParam = (POINTER_NEW_UPDATE*) msg->wParam;
@ -2091,11 +2084,11 @@ static int update_message_process_pointer_update_class(rdpUpdateProxy* proxy, wM
break;
case PointerUpdate_PointerColor:
IFCALL(proxy->PointerColor, msg->context, (POINTER_COLOR_UPDATE*) msg->wParam);
IFCALL(proxy->PointerColor, msg->context, (POINTER_COLOR_UPDATE*) msg->wParam);
break;
case PointerUpdate_PointerNew:
IFCALL(proxy->PointerNew, msg->context, (POINTER_NEW_UPDATE*) msg->wParam);
IFCALL(proxy->PointerNew, msg->context, (POINTER_NEW_UPDATE*) msg->wParam);
break;
case PointerUpdate_PointerCached:
@ -2220,7 +2213,7 @@ int update_message_queue_free_message(wMessage *message)
int msgType;
assert(message);
if (message->id == WMQ_QUIT)
return 0;

View File

@ -1728,7 +1728,7 @@ BOOL update_read_fast_glyph_order(wStream* s, ORDER_INFO* orderInfo, FAST_GLYPH_
}
}
Stream_Pointer(s) = phold + fastGlyph->cbData;
Stream_SetPointer(s, phold + fastGlyph->cbData);
}
return TRUE;
@ -3546,7 +3546,7 @@ BOOL update_recv_secondary_order(rdpUpdate* update, wStream* s, BYTE flags)
break;
}
Stream_Pointer(s) = next;
Stream_SetPointer(s, next);
return TRUE;
}

View File

@ -67,7 +67,7 @@ const char* DATA_PDU_TYPE_STRINGS[80] =
"ARC Status", /* 0x32 */
"?", "?", "?", /* 0x33 - 0x35 */
"Status Info", /* 0x36 */
"Monitor Layout" /* 0x37 */
"Monitor Layout", /* 0x37 */
"FrameAcknowledge", "?", "?", /* 0x38 - 0x40 */
"?", "?", "?", "?", "?", "?" /* 0x41 - 0x46 */
};
@ -248,15 +248,19 @@ BOOL rdp_set_error_info(rdpRdp* rdp, UINT32 errorInfo)
if (rdp->errorInfo != ERRINFO_SUCCESS)
{
ErrorInfoEventArgs e;
rdpContext* context = rdp->instance->context;
rdp->context->LastError = MAKE_FREERDP_ERROR(ERRINFO, errorInfo);
rdpContext* context = rdp->context;
rdp_print_errinfo(rdp->errorInfo);
EventArgsInit(&e, "freerdp");
e.code = rdp->errorInfo;
PubSub_OnErrorInfo(context->pubSub, context, &e);
if (context)
{
context->LastError = MAKE_FREERDP_ERROR(ERRINFO, errorInfo);
if (context->pubSub)
{
ErrorInfoEventArgs e;
EventArgsInit(&e, "freerdp");
e.code = rdp->errorInfo;
PubSub_OnErrorInfo(context->pubSub, context, &e);
}
}
}
else
{
@ -1056,7 +1060,7 @@ BOOL rdp_decrypt(rdpRdp* rdp, wStream* s, int length, UINT16 securityFlags)
return FALSE; /* TODO */
}
Stream_Length(s) -= pad;
Stream_SetLength(s, Stream_Length(s) - pad);
return TRUE;
}

View File

@ -30,7 +30,7 @@
#define TAG FREERDP_TAG("core.redirection")
void rdp_print_redirection_flags(UINT32 flags)
static void rdp_print_redirection_flags(UINT32 flags)
{
WLog_DBG(TAG, "redirectionFlags = {");
@ -76,9 +76,10 @@ void rdp_print_redirection_flags(UINT32 flags)
WLog_DBG(TAG, "}");
}
BOOL rdp_redirection_read_string(wStream* s, char** str)
static BOOL rdp_redirection_read_unicode_string(wStream* s, char** str, size_t maxLength)
{
UINT32 length;
WCHAR* wstr = NULL;
if (Stream_GetRemainingLength(s) < 4)
{
@ -88,13 +89,31 @@ BOOL rdp_redirection_read_string(wStream* s, char** str)
Stream_Read_UINT32(s, length);
if (Stream_GetRemainingLength(s) < length)
if ((length % 2) || length < 2 || length > maxLength)
{
WLog_ERR(TAG, "rdp_redirection_read_string failure: incorrect length %d", length);
WLog_ERR(TAG, "rdp_redirection_read_string failure: invalid unicode string length: %lu", length);
return FALSE;
}
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), length / 2, str, 0, NULL, NULL);
if (Stream_GetRemainingLength(s) < length)
{
WLog_ERR(TAG, "rdp_redirection_read_string failure: insufficient stream length (%lu bytes required)", length);
return FALSE;
}
wstr = (WCHAR*) Stream_Pointer(s);
if (wstr[length / 2 - 1])
{
WLog_ERR(TAG, "rdp_redirection_read_string failure: unterminated unicode string");
return FALSE;
}
if (ConvertFromUnicode(CP_UTF8, 0, wstr, -1, str, 0, NULL, NULL) < 1)
{
WLog_ERR(TAG, "rdp_redirection_read_string failure: string conversion failed");
return FALSE;
}
Stream_Seek(s, length);
return TRUE;
}
@ -173,7 +192,10 @@ int rdp_redirection_apply_settings(rdpRdp* rdp)
/* Password may be a cookie without a null terminator */
free(settings->RedirectionPassword);
settings->RedirectionPasswordLength = redirection->PasswordLength;
settings->RedirectionPassword = (BYTE*) malloc(settings->RedirectionPasswordLength);
/* For security reasons we'll allocate an additional zero WCHAR at the
* end of the buffer that is not included in RedirectionPasswordLength
*/
settings->RedirectionPassword = (BYTE*) calloc(1, settings->RedirectionPasswordLength + sizeof(WCHAR));
if (!settings->RedirectionPassword)
return -1;
CopyMemory(settings->RedirectionPassword, redirection->Password, settings->RedirectionPasswordLength);
@ -219,7 +241,7 @@ int rdp_redirection_apply_settings(rdpRdp* rdp)
return 0;
}
BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
static BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
{
UINT16 flags;
UINT16 length;
@ -238,14 +260,33 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
rdp_print_redirection_flags(redirection->flags);
/* Although MS-RDPBCGR does not mention any length constraints limits for the
* variable length null-terminated unicode strings in the RDP_SERVER_REDIRECTION_PACKET
* structure we will use the following limits in bytes including the null terminator:
*
* TargetNetAddress: 80 bytes
* UserName: 512 bytes
* Domain: 52 bytes
* Password(Cookie): 512 bytes
* TargetFQDN: 512 bytes
* TargetNetBiosName: 32 bytes
*/
if (redirection->flags & LB_TARGET_NET_ADDRESS)
{
if (!rdp_redirection_read_string(s, &(redirection->TargetNetAddress)))
if (!rdp_redirection_read_unicode_string(s, &(redirection->TargetNetAddress), 80))
return -1;
}
if (redirection->flags & LB_LOAD_BALANCE_INFO)
{
/* See [MSFT-SDLBTS] (a.k.a. TS_Session_Directory.doc)
* load balance info example data:
* 0000 43 6f 6f 6b 69 65 3a 20 6d 73 74 73 3d 32 31 33 Cookie: msts=213
* 0010 34 30 32 36 34 33 32 2e 31 35 36 32 39 2e 30 30 4026432.15629.00
* 0020 30 30 0d 0a 00..
*/
if (Stream_GetRemainingLength(s) < 4)
return -1;
@ -265,7 +306,7 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
if (redirection->flags & LB_USERNAME)
{
if (!rdp_redirection_read_string(s, &(redirection->Username)))
if (!rdp_redirection_read_unicode_string(s, &(redirection->Username), 512))
return -1;
WLog_DBG(TAG, "Username: %s", redirection->Username);
@ -273,7 +314,7 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
if (redirection->flags & LB_DOMAIN)
{
if (!rdp_redirection_read_string(s, &(redirection->Domain)))
if (!rdp_redirection_read_unicode_string(s, &(redirection->Domain), 52))
return FALSE;
WLog_DBG(TAG, "Domain: %s", redirection->Domain);
@ -281,12 +322,45 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
if (redirection->flags & LB_PASSWORD)
{
/* Note: length (hopefully) includes double zero termination */
/* Note: Password is a variable-length array of bytes containing the
* password used by the user in Unicode format, including a null-terminator
* or (!) or a cookie value that MUST be passed to the target server on
* successful connection.
* Since the format of the password cookie (probably some salted hash) is
* currently unknown we'll treat it as opaque data. All cookies seen so far
* are 120 bytes including \0\0 termination.
* Here is an observed example of a redirection password cookie:
*
* 0000 02 00 00 80 44 53 48 4c 60 ab 69 2f 07 d6 9e 2d ....DSHL`.i/...-
* 0010 f0 3a 97 3b a9 c5 ec 7e 66 bd b3 84 6c b1 ef b9 .:.;...~f...l...
* 0020 b6 82 4e cc 3a df 64 b7 7b 25 04 54 c2 58 98 f8 ..N.:.d.{%.T.X..
* 0030 97 87 d4 93 c7 c1 e1 5b c2 85 f8 22 49 1f 81 88 .......[..."I...
* 0040 43 44 83 f6 9a 72 40 24 dc 4d 43 cb d9 92 3c 8f CD...r@$.MC...<.
* 0050 3a 37 5c 77 13 a0 72 3c 72 08 64 2a 29 fb dc eb :7\w..r<r.d*)...
* 0060 0d 2b 06 b4 c6 08 b4 73 34 16 93 62 6d 24 e9 93 .+.....s4..bm$..
* 0070 97 27 7b dd 9a 72 00 00 .'{..r..
*
* Notwithstanding the above, we'll allocated an additional zero WCHAR at the
* end of the buffer which won't get counted in PasswordLength.
*/
if (Stream_GetRemainingLength(s) < 4)
return -1;
Stream_Read_UINT32(s, redirection->PasswordLength);
redirection->Password = (BYTE*) malloc(redirection->PasswordLength);
/* [MS-RDPBCGR] specifies 512 bytes as the upper limit for the password length
* including the null terminatior(s). This should also be enough for the unknown
* password cookie format (see previous comment).
*/
if (Stream_GetRemainingLength(s) < redirection->PasswordLength)
return -1;
if (redirection->PasswordLength > 512)
return -1;
redirection->Password = (BYTE*) calloc(1, redirection->PasswordLength + sizeof(WCHAR));
if (!redirection->Password)
return -1;
Stream_Read(s, redirection->Password, redirection->PasswordLength);
@ -297,7 +371,7 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
if (redirection->flags & LB_TARGET_FQDN)
{
if (!rdp_redirection_read_string(s, &(redirection->TargetFQDN)))
if (!rdp_redirection_read_unicode_string(s, &(redirection->TargetFQDN), 512))
return -1;
WLog_DBG(TAG, "TargetFQDN: %s", redirection->TargetFQDN);
@ -305,7 +379,7 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
if (redirection->flags & LB_TARGET_NETBIOS_NAME)
{
if (!rdp_redirection_read_string(s, &(redirection->TargetNetBiosName)))
if (!rdp_redirection_read_unicode_string(s, &(redirection->TargetNetBiosName), 32))
return -1;
WLog_DBG(TAG, "TargetNetBiosName: %s", redirection->TargetNetBiosName);
@ -352,7 +426,7 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
for (i = 0; i < (int) count; i++)
{
if (!rdp_redirection_read_string(s, &(redirection->TargetNetAddresses[i])))
if (!rdp_redirection_read_unicode_string(s, &(redirection->TargetNetAddresses[i]), 80))
return FALSE;
WLog_DBG(TAG, "TargetNetAddresses[%d]: %s", i, redirection->TargetNetAddresses[i]);
@ -371,13 +445,6 @@ BOOL rdp_recv_server_redirection_pdu(rdpRdp* rdp, wStream* s)
return 1;
}
int rdp_recv_redirection_packet(rdpRdp* rdp, wStream* s)
{
int status = 0;
status = rdp_recv_server_redirection_pdu(rdp, s);
return status;
}
int rdp_recv_enhanced_security_redirection_packet(rdpRdp* rdp, wStream* s)
{
int status = 0;

View File

@ -493,40 +493,46 @@ rdpSettings* freerdp_settings_new(DWORD flags)
if(!settings->DynamicChannelArray)
goto out_fail;
settings->HomePath = GetKnownPath(KNOWN_PATH_HOME);
if (!settings->HomePath)
goto out_fail;
/* For default FreeRDP continue using same config directory
* as in old releases.
* Custom builds use <Vendor>/<Product> as config folder. */
if (_stricmp(FREERDP_VENDOR_STRING, FREERDP_PRODUCT_STRING))
if (!settings->ServerMode)
{
base = GetKnownSubPath(KNOWN_PATH_XDG_CONFIG_HOME,
FREERDP_VENDOR_STRING);
if (base)
/* these values are used only by the client part */
settings->HomePath = GetKnownPath(KNOWN_PATH_HOME);
if (!settings->HomePath)
goto out_fail;
/* For default FreeRDP continue using same config directory
* as in old releases.
* Custom builds use <Vendor>/<Product> as config folder. */
if (_stricmp(FREERDP_VENDOR_STRING, FREERDP_PRODUCT_STRING))
{
settings->ConfigPath = GetCombinedPath(
base,
FREERDP_PRODUCT_STRING);
base = GetKnownSubPath(KNOWN_PATH_XDG_CONFIG_HOME,
FREERDP_VENDOR_STRING);
if (base)
{
settings->ConfigPath = GetCombinedPath(
base,
FREERDP_PRODUCT_STRING);
}
free (base);
} else {
int i;
char product[sizeof(FREERDP_PRODUCT_STRING)];
memset(product, 0, sizeof(product));
for (i=0; i<sizeof(product); i++)
product[i] = tolower(FREERDP_PRODUCT_STRING[i]);
settings->ConfigPath = GetKnownSubPath(
KNOWN_PATH_XDG_CONFIG_HOME,
product);
}
free (base);
} else {
int i;
char product[sizeof(FREERDP_PRODUCT_STRING)];
memset(product, 0, sizeof(product));
for (i=0; i<sizeof(product); i++)
product[i] = tolower(FREERDP_PRODUCT_STRING[i]);
settings->ConfigPath = GetKnownSubPath(
KNOWN_PATH_XDG_CONFIG_HOME,
product);
if (!settings->ConfigPath)
goto out_fail;
}
if (!settings->ConfigPath)
goto out_fail;
settings_load_hkey_local_machine(settings);
settings->SettingsModified = (BYTE*) calloc(1, sizeof(rdpSettings) / 8 );

View File

@ -733,8 +733,7 @@ out_cleanup:
transport->layer = TRANSPORT_LAYER_CLOSED;
}
if (s->pool)
Stream_Release(s);
Stream_Release(s);
LeaveCriticalSection(&(transport->WriteLock));
return status;

View File

@ -371,6 +371,7 @@ BOOL update_recv_window_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_I
{
rdpContext* context = update->context;
rdpWindowUpdate* window = update->window;
BOOL result = TRUE;
if (Stream_GetRemainingLength(s) < 4)
return FALSE;
@ -382,20 +383,20 @@ BOOL update_recv_window_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_I
if (!update_read_window_icon_order(s, orderInfo, &window->window_icon))
return FALSE;
WLog_Print(update->log, WLOG_DEBUG, "WindowIcon");
IFCALL(window->WindowIcon, context, orderInfo, &window->window_icon);
IFCALLRET(window->WindowIcon, result, context, orderInfo, &window->window_icon);
}
else if (orderInfo->fieldFlags & WINDOW_ORDER_CACHED_ICON)
{
if (!update_read_window_cached_icon_order(s, orderInfo, &window->window_cached_icon))
return FALSE;
WLog_Print(update->log, WLOG_DEBUG, "WindowCachedIcon");
IFCALL(window->WindowCachedIcon, context, orderInfo, &window->window_cached_icon);
IFCALLRET(window->WindowCachedIcon, result, context, orderInfo, &window->window_cached_icon);
}
else if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_DELETED)
{
update_read_window_delete_order(s, orderInfo);
WLog_Print(update->log, WLOG_DEBUG, "WindowDelete");
IFCALL(window->WindowDelete, context, orderInfo);
IFCALLRET(window->WindowDelete, result, context, orderInfo);
}
else
{
@ -405,16 +406,16 @@ BOOL update_recv_window_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_I
if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW)
{
WLog_Print(update->log, WLOG_DEBUG, "WindowCreate");
IFCALL(window->WindowCreate, context, orderInfo, &window->window_state);
IFCALLRET(window->WindowCreate, result, context, orderInfo, &window->window_state);
}
else
{
WLog_Print(update->log, WLOG_DEBUG, "WindowUpdate");
IFCALL(window->WindowUpdate, context, orderInfo, &window->window_state);
IFCALLRET(window->WindowUpdate, result, context, orderInfo, &window->window_state);
}
}
return TRUE;
return result;
}
BOOL update_read_notification_icon_state_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, NOTIFY_ICON_STATE_ORDER* notify_icon_state)
@ -470,6 +471,7 @@ BOOL update_recv_notification_icon_info_order(rdpUpdate* update, wStream* s, WIN
{
rdpContext* context = update->context;
rdpWindowUpdate* window = update->window;
BOOL result = TRUE;
if (Stream_GetRemainingLength(s) < 8)
return FALSE;
@ -481,7 +483,7 @@ BOOL update_recv_notification_icon_info_order(rdpUpdate* update, wStream* s, WIN
{
update_read_notification_icon_delete_order(s, orderInfo);
WLog_Print(update->log, WLOG_DEBUG, "NotifyIconDelete");
IFCALL(window->NotifyIconDelete, context, orderInfo);
IFCALLRET(window->NotifyIconDelete, result, context, orderInfo);
}
else
{
@ -491,16 +493,16 @@ BOOL update_recv_notification_icon_info_order(rdpUpdate* update, wStream* s, WIN
if (orderInfo->fieldFlags & WINDOW_ORDER_STATE_NEW)
{
WLog_Print(update->log, WLOG_DEBUG, "NotifyIconCreate");
IFCALL(window->NotifyIconCreate, context, orderInfo, &window->notify_icon_state);
IFCALLRET(window->NotifyIconCreate, result, context, orderInfo, &window->notify_icon_state);
}
else
{
WLog_Print(update->log, WLOG_DEBUG, "NotifyIconUpdate");
IFCALL(window->NotifyIconUpdate, context, orderInfo, &window->notify_icon_state);
IFCALLRET(window->NotifyIconUpdate, result, context, orderInfo, &window->notify_icon_state);
}
}
return TRUE;
return result;
}
BOOL update_read_desktop_actively_monitored_order(wStream* s, WINDOW_ORDER_INFO* orderInfo, MONITORED_DESKTOP_ORDER* monitored_desktop)
@ -560,22 +562,23 @@ BOOL update_recv_desktop_info_order(rdpUpdate* update, wStream* s, WINDOW_ORDER_
{
rdpContext* context = update->context;
rdpWindowUpdate* window = update->window;
BOOL result = TRUE;
if (orderInfo->fieldFlags & WINDOW_ORDER_FIELD_DESKTOP_NONE)
{
update_read_desktop_non_monitored_order(s, orderInfo);
WLog_Print(update->log, WLOG_DEBUG, "NonMonitoredDesktop");
IFCALL(window->NonMonitoredDesktop, context, orderInfo);
IFCALLRET(window->NonMonitoredDesktop, result, context, orderInfo);
}
else
{
if (!update_read_desktop_actively_monitored_order(s, orderInfo, &window->monitored_desktop))
return FALSE;
WLog_Print(update->log, WLOG_DEBUG, "ActivelyMonitoredDesktop");
IFCALL(window->MonitoredDesktop, context, orderInfo, &window->monitored_desktop);
IFCALLRET(window->MonitoredDesktop, result, context, orderInfo, &window->monitored_desktop);
}
return TRUE;
return result;
}
BOOL update_recv_altsec_window_order(rdpUpdate* update, wStream* s)

View File

@ -65,14 +65,21 @@ UINT gdi_ResetGraphics(RdpgfxClientContext* context, RDPGFX_RESET_GRAPHICS_PDU*
if (!surface || !surface->outputMapped)
continue;
freerdp_client_codecs_reset(surface->codecs, FREERDP_CODEC_ALL);
if (!freerdp_client_codecs_reset(surface->codecs, FREERDP_CODEC_ALL,
surface->width, surface->height))
{
free (pSurfaceIds);
return ERROR_INTERNAL_ERROR;
}
region16_clear(&surface->invalidRegion);
}
free(pSurfaceIds);
freerdp_client_codecs_reset(gdi->codecs, FREERDP_CODEC_ALL);
if (!freerdp_client_codecs_reset(gdi->codecs, FREERDP_CODEC_ALL,
gdi->width, gdi->height))
return ERROR_INTERNAL_ERROR;
gdi->graphicsReset = TRUE;
@ -454,39 +461,38 @@ UINT gdi_SurfaceCommand_Planar(rdpGdi* gdi, RdpgfxClientContext* context, RDPGFX
*
* @return 0 on success, otherwise a Win32 error code
*/
UINT gdi_SurfaceCommand_H264(rdpGdi* gdi, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
static UINT gdi_SurfaceCommand_AVC420(rdpGdi* gdi, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
int status;
UINT32 i;
BYTE* DstData = NULL;
gdiGfxSurface* surface;
RDPGFX_H264_METABLOCK* meta;
RDPGFX_H264_BITMAP_STREAM* bs;
RDPGFX_AVC420_BITMAP_STREAM* bs;
surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
if (!surface)
return ERROR_INTERNAL_ERROR;
if (!freerdp_client_codecs_prepare(surface->codecs, FREERDP_CODEC_H264))
if (!freerdp_client_codecs_prepare(surface->codecs, FREERDP_CODEC_AVC420))
return ERROR_INTERNAL_ERROR;
bs = (RDPGFX_H264_BITMAP_STREAM*) cmd->extra;
bs = (RDPGFX_AVC420_BITMAP_STREAM*) cmd->extra;
if (!bs)
return ERROR_INTERNAL_ERROR;
meta = &(bs->meta);
DstData = surface->data;
status = h264_decompress(surface->codecs->h264, bs->data, bs->length, &DstData,
PIXEL_FORMAT_XRGB32, surface->scanline, surface->width, surface->height,
meta->regionRects, meta->numRegionRects);
status = avc420_decompress(surface->codecs->h264, bs->data, bs->length,
surface->data, PIXEL_FORMAT_XRGB32,
surface->scanline, surface->width,
surface->height, meta->regionRects,
meta->numRegionRects);
if (status < 0)
{
WLog_WARN(TAG, "h264_decompress failure: %d, ignoring update.", status);
WLog_WARN(TAG, "avc420_decompress failure: %d, ignoring update.", status);
return CHANNEL_RC_OK;
}
@ -501,6 +507,77 @@ UINT gdi_SurfaceCommand_H264(rdpGdi* gdi, RdpgfxClientContext* context, RDPGFX_S
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT gdi_SurfaceCommand_AVC444(rdpGdi* gdi, RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cmd)
{
int status;
UINT32 i;
gdiGfxSurface* surface;
RDPGFX_AVC444_BITMAP_STREAM* bs;
RDPGFX_AVC420_BITMAP_STREAM* avc1;
RDPGFX_H264_METABLOCK* meta1;
RDPGFX_AVC420_BITMAP_STREAM* avc2;
RDPGFX_H264_METABLOCK* meta2;
RECTANGLE_16* regionRects = NULL;
surface = (gdiGfxSurface*) context->GetSurfaceData(context, cmd->surfaceId);
if (!surface)
return ERROR_INTERNAL_ERROR;
if (!freerdp_client_codecs_prepare(surface->codecs, FREERDP_CODEC_AVC444))
return ERROR_INTERNAL_ERROR;
bs = (RDPGFX_AVC444_BITMAP_STREAM*) cmd->extra;
if (!bs)
return ERROR_INTERNAL_ERROR;
avc1 = &bs->bitstream[0];
avc2 = &bs->bitstream[1];
meta1 = &avc1->meta;
meta2 = &avc2->meta;
status = avc444_decompress(surface->codecs->h264, bs->LC,
meta1->regionRects, meta1->numRegionRects,
avc1->data, avc1->length,
meta2->regionRects, meta2->numRegionRects,
avc2->data, avc2->length,
surface->data, PIXEL_FORMAT_XRGB32,
surface->scanline, surface->width,
surface->height);
if (status < 0)
{
WLog_WARN(TAG, "avc444_decompress failure: %d, ignoring update.", status);
return CHANNEL_RC_OK;
}
for (i = 0; i < meta1->numRegionRects; i++)
{
region16_union_rect(&(surface->invalidRegion),
&(surface->invalidRegion),
&(meta1->regionRects[i]));
}
for (i = 0; i < meta2->numRegionRects; i++)
{
region16_union_rect(&(surface->invalidRegion),
&(surface->invalidRegion),
&(meta2->regionRects[i]));
}
if (!gdi->inGfxFrame)
gdi_UpdateSurfaces(gdi);
free(regionRects);
return CHANNEL_RC_OK;
}
/**
* Function description
*
@ -670,8 +747,12 @@ UINT gdi_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cm
status = gdi_SurfaceCommand_Planar(gdi, context, cmd);
break;
case RDPGFX_CODECID_H264:
status = gdi_SurfaceCommand_H264(gdi, context, cmd);
case RDPGFX_CODECID_AVC420:
status = gdi_SurfaceCommand_AVC420(gdi, context, cmd);
break;
case RDPGFX_CODECID_AVC444:
status = gdi_SurfaceCommand_AVC444(gdi, context, cmd);
break;
case RDPGFX_CODECID_ALPHA:
@ -683,6 +764,11 @@ UINT gdi_SurfaceCommand(RdpgfxClientContext* context, RDPGFX_SURFACE_COMMAND* cm
break;
case RDPGFX_CODECID_CAPROGRESSIVE_V2:
WLog_WARN(TAG, "SurfaceCommand %08X not implemented", cmd->codecId);
break;
default:
WLog_WARN(TAG, "Invalid SurfaceCommand %08X", cmd->codecId);
break;
}
@ -722,6 +808,13 @@ UINT gdi_CreateSurface(RdpgfxClientContext* context, RDPGFX_CREATE_SURFACE_PDU*
return CHANNEL_RC_NO_MEMORY;
}
if (!freerdp_client_codecs_reset(surface->codecs, FREERDP_CODEC_ALL,
createSurface->width, createSurface->height))
{
free (surface);
return ERROR_INTERNAL_ERROR;
}
surface->surfaceId = createSurface->surfaceId;
surface->width = (UINT32) createSurface->width;
surface->height = (UINT32) createSurface->height;
@ -788,7 +881,7 @@ UINT gdi_SolidFill(RdpgfxClientContext* context, RDPGFX_SOLID_FILL_PDU* solidFil
UINT32 color;
BYTE a, r, g, b;
int nWidth, nHeight;
RDPGFX_RECT16* rect;
RECTANGLE_16* rect;
gdiGfxSurface* surface;
RECTANGLE_16 invalidRect;
rdpGdi* gdi = (rdpGdi*) context->custom;
@ -842,7 +935,7 @@ UINT gdi_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFAC
UINT16 index;
BOOL sameSurface;
int nWidth, nHeight;
RDPGFX_RECT16* rectSrc;
RECTANGLE_16* rectSrc;
RDPGFX_POINT16* destPt;
RECTANGLE_16 invalidRect;
gdiGfxSurface* surfaceSrc;
@ -903,7 +996,7 @@ UINT gdi_SurfaceToSurface(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_SURFAC
*/
UINT gdi_SurfaceToCache(RdpgfxClientContext* context, RDPGFX_SURFACE_TO_CACHE_PDU* surfaceToCache)
{
RDPGFX_RECT16* rect;
RECTANGLE_16* rect;
gdiGfxSurface* surface;
gdiGfxCacheEntry* cacheEntry;
rdpGdi* gdi = (rdpGdi*) context->custom;

View File

@ -26,43 +26,368 @@
#include "prim_YUV.h"
static INLINE BYTE CLIP(INT32 X)
{
if (X > 255L)
return 255L;
if (X < 0L)
return 0L;
return X;
}
/**
* @brief general_YUV420CombineToYUV444
*
* @param pMainSrc Pointer to luma YUV420 data
* @param srcMainStep Step width in luma YUV420 data
* @param pAuxSrc Pointer to chroma YUV420 data
* @param srcAuxStep Step width in chroma YUV420 data
* @param pDst Pointer to YUV444 data
* @param dstStep Step width in YUV444 data
* @param roi Region of source to combine in destination.
*
* @return PRIMITIVES_SUCCESS on success, an error code otherwise.
*/
static pstatus_t general_YUV420CombineToYUV444(
const BYTE* pMainSrc[3], const UINT32 srcMainStep[3],
const BYTE* pAuxSrc[3], const UINT32 srcAuxStep[3],
BYTE* pDst[3], const UINT32 dstStep[3],
const prim_size_t* roi)
{
const UINT32 mod = 16;
UINT32 uY = 0;
UINT32 vY = 0;
UINT32 x, y;
UINT32 nWidth, nHeight;
UINT32 halfWidth, halfHeight;
const UINT32 oddY = 1;
const UINT32 evenY = 0;
const UINT32 oddX = 1;
const UINT32 evenX = 0;
/* The auxilary frame is aligned to multiples of 16x16.
* We need the padded height for B4 and B5 conversion. */
const UINT32 padHeigth = roi->height + 16 - roi->height % 16;
nWidth = roi->width;
nHeight = roi->height;
halfWidth = (nWidth ) / 2;
halfHeight = (nHeight) / 2;
if (pMainSrc)
{
/* Y data is already here... */
/* B1 */
for (y=0; y<nHeight; y++)
{
const BYTE* Ym = pMainSrc[0] + srcMainStep[0] * y;
BYTE* pY = pDst[0] + dstStep[0] * y;
memcpy(pY, Ym, nWidth);
}
/* The first half of U, V are already here part of this frame. */
/* B2 and B3 */
for (y=0; y<halfHeight; y++)
{
const UINT32 val2y = (2 * y + evenY);
const UINT32 val2y1 = val2y + oddY;
const BYTE* Um = pMainSrc[1] + srcMainStep[1] * y;
const BYTE* Vm = pMainSrc[2] + srcMainStep[2] * y;
BYTE* pU = pDst[1] + dstStep[1] * val2y;
BYTE* pV = pDst[2] + dstStep[2] * val2y;
BYTE* pU1 = pDst[1] + dstStep[1] * val2y1;
BYTE* pV1 = pDst[2] + dstStep[2] * val2y1;
for (x=0; x<halfWidth; x++)
{
const UINT32 val2x = 2*x + evenX;
const UINT32 val2x1 = val2x+oddX;
pU[val2x] = Um[x];
pV[val2x] = Vm[x];
pU[val2x1] = Um[x];
pV[val2x1] = Vm[x];
pU1[val2x] = Um[x];
pV1[val2x] = Vm[x];
pU1[val2x1] = Um[x];
pV1[val2x1] = Vm[x];
}
}
}
if (!pAuxSrc)
return PRIMITIVES_SUCCESS;
/* The second half of U and V is a bit more tricky... */
/* B4 and B5 */
for (y=0; y<padHeigth; y++)
{
const BYTE* Ya = pAuxSrc[0] + srcAuxStep[0] * y;
BYTE* pX;
if ((y) % mod < (mod + 1)/2)
{
const UINT32 pos = (2 * uY++ + oddY);
if (pos >= nHeight)
continue;
pX = pDst[1] + dstStep[1] * pos;
}
else
{
const UINT32 pos = (2 * vY++ + oddY);
if (pos >= nHeight)
continue;
pX = pDst[2] + dstStep[2] * pos;
}
memcpy(pX, Ya, nWidth);
}
/* B6 and B7 */
for (y=0; y<halfHeight; y++)
{
const UINT32 val2y = (y * 2 + evenY);
const BYTE* Ua = pAuxSrc[1] + srcAuxStep[1] * y;
const BYTE* Va = pAuxSrc[2] + srcAuxStep[2] * y;
BYTE* pU = pDst[1] + dstStep[1] * val2y;
BYTE* pV = pDst[2] + dstStep[2] * val2y;
for (x=0; x<halfWidth; x++)
{
const UINT32 val2x1 = (x * 2 + oddX);
pU[val2x1] = Ua[x];
pV[val2x1] = Va[x];
}
}
/* Filter */
for (y=0; y<halfHeight; y++)
{
const UINT32 val2y = (y * 2 + evenY);
const UINT32 val2y1 = val2y + oddY;
BYTE* pU1 = pDst[1] + dstStep[1] * val2y1;
BYTE* pV1 = pDst[2] + dstStep[2] * val2y1;
BYTE* pU = pDst[1] + dstStep[1] * val2y;
BYTE* pV = pDst[2] + dstStep[2] * val2y;
if (val2y1 > nHeight)
continue;
for (x=0; x<halfWidth; x++)
{
const UINT32 val2x = (x * 2);
const UINT32 val2x1 = val2x + 1;
const INT32 up = pU[val2x] * 4;
const INT32 vp = pV[val2x] * 4;
INT32 u2020;
INT32 v2020;
if (val2x1 > nWidth)
continue;
u2020 = up - pU[val2x1] - pU1[val2x] - pU1[val2x1];
v2020 = vp - pV[val2x1] - pV1[val2x] - pV1[val2x1];
pU[val2x] = CLIP(u2020);
pV[val2x] = CLIP(v2020);
}
}
return PRIMITIVES_SUCCESS;
}
static pstatus_t general_YUV444SplitToYUV420(
const BYTE* pSrc[3], const UINT32 srcStep[3],
BYTE* pMainDst[3], const UINT32 dstMainStep[3],
BYTE* pAuxDst[3], const UINT32 dstAuxStep[3],
const prim_size_t* roi)
{
UINT32 x, y, uY = 0, vY = 0;
UINT32 halfWidth, halfHeight;
/* The auxilary frame is aligned to multiples of 16x16.
* We need the padded height for B4 and B5 conversion. */
const UINT32 padHeigth = roi->height + 16 - roi->height % 16;
halfWidth = (roi->width + 1) / 2;
halfHeight = (roi->height + 1) / 2;
/* B1 */
for (y=0; y<roi->height; y++)
{
const BYTE* pSrcY = pSrc[0] + y * srcStep[0];
BYTE* pY = pMainDst[0] + y * dstMainStep[0];
memcpy(pY, pSrcY, roi->width);
}
/* B2 and B3 */
for (y=0; y<halfHeight; y++)
{
const BYTE* pSrcU = pSrc[1] + 2 * y * srcStep[1];
const BYTE* pSrcV = pSrc[2] + 2 * y * srcStep[2];
const BYTE* pSrcU1 = pSrc[1] + (2 * y + 1) * srcStep[1];
const BYTE* pSrcV1 = pSrc[2] + (2 * y + 1) * srcStep[2];
BYTE* pU = pMainDst[1] + y * dstMainStep[1];
BYTE* pV = pMainDst[2] + y * dstMainStep[2];
for (x=0; x<halfWidth; x++)
{
/* Filter */
const INT32 u = pSrcU[2*x] + pSrcU[2*x+1] + pSrcU1[2*x]
+ pSrcU1[2*x+1];
const INT32 v = pSrcV[2*x] + pSrcV[2*x+1] + pSrcV1[2*x]
+ pSrcV1[2*x+1];
pU[x] = CLIP(u / 4L);
pV[x] = CLIP(v / 4L);
}
}
/* B4 and B5 */
for (y=0; y<padHeigth; y++)
{
BYTE* pY = pAuxDst[0] + y * dstAuxStep[0];
if (y % 16 < 8)
{
const UINT32 pos = (2 * uY++ + 1);
const BYTE* pSrcU = pSrc[1] + pos * srcStep[1];
if (pos >= roi->height)
continue;
memcpy(pY, pSrcU, roi->width);
}
else
{
const UINT32 pos = (2 * vY++ + 1);
const BYTE* pSrcV = pSrc[2] + pos * srcStep[2];
if (pos >= roi->height)
continue;
memcpy(pY, pSrcV, roi->width);
}
}
/* B6 and B7 */
for (y=0; y<halfHeight; y++)
{
const BYTE* pSrcU = pSrc[1] + 2 * y * srcStep[1];
const BYTE* pSrcV = pSrc[2] + 2 * y * srcStep[2];
BYTE* pU = pAuxDst[1] + y * dstAuxStep[1];
BYTE* pV = pAuxDst[2] + y * dstAuxStep[2];
for (x=0; x<halfWidth; x++)
{
pU[x] = pSrcU[2*x+1];
pV[x] = pSrcV[2*x+1];
}
}
return PRIMITIVES_SUCCESS;
}
/**
* | R | ( | 256 0 403 | | Y | )
* | G | = ( | 256 -48 -120 | | U - 128 | ) >> 8
* | B | ( | 256 475 0 | | V - 128 | )
*/
static INLINE INT32 C(INT32 Y)
{
return (Y) - 0L;
}
static INLINE INT32 D(INT32 U)
{
return (U) - 128L;
}
static INLINE INT32 E(INT32 V)
{
return (V) - 128L;
}
static INLINE BYTE YUV2R(INT32 Y, INT32 U, INT32 V)
{
const INT32 r = ( 256L * C(Y) + 0L * D(U) + 403L * E(V));
const INT32 r8 = r >> 8L;
return CLIP(r8);
}
static INLINE BYTE YUV2G(INT32 Y, INT32 U, INT32 V)
{
const INT32 g = ( 256L * C(Y) - 48L * D(U) - 120L * E(V));
const INT32 g8 = g >> 8L;
return CLIP(g8);
}
static INLINE BYTE YUV2B(INT32 Y, INT32 U, INT32 V)
{
const INT32 b = ( 256L * C(Y) + 475L * D(U) + 0L * E(V));
const INT32 b8 = b >> 8L;
return CLIP(b8);
}
static pstatus_t general_YUV444ToRGB_8u_P3AC4R(
const BYTE* pSrc[3], const UINT32 srcStep[3],
BYTE* pDst, UINT32 dstStep, const prim_size_t* roi)
{
UINT32 x, y;
UINT32 nWidth, nHeight;
nWidth = roi->width;
nHeight = roi->height;
for (y = 0; y < nHeight; y++)
{
const BYTE* pY = pSrc[0] + y * srcStep[0];
const BYTE* pU = pSrc[1] + y * srcStep[1];
const BYTE* pV = pSrc[2] + y * srcStep[2];
BYTE* pRGB = pDst + y * dstStep;
for (x = 0; x < nWidth; x++)
{
const BYTE Y = pY[x];
const INT32 U = pU[x];
const INT32 V = pV[x];
pRGB[4*x+0] = YUV2B(Y, U, V);
pRGB[4*x+1] = YUV2G(Y, U, V);
pRGB[4*x+2] = YUV2R(Y, U, V);
pRGB[4*x+3] = 0xFF;
}
}
return PRIMITIVES_SUCCESS;
}
/**
* | R | ( | 256 0 403 | | Y | )
* | G | = ( | 256 -48 -120 | | U - 128 | ) >> 8
* | B | ( | 256 475 0 | | V - 128 | )
*
* | Y | ( | 54 183 18 | | R | ) | 0 |
* | U | = ( | -29 -99 128 | | G | ) >> 8 + | 128 |
* | V | ( | 128 -116 -12 | | B | ) | 128 |
*/
pstatus_t general_YUV420ToRGB_8u_P3AC4R(const BYTE* pSrc[3], int srcStep[3],
BYTE* pDst, int dstStep, const prim_size_t* roi)
static pstatus_t general_YUV420ToRGB_8u_P3AC4R(
const BYTE* pSrc[3], const UINT32 srcStep[3],
BYTE* pDst, UINT32 dstStep, const prim_size_t* roi)
{
int x, y;
int dstPad;
int srcPad[3];
UINT32 x, y;
UINT32 dstPad;
UINT32 srcPad[3];
BYTE Y, U, V;
int halfWidth;
int halfHeight;
UINT32 halfWidth;
UINT32 halfHeight;
const BYTE* pY;
const BYTE* pU;
const BYTE* pV;
int R, G, B;
int Yp, Up, Vp;
int Up48, Up475;
int Vp403, Vp120;
BYTE* pRGB = pDst;
int nWidth, nHeight;
int lastRow, lastCol;
UINT32 nWidth, nHeight;
UINT32 lastRow, lastCol;
pY = pSrc[0];
pU = pSrc[1];
pV = pSrc[2];
lastCol = roi->width & 0x01;
lastRow = roi->height & 0x01;
nWidth = (roi->width + 1) & ~0x0001;
nHeight = (roi->height + 1) & ~0x0001;
@ -88,73 +413,22 @@ pstatus_t general_YUV420ToRGB_8u_P3AC4R(const BYTE* pSrc[3], int srcStep[3],
U = *pU++;
V = *pV++;
Up = U - 128;
Vp = V - 128;
Up48 = 48 * Up;
Up475 = 475 * Up;
Vp403 = Vp * 403;
Vp120 = Vp * 120;
/* 1st pixel */
Y = *pY++;
Yp = Y << 8;
R = (Yp + Vp403) >> 8;
G = (Yp - Up48 - Vp120) >> 8;
B = (Yp + Up475) >> 8;
if (R < 0)
R = 0;
else if (R > 255)
R = 255;
if (G < 0)
G = 0;
else if (G > 255)
G = 255;
if (B < 0)
B = 0;
else if (B > 255)
B = 255;
*pRGB++ = (BYTE) B;
*pRGB++ = (BYTE) G;
*pRGB++ = (BYTE) R;
*pRGB++ = YUV2B(Y, U, V);
*pRGB++ = YUV2G(Y, U, V);
*pRGB++ = YUV2R(Y, U, V);
*pRGB++ = 0xFF;
/* 2nd pixel */
if (!(lastCol & 0x02))
{
Y = *pY++;
Yp = Y << 8;
R = (Yp + Vp403) >> 8;
G = (Yp - Up48 - Vp120) >> 8;
B = (Yp + Up475) >> 8;
if (R < 0)
R = 0;
else if (R > 255)
R = 255;
if (G < 0)
G = 0;
else if (G > 255)
G = 255;
if (B < 0)
B = 0;
else if (B > 255)
B = 255;
*pRGB++ = (BYTE) B;
*pRGB++ = (BYTE) G;
*pRGB++ = (BYTE) R;
*pRGB++ = YUV2B(Y, U, V);
*pRGB++ = YUV2G(Y, U, V);
*pRGB++ = YUV2R(Y, U, V);
*pRGB++ = 0xFF;
}
else
@ -170,6 +444,9 @@ pstatus_t general_YUV420ToRGB_8u_P3AC4R(const BYTE* pSrc[3], int srcStep[3],
pV -= halfWidth;
pRGB += dstPad;
if (lastRow & 0x02)
break;
for (x = 0; x < halfWidth; )
{
if (++x == halfWidth)
@ -178,73 +455,22 @@ pstatus_t general_YUV420ToRGB_8u_P3AC4R(const BYTE* pSrc[3], int srcStep[3],
U = *pU++;
V = *pV++;
Up = U - 128;
Vp = V - 128;
Up48 = 48 * Up;
Up475 = 475 * Up;
Vp403 = Vp * 403;
Vp120 = Vp * 120;
/* 3rd pixel */
Y = *pY++;
Yp = Y << 8;
R = (Yp + Vp403) >> 8;
G = (Yp - Up48 - Vp120) >> 8;
B = (Yp + Up475) >> 8;
if (R < 0)
R = 0;
else if (R > 255)
R = 255;
if (G < 0)
G = 0;
else if (G > 255)
G = 255;
if (B < 0)
B = 0;
else if (B > 255)
B = 255;
*pRGB++ = (BYTE) B;
*pRGB++ = (BYTE) G;
*pRGB++ = (BYTE) R;
*pRGB++ = YUV2B(Y, U, V);
*pRGB++ = YUV2G(Y, U, V);
*pRGB++ = YUV2R(Y, U, V);
*pRGB++ = 0xFF;
/* 4th pixel */
if (!(lastCol & 0x02))
{
Y = *pY++;
Yp = Y << 8;
R = (Yp + Vp403) >> 8;
G = (Yp - Up48 - Vp120) >> 8;
B = (Yp + Up475) >> 8;
if (R < 0)
R = 0;
else if (R > 255)
R = 255;
if (G < 0)
G = 0;
else if (G > 255)
G = 255;
if (B < 0)
B = 0;
else if (B > 255)
B = 255;
*pRGB++ = (BYTE) B;
*pRGB++ = (BYTE) G;
*pRGB++ = (BYTE) R;
*pRGB++ = YUV2B(Y, U, V);
*pRGB++ = YUV2G(Y, U, V);
*pRGB++ = YUV2R(Y, U, V);
*pRGB++ = 0xFF;
}
else
@ -264,102 +490,142 @@ pstatus_t general_YUV420ToRGB_8u_P3AC4R(const BYTE* pSrc[3], int srcStep[3],
return PRIMITIVES_SUCCESS;
}
pstatus_t general_RGBToYUV420_8u_P3AC4R(const BYTE* pSrc, INT32 srcStep,
BYTE* pDst[3], INT32 dstStep[3], const prim_size_t* roi)
/**
* | Y | ( | 54 183 18 | | R | ) | 0 |
* | U | = ( | -29 -99 128 | | G | ) >> 8 + | 128 |
* | V | ( | 128 -116 -12 | | B | ) | 128 |
*/
static INLINE BYTE RGB2Y(INT32 R, INT32 G, INT32 B)
{
int x, y;
int dstPad[3];
int halfWidth;
int halfHeight;
BYTE* pY;
BYTE* pU;
BYTE* pV;
int Y, U, V;
int R, G, B;
int Ra, Ga, Ba;
const BYTE* pRGB;
int nWidth, nHeight;
const INT32 y = ( 54L * (R) + 183L * (G) + 18L * (B));
const INT32 y8 = (y >> 8L);
pU = pDst[1];
pV = pDst[2];
return CLIP(y8);
}
nWidth = (roi->width + 1) & ~0x0001;
nHeight = (roi->height + 1) & ~0x0001;
static INLINE BYTE RGB2U(INT32 R, INT32 G, INT32 B)
{
const INT32 u = ( -29L * (R) - 99L * (G) + 128L * (B));
const INT32 u8 = (u >> 8L) + 128L;
halfWidth = nWidth / 2;
halfHeight = nHeight / 2;
return CLIP(u8);
}
dstPad[0] = (dstStep[0] - nWidth);
dstPad[1] = (dstStep[1] - halfWidth);
dstPad[2] = (dstStep[2] - halfWidth);
static INLINE BYTE RGB2V(INT32 R, INT32 G, INT32 B)
{
const INT32 v = ( 128L * (R) - 116L * (G) - 12L * (B));
const INT32 v8 = (v >> 8L) + 128L;
return CLIP(v8);
}
static pstatus_t general_RGBToYUV444_8u_P3AC4R(
const BYTE* pSrc, const UINT32 srcStep,
BYTE* pDst[3], UINT32 dstStep[3], const prim_size_t* roi)
{
UINT32 x, y;
UINT32 nWidth, nHeight;
nWidth = roi->width;
nHeight = roi->height;
for (y=0; y<nHeight; y++)
{
const BYTE* pRGB = pSrc + y * srcStep;
BYTE* pY = pDst[0] + y * dstStep[0];
BYTE* pU = pDst[1] + y * dstStep[1];
BYTE* pV = pDst[2] + y * dstStep[2];
for (x=0; x<nWidth; x++)
{
const BYTE B = pRGB[4*x+0];
const BYTE G = pRGB[4*x+1];
const BYTE R = pRGB[4*x+2];
pY[x] = RGB2Y(R, G, B);
pU[x] = RGB2U(R, G, B);
pV[x] = RGB2V(R, G, B);
}
}
return PRIMITIVES_SUCCESS;
}
static pstatus_t general_RGBToYUV420_8u_P3AC4R(
const BYTE* pSrc, UINT32 srcStep,
BYTE* pDst[3], UINT32 dstStep[3], const prim_size_t* roi)
{
UINT32 x, y;
UINT32 halfWidth;
UINT32 halfHeight;
UINT32 nWidth, nHeight;
nWidth = roi->width + roi->width % 2;
nHeight = roi->height + roi->height % 2;
halfWidth = (nWidth + nWidth % 2) / 2;
halfHeight = (nHeight + nHeight % 2) / 2;
for (y = 0; y < halfHeight; y++)
{
const UINT32 val2y = (y * 2);
const UINT32 val2y1 = val2y + 1;
const BYTE* pRGB = pSrc + val2y * srcStep;
const BYTE* pRGB1 = pSrc + val2y1 * srcStep;
BYTE* pY = pDst[0] + val2y * dstStep[0];
BYTE* pY1 = pDst[0] + val2y1 * dstStep[0];
BYTE* pU = pDst[1] + y * dstStep[1];
BYTE* pV = pDst[2] + y * dstStep[2];
for (x = 0; x < halfWidth; x++)
{
/* 1st pixel */
pRGB = pSrc + y * 2 * srcStep + x * 2 * 4;
pY = pDst[0] + y * 2 * dstStep[0] + x * 2;
Ba = B = pRGB[0];
Ga = G = pRGB[1];
Ra = R = pRGB[2];
Y = (54 * R + 183 * G + 18 * B) >> 8;
pY[0] = (BYTE) Y;
INT32 R, G, B;
INT32 Ra, Ga, Ba;
const UINT32 val2x = (x * 2);
const UINT32 val2x1 = val2x + 1;
if (x * 2 + 1 < roi->width)
/* 1st pixel */
Ba = B = pRGB[val2x * 4 + 0];
Ga = G = pRGB[val2x * 4 + 1];
Ra = R = pRGB[val2x * 4 + 2];
pY[val2x] = RGB2Y(R, G, B);
if (val2x1 < nWidth)
{
/* 2nd pixel */
Ba += B = pRGB[4];
Ga += G = pRGB[5];
Ra += R = pRGB[6];
Y = (54 * R + 183 * G + 18 * B) >> 8;
pY[1] = (BYTE) Y;
Ba += B = pRGB[val2x * 4 + 4];
Ga += G = pRGB[val2x * 4 + 5];
Ra += R = pRGB[val2x * 4 + 6];
pY[val2x1] = RGB2Y(R, G, B);
}
if (y * 2 + 1 < roi->height)
if (val2y1 < nHeight)
{
/* 3rd pixel */
pRGB += srcStep;
pY += dstStep[0];
Ba += B = pRGB[0];
Ga += G = pRGB[1];
Ra += R = pRGB[2];
Y = (54 * R + 183 * G + 18 * B) >> 8;
pY[0] = (BYTE) Y;
Ba += B = pRGB1[val2x * 4 + 0];
Ga += G = pRGB1[val2x * 4 + 1];
Ra += R = pRGB1[val2x * 4 + 2];
pY1[val2x] = RGB2Y(R, G, B);
if (x * 2 + 1 < roi->width)
if (val2x1 < nWidth)
{
/* 4th pixel */
Ba += B = pRGB[4];
Ga += G = pRGB[5];
Ra += R = pRGB[6];
Y = (54 * R + 183 * G + 18 * B) >> 8;
pY[1] = (BYTE) Y;
Ba += B = pRGB1[val2x * 4 + 4];
Ga += G = pRGB1[val2x * 4 + 5];
Ra += R = pRGB1[val2x * 4 + 6];
pY1[val2x1] = RGB2Y(R, G, B);
}
}
/* U */
Ba >>= 2;
Ga >>= 2;
Ra >>= 2;
U = ((-29 * Ra - 99 * Ga + 128 * Ba) >> 8) + 128;
if (U < 0)
U = 0;
else if (U > 255)
U = 255;
*pU++ = (BYTE) U;
/* V */
V = ((128 * Ra - 116 * Ga - 12 * Ba) >> 8) + 128;
if (V < 0)
V = 0;
else if (V > 255)
V = 255;
*pV++ = (BYTE) V;
pU[x] = RGB2U(Ra, Ga, Ba);
pV[x] = RGB2V(Ra, Ga, Ba);
}
pU += dstPad[1];
pV += dstPad[2];
}
return PRIMITIVES_SUCCESS;
@ -368,8 +634,12 @@ pstatus_t general_RGBToYUV420_8u_P3AC4R(const BYTE* pSrc, INT32 srcStep,
void primitives_init_YUV(primitives_t* prims)
{
prims->YUV420ToRGB_8u_P3AC4R = general_YUV420ToRGB_8u_P3AC4R;
prims->YUV444ToRGB_8u_P3AC4R = general_YUV444ToRGB_8u_P3AC4R;
prims->RGBToYUV420_8u_P3AC4R = general_RGBToYUV420_8u_P3AC4R;
prims->RGBToYUV444_8u_P3AC4R = general_RGBToYUV444_8u_P3AC4R;
prims->YUV420CombineToYUV444 = general_YUV420CombineToYUV444;
prims->YUV444SplitToYUV420 = general_YUV444SplitToYUV420;
primitives_init_YUV_opt(prims);
}

View File

@ -22,27 +22,27 @@
#include <emmintrin.h>
#include <tmmintrin.h>
pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, int *srcStep,
BYTE *pDst, int dstStep, const prim_size_t *roi)
pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, const UINT32 *srcStep,
BYTE *pDst, UINT32 dstStep, const prim_size_t *roi)
{
int lastRow, lastCol;
UINT32 lastRow, lastCol;
BYTE *UData,*VData,*YData;
int i,nWidth,nHeight,VaddDst,VaddY,VaddU,VaddV;
UINT32 i,nWidth,nHeight,VaddDst,VaddY,VaddU,VaddV;
__m128i r0,r1,r2,r3,r4,r5,r6,r7;
__m128i *buffer;
/* last_line: if the last (U,V doubled) line should be skipped, set to 10B
* last_column: if it's the last column in a line, set to 10B (for handling line-endings not multiple by four) */
buffer = _aligned_malloc(4 * 16, 16);
YData = (BYTE*) pSrc[0];
UData = (BYTE*) pSrc[1];
VData = (BYTE*) pSrc[2];
nWidth = roi->width;
nHeight = roi->height;
if ((lastCol = (nWidth & 3)))
{
switch (lastCol)
@ -63,26 +63,26 @@ pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, int *srcStep,
_mm_store_si128(buffer+3,r7);
lastCol = 1;
}
nWidth += 3;
nWidth = nWidth >> 2;
lastRow = nHeight & 1;
nHeight++;
nHeight = nHeight >> 1;
VaddDst = (dstStep << 1) - (nWidth << 4);
VaddY = (srcStep[0] << 1) - (nWidth << 2);
VaddU = srcStep[1] - (((nWidth << 1) + 2) & 0xFFFC);
VaddV = srcStep[2] - (((nWidth << 1) + 2) & 0xFFFC);
while (nHeight-- > 0)
{
if (nHeight == 0)
lastRow <<= 1;
i = 0;
do
{
if (!(i & 0x01))
@ -97,16 +97,16 @@ pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, int *srcStep,
r0 = _mm_cvtsi32_si128(*(UINT32 *)UData);
r5 = _mm_set_epi32(0x80038003,0x80028002,0x80018001,0x80008000);
r0 = _mm_shuffle_epi8(r0,r5);
UData += 4;
/* then we subtract 128 from each value, so we get D */
r3 = _mm_set_epi16(128,128,128,128,128,128,128,128);
r0 = _mm_subs_epi16(r0,r3);
/* we need to do two things with our D, so let's store it for later use */
r2 = r0;
/* now we can multiply our D with 48 and unpack it to xmm4:xmm0
* this is what we need to get G data later on */
r4 = r0;
@ -116,7 +116,7 @@ pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, int *srcStep,
r7 = r0;
r0 = _mm_unpacklo_epi16(r0,r4);
r4 = _mm_unpackhi_epi16(r7,r4);
/* to get B data, we need to prepare a second value, D*475 */
r1 = r2;
r7 = _mm_set_epi16(475,475,475,475,475,475,475,475);
@ -125,23 +125,23 @@ pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, int *srcStep,
r7 = r1;
r1 = _mm_unpacklo_epi16(r1,r2);
r7 = _mm_unpackhi_epi16(r7,r2);
/* so we got something like this: xmm7:xmm1
* this pair contains values for 16 pixel:
* aabbccdd
* aabbccdd, but we can only work on four pixel at once, so we need to save upper values */
_mm_store_si128(buffer+1,r7);
/* Now we've prepared U-data. Preparing V-data is actually the same, just with other coefficients */
r2 = _mm_cvtsi32_si128(*(UINT32 *)VData);
r2 = _mm_shuffle_epi8(r2,r5);
VData += 4;
r2 = _mm_subs_epi16(r2,r3);
r5 = r2;
/* this is also known as E*403, we need it to convert R data */
r3 = r2;
r7 = _mm_set_epi16(403,403,403,403,403,403,403,403);
@ -150,10 +150,10 @@ pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, int *srcStep,
r7 = r2;
r2 = _mm_unpacklo_epi16(r2,r3);
r7 = _mm_unpackhi_epi16(r7,r3);
/* and preserve upper four values for future ... */
_mm_store_si128(buffer+2,r7);
/* doing this step: E*120 */
r3 = r5;
r7 = _mm_set_epi16(120,120,120,120,120,120,120,120);
@ -162,12 +162,12 @@ pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, int *srcStep,
r7 = r3;
r3 = _mm_unpacklo_epi16(r3,r5);
r7 = _mm_unpackhi_epi16(r7,r5);
/* now we complete what we've begun above:
* (48*D) + (120*E) = (48*D +120*E) */
r0 = _mm_add_epi32(r0,r3);
r4 = _mm_add_epi32(r4,r7);
/* and store to memory ! */
_mm_store_si128(buffer,r4);
}
@ -180,25 +180,25 @@ pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, int *srcStep,
r2 = _mm_load_si128(buffer+2);
r0 = _mm_load_si128(buffer);
}
if (++i == nWidth)
lastCol <<= 1;
/* We didn't produce any output yet, so let's do so!
* Ok, fetch four pixel from the Y-data array and shuffle them like this:
* 00d0 00c0 00b0 00a0, to get signed dwords and multiply by 256 */
r4 = _mm_cvtsi32_si128(*(UINT32 *)YData);
r7 = _mm_set_epi32(0x80800380,0x80800280,0x80800180,0x80800080);
r4 = _mm_shuffle_epi8(r4,r7);
r5 = r4;
r6 = r4;
/* no we can perform the "real" conversion itself and produce output! */
r4 = _mm_add_epi32(r4,r2);
r5 = _mm_sub_epi32(r5,r0);
r6 = _mm_add_epi32(r6,r1);
/* in the end, we only need bytes for RGB values.
* So, what do we do? right! shifting left makes values bigger and thats always good.
* before we had dwords of data, and by shifting left and treating the result
@ -208,7 +208,7 @@ pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, int *srcStep,
r4 = _mm_slli_epi32(r4,8);
r5 = _mm_slli_epi32(r5,8);
r6 = _mm_slli_epi32(r6,8);
/* one thing we still have to face is the clip() function ...
* we have still signed words, and there are those min/max instructions in SSE2 ...
* the max instruction takes always the bigger of the two operands and stores it in the first one,
@ -219,35 +219,35 @@ pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, int *srcStep,
r4 = _mm_max_epi16(r4,r7);
r5 = _mm_max_epi16(r5,r7);
r6 = _mm_max_epi16(r6,r7);
/* the same thing just completely different can be used to limit our values to 255,
* but now using the min instruction and 255s */
r7 = _mm_set_epi32(0x00FF0000,0x00FF0000,0x00FF0000,0x00FF0000);
r4 = _mm_min_epi16(r4,r7);
r5 = _mm_min_epi16(r5,r7);
r6 = _mm_min_epi16(r6,r7);
/* Now we got our bytes.
* the moment has come to assemble the three channels R,G and B to the xrgb dwords
* on Red channel we just have to and each futural dword with 00FF0000H */
//r7=_mm_set_epi32(0x00FF0000,0x00FF0000,0x00FF0000,0x00FF0000);
r4 = _mm_and_si128(r4,r7);
/* on Green channel we have to shuffle somehow, so we get something like this:
* 00d0 00c0 00b0 00a0 */
r7 = _mm_set_epi32(0x80800E80,0x80800A80,0x80800680,0x80800280);
r5 = _mm_shuffle_epi8(r5,r7);
/* and on Blue channel that one:
* 000d 000c 000b 000a */
r7 = _mm_set_epi32(0x8080800E,0x8080800A,0x80808006,0x80808002);
r6 = _mm_shuffle_epi8(r6,r7);
/* and at last we or it together and get this one:
* xrgb xrgb xrgb xrgb */
r4 = _mm_or_si128(r4,r5);
r4 = _mm_or_si128(r4,r6);
/* Only thing to do know is writing data to memory, but this gets a bit more
* complicated if the width is not a multiple of four and it is the last column in line. */
if (lastCol & 0x02)
@ -269,7 +269,7 @@ pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, int *srcStep,
r4 = _mm_or_si128(r4,r6);
}
_mm_storeu_si128((__m128i *)pDst,r4);
if (!(lastRow & 0x02))
{
/* Because UV data is the same for two lines, we can process the secound line just here,
@ -280,40 +280,40 @@ pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, int *srcStep,
r4 = _mm_cvtsi32_si128(*(UINT32 *)(YData+srcStep[0]));
r7 = _mm_set_epi32(0x80800380,0x80800280,0x80800180,0x80800080);
r4 = _mm_shuffle_epi8(r4,r7);
r5 = r4;
r6 = r4;
r4 = _mm_add_epi32(r4,r2);
r5 = _mm_sub_epi32(r5,r0);
r6 = _mm_add_epi32(r6,r1);
r4 = _mm_slli_epi32(r4,8);
r5 = _mm_slli_epi32(r5,8);
r6 = _mm_slli_epi32(r6,8);
r7 = _mm_set_epi32(0,0,0,0);
r4 = _mm_max_epi16(r4,r7);
r5 = _mm_max_epi16(r5,r7);
r6 = _mm_max_epi16(r6,r7);
r7 = _mm_set_epi32(0x00FF0000,0x00FF0000,0x00FF0000,0x00FF0000);
r4 = _mm_min_epi16(r4,r7);
r5 = _mm_min_epi16(r5,r7);
r6 = _mm_min_epi16(r6,r7);
r7 = _mm_set_epi32(0x00FF0000,0x00FF0000,0x00FF0000,0x00FF0000);
r4 = _mm_and_si128(r4,r7);
r7 = _mm_set_epi32(0x80800E80,0x80800A80,0x80800680,0x80800280);
r5 = _mm_shuffle_epi8(r5,r7);
r7 = _mm_set_epi32(0x8080800E,0x8080800A,0x80808006,0x80808002);
r6 = _mm_shuffle_epi8(r6,r7);
r4 = _mm_or_si128(r4,r5);
r4 = _mm_or_si128(r4,r6);
if (lastCol & 0x02)
{
r6 = _mm_load_si128(buffer+3);
@ -321,20 +321,20 @@ pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, int *srcStep,
r5 = _mm_lddqu_si128((__m128i *)(pDst+dstStep));
r6 = _mm_andnot_si128(r6,r5);
r4 = _mm_or_si128(r4,r6);
/* only thing is, we should shift [rbp-42] back here, because we have processed the last column,
* and this "special condition" can be released */
lastCol >>= 1;
}
_mm_storeu_si128((__m128i *)(pDst+dstStep),r4);
}
/* after all we have to increase the destination- and Y-data pointer by four pixel */
pDst += 16;
YData += 4;
}
while (i < nWidth);
/* after each line we have to add the scanline to the destination pointer, because
* we are processing two lines at once, but only increasing the destination pointer
* in the first line. Well, we only have one pointer, so it's the easiest way to access
@ -343,10 +343,10 @@ pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, int *srcStep,
* output buffer was "designed" for 1920p HD, we have to add the remaining length for each line,
* to get into the next line. */
pDst += VaddDst;
/* same thing has to be done for Y-data, but with iStride[0] instead of the target scanline */
YData += VaddY;
/* and again for UV data, but here it's enough to add the remaining length, because
* UV data is the same for two lines and there exists only one "UV line" on two "real lines" */
UData += VaddU;
@ -354,7 +354,7 @@ pstatus_t ssse3_YUV420ToRGB_8u_P3AC4R(const BYTE **pSrc, int *srcStep,
}
_aligned_free(buffer);
return PRIMITIVES_SUCCESS;
}
#endif

View File

@ -14,6 +14,7 @@ set(${MODULE_PREFIX}_TESTS
TestPrimitivesSet.c
TestPrimitivesShift.c
TestPrimitivesSign.c
TestPrimitivesYUV.c
TestPrimitivesYCbCr.c
TestPrimitivesYCoCg.c)

View File

@ -57,8 +57,10 @@ static BOOL try_16To32(
const UINT16 *src;
UINT32 ALIGN(outNN1[4096+3]), ALIGN(outAN1[4096+3]),
ALIGN(outNI1[4096+3]), ALIGN(outAI1[4096+3]);
#ifdef WITH_SSE2
UINT32 ALIGN(outNN2[4096+3]), ALIGN(outAN2[4096+3]),
ALIGN(outNI2[4096+3]), ALIGN(outAI2[4096+3]);
#endif
assert(sOffset < 4);
assert(dOffset < 4);
@ -161,7 +163,7 @@ int test_RGB565ToARGB_16u32u_C3C4_func(void)
STD_SPEED_TEST(
test16to32_speed, UINT16, UINT32, PRIM_NOP,
TRUE, general_RGB565ToARGB_16u32u_C3C4(
(const UINT16 *) src1, 64*2, (UINT32 *) dst, 64*4,
(const UINT16 *) src1, 64*2, (UINT32 *) dst, 64*4,
64,64, TRUE, TRUE),
#ifdef WITH_SSE2
TRUE, sse3_RGB565ToARGB_16u32u_C3C4(
@ -182,7 +184,7 @@ int test_RGB565ToARGB_16u32u_C3C4_speed(void)
get_random_data(src, sizeof(src));
test16to32_speed("16-to-32bpp", "aligned",
test16to32_speed("16-to-32bpp", "aligned",
(const UINT16 *) src, 0, 0, (UINT32 *) dst,
size_array, 1, RGB_TRIAL_ITERATIONS, TEST_TIME);
return SUCCESS;

View File

@ -38,12 +38,14 @@ extern pstatus_t ssse3_YCoCgRToRGB_8u_AC4R(const BYTE *pSrc, INT32 srcStep,
/* ------------------------------------------------------------------------- */
int test_YCoCgRToRGB_8u_AC4R_func(void)
{
#ifdef WITH_SSE2
int i;
INT32 ALIGN(out_sse[4098]), ALIGN(out_sse_inv[4098]);
#endif
INT32 ALIGN(in[4098]);
INT32 ALIGN(out_c[4098]), ALIGN(out_c_inv[4098]);
INT32 ALIGN(out_sse[4098]), ALIGN(out_sse_inv[4098]);
char testStr[256];
BOOL failed = FALSE;
int i;
testStr[0] = '\0';
get_random_data(in, sizeof(in));

View File

@ -0,0 +1,427 @@
#include "prim_test.h"
#include <winpr/wlog.h>
#include <winpr/crypto.h>
#include <freerdp/primitives.h>
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#define TAG __FILE__
/* YUV to RGB conversion is lossy, so consider every value only
* differing by less than 2 abs equal. */
static BOOL similar(const BYTE* src, const BYTE* dst, size_t size)
{
size_t x;
for (x=0; x<size; x++)
{
volatile double val1 = (double)src[x];
volatile double val2 = (double)dst[x];
volatile double diff = val1 - val2;
if (abs(diff) > 2)
{
fprintf(stderr, "%zd %02X : %02X diff=%lf\n", x, val1, val2, diff);
return FALSE;
}
}
return TRUE;
}
static void get_size(UINT32* width, UINT32* height)
{
winpr_RAND((BYTE*)width, sizeof(*width));
winpr_RAND((BYTE*)height, sizeof(*height));
// TODO: Algorithm only works on even resolutions...
*width = (*width % 4000) << 1;
*height = (*height % 4000 << 1);
}
static BOOL check_padding(const BYTE* psrc, size_t size, size_t padding, const char* buffer)
{
size_t x;
BOOL rc = TRUE;
const BYTE* src;
const BYTE* esrc;
size_t halfPad = (padding+1)/2;
if (!psrc)
return FALSE;
src = psrc - halfPad;
esrc = src + size + halfPad;
for (x=0; x<halfPad; x++)
{
const BYTE s = *src++;
const BYTE d = *esrc++;
if (s != 'A')
{
size_t start = x;
while((x < halfPad) && (*esrc++ != 'A'))
x++;
fprintf(stderr, "Buffer underflow detected %02x != %02X %s [%zd-%zd]\n",
d, 'A', buffer, start, x);
return FALSE;
}
if(d != 'A')
{
size_t start = x;
while((x < halfPad) && (*esrc++ != 'A'))
x++;
fprintf(stderr, "Buffer overflow detected %02x != %02X %s [%zd-%zd]\n",
d, 'A', buffer, start, x);
return FALSE;
}
}
return rc;
}
static void* set_padding(size_t size, size_t padding)
{
size_t halfPad = (padding + 1) / 2;
BYTE* psrc;
BYTE* src = calloc(1, size + 2 * halfPad);
if (!src)
return NULL;
memset(&src[0], 'A', halfPad);
memset(&src[halfPad+size], 'A', halfPad);
psrc = &src[halfPad];
if (!check_padding(psrc, size, padding, "init"))
{
free (src);
return NULL;
}
return psrc;
}
static void free_padding(void* src, size_t padding)
{
BYTE* ptr;
if (!src)
return;
ptr = ((BYTE*)src) - (padding+1)/2;
free(ptr);
}
/* Create 2 pseudo YUV420 frames of same size.
* Combine them and check, if the data is at the expected position. */
static BOOL TestPrimitiveYUVCombine(void)
{
UINT32 x, y, i;
UINT32 awidth, aheight;
BOOL rc = FALSE;
BYTE* luma[3] = { 0 };
BYTE* chroma[3] = { 0 };
BYTE* yuv[3] = { 0 };
BYTE* pmain[3] = { 0 };
BYTE* paux[3] = { 0 };
UINT32 lumaStride[3];
UINT32 chromaStride[3];
UINT32 yuvStride[3];
size_t padding = 10000;
prim_size_t roi;
primitives_t* prims = primitives_get();
get_size(&roi.width, &roi.height);
awidth = roi.width + 16 - roi.width % 16;
aheight = roi.height + 16 - roi.height % 16;
fprintf(stderr, "Running YUVCombine on frame size %lux%lu [%lux%lu]\n",
roi.width, roi.height, awidth, aheight);
if (!prims || !prims->YUV420CombineToYUV444)
goto fail;
for (x=0; x<3; x++)
{
size_t halfStride = ((x>0)?awidth/2:awidth);
size_t size = aheight * awidth;
size_t halfSize = ((x>0)?halfStride*aheight/2:awidth*aheight);
yuvStride[x] = awidth;
if (!(yuv[x] = set_padding(size, padding)))
goto fail;
lumaStride[x] = halfStride;
if (!(luma[x] = set_padding(halfSize, padding)))
goto fail;
if (!(pmain[x] = set_padding(halfSize, padding)))
goto fail;
chromaStride[x] = halfStride;
if (!(chroma[x] = set_padding(halfSize, padding)))
goto fail;
if (!(paux[x] = set_padding(halfSize, padding)))
goto fail;
memset(luma[x], 0xAB + 3*x, halfSize);
memset(chroma[x], 0x80 + 2*x, halfSize);
if (!check_padding(luma[x], halfSize, padding, "luma"))
goto fail;
if (!check_padding(chroma[x], halfSize, padding, "chroma"))
goto fail;
if (!check_padding(pmain[x], halfSize, padding, "main"))
goto fail;
if (!check_padding(paux[x], halfSize, padding, "aux"))
goto fail;
if (!check_padding(yuv[x], size, padding, "yuv"))
goto fail;
}
if (prims->YUV420CombineToYUV444((const BYTE**)luma, lumaStride,
(const BYTE**) chroma, chromaStride,
yuv, yuvStride, &roi) != PRIMITIVES_SUCCESS)
goto fail;
for (x=0; x<3; x++)
{
size_t halfStride = ((x>0)?awidth/2:awidth);
size_t size = aheight * awidth;
size_t halfSize = ((x>0)?halfStride*aheight/2:awidth*aheight);
if (!check_padding(luma[x], halfSize, padding, "luma"))
goto fail;
if (!check_padding(chroma[x], halfSize, padding, "chroma"))
goto fail;
if (!check_padding(yuv[x], size, padding, "yuv"))
goto fail;
}
if (prims->YUV444SplitToYUV420(yuv, yuvStride, pmain, lumaStride,
paux, chromaStride, &roi) != PRIMITIVES_SUCCESS)
goto fail;
for (x=0; x<3; x++)
{
size_t halfStride = ((x>0)?awidth/2:awidth);
size_t size = aheight * awidth;
size_t halfSize = ((x>0)?halfStride*aheight/2:awidth*aheight);
if (!check_padding(pmain[x], halfSize, padding, "main"))
goto fail;
if (!check_padding(paux[x], halfSize, padding, "aux"))
goto fail;
if (!check_padding(yuv[x], size, padding, "yuv"))
goto fail;
}
for (i=0; i<3; i++)
{
for (y=0; y<roi.height; y++)
{
UINT32 w = roi.width;
UINT32 lstride = lumaStride[i];
UINT32 cstride = chromaStride[i];
if (i > 0)
{
w = (roi.width+3) / 4;
if (roi.height > (roi.height+1)/2)
continue;
}
if (!similar(luma[i] + y * lstride,
pmain[i] + y * lstride,
w))
goto fail;
/* Need to ignore lines of destination Y plane,
* if the lines are not a multiple of 16
* as the UV planes are packed in 8 line stripes. */
if (i == 0)
{
/* TODO: This check is not perfect, it does not
* include the last V lines packed to the Y
* frame. */
UINT32 rem = roi.height % 16;
if (y > roi.height - rem)
continue;
}
if (!similar(chroma[i] + y * cstride,
paux[i] + y * cstride,
w))
goto fail;
}
}
rc = TRUE;
fail:
for (x=0; x<3; x++)
{
free_padding(yuv[x], padding);
free_padding(luma[x], padding);
free_padding(chroma[x], padding);
free_padding(pmain[x], padding);
free_padding(paux[x], padding);
}
return rc;
}
static BOOL TestPrimitiveYUV(BOOL use444)
{
BOOL rc = FALSE;
UINT32 x, y;
UINT32 awidth, aheight;
BYTE* yuv[3] = {0};
UINT32 yuv_step[3];
prim_size_t roi;
BYTE* rgb = NULL;
BYTE* rgb_dst = NULL;
size_t size;
primitives_t* prims = primitives_get();
size_t uvsize, uvwidth;
size_t padding = 10000;
size_t stride;
get_size(&roi.width, &roi.height);
/* Buffers need to be 16x16 aligned. */
awidth = roi.width + 16 - roi.width % 16;
aheight = roi.height + 16 - roi.height % 16;
stride = awidth * sizeof(UINT32);
size = awidth * aheight;
if (use444)
{
uvwidth = awidth;
uvsize = size;
if (!prims || !prims->RGBToYUV444_8u_P3AC4R || !prims->YUV444ToRGB_8u_P3AC4R)
return FALSE;
}
else
{
uvwidth = (awidth + 1) / 2;
uvsize = (aheight + 1) / 2 * uvwidth;
if (!prims || !prims->RGBToYUV420_8u_P3AC4R || !prims->YUV420ToRGB_8u_P3AC4R)
return FALSE;
}
fprintf(stderr, "Running AVC%s on frame size %lux%lu\n", use444 ? "444" : "420",
roi.width, roi.height);
/* Test RGB to YUV444 conversion and vice versa */
if (!(rgb = set_padding(size * sizeof(UINT32), padding)))
goto fail;
if (!(rgb_dst = set_padding(size * sizeof(UINT32), padding)))
goto fail;
if (!(yuv[0] = set_padding(size, padding)))
goto fail;
if (!(yuv[1] = set_padding(uvsize, padding)))
goto fail;
if (!(yuv[2] = set_padding(uvsize, padding)))
goto fail;
for (y=0; y<roi.height; y++)
{
BYTE* line = &rgb[y*stride];
for (x=0; x<roi.width; x++)
{
line[x*4+0] = 0x81;
line[x*4+1] = 0x33;
line[x*4+2] = 0xAB;
line[x*4+3] = 0xFF;
}
}
yuv_step[0] = awidth;
yuv_step[1] = uvwidth;
yuv_step[2] = uvwidth;
if (use444)
{
if (prims->RGBToYUV444_8u_P3AC4R(rgb, stride, yuv, yuv_step, &roi) != PRIMITIVES_SUCCESS)
goto fail;
}
else if (prims->RGBToYUV420_8u_P3AC4R(rgb, stride, yuv, yuv_step, &roi) != PRIMITIVES_SUCCESS)
goto fail;
if (!check_padding(rgb, size * sizeof(UINT32), padding, "rgb"))
goto fail;
if ((!check_padding(yuv[0], size, padding, "Y")) ||
(!check_padding(yuv[1], uvsize, padding, "U")) ||
(!check_padding(yuv[2], uvsize, padding, "V")))
goto fail;
if (use444)
{
if (prims->YUV444ToRGB_8u_P3AC4R((const BYTE**)yuv, yuv_step, rgb_dst, stride, &roi) != PRIMITIVES_SUCCESS)
goto fail;
}
else if (prims->YUV420ToRGB_8u_P3AC4R((const BYTE**)yuv, yuv_step, rgb_dst, stride, &roi) != PRIMITIVES_SUCCESS)
goto fail;
if (!check_padding(rgb_dst, size * sizeof(UINT32), padding, "rgb dst"))
goto fail;
if ((!check_padding(yuv[0], size, padding, "Y")) ||
(!check_padding(yuv[1], uvsize, padding, "U")) ||
(!check_padding(yuv[2], uvsize, padding, "V")))
goto fail;
for (y=0; y<roi.height; y++)
{
BYTE* srgb = &rgb[y*stride];
BYTE* drgb = &rgb_dst[y*stride];
if (!similar(srgb, drgb, roi.width*sizeof(UINT32)))
goto fail;
}
rc = TRUE;
fail:
free_padding (rgb, padding);
free_padding (rgb_dst, padding);
free_padding (yuv[0], padding);
free_padding (yuv[1], padding);
free_padding (yuv[2], padding);
return rc;
}
int TestPrimitivesYUV(int argc, char* argv[])
{
UINT32 x;
int rc = -1;
primitives_init();
for (x=0; x<10; x++)
{
/* TODO: This test fails on value comparison,
* there seems to be some issue left with encoder / decoder pass.
if (!TestPrimitiveYUV(FALSE))
goto end;
*/
if (!TestPrimitiveYUV(TRUE))
goto end;
if (!TestPrimitiveYUVCombine())
goto end;
}
rc = 0;
end:
primitives_deinit();
return rc;
}

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