Imported Upstream version 2.0.0~git75ae3f5
This commit is contained in:
parent
9a34f3e181
commit
7878df420c
@ -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
518
ChangeLog
@ -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
|
||||
|
||||
@ -522,6 +522,8 @@ static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* arg
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_audin_client_subsystem_entry alsa_freerdp_audin_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@ -82,7 +82,7 @@ struct _AUDIN_PLUGIN
|
||||
|
||||
/* Parsed plugin data */
|
||||
UINT16 fixed_format;
|
||||
UINT16 fixed_channel;
|
||||
UINT16 fixed_channel;
|
||||
UINT32 fixed_rate;
|
||||
char* subsystem;
|
||||
char* device_name;
|
||||
@ -93,6 +93,8 @@ struct _AUDIN_PLUGIN
|
||||
rdpContext* rdpcontext;
|
||||
};
|
||||
|
||||
static BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args);
|
||||
|
||||
/**
|
||||
* Function description
|
||||
*
|
||||
@ -639,8 +641,12 @@ static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDI
|
||||
{
|
||||
PFREERDP_AUDIN_DEVICE_ENTRY entry;
|
||||
FREERDP_AUDIN_DEVICE_ENTRY_POINTS entryPoints;
|
||||
AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*)pPlugin;
|
||||
UINT error;
|
||||
|
||||
if (!audin_process_addin_args(audin, args))
|
||||
return CHANNEL_RC_INITIALIZATION_ERROR;
|
||||
|
||||
entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_channel_addin_entry("audin", (LPSTR) name, NULL, 0);
|
||||
|
||||
if (entry == NULL)
|
||||
@ -660,6 +666,7 @@ static UINT audin_load_device_plugin(IWTSPlugin* pPlugin, const char* name, ADDI
|
||||
return error;
|
||||
}
|
||||
|
||||
WLog_INFO(TAG, "Loaded %s backend for audin", name);
|
||||
return CHANNEL_RC_OK;
|
||||
}
|
||||
|
||||
@ -707,18 +714,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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
/**
|
||||
|
||||
@ -485,6 +485,8 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice *device, ADDIN_ARGV *args)
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_audin_client_subsystem_entry oss_freerdp_audin_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@ -525,6 +525,8 @@ static UINT audin_pulse_parse_addin_args(AudinPulseDevice* device, ADDIN_ARGV* a
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_audin_client_subsystem_entry pulse_freerdp_audin_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@ -393,6 +393,8 @@ static UINT audin_winmm_parse_addin_args(AudinWinmmDevice* device, ADDIN_ARGV* a
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_audin_client_subsystem_entry winmm_freerdp_audin_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@ -102,16 +102,25 @@ UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data
|
||||
|
||||
formats[index].formatName = NULL;
|
||||
|
||||
/* According to MS-RDPECLIP 2.2.3.1.1.1 formatName is "a 32-byte block containing
|
||||
* the *null-terminated* name assigned to the Clipboard Format: (32 ASCII 8 characters
|
||||
* or 16 Unicode characters)"
|
||||
* However, both Windows RDSH and mstsc violate this specs as seen in the following
|
||||
* example of a transferred short format name string: [R.i.c.h. .T.e.x.t. .F.o.r.m.a.t.]
|
||||
* These are 16 unicode charaters - *without* terminating null !
|
||||
*/
|
||||
|
||||
if (asciiNames)
|
||||
{
|
||||
szFormatName = (char*) Stream_Pointer(s);
|
||||
|
||||
if (szFormatName[0])
|
||||
{
|
||||
/* ensure null termination */
|
||||
formats[index].formatName = (char*) malloc(32 + 1);
|
||||
if (!formats[index].formatName)
|
||||
{
|
||||
WLog_ERR(TAG, "calloc failed!");
|
||||
WLog_ERR(TAG, "malloc failed!");
|
||||
error = CHANNEL_RC_NO_MEMORY;
|
||||
goto error_out;
|
||||
}
|
||||
@ -125,8 +134,16 @@ UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data
|
||||
|
||||
if (wszFormatName[0])
|
||||
{
|
||||
ConvertFromUnicode(CP_UTF8, 0, wszFormatName,
|
||||
16, &(formats[index].formatName), 0, NULL, NULL);
|
||||
/* ConvertFromUnicode always returns a null-terminated
|
||||
* string on success, even if the source string isn't.
|
||||
*/
|
||||
if (ConvertFromUnicode(CP_UTF8, 0, wszFormatName, 16,
|
||||
&(formats[index].formatName), 0, NULL, NULL) < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "failed to convert short clipboard format name");
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
goto error_out;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,8 +202,13 @@ UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data
|
||||
|
||||
if (formatNameLength)
|
||||
{
|
||||
ConvertFromUnicode(CP_UTF8, 0, wszFormatName,
|
||||
-1, &(formats[index].formatName), 0, NULL, NULL);
|
||||
if (ConvertFromUnicode(CP_UTF8, 0, wszFormatName, -1,
|
||||
&(formats[index].formatName), 0, NULL, NULL) < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "failed to convert long clipboard format name");
|
||||
error = ERROR_INTERNAL_ERROR;
|
||||
goto error_out;
|
||||
}
|
||||
}
|
||||
|
||||
Stream_Seek(s, (formatNameLength + 1) * 2);
|
||||
|
||||
@ -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]",
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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) | \
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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")
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -6,6 +6,8 @@
|
||||
* Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
|
||||
* Copyright 2015 Thincast Technologies GmbH
|
||||
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
|
||||
* Copyright 2016 Inuvika Inc.
|
||||
* Copyright 2016 David PHAM-VAN <d.phamvan@inuvika.com>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -36,6 +38,10 @@
|
||||
#include <freerdp/channels/rdpdr.h>
|
||||
#include <freerdp/channels/log.h>
|
||||
|
||||
#ifdef __MACOSX__
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#endif
|
||||
|
||||
#define TAG CHANNELS_TAG("rdpdr.client")
|
||||
|
||||
typedef struct rdpdr_plugin rdpdrPlugin;
|
||||
@ -64,6 +70,8 @@ struct rdpdr_plugin
|
||||
HANDLE hotplugThread;
|
||||
#ifdef _WIN32
|
||||
HWND hotplug_wnd;
|
||||
#elif __MACOSX__
|
||||
CFRunLoopRef runLoop;
|
||||
#else
|
||||
HANDLE stopEvent;
|
||||
#endif
|
||||
|
||||
@ -152,9 +152,10 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context
|
||||
Stream_Seek_UINT32(s); /* CodePage (4 bytes), MUST be set to zero */
|
||||
Stream_Read_UINT32(s, ComputerNameLen); /* ComputerNameLen (4 bytes) */
|
||||
|
||||
if (Stream_GetRemainingLength(s) < ComputerNameLen)
|
||||
|
||||
if (UnicodeFlag > 1) /* must be 0x00000000 or 0x00000001 */
|
||||
{
|
||||
WLog_ERR(TAG, "not enough data in stream!");
|
||||
WLog_ERR(TAG, "invalid UnicodeFlag value: 0x%08X", UnicodeFlag);
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
@ -164,6 +165,39 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context
|
||||
* not in characters, including the NULL terminator!
|
||||
*/
|
||||
|
||||
if (UnicodeFlag)
|
||||
{
|
||||
if ((ComputerNameLen % 2) || ComputerNameLen > 512 || ComputerNameLen < 2)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid unicode computer name length: %u", ComputerNameLen);
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ComputerNameLen > 256 || ComputerNameLen < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "invalid ascii computer name length: %u", ComputerNameLen);
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
}
|
||||
|
||||
if (Stream_GetRemainingLength(s) < ComputerNameLen)
|
||||
{
|
||||
WLog_ERR(TAG, "not enough data in stream!");
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
/* ComputerName must be null terminated, check if it really is */
|
||||
|
||||
if (Stream_Pointer(s)[ComputerNameLen-1] ||
|
||||
(UnicodeFlag && Stream_Pointer(s)[ComputerNameLen-2]))
|
||||
{
|
||||
WLog_ERR(TAG, "computer name must be null terminated");
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
|
||||
|
||||
if (context->priv->ClientComputerName)
|
||||
{
|
||||
free(context->priv->ClientComputerName);
|
||||
@ -172,12 +206,21 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context
|
||||
|
||||
if (UnicodeFlag)
|
||||
{
|
||||
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s),
|
||||
-1, &(context->priv->ClientComputerName), 0, NULL, NULL);
|
||||
if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), -1,
|
||||
&(context->priv->ClientComputerName), 0, NULL, NULL) < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "failed to convert client computer name");
|
||||
return ERROR_INVALID_DATA;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
context->priv->ClientComputerName = _strdup((char*) Stream_Pointer(s));
|
||||
if (!context->priv->ClientComputerName)
|
||||
{
|
||||
WLog_ERR(TAG, "failed to duplicate client computer name");
|
||||
return CHANNEL_RC_NO_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
Stream_Seek(s, ComputerNameLen);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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) */
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -649,6 +649,8 @@ static UINT rdpsnd_alsa_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV*
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry alsa_freerdp_rdpsnd_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@ -281,6 +281,8 @@ static void rdpsnd_ios_free(rdpsndDevicePlugin* device)
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry ios_freerdp_rdpsnd_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@ -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
|
||||
|
||||
/**
|
||||
|
||||
@ -407,6 +407,9 @@ static int rdpsnd_opensles_parse_addin_args(rdpsndDevicePlugin* device,
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry \
|
||||
opensles_freerdp_rdpsnd_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_rdpsnd_client_subsystem_entry \
|
||||
FREERDP_API freerdp_rdpsnd_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@ -477,6 +477,8 @@ static int rdpsnd_oss_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV* a
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry oss_freerdp_rdpsnd_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@ -636,6 +636,8 @@ static UINT rdpsnd_pulse_parse_addin_args(rdpsndDevicePlugin* device, ADDIN_ARGV
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_rdpsnd_client_subsystem_entry pulse_freerdp_rdpsnd_client_subsystem_entry
|
||||
#else
|
||||
#define freerdp_rdpsnd_client_subsystem_entry FREERDP_API freerdp_rdpsnd_client_subsystem_entry
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
/**
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -707,7 +707,12 @@ void smartcard_trace_list_readers_return(SMARTCARD_DEVICE* smartcard, ListReader
|
||||
if (unicode)
|
||||
{
|
||||
length = ret->cBytes / 2;
|
||||
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) ret->msz, (int)length, &mszA, 0, NULL, NULL);
|
||||
if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) ret->msz, (int)length,
|
||||
&mszA, 0, NULL, NULL) < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "ConvertFromUnicode failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1767,7 +1772,12 @@ void smartcard_trace_status_return(SMARTCARD_DEVICE* smartcard, Status_Return* r
|
||||
if (unicode)
|
||||
{
|
||||
length = ret->cBytes / 2;
|
||||
ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) ret->mszReaderNames, (int)length, &mszReaderNamesA, 0, NULL, NULL);
|
||||
if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) ret->mszReaderNames, (int)length,
|
||||
&mszReaderNamesA, 0, NULL, NULL) < 1)
|
||||
{
|
||||
WLog_ERR(TAG, "ConvertFromUnicode failed");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -233,6 +233,8 @@ static void tsmf_alsa_free(ITSMFAudioDevice *audio)
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_tsmf_client_audio_subsystem_entry alsa_freerdp_tsmf_client_audio_subsystem_entry
|
||||
#else
|
||||
#define freerdp_tsmf_client_audio_subsystem_entry FREERDP_API freerdp_tsmf_client_audio_subsystem_entry
|
||||
#endif
|
||||
|
||||
ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void)
|
||||
|
||||
@ -543,6 +543,8 @@ static BOOL initialized = FALSE;
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_tsmf_client_subsystem_entry ffmpeg_freerdp_tsmf_client_decoder_subsystem_entry
|
||||
#else
|
||||
#define freerdp_tsmf_client_subsystem_entry FREERDP_API freerdp_tsmf_client_decoder_subsystem_entry
|
||||
#endif
|
||||
|
||||
ITSMFDecoder* freerdp_tsmf_client_subsystem_entry(void)
|
||||
|
||||
@ -1012,6 +1012,8 @@ BOOL tsmf_gstreamer_sync(ITSMFDecoder* decoder, void (*cb)(void *), void *stream
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_tsmf_client_subsystem_entry gstreamer_freerdp_tsmf_client_decoder_subsystem_entry
|
||||
#else
|
||||
#define freerdp_tsmf_client_subsystem_entry FREERDP_API freerdp_tsmf_client_decoder_subsystem_entry
|
||||
#endif
|
||||
|
||||
ITSMFDecoder* freerdp_tsmf_client_subsystem_entry(void)
|
||||
|
||||
@ -238,6 +238,8 @@ static void tsmf_oss_free(ITSMFAudioDevice* audio)
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_tsmf_client_audio_subsystem_entry oss_freerdp_tsmf_client_audio_subsystem_entry
|
||||
#else
|
||||
#define freerdp_tsmf_client_audio_subsystem_entry FREERDP_API freerdp_tsmf_client_audio_subsystem_entry
|
||||
#endif
|
||||
|
||||
ITSMFAudioDevice* freerdp_tsmf_client_audio_subsystem_entry(void)
|
||||
|
||||
@ -360,6 +360,8 @@ static void tsmf_pulse_free(ITSMFAudioDevice *audio)
|
||||
|
||||
#ifdef STATIC_CHANNELS
|
||||
#define freerdp_tsmf_client_audio_subsystem_entry pulse_freerdp_tsmf_client_audio_subsystem_entry
|
||||
#else
|
||||
#define freerdp_tsmf_client_audio_subsystem_entry FREERDP_API freerdp_tsmf_client_audio_subsystem_entry
|
||||
#endif
|
||||
|
||||
ITSMFAudioDevice *freerdp_tsmf_client_audio_subsystem_entry(void)
|
||||
|
||||
@ -79,7 +79,7 @@ UINT tsmf_ifman_exchange_capability_request(TSMF_IFMAN* ifman)
|
||||
if (!Stream_EnsureRemainingCapacity(ifman->output, ifman->input_size + 4))
|
||||
return ERROR_OUTOFMEMORY;
|
||||
pos = Stream_GetPosition(ifman->output);
|
||||
Stream_Copy(ifman->output, ifman->input, ifman->input_size);
|
||||
Stream_Copy(ifman->input, ifman->output, ifman->input_size);
|
||||
Stream_SetPosition(ifman->output, pos);
|
||||
|
||||
if (Stream_GetRemainingLength(ifman->output) < 4)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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()
|
||||
|
||||
|
||||
@ -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)));
|
||||
|
||||
@ -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)))
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 */
|
||||
|
||||
|
||||
@ -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 */
|
||||
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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 */
|
||||
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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})
|
||||
|
||||
@ -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
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 );
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -14,6 +14,7 @@ set(${MODULE_PREFIX}_TESTS
|
||||
TestPrimitivesSet.c
|
||||
TestPrimitivesShift.c
|
||||
TestPrimitivesSign.c
|
||||
TestPrimitivesYUV.c
|
||||
TestPrimitivesYCbCr.c
|
||||
TestPrimitivesYCoCg.c)
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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));
|
||||
|
||||
427
libfreerdp/primitives/test/TestPrimitivesYUV.c
Normal file
427
libfreerdp/primitives/test/TestPrimitivesYUV.c
Normal 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
Loading…
Reference in New Issue
Block a user