Compare commits

...

941 Commits

Author SHA1 Message Date
akallabeth
393560dedf
Merge pull request #10861 from Rubycat-R-D-Labs/bitmap_updates_with_no_gdi
do not always return FALSE when gdi is NULL
2024-11-14 18:35:02 +01:00
cbr-rc
7db06cc359 do not always return FALSE when gdi is NULL 2024-11-14 17:27:10 +01:00
akallabeth
d0db9603fc
Merge pull request #10860 from akallabeth/nightly-dep
[ci,coverity] explicitly set clang as compiler
2024-11-14 16:30:43 +01:00
akallabeth
bc5b9e3ccb
[ci,coverity] explicitly set clang as compiler 2024-11-14 16:29:45 +01:00
akallabeth
fe998468b5
Merge pull request #10859 from akallabeth/nightly-dep
[ci,nightly] add libsoxr to debian dependencies
2024-11-14 16:25:05 +01:00
akallabeth
950aa7e3af
[ci,nightly] add libsoxr to debian dependencies 2024-11-14 16:24:02 +01:00
akallabeth
d24cedbcdc
Merge pull request #10858 from akallabeth/cov-deps
[ci,coverity] add equivs dependency
2024-11-14 16:18:33 +01:00
akallabeth
1921c320d2
[ci,coverity] add equivs dependency 2024-11-14 16:17:46 +01:00
akallabeth
ad242072d9
Merge pull request #10857 from akallabeth/cov-indent
[ci,coverity] fix command name
2024-11-14 16:13:24 +01:00
akallabeth
a4a406305f
[ci,coverity] fix command name 2024-11-14 16:12:47 +01:00
akallabeth
094d043c6a
Merge pull request #10856 from akallabeth/cov-indent
[ci,coverity] fix typo in package name
2024-11-14 16:11:26 +01:00
akallabeth
dabd3af552
[ci,coverity] fix typo in package name 2024-11-14 16:10:47 +01:00
akallabeth
a7529b5e87
Merge pull request #10855 from akallabeth/cov-indent
[ci,coverity] fix package installation
2024-11-14 16:09:52 +01:00
akallabeth
498b16b4ee
[ci,coverity] fix package installation 2024-11-14 16:09:01 +01:00
akallabeth
e1df042a3c
Merge pull request #10854 from akallabeth/cov-indent
[ci,coverity] fix indentation
2024-11-14 16:07:48 +01:00
akallabeth
0bb38d0acf
[ci,coverity] fix indentation 2024-11-14 16:07:12 +01:00
akallabeth
c84bb6339b
Merge pull request #10852 from akallabeth/coverity-update
Coverity update
2024-11-14 16:02:53 +01:00
akallabeth
4cb3df46e7
[coverity] update build workflow 2024-11-14 15:01:16 +01:00
akallabeth
6f3e9d3dfc
Merge pull request #10850 from akallabeth/pragma-warn
Pragma warn
2024-11-14 15:01:07 +01:00
Martin Fleisz
cf993d56a2
Merge pull request #10851 from akallabeth/debug-rel-path
[cmake] prefer relative paths for debug symbols
2024-11-14 14:29:45 +01:00
akallabeth
ebf0298e9a
Merge pull request #10849 from mfleisz/fix-rail-logging
[core]: Fix some issues with RAIL window state order logging
2024-11-14 14:08:10 +01:00
akallabeth
9b3f5cd86e
[ci,coverity] define COVERITY_BUILD
By defining this symbol the build will enable coverity related pragma
definitions
2024-11-14 13:53:41 +01:00
akallabeth
af7849b579
[cmake] use relative paths for debug symbols
When not building a Debug configuration use relative paths for __FILE__
et al in the debug symbol entries
2024-11-14 13:45:05 +01:00
akallabeth
8883ccc503
[cmake] remove GCC -Wunknown-pragmas workaround
The offending pragma definitions are now only defined for coverity
builds
2024-11-14 13:26:21 +01:00
akallabeth
541fc3a8c6
[channels,remdesk] fix const correctness of function 2024-11-14 13:26:19 +01:00
akallabeth
3c8cd7fb7e
[winpr,assert] add WINPR_ASSERT_AT
Add a version of assert that allows setting the location (useful for
macros or static functions wrapping something where the location of the
call is more significant than the function the macro was used in)
2024-11-14 13:26:16 +01:00
Martin Fleisz
16789a181a [core]: Fix some issues with RAIL window state order logging
This commit fixes following issues when logging window state orders:

- Always print Window and Owner Ids as integer numbers
- Log all window styles (including extended styles)
- Log window title (very useful to identify the window in the log)
2024-11-14 10:19:43 +01:00
David Fort
780f6dddce
Merge pull request #10848 from akallabeth/silence-pragma
[cmake] workaround for older GCC
2024-11-13 22:25:20 +01:00
akallabeth
0c57fdc300
[winpr,crt] add winpr_asprintf unit test 2024-11-13 21:49:11 +01:00
akallabeth
0b8de6f4b5
[winpr,crt] fix off by one in winpr_vasprintf 2024-11-13 21:04:02 +01:00
akallabeth
16657adf60
[cmake] workaround for older GCC
To fix the missing pragma -Wunknown-pragmas support for older GCC
disable this warning altogether if such a compiler is detected
2024-11-13 20:21:33 +01:00
akallabeth
43e471938b
Merge pull request #10843 from akallabeth/cleanups3
Cleanups3
2024-11-12 17:52:55 +01:00
akallabeth
51b2b76cbd
Merge pull request #10846 from akallabeth/xcrush-fix
[codec,xcrush] fix a regression with xcrush_generate_output
2024-11-12 17:26:11 +01:00
akallabeth
387147bb4e
[codec,xcrush] fix a regression with xcrush_generate_output 2024-11-12 17:14:52 +01:00
akallabeth
9e15af8850
[winpr,assert] fix coverity pragma
rewrite pragma according to https://community.blackduck.com/s/article/Suppressing-False-Positive-Intentional-defects
2024-11-12 16:46:13 +01:00
akallabeth
db07add07a
[deprecation] replace all usages of sprintf 2024-11-12 16:46:11 +01:00
akallabeth
7797d8d669
[ci,tidy] disable readability-avoid-nested-conditional-operator
the check is flagging every (cond) ? foo : bar as too complicated,
useless check.
2024-11-12 16:46:06 +01:00
akallabeth
08839a11de
[utils,passphrase] NULL checks 2024-11-12 16:46:04 +01:00
akallabeth
7f27e168b3
[emu,scard] flag allocator with nolint
The allocator keeps an internal list of allocated contexts. No manual
free required.
2024-11-12 16:46:01 +01:00
akallabeth
48a387938d
[winpr,env] fix use of getcwd
do not rely on GNU_SOURCE extensions
2024-11-12 16:45:55 +01:00
akallabeth
08d21e9f09
Merge pull request #10838 from akallabeth/channel-remdesk-common
[channels,remdesk] create common components
2024-11-12 12:35:09 +01:00
akallabeth
148549165d
Merge pull request #10842 from akallabeth/x11-clip-leak
[client,x11] fix clipboard leak on shutdown
2024-11-11 15:41:48 +01:00
akallabeth
24899fa414
[client,x11] fix clipboard leak on shutdown 2024-11-11 15:26:55 +01:00
akallabeth
0c35fd1a48
[channels,remdesk] create common components
Extract common functions from server and client channel and move it to a
static library linked by both
2024-11-11 12:23:52 +01:00
akallabeth
cdeb29dbd1
Merge pull request #10839 from akallabeth/rpm-debug-fix
[nightly,rpm] disable debugpackage
2024-11-11 11:55:55 +01:00
Armin Novak
a0d6a8d801
[nightly,rpm] disable debugpackage 2024-11-11 11:42:48 +01:00
Martin Fleisz
75ff6db4cd
Merge pull request #10740 from akallabeth/Wshorten-64-to-32
Wshorten 64 to 32
2024-11-11 11:26:51 +01:00
akallabeth
78acedb40e
[warnigns] fix Wshorten-64-to-32 2024-11-11 10:22:37 +01:00
akallabeth
f88eda3f11
Merge pull request #10835 from akallabeth/create_deb.sh
[packaging,scripts] add create_deb.sh
2024-11-08 10:19:49 +01:00
akallabeth
c0ed8ed6e0
[packaging,scripts] add create_deb.sh 2024-11-08 10:06:54 +01:00
akallabeth
0a7c845eec
Merge pull request #10832 from akallabeth/file-macro-unify
[cmake,gcc,clang] use -fmacro-prefix-map and -ffile-prefix-map
2024-11-08 09:25:16 +01:00
akallabeth
cb73d77d6e
Merge pull request #10823 from akallabeth/rdpdr-caps-filter
[channels,rdpdr] send only used caps to server
2024-11-08 09:08:32 +01:00
akallabeth
d2ddbd81f6
Merge pull request #10834 from akallabeth/coverity-pragma
[winpr,assert] coverity suppress CONSTANT_EXPRESSION_RESULT
2024-11-08 09:04:03 +01:00
akallabeth
bc70bbd30e
[cmake] unify -fno-omit-frame-pointer 2024-11-08 09:01:25 +01:00
akallabeth
c5711f0a2e
[winpr,assert] coverity suppress CONSTANT_EXPRESSION_RESULT 2024-11-08 08:40:28 +01:00
akallabeth
c43242fdde
[cmake,buildflags] replace CMAKE_SOURCE_DIR and CMAKE_BUILD_DIR
replace source and build directories with palceholders
2024-11-07 20:10:57 +01:00
akallabeth
ebcf4c44a9
[cmake,gcc,clang] use -fmacro-prefix-map and -ffile-prefix-map
Instead of some bash path substitution only working with Makefiles use
the compiler options to map source and build directories to some
defaults
2024-11-07 16:52:01 +01:00
Martin Fleisz
1520d94d33
Merge pull request #10797 from akallabeth/warn-fixes
Warn fixes
2024-11-07 13:50:51 +01:00
Martin Fleisz
c7486fc47b
Merge pull request #10801 from akallabeth/cleanups
Cleanups
2024-11-07 13:03:36 +01:00
akallabeth
4726d5a01e
Merge pull request #10829 from akallabeth/winpr-fixes
Winpr fixes
2024-11-07 12:15:16 +01:00
akallabeth
d070857c03
[winpr,string] add wcsndup 2024-11-07 11:46:55 +01:00
akallabeth
3a1251fa0e
[winpr,path] WINPR_ATTR_MALLOC for winpr_GetConfigFilePath 2024-11-07 11:46:53 +01:00
akallabeth
7e7ea3e688
[core,settings] WINPR_ATTR_MALLOC for alloc_array 2024-11-07 11:46:50 +01:00
akallabeth
3f824daca4
Merge pull request #10827 from akallabeth/rdstls-log
[core,rdstls] use less verbose logging
2024-11-06 21:30:19 +01:00
akallabeth
315ab17984
[core,rdstls] use less verbose logging
the rdstls_recv function is called with possibly incomplete data, do not
log length check failures
2024-11-06 20:41:01 +01:00
akallabeth
93c4843399
Merge pull request #10826 from Devolutions/devops/upload
[ci] update upload-artifact action to version 4
2024-11-06 14:47:25 +01:00
Richard Boisvert
d5149d7b37
[ci] update upload-artifact action to version 4 2024-11-06 08:23:45 -05:00
akallabeth
cbc5d6d48b
Merge pull request #10825 from akallabeth/rpm-nightly-fix
[ci,nightly] fix build for fedora 41
2024-11-06 11:15:17 +01:00
Armin Novak
fbca659cb5
[ci,nightly] fix build for fedora 41 2024-11-06 12:14:10 +01:00
akallabeth
c9421d3714
Merge pull request #10822 from akallabeth/rdstls-silence
[core,rdstls] do silent password check
2024-11-06 11:06:36 +01:00
akallabeth
aa371dcdd6
[channels,rdpdr] only reply enabled caps 2024-11-05 19:56:28 +01:00
akallabeth
c4412a92e2
[channels,rdpdr] send only used caps to server
* When using RDPDR only send capabilities to server we have activated,
  e.g. smartcard, drive, printer, port (serial or parallel) redirection
* Check return value of write functions
2024-11-05 19:44:03 +01:00
akallabeth
ec9b5c33bc
[core,rdstls] do silent password check
In rdstls_parse_pdu_data_type do not use logging stream functions. This
function might be called with incomplete data so avoid spamming the log.
2024-11-05 17:50:47 +01:00
akallabeth
9089150e28
Merge pull request #10821 from akallabeth/ios-ci
[winpr,comm] enable comm for iOS
2024-11-05 17:25:12 +01:00
akallabeth
c2cb03efd8
Merge pull request #10819 from akallabeth/ios-ci
[ci,ios] add configuration for dynamic build
2024-11-05 17:02:15 +01:00
akallabeth
617b4d966a [winpr,comm] enable comm for iOS
The functions are supported in the SDK so compile it in
2024-11-05 17:01:35 +01:00
akallabeth
d9f551b7ca
[winpr,comm] add dummy implementation
Add dummy implementation for platforms not supporting serial interfaces
2024-11-05 16:37:17 +01:00
akallabeth
b57a098bf9
[ci,ios] add configuration for dynamic build
* Add build configuration for shared libraries
* Fix ENABLE_BITCONFIG setting for ci builds
* Enable unit tests for iOS
2024-11-05 16:37:10 +01:00
Martin Fleisz
7d8711cd72
Merge pull request #10817 from llyzs/rgbcopy
[core,primitive] fix rgb primitive copy without conversion.
2024-11-04 15:10:00 +01:00
Vic Lee
ce604a5a81 [core,primitive] fix rgb primitive copy without conversion. 2024-11-04 17:53:59 +08:00
akallabeth
7d5193d3d5
Merge pull request #10815 from akallabeth/improve-client-config
[client,common] include binary name in client buildconfig
2024-11-04 09:47:37 +01:00
akallabeth
fb3a127d00
[common,cmdline] add new functions
* Add freerdp_client_print_version_ex and
  freerdp_client_print_buildconfig_ex to print version and build
  configuration along with the binary name calling it
* Use these new functions instead of the ones that only print out
  version and/or buildconfig
2024-11-04 09:06:12 +01:00
akallabeth
ecc84158b7
[client,common] include binary name in client buildconfig 2024-11-04 08:42:13 +01:00
David Fort
edf562126e
Merge pull request #10814 from akallabeth/sdl3-fix
[client,sdl] fix sdl3 SDL_GetDisplayBounds checks
2024-11-04 07:08:18 +01:00
akallabeth
f1877d15d4
[client,sdl] fix sdl3 SDL_GetDisplayBounds checks
Fix #10813, return value changed to bool, so fix checks meant for SDL2
2024-11-03 21:21:05 +01:00
David Fort
070115e77b
Merge pull request #10806 from akallabeth/assert-fix
[core,security] fix assertion
2024-10-31 22:09:08 +01:00
akallabeth
1b177eeda9
[core,security] fix assertion
The assert for the buffer size required too many bytes in the output
buffer.
2024-10-31 13:11:57 +01:00
akallabeth
d06a6d78cb
[file,namedpipe] clean up NamedPipeClientCreateFileA
simplify and improve error handling
2024-10-31 11:42:36 +01:00
akallabeth
a58a390726
[gdi,shape] fix logically dead code 2024-10-31 11:42:34 +01:00
akallabeth
7f44ef8114
[cache,glyph] eliminate logically dead code 2024-10-31 11:42:31 +01:00
akallabeth
4ec28e1f82
[warnings] fix -Wimplicit-int-conversion 2024-10-31 11:42:29 +01:00
akallabeth
b6e051f16c
[warnings] fix float-conversion 2024-10-31 11:42:26 +01:00
akallabeth
dcf5a8e28c
[warnings] fix -Wswitch-default 2024-10-31 11:42:24 +01:00
akallabeth
63121583eb
Merge pull request #10802 from akallabeth/compile-fix
[utils,helpers] revert removed define
2024-10-31 09:10:48 +01:00
akallabeth
6b6ae5fa9d
[utils,helpers] revert removed define
the define was conditionally unused. guard it now so it does not show up
as unused
2024-10-31 08:51:55 +01:00
akallabeth
2bdb059644
Merge pull request #10799 from akallabeth/generic-cleanups
[warnings] fix some compiler warnings
2024-10-30 19:32:22 +01:00
akallabeth
a5b64effab
[winpr,stream] add functions to write INT16_BE and INT32_BE 2024-10-30 19:18:04 +01:00
akallabeth
8bb5d598fc
[winpr,stream] fix missing comma 2024-10-30 17:10:03 +01:00
akallabeth
d232037e18
[winpr,asn1] fix writing integers
ASN1 integers are signed.
2024-10-30 16:55:56 +01:00
akallabeth
dc76879e0b
[warnings] fix some compiler warnings
* fix compiler warnings found in a lot of places
* add missing enum type for clipboard channel
* mark deallocator for winpr image function
2024-10-30 16:12:20 +01:00
akallabeth
d11be9025d
Merge pull request #10794 from akallabeth/internal-rc4
Internal rc4
2024-10-30 13:46:01 +01:00
akallabeth
8e33854c62
[tests] improve TestCommonAssistance
Compare encrypted passwords against reference values to ensure the
encryption routines work as expected
2024-10-30 13:22:59 +01:00
akallabeth
555d46f7e2
[winpr,crypto] deactivate key and IV lenght checks
OpenSSL does not support that in older versions, deactivate for the time
being.
2024-10-30 13:22:57 +01:00
akallabeth
2a41730f70
[common,assistance] replace winpr_Cipher_New
* use winpr_Cipher_NewEx where possible
* use winpr_RC4_New where RC4 is used
2024-10-30 13:22:55 +01:00
akallabeth
3ae0a10142
[core] replace usage of winpr_Cipher_New
prefer winpr_CipherNewEx to be on the safe side.
2024-10-30 13:22:52 +01:00
akallabeth
2b0b52be9e
[core,rdp] adjust warning for RC4
RC4 is not supported by winpr_Cipher_New but only by explicitly calling
winpr_RC4_New. Adjust the availability test to use the correct
functions.
2024-10-30 13:22:50 +01:00
akallabeth
1eac8fa15e
[winpr,crypto] deprecate winpr_Cipher_New
Deprecate function in favor of new winpr_CipherNewEx with explict key
and IV length parameters, adjust test cases to test both.
2024-10-30 13:22:45 +01:00
akallabeth
9db7deb30b
[warnings] initialize ULARGE_INTEGER 2024-10-30 10:20:41 +01:00
akallabeth
a7638bb0e4
Merge pull request #10798 from akallabeth/kbd-remap-fix
[utils,string] fix freerdp_extract_key_value
2024-10-29 17:20:52 +01:00
akallabeth
24ab4b297f
[utils,string] fix freerdp_extract_key_value
reset errno before strtoul to avoid aborting due to a previous errno
value from a different function call
2024-10-29 16:50:00 +01:00
akallabeth
566d4cf637
[stream] fix sign issues with stream API use 2024-10-29 15:50:07 +01:00
akallabeth
10e7acdd49
[winpr,stream] add functions to write INT16_BE and INT32_BE 2024-10-29 15:50:05 +01:00
akallabeth
8aa49c3e93
[warnings] fix C23 extension warnings 2024-10-29 15:50:02 +01:00
akallabeth
2b95757a7a
[warnings] fix redundant casts 2024-10-29 15:49:59 +01:00
akallabeth
8ee84ff054
[client,sdl] fix empty catch 2024-10-29 15:49:57 +01:00
akallabeth
3c9a45e9d0
[client,sdl] fix move constructors
use default implementation to avoid use after move
2024-10-29 15:49:54 +01:00
akallabeth
6548f1f9dd
[compiler] disable unknown pragma warnings
we compile with different compilers/checkers whith their own #pragma
do not warn us about that, we already know
2024-10-29 15:49:51 +01:00
akallabeth
aa954d9be9
[warnings] fix various compiler warnings 2024-10-29 15:49:43 +01:00
akallabeth
4078b0d5b9
[clang,tidy] disable readability-math-missing-parentheses 2024-10-29 12:32:38 +01:00
akallabeth
e9b942f612
Merge pull request #10791 from akallabeth/vmconnect
[client,common] tighten /vmconnect checks
2024-10-28 10:04:54 +01:00
akallabeth
f0d0105d50
[client,common] tighten /vmconnect checks
Fixes #5300:
* abort if +/-nego is used, /vmconnect overrides these.
* only set custom port if no /port or /v:host:port is in use allowing
  overriding default port
2024-10-28 09:44:21 +01:00
Martin Fleisz
fa71cb18f0
Merge pull request #10793 from akallabeth/ntlm-fixes
[winpr,sspi] fix NULL NTLM password handling
2024-10-28 09:44:20 +01:00
akallabeth
882060031f
Merge pull request #10787 from akallabeth/proxy-arg-check
[server,proxy] stricter argument parsing
2024-10-28 09:32:30 +01:00
akallabeth
98335b7dde
Merge pull request #10792 from akallabeth/cov-assert-silence
[ci,assert] silence coverity on WINPR_ASSERT
2024-10-28 09:22:54 +01:00
akallabeth
c9a946f272
[winpr,sspi] fix NULL NTLM password handling
* Pass through the NULL, but fail as the hash matches the NULL hash
2024-10-28 09:09:56 +01:00
Martin Fleisz
56786ea606
Merge pull request #10786 from akallabeth/ntlm-fixes
Ntlm fixes
2024-10-28 09:04:57 +01:00
akallabeth
c513886914
[ci,assert] silence coverity on WINPR_ASSERT
silence covertiy NO_EFFECT with _Pragma when using WINPR_ASSERT.
We´ve got a lot of situations where a check is mostly useless when
functions are called correctly, but the check triggers on common errors.
So silence this warning on our perfectly fine usage situations
2024-10-28 08:36:23 +01:00
akallabeth
259b4f40c8
Merge pull request #10790 from akallabeth/ci
[compiler,macros] fix pragma by compiler support
2024-10-27 22:36:35 +01:00
akallabeth
a60ac2321d
[compiler,macros] fix pragma by compiler support 2024-10-27 21:58:58 +01:00
akallabeth
42178b6191
Merge pull request #10789 from akallabeth/ci
Ci
2024-10-27 20:35:11 +01:00
akallabeth
fd1c850c62
[ci,preloads] fix CMAKE_BUILD_TYPE 2024-10-27 20:07:41 +01:00
akallabeth
7adb9517fc
[ci,alt-arch] use v2.8.1 of alt-architecture build 2024-10-27 20:07:33 +01:00
akallabeth
a0cb7ce166
Merge pull request #10788 from akarl10/websocket-negotiate-non-plain-ntlm-fix
[rdg,websockets] Fix Http Negotiate for Websocket
2024-10-27 19:17:09 +01:00
akarl10
1ea08b776f Fix Http Negotiate for Websocket
When using negotiate in non direct NTLM mode the success response
contains an aditional token for the authentication layer.
Add HTTP_STATUS_SWITCH_PROTOCOLS to the list of valid HTTP status codes
where to extract the last auth token
2024-10-26 23:43:37 +02:00
akallabeth
940d067f52
[server,proxy] stricter argument parsing
* Check number of arguments is valid (don't allow additional ones)
* Replace exit() with normal return for helper functions
2024-10-26 19:53:36 +02:00
akallabeth
d2ec568d39
[winpr,sspi] improve NTLM unit test
* Test empty passwords as well
* Improve return value checks
2024-10-26 15:18:29 +02:00
akallabeth
91a5f06ba3
[winpr,sspi] allow empty NTLM passwords 2024-10-26 15:18:26 +02:00
akallabeth
e560733f8e
[winpr,sspi] fix NTLM debug message
dump only hex of received data, the symbols might not be printable.
2024-10-26 14:42:12 +02:00
akallabeth
d19b7fa5d0
Merge pull request #10768 from akallabeth/stream-write-assert
[winpr,stream] assert Stream_Write_(U)INT[8|16|32] ranges
2024-10-26 14:40:43 +02:00
akallabeth
11570395bc [winpr,stream] updated function documentation 2024-10-25 14:36:28 +02:00
akallabeth
0a6679b793
Merge pull request #10783 from akallabeth/rpm-fix
[ci,nightly] fix missing files in RPM spec
2024-10-25 14:11:37 +02:00
akallabeth
75c2e9f6a5
[ci,nightly] add a script to build an RPM nightly 2024-10-25 14:09:40 +02:00
akallabeth
e7414ef635
[ci,nightly] fix missing files in RPM spec 2024-10-25 13:47:13 +02:00
Martin Fleisz
9a21b81422
Merge pull request #10465 from akallabeth/desktop-files
[client,common] add WITH_INSTALL_CLIENT_DESKTOP_FILES
2024-10-25 12:33:27 +02:00
akallabeth
c377b0ce86
[client,common] add WITH_INSTALL_CLIENT_DESKTOP_FILES
This new CMake option allows installing .desktop files and application
icons if turned on.
2024-10-25 12:11:54 +02:00
akallabeth
e4e6e254a2
Merge pull request #10781 from akallabeth/nightly-update
Nightly update
2024-10-25 12:08:08 +02:00
akallabeth
0a02afc225
[winpr,assert] silence -Wtautological-value-range-compare
assertions sometimes check for values that are not possible (checks in
defines that are used on different types, ...) so silence these
warnings.
2024-10-25 12:04:06 +02:00
akallabeth
88d9b1f110
[crypto,per] abort on invalid parameters 2024-10-25 11:48:16 +02:00
akallabeth
5f86284663
[core,orders] fix update_write_coord
* Add value range checks
* Add proper log message
* Add failure return
2024-10-25 11:48:14 +02:00
akallabeth
738cbd54b2
[core] fix issues with value ranges written 2024-10-25 11:48:12 +02:00
akallabeth
04a5bbed4a
[winpr,stream] unify Stream_Fill and Stream_Zero 2024-10-25 11:48:09 +02:00
akallabeth
941c36f4f6
[winpr,stream] assert Stream_Write_(U)INT[8|16|32] ranges
* Every function takes a (U)INT64 as argument to avoid shortening the
  original value
* The limits are asserted so invalid values can be found during runtime
2024-10-25 11:48:07 +02:00
Armin Novak
8c9f83a12f
[ci,nightly] update rpm spec 2024-10-25 11:40:48 +02:00
akallabeth
edde0f542e
[ci,nightly] update debian nightly
* Use keyboard layouts from installed JSON
* Use timezones from installed JSON
* Run unit tests during package build
* Enable internal RC4/MD4/MD5
2024-10-25 11:40:46 +02:00
akallabeth
a27d9508e2
[cmake] unify CFLAGS to string
* move to common CMake function
* escape CFLAGS
2024-10-25 11:40:43 +02:00
akallabeth
a3aa01214c
[resource root] unify locations
unify resource locations in case WITH_BINARY_VERSIONING is set.
2024-10-25 11:40:40 +02:00
akallabeth
5538681fc3
Merge pull request #10780 from akallabeth/window-fake-monitor
Window fake monitor
2024-10-24 14:24:18 +02:00
akallabeth
392a085728
[core,settings] enforce fullscreen monitor requirements
* Monitor must start at 0/0
* Monitor must be primary
2024-10-24 11:32:10 +02:00
akallabeth
7ab30a1b18
[client,common] const correct pointer array arguments 2024-10-24 11:32:08 +02:00
akallabeth
14c4cd8dc3
[client,sdl] ignore window properties if not fullscreen/multimon 2024-10-24 11:32:05 +02:00
akallabeth
401f81683c
[core,settings] fake monitor in window mode
RDP requires sending monitor information to the server. If we are in
windowed mode fake that information with the windows size
2024-10-24 11:32:03 +02:00
akallabeth
1675d926d2
Merge pull request #10776 from akallabeth/packaging-tests
[cmake] split tests
2024-10-24 11:26:17 +02:00
akallabeth
de055a6765
Merge pull request #10777 from akallabeth/cmake-build-type
[cmake] enforce a supported build type
2024-10-24 09:47:47 +02:00
akallabeth
a5208f948d
Merge pull request #10774 from akallabeth/cov-fix
[sysconf] _SC_GETPW_R_SIZE_MAX return checks
2024-10-24 09:47:21 +02:00
Armin Novak
527db6783b
[cmake] split tests
* Keep BUILD_TESTING, but only run tests compatible with API (for
  packaging)
* Add BUILD_TESTING_INTERNAL for all tests including internal function
  tests that modify API to be run on our CI
2024-10-24 09:45:44 +02:00
akallabeth
d511316e86
[core,rdp] add build and supported cipher/digest checks
checking for:
 * WITH_VERBOSE_WINPR_ASSERT (runtime slowdown)
 * digests MD4, MD5, SHA1 and SHA256
 * HMAC md5 and sha1
 * Cipher RC4/ARC4_128, DES_EDE3_CBC, AES128_CBC, AES192_CBC,
   AES_256_CBC
2024-10-24 09:12:22 +02:00
akallabeth
180a0e6c9e
[winpr,crypto] add functions stringify ciphers
* add funtion to get the name of a cipher
* add function to get the cipher from name
* make ciphers an enum
2024-10-24 09:08:11 +02:00
akallabeth
aa9b03df25
[cmake] generate full buildflags.h CFLAGS
Combine current configuration flags with CMAKE_C_FLAGS
2024-10-24 09:08:08 +02:00
Armin Novak
98f4a2b022
[client,various] print client specific only on help
do not print if version or other command was run
2024-10-24 09:08:06 +02:00
Armin Novak
e48fb1eabd
[core,warnings] warn about runtime check options 2024-10-24 09:08:03 +02:00
Armin Novak
0d7edfd884
[cmake] enforce a supported build type
We check for build types internally to enable/disable debug options.
Ensure the CMAKE_BUILD_TYPE is either not set or set to a supported
value.
2024-10-24 09:08:00 +02:00
Armin Novak
f488d15b7a
[winpr,utils] update TestStream 2024-10-23 16:01:30 +02:00
Armin Novak
d3f8cd3073
[client,common] fix data race 2024-10-23 11:39:29 +02:00
Armin Novak
0cb84a0d8f
[crypto,cert] fix error handling for bio_read_pem 2024-10-23 11:34:06 +02:00
Armin Novak
0545a8a5ef
[uwac] fix sign warnings 2024-10-23 11:02:52 +02:00
Armin Novak
9b32cc59b8
[core,gateway] restore non-local value 2024-10-23 10:52:21 +02:00
Armin Novak
74b596758c
[crypto,tls] add check for overflow 2024-10-23 10:50:07 +02:00
Armin Novak
a84b303c23
[sysconf] _SC_GETPW_R_SIZE_MAX return checks
fix possible overflow with value returned from sysconf(_SC_GETPW_R_SIZE_MAX)
2024-10-23 10:34:11 +02:00
akallabeth
ae5f655f12
Merge pull request #10772 from akallabeth/command-line-parser
[warnings] unify CommandLineParseCommaSeparatedValues
2024-10-23 09:44:47 +02:00
akallabeth
9caf38bbb6 [warnings] unify CommandLineParseCommaSeparatedValues
CommandLineParseCommaSeparatedValues does some internal hack to allow
the allocated char** to be cleaned up by free.
This enforces compiler warnings as the pointer types do not match.
Use a new free function CommandLineParserFree instead
2024-10-22 21:11:58 +02:00
akallabeth
6c7f88aecc
Merge pull request #10771 from akallabeth/clang-update
Clang update
2024-10-22 16:49:13 +02:00
akallabeth
2329cb23ae
[channels,rdpgfx] reset pointer to local variable 2024-10-22 16:19:47 +02:00
akallabeth
4b850f765f
[channels,rdpecam] fix format string 2024-10-22 16:02:41 +02:00
akallabeth
575b926626
[cmake] disable -Wpre-c11-compat 2024-10-22 16:02:38 +02:00
akallabeth
563c05c499
Merge pull request #10765 from akallabeth/overlap-fix
[codec,color] fix overlapping check
2024-10-22 15:36:12 +02:00
akallabeth
210249e5c3
Merge pull request #10770 from akallabeth/crypto
[winpr,crypto] rename OUT
2024-10-22 13:42:31 +02:00
akallabeth
e139ff8c86
Merge pull request #10769 from akallabeth/cmdline-improve
[client,common] update help text for /monitors
2024-10-22 13:36:41 +02:00
akallabeth
f4270aeab8
[winpr,crypto] rename OUT
visual studio compilers do have some symbol clashes, rename the function
2024-10-22 13:30:40 +02:00
akallabeth
b5f8faa7ae
[client,common] update help text for /monitors 2024-10-22 13:18:47 +02:00
akallabeth
d8dc2956e5
[codec,color] fix overlapping check
only consider images that do not contain the same lines not overlapping.
Ignore any x offsets as this may lead to alignment problems resulting in
invalid overlapping areas.
2024-10-22 11:03:14 +02:00
akallabeth
5ad826a503
Merge pull request #10763 from akallabeth/fix-our-mistakes
Fix some mistakes
2024-10-22 10:48:54 +02:00
akallabeth
6ac2a961b6
[channels,audin] fix variable shadowing 2024-10-22 10:11:41 +02:00
akallabeth
28037f100c
[warnings] fix sign comparison issues 2024-10-22 10:11:38 +02:00
akallabeth
9e18bd94f9
[crypto,x509] replace sprintf 2024-10-22 09:50:39 +02:00
akallabeth
4f4d400f7e
[core,gateway] fix out of range check 2024-10-22 09:50:36 +02:00
akallabeth
efffcee119
[channels,rdpecam] fix casts 2024-10-22 09:50:34 +02:00
akallabeth
b6e0a2381c
[winpr,crypto] fix duplicate include 2024-10-22 09:50:29 +02:00
akallabeth
b9aa91bfcb
[winpr,crypto] use inline functions for md4 2024-10-22 09:50:26 +02:00
akallabeth
6929ade1c4
[crypto,tls] fix cast 2024-10-22 09:50:24 +02:00
akallabeth
e41f8eb61f
[warnings] redundant cast 2024-10-22 09:50:22 +02:00
akallabeth
c0a3abfc62
[warnings] duplicate include 2024-10-22 09:50:20 +02:00
akallabeth
6e3cc23ad2
[ci] enable WITH_INTERNAL_[RC4|MD4|MD5]
test the implementations on qa tester
2024-10-22 09:50:18 +02:00
akallabeth
4cf5b32733
[winpr,crypto] prefer inline functions for md5 2024-10-22 09:50:16 +02:00
akallabeth
0ace936943
[clang-tidy] disable readability-string-compare
we have mostly C strings, so c++string.compare(c-string) is to be
preferred to c++string == c-string
2024-10-22 09:47:59 +02:00
akallabeth
fd8947ddc1
[winpr,kerberos] fix a leak in failure handling 2024-10-22 09:47:57 +02:00
akallabeth
b4dab0f419
[warnings] replace getpwnam 2024-10-22 09:41:35 +02:00
akallabeth
f1725b2d99
Merge pull request #10739 from akallabeth/release-3.9.0
Release 3.9.0
2024-10-21 15:55:46 +02:00
akallabeth
79b0926b60
[dev-cycle] start 3.9.1-dev0 2024-10-21 15:36:04 +02:00
akallabeth
4ae5b6c254
[release 3.9.0] update version 2024-10-21 15:36:02 +02:00
akallabeth
bd0a3055b3
[release 3.9.0] changelog 2024-10-21 15:35:59 +02:00
Martin Fleisz
9368030b3c
Merge pull request #10692 from akallabeth/warn-fixes-kerberos
Warn fixes kerberos
2024-10-21 15:28:04 +02:00
akallabeth
b253e6ba0a
[winpr,sspi] refactor kerberos_rd_tgt_token
the function was quite complex, split it up into multiple subfunctions:

* kerberos_rd_tgt_req
  * kerberos_rd_tgt_req_tag2
  * kerberos_rd_tgt_req_tag3
* kerberos_rd_tgt_rep
2024-10-21 15:05:51 +02:00
akallabeth
ab31eb7a50
[winpr,sspi] add better return values for NTLM 2024-10-21 15:05:43 +02:00
akallabeth
1c061423bc
Merge pull request #10758 from akallabeth/cmake-clean-reconfig
[cmake] watch config files
2024-10-17 22:52:04 +02:00
akallabeth
57969939e3
[cmake] watch config files
As we do add configure_file output to clean target cmake configure must
be rerun. To trigger that add source and generated file to
CMAKE_CONFIGURE_DEPENDS
2024-10-17 22:27:45 +02:00
akallabeth
02104bc2c3
Merge pull request #10757 from akallabeth/format-warn
[warnings] fix format warnings
2024-10-17 21:41:16 +02:00
akallabeth
8b3f807a0a
[warnings] fix format warnings 2024-10-17 20:47:29 +02:00
akallabeth
782f349bd7
Merge pull request #10755 from akallabeth/cmake-choice
[cmake] make CMAKE_BUILD_TYPE selectable
2024-10-17 16:12:05 +02:00
akallabeth
24954bf6ed
[cmake] make CMAKE_BUILD_TYPE selectable 2024-10-17 15:56:33 +02:00
Martin Fleisz
fb1ce1eb53
Merge pull request #10753 from akallabeth/size_t_def
replace SIZE_T with size_t
2024-10-17 14:10:13 +02:00
Martin Fleisz
00fdc97861
Merge pull request #10751 from akallabeth/libressl
[crypto,cert] fix builds with LibRESSL
2024-10-17 13:07:56 +02:00
akallabeth
f346b94835
replace SIZE_T with size_t 2024-10-17 12:40:22 +02:00
akallabeth
5f3be98c61
[crypto,cert] fix builds with LibRESSL 2024-10-17 12:02:39 +02:00
Martin Fleisz
7bca994dd2
Merge pull request #10748 from akallabeth/static_assert
Static assert
2024-10-17 09:16:28 +02:00
akallabeth
d870035509
[winpr,pragma] require VS2019 for warning pragma 2024-10-16 20:25:46 +02:00
akallabeth
122aa76ef1
[winpr,macros] Remove check for _STDC_, check only __STDC_VERSION__ 2024-10-16 20:04:02 +02:00
akallabeth
96730a0be5
[winpr,macros] move WINPR_RESTRICT and WINPR_DEPRECATED
* Move macros from wtypes.h.in to platform.h
2024-10-16 20:03:46 +02:00
akallabeth
5353bff104
[assert] use WINPR_STATIC_ASSERT 2024-10-16 19:07:07 +02:00
akallabeth
d19c0bde21
[winpr] add WINPR_STATIC_ASSERT 2024-10-16 19:06:57 +02:00
akallabeth
deb987e491
Merge pull request #10749 from akallabeth/sdl-client-fix
Sdl client fix
2024-10-16 15:44:17 +02:00
akallabeth
21668dc941
[client,sdl] fix sdl3 warnings 2024-10-16 15:21:27 +02:00
akallabeth
32169be68e
[winpr] add WINPR_PRAGMA_WARNING
a compiler independent version of #warning
2024-10-16 15:21:20 +02:00
Martin Fleisz
0b65bf5ba8
Merge pull request #10747 from akallabeth/dead-code
[winpr,tools] makecert fix relative path usage
2024-10-16 14:19:23 +02:00
akallabeth
e3430eeff5
[codec,dsp] fix unreachable code 2024-10-16 13:32:27 +02:00
akallabeth
0f8a6392d1
[crypto,tls] remove dead code
unreachable condition in is_accepted_fingerprint removed
2024-10-16 13:32:22 +02:00
akallabeth
acf80baeb7
[locale,xkbfile] fix comparison function 2024-10-16 13:32:20 +02:00
akallabeth
52d32d812c
[winpr,utils] lock message queue on size 2024-10-16 13:32:18 +02:00
akallabeth
005d70c9e4
[winpr,tools] makecert fix relative path usage 2024-10-16 13:32:15 +02:00
Martin Fleisz
2fd3ace997
Merge pull request #10641 from akallabeth/tcscpy
replace strcpy/tcscpy/wcscpy strlen/tcslen/wcslen
2024-10-16 08:31:46 +02:00
akallabeth
387f0efd24
Merge pull request #10746 from akallabeth/fastpath-unlock
[core,fastpath] fix error unlock
2024-10-15 23:00:49 +02:00
akallabeth
b5d4339d86 [core,fastpath] fix error unlock 2024-10-15 22:44:16 +02:00
akallabeth
6e8c867ec5
Merge pull request #10745 from akallabeth/ci-simd
[ci,qa] enable NEON and SSE optimized builds
2024-10-15 22:18:44 +02:00
akallabeth
12b2cb9d2f [ci,qa] enable NEON and SSE optimized builds 2024-10-15 21:59:40 +02:00
akallabeth
2e73ead996
[c stdlib] replace strlen/strcpy/strcmp
Use length checking versions if possible. Also replaces the wide
character versions and TCHAR versions
2024-10-15 16:30:13 +02:00
akallabeth
60609251fb
Merge pull request #10741 from akallabeth/sdl3-api-update
[client,sdl3] update to current API
2024-10-15 09:00:54 +02:00
akallabeth
7d5876bdb2
[client,sdl3] update to current API 2024-10-15 08:42:48 +02:00
Martin Fleisz
e6abf49a80
Merge pull request #10706 from akallabeth/narrow-fixes-more-more-more
Narrow fixes more more more
2024-10-14 10:48:17 +02:00
akallabeth
026b5218ff
[warnings] fix integer narrowing 2024-10-14 10:32:09 +02:00
akallabeth
f0c1cbe20f
[warnings] fix integer narrowing 2024-10-14 10:32:03 +02:00
akallabeth
dceb15d14e
[warnings] fix integer narrowing 2024-10-14 10:32:01 +02:00
akallabeth
8f069b2be4
[warnings] fix integer narrowing 2024-10-14 10:31:58 +02:00
akallabeth
e6cf35c518
[warnings] fix integer narrowing 2024-10-14 10:31:55 +02:00
akallabeth
15d408d6fc
[warnings] fix integer narrowing 2024-10-14 10:31:45 +02:00
akallabeth
62e556f4d0
[warnings] fix integer narrowing 2024-10-14 10:31:43 +02:00
akallabeth
bd28c2d4bf
[warnings] fix integer narrowing 2024-10-14 10:31:41 +02:00
akallabeth
1cdc864c7d
[warnings] fix integer narrowing 2024-10-14 10:31:38 +02:00
akallabeth
343900d227
[crypto,cert] make a deep copy of the certificate chain
The parameters of freerdp_certificate_new_from_x509 are const, so only
work with a copy of the input.
2024-10-14 10:31:35 +02:00
Martin Fleisz
dcc288c3d1
Merge pull request #10704 from akallabeth/int-narrow-cleanups
Int narrow cleanups
2024-10-14 09:51:06 +02:00
akallabeth
1432c65592
Merge pull request #10735 from FreeRDP/timezone-patches-1728716894
[timezones] Update definitions
2024-10-12 09:23:18 +02:00
akallabeth
7ea8774728 Update timezone definitions 2024-10-12 07:08:14 +00:00
akallabeth
d53e8c2574
Merge pull request #10734 from akallabeth/tz-gen-fix
[ci,timezone] remove clang-format off
2024-10-12 09:06:32 +02:00
akallabeth
d56fac7582
[ci,timezone] remove clang-format off
we do format the files now properly before creating the automated pull,
the workaround is no longer required
2024-10-12 09:04:39 +02:00
akallabeth
4988ba1188
Merge pull request #10732 from akallabeth/tz-gen-fix
[ci,timezone] update timezone generation
2024-10-12 09:00:51 +02:00
akallabeth
a01b97e991
[ci,timezone] update timezone generation 2024-10-12 08:59:26 +02:00
akallabeth
91da1e7473
Merge pull request #10730 from akallabeth/tz-gen-fix
Tz gen fix
2024-10-12 08:54:47 +02:00
akallabeth
969e212570
[winpr,timezone] skip newline in generated timezonemap 2024-10-12 08:51:00 +02:00
akallabeth
c7ce6ebe67
[ci,timezones] fix file formatting 2024-10-12 08:50:57 +02:00
akallabeth
bbc27d53db
Merge pull request #10726 from oleg0421/rdpecam_client_mjpeg_fix
RDPECAM client MJPEG decoder fix to skip corrupted frames
2024-10-12 08:37:08 +02:00
akallabeth
c73dc72b47
Merge pull request #10728 from akallabeth/timezone-no-format
[winpr,timezone] deactivate clang-format for generated files
2024-10-12 08:33:24 +02:00
akallabeth
2cbb5685b4 [winpr,timezone] deactivate clang-format for generated files 2024-10-11 09:16:37 +02:00
oleg0421
f0922350ee RDPECAM client MJPEG decoder fix to skip corrupted frames 2024-10-10 18:05:22 -07:00
David Fort
88ce44ed2e
Merge pull request #10724 from akallabeth/scard-status-string-terminate
[utils,smartcard] ensure '\0' termination for NDR
2024-10-10 22:21:38 +02:00
akallabeth
6ebef063b5
Merge pull request #10720 from akallabeth/prim-copy-fix2
[primitives,copy] remove bgr24 to bgrx32 optimized
2024-10-10 17:22:56 +02:00
akallabeth
a12a2dc6af
[gdi,gfx] remove broken overlap check 2024-10-10 16:40:16 +02:00
akallabeth
dc8d8553e8
[utils,smartcard] ensure '\0' termination for NDR
NDR read functions do not exactly know which kind of string is read and
if it contains a '\0', so ensure that we add one large enought to hold a
unicode '\0'
2024-10-10 16:25:41 +02:00
akallabeth
b4dbecd506
[primitives,copy] fix issues with SSE 4.1 and AVX2
* Deactivate optimized image_copy_bgr24_bgrx32
* Fall back to generic implementation instead of copying that code
2024-10-10 15:23:43 +02:00
akallabeth
7e28e0890c
[primitives,copy] remove invalid optimized branch 2024-10-10 15:23:33 +02:00
akallabeth
3ddc0e7c73
[primitives,copy] use loop unroll pragma 2024-10-10 15:23:30 +02:00
akallabeth
f5171b6b47
[primitives,sse] skip optimized copy on wrong alignment 2024-10-10 15:23:28 +02:00
akallabeth
62e8270db1
[codec,color] assert overlapping state in image copy 2024-10-10 15:23:26 +02:00
akallabeth
0fa9e73de6
[primitives,test] add new unittest for copy_no_overlap 2024-10-10 15:23:24 +02:00
Martin Fleisz
3d018a827f
Merge pull request #10708 from akallabeth/manpage-pre-generated
Manpage pre generated
2024-10-10 11:09:02 +02:00
Armin Novak
c3a5387187
[manpages] switch generation to pure CMake
* Ditch docbook/xmlto, use plain manpage files
* Add CMake functions to concatenate manpate sections
* Modify generate_argument_manpage helper tool to generate manpage
2024-10-09 21:41:14 +02:00
Armin Novak
8fcc59ed27
[ci] remove docbook and xml dependencies 2024-10-09 20:42:09 +02:00
Armin Novak
b9adc1dd24
[ci] remove travis configuration 2024-10-09 20:42:06 +02:00
Armin Novak
f72db3f9f7
[cmake] fix TODAY macro 2024-10-09 20:41:59 +02:00
akallabeth
815d6a9fdd
Merge pull request #10721 from akallabeth/language-extension
Language extension
2024-10-09 13:37:26 +02:00
Armin Novak
9531b7b270
[winpr,file] add missing WINPR_ATTR_MALLOC 2024-10-09 10:41:19 +02:00
Armin Novak
b73befd677
[cmake] reenable -Wlanguage-extension-token
since the offending macros are now silenced reenable the warning so we
are warned about unintentional use of extensions.
2024-10-09 10:09:49 +02:00
Armin Novak
8abf9cbe7c
[winpr] mark GNU macros with __extension__
mark GNU and clang definition of macros using statement expressions with
__extension__ to silence warnings. We know the compilers support that
and do not use it with others.
2024-10-09 10:09:43 +02:00
akallabeth
2d10effd3c
Merge pull request #10716 from akallabeth/kerberos-return
[winpr,sspi] fix kerberos return on get_credentials
2024-10-08 17:26:43 +02:00
akallabeth
4b52062658
Merge pull request #10718 from akallabeth/win-ci-proxy-modules
[ci,windows] build proxy modules
2024-10-08 17:17:20 +02:00
akallabeth
008de893fe [cmake,c++] define NOMINMAX
Windows header define min and max posing issues with c++ standard
library
https://stackoverflow.com/questions/4913922/possible-problems-with-nominmax-on-visual-c
2024-10-08 16:36:01 +02:00
akallabeth
fdd02c945a [ci,windows] build proxy modules 2024-10-08 16:36:01 +02:00
Martin Fleisz
25c281818a
Merge pull request #10714 from akallabeth/sse-fix
[primitives,sse] fix a bug in sse4.1 primitives copy
2024-10-08 12:31:56 +02:00
akallabeth
4e65fdb9eb
Merge pull request #10717 from akallabeth/revert-alt
[ci,workflow] set USE_UNWIND=OFF again
2024-10-08 12:08:00 +02:00
akallabeth
3eca097b34
[ci,workflow] set USE_UNWIND=OFF again
arm builds do not work with unwind backtrace on.
[winpr_unwind_backtrace]: _Unwind_Backtrace failed with _URC_FAILURE [0x09]
2024-10-08 11:10:18 +02:00
akallabeth
4c034ac36f
[client,x11] fix memory leak in clipboard 2024-10-08 11:03:24 +02:00
akallabeth
de5e837c76
Merge pull request #10715 from akallabeth/unwind-arm
[winpr,utils] fix undefined unwind symbols
2024-10-08 10:41:58 +02:00
akallabeth
1fe0a6f40e
[winpr,sspi] fix kerberos return on get_credentials
return SEC_E_NO_CREDENTIALS
2024-10-08 10:33:30 +02:00
akallabeth
1952cd0e66
[winpr,utils] fix undefined unwind symbols
on arm some reason codes are not defined.
2024-10-08 10:09:19 +02:00
akallabeth
99b5d2298b
[primitives,sse] fix a bug in sse4.1 primitives copy 2024-10-08 09:38:20 +02:00
akallabeth
0c0a5f4234
Merge pull request #10711 from hardening/sdl3_fix3
Fixes for the SDL3 client
2024-10-07 12:11:32 +02:00
David Fort
d05c781cd9 sdl3 client: take in account last SDL changes
This patch uses the last changes in the SDL3 clipboard to have that clean separation
between mime type announcement and retrieving the corresponding clipboard data. With
these changes we don't have anymore that spurious notifications where we loose the
clipboard ownership, and also we don't trigger data retrieval by calling functions
like SDL_ClipboardHasText().
2024-10-07 11:48:41 +02:00
akallabeth
4cd680c9fc
Merge pull request #10712 from akallabeth/file-handle-fixes
[winpr,file] make handle creators return const
2024-10-07 11:26:26 +02:00
akallabeth
7e8c374fe2
[winpr,file] make handle creators return const
* let the file handle creators return const HANDLE_CREATOR
* for comm port use winpr_definition_add(-DWINPR_HAVE_SERIAL_SUPPORT) to
  have the definition visible at correct scope
* create namedPipeClient.h for handle creator function declaration
2024-10-07 10:15:34 +02:00
akallabeth
326fb337ef
Merge pull request #10292 from oleg0421/rdpecam_client_mjpeg_support
[channel,rdpecam] MJPEG input format support
2024-10-07 09:45:56 +02:00
David Fort
35df9e95ad sdl3: fix build with last SDL_ttf 2024-10-07 09:42:47 +02:00
oleg0421
4797609b80 [channel,rdpecam] MJPEG input format support 2024-10-05 17:32:43 -07:00
akallabeth
48eb68b53b
Merge pull request #10707 from akallabeth/alsa-mic-fix
Alsa mic fix
2024-10-04 21:20:15 +02:00
akallabeth
8ea903091b
[winpr,platform] disable GCC pragma
GCC does not support -Wtautological-constant-out-of-range-compare
2024-10-04 16:12:03 +02:00
akallabeth
cf46f341f6
[channels,audin] fix alsa backend
* Fix wrong variable passed to receive
* Improve logging/error handling
2024-10-04 16:11:53 +02:00
akallabeth
f4cac29f3c
[channels,audin] fix string to int conversion
use strtoul for unsigned values
2024-10-04 12:05:10 +02:00
akallabeth
140fe9c50f
[clang-tidy] disable readability-misleading-indentation
this only triggers because of some #ifdef and some of our macros. As all
the code is clang-formatted anyway the warning is useless.
2024-10-03 21:21:46 +02:00
akallabeth
f00d9c45e0
[warnings] fix integer narrowing
fix function freerdp_tls_write_all
2024-10-03 21:21:46 +02:00
akallabeth
503b9f0bb7
[warnings] fix integer narrowing 2024-10-03 21:21:45 +02:00
akallabeth
4fc2e1bb3e
[warnings] fix integer narrowing 2024-10-03 21:21:44 +02:00
akallabeth
4b5274c34f
[warnings] fix integer narrowing 2024-10-03 21:21:44 +02:00
akallabeth
04bd097455
[warnings] fix integer narrowing 2024-10-03 21:21:43 +02:00
akallabeth
544c6ddce6
[warnings] fix integer narrowing 2024-10-03 21:21:42 +02:00
akallabeth
53497a572d
[warnings] fix integer narrowing 2024-10-03 21:21:42 +02:00
akallabeth
57ed259be2
[warnings] fix integer narrowing 2024-10-03 21:21:41 +02:00
akallabeth
b19dcf8d68
[warnings] fix integer narrowing 2024-10-03 21:21:41 +02:00
akallabeth
eceab9aedb
[warnings] fix integer narrowing 2024-10-03 21:21:40 +02:00
akallabeth
704597937d
[warnings] fix integer narrowing 2024-10-03 21:21:39 +02:00
akallabeth
efeac25fa9
[warnings] fix integer narrowing 2024-10-03 21:21:38 +02:00
akallabeth
cdb25ea11b
[warnings] fix integer narrowing 2024-10-03 21:21:38 +02:00
akallabeth
08afc250a3
[warnings] fix integer narrowing 2024-10-03 21:21:36 +02:00
akallabeth
40ba7aa03a
[warnings] fix integer narrowing 2024-10-03 21:21:36 +02:00
akallabeth
429474cd0f
[warnings] fix integer narrowing 2024-10-03 21:21:35 +02:00
akallabeth
5e6d0a4183
[warnings] fix integer narrowing 2024-10-03 21:21:35 +02:00
akallabeth
eea56dcf60
[warnings] fix integer narrowing 2024-10-03 21:21:34 +02:00
akallabeth
69b9f81c29
[warnings] fix integer narrowing 2024-10-03 21:21:33 +02:00
akallabeth
afc4f9b92a
[warnings] fix integer narrowing 2024-10-03 21:21:33 +02:00
akallabeth
142d112eee
[warnings] fix integer narrowing 2024-10-03 21:21:32 +02:00
akallabeth
83921b0f67
[warnings] fix integer narrowing 2024-10-03 21:21:32 +02:00
akallabeth
42d66eaebe
[warnings] fix integer narrowing 2024-10-03 21:21:31 +02:00
akallabeth
f9bfaba0d2
[warnings] fix integer narrowing 2024-10-03 21:21:30 +02:00
akallabeth
e878927cd7
[warnings] fix integer narrowing 2024-10-03 21:21:29 +02:00
akallabeth
2e23ddfc1c
[warnings] fix integer narrowing 2024-10-03 21:21:27 +02:00
akallabeth
fe8e1950aa
[warnings] fix integer narrowing 2024-10-03 21:21:21 +02:00
akallabeth
6c8c67b385
Merge pull request #10677 from akallabeth/int-narrow
Int narrow
2024-10-03 21:17:56 +02:00
akallabeth
e14b7a1f29
[crypto,cert] cleanup cert chain duplication/cleanup 2024-10-03 20:35:39 +02:00
akallabeth
830f208ec4
[cyrpto,x509] delete unused function 2024-10-03 19:36:47 +02:00
akallabeth
ac1a922774
[common,settings] annotate freerdp_settings_set_value_for_name
we cast a SSIZE_T to the required enum value. Since we do not know the
enum contains any value at all it might lead to compiler/analyzer
warning us about that. Silence the warning as we can not avoid it.
2024-10-03 18:59:20 +02:00
akallabeth
31570e31e1
[crypto] fix integer narrowing 2024-10-03 18:59:18 +02:00
akallabeth
46c1ae145c
[crypto,certificate] fix integer narrowing 2024-10-03 18:59:16 +02:00
akallabeth
a54a602dcc
[crypto,certificate] fix stackof handling 2024-10-03 18:59:14 +02:00
akallabeth
315f793078
[common,settings] fix integer narrowing 2024-10-03 18:59:11 +02:00
akallabeth
2c7ca7f4b2
[rdtk] fix integer narrow 2024-10-03 18:59:08 +02:00
akallabeth
911ed13efc
[channels,rdpei] fix integer narrow 2024-10-03 18:59:05 +02:00
akallabeth
15141385f6
[client,x11] fix integer narrow 2024-10-03 18:59:03 +02:00
akallabeth
7037a8a846
[client,sample] fix integer narrow 2024-10-03 18:59:01 +02:00
akallabeth
6c25607c76
[client,common] fix integer narrow 2024-10-03 18:58:58 +02:00
akallabeth
3a2a65bbed
[server,shadow] fix integer narrow 2024-10-03 18:58:56 +02:00
akallabeth
997ff57301
[proxy,rdpdr] fix integer narrow 2024-10-03 18:58:53 +02:00
akallabeth
f55a1e2bc3
[proxy,modules] fix integer narrow 2024-10-03 18:58:51 +02:00
akallabeth
10bb42e4d8
[server,proxy] fix integer narrowing 2024-10-03 18:58:48 +02:00
akallabeth
b5dbe5a167
[emu,scard] fix integer narrow 2024-10-03 18:58:46 +02:00
akallabeth
e13273d94d
[utils,test] fix integer narrow 2024-10-03 18:58:44 +02:00
akallabeth
4783546582
[winpr,wlog] fix integer narrow 2024-10-03 18:58:41 +02:00
akallabeth
8a042b33d6
[winpr,utils] fix integer narrow 2024-10-03 18:58:39 +02:00
akallabeth
4a0f996d42
[winpr,timezone] fix integer narrow 2024-10-03 18:58:37 +02:00
akallabeth
57f69ad77d
[winpr,synch] fix integer narrow 2024-10-03 18:58:34 +02:00
akallabeth
22d1810e12
[winpr,sspi] fix integer narrow 2024-10-03 18:58:32 +02:00
akallabeth
a0dbb901df
[winpr,shell] fix integer narrow 2024-10-03 18:58:29 +02:00
akallabeth
cb2cbdabfe
[winpr,ncrypt] fix integer narrow 2024-10-03 18:58:26 +02:00
akallabeth
a5b80925e2
[winpr,interlocked] fix integer narrow 2024-10-03 18:58:23 +02:00
akallabeth
952076afb7
[winpr,crypto] fix integer narrow 2024-10-03 18:58:21 +02:00
akallabeth
67817886ab
[winpr,clipboard] fix integer narrow 2024-10-03 18:58:13 +02:00
Martin Fleisz
966ddd13df
Merge pull request #10694 from akallabeth/qa-fixes
Qa fixes
2024-10-03 13:09:06 +02:00
Martin Fleisz
4c5fba4526
Merge pull request #10702 from akallabeth/global-config
Global config
2024-10-03 11:54:58 +02:00
akallabeth
cfc37caeb8
[cmake] cleaning_configure_file
add a wrapper to automatically add generated files to clean target
2024-10-02 23:28:08 +02:00
Armin Novak
c86a78bef7
[man] add manpage for global configuration 2024-10-02 23:28:05 +02:00
Armin Novak
0146deb4c0
[crypto,tls] global certificate configuration
Add a global configuration file which allows predefined settings for
certificate handling.
2024-10-02 23:28:03 +02:00
Armin Novak
dcdb0bb3b2
[utils,helpers] add a function to get FreeRDP config file paths 2024-10-02 23:28:00 +02:00
Armin Novak
1f7ec7324d
[winpr,registry] use HKLM.reg relative to config home 2024-10-02 23:27:57 +02:00
Armin Novak
934cf668a2
[winpr,utils] use sam file relative to config home 2024-10-02 23:27:55 +02:00
Armin Novak
276e3d67e0
[winpr,path] add a function to get WinPR config file paths 2024-10-02 23:27:53 +02:00
Armin Novak
ac0acd0463
[winpr,path] add KNOWN_PATH_SYSTEM_CONFIG_HOME 2024-10-02 23:27:49 +02:00
David Fort
d06d2e0e29
Merge pull request #10700 from akallabeth/avx-option
[cmake] Allow disabling AVX2 extensions
2024-10-02 16:59:58 +02:00
Armin Novak
0df01bcf8d
[cmake] Allow disabling AVX2 extensions 2024-10-02 15:14:29 +02:00
akallabeth
fef9b1a012
[client,common] annotate clang-analyzer-optin.core.EnumCastOutOfRange 2024-10-01 13:05:53 +02:00
akallabeth
032b34702d
[channels,urbdrc] fix sign warnings 2024-10-01 13:05:50 +02:00
akallabeth
5e1aa072f1
[client,common] fix sign warnings 2024-10-01 13:05:48 +02:00
akallabeth
a57263c209
[channels,rdpecam] refactor cam_v4l_get_fourcc_str 2024-10-01 13:05:46 +02:00
akallabeth
04a8bcd8a5
[channels,cliprdr] make global strings arrays 2024-10-01 13:05:43 +02:00
akallabeth
582ff2c319
[winpr,wincrypt] fix a define typo 2024-10-01 13:05:41 +02:00
akallabeth
f6d71a592e
[winpr,assert] silence tautological-constant-out-of-range-compare
we do some assertions that can with correct code never trigger. (check
for a unsinged char > 256, ...)
2024-10-01 13:05:39 +02:00
akallabeth
fe8555a4fd
[warnings] annotate cert-err34-c 2024-10-01 13:05:36 +02:00
akallabeth
f6eb6ad4d7
[utils,string] add freerdp_extract_key_value
* Add new function freerdp_extract_key_value to extract key/value pairs
  from a string
* replace all sscanf usages with this new function
2024-10-01 13:05:34 +02:00
akallabeth
e95707f3c7
[server,proxy] annotate bugprone-signal-handler 2024-10-01 13:05:32 +02:00
akallabeth
ee81bb017b
[warnings] fix assign enum
* add missing value for rdpecam
* use an integer for a badly designed API
2024-10-01 13:05:30 +02:00
akallabeth
72350e2587
[channels,cliprdr] log clipboard format requested 2024-10-01 13:05:27 +02:00
akallabeth
9c33717522
[winpr,file] fix sign warnings 2024-10-01 13:05:25 +02:00
akallabeth
5f9ef68b07
[warnigs] fixed readability-non-const-parameter 2024-10-01 13:05:23 +02:00
akallabeth
8d64d75aa2
[client,SDL] fix clang-diagnostic-global-constructors 2024-10-01 13:05:20 +02:00
akallabeth
574742bae8
[warnings] annotate readability-non-const-parameter 2024-10-01 13:05:19 +02:00
akallabeth
ae61278d18
[core,gateway] annotate DeadStore warnings 2024-10-01 13:05:16 +02:00
akallabeth
a1a8846ad2
[utils,proxy] refactor proxy_parse_uri
* eliminate deadstore warnings
* fix missing input checks
2024-10-01 13:05:14 +02:00
akallabeth
8a0194c105
[clang-tidy] annotate suspicious-memory-comparison 2024-10-01 13:05:11 +02:00
akallabeth
7fdb3a68bd
[clang-tidy] annotate bugprone-suspicious-missing-comma 2024-10-01 13:05:09 +02:00
akallabeth
9eeeef6976
[channels,rdpecam] fix redundant-control-flow 2024-10-01 13:05:07 +02:00
akallabeth
fa21806734
[winpr,error] fix sign of NTE_* defines 2024-10-01 13:05:04 +02:00
akallabeth
1c12a15de1
[channels,rdpecam] fix iterator types 2024-10-01 13:05:00 +02:00
akallabeth
485ebe03bf
[*printf] cast return to void 2024-10-01 13:04:57 +02:00
akallabeth
95bafbf8d4
[client,sdl] remove unused private fields 2024-10-01 13:04:54 +02:00
akallabeth
e2eb8f6a28
[codec,xcrush] annotate bugprone-sizeof 2024-10-01 13:04:52 +02:00
akallabeth
7cd4884de1
[channels,rdpecam] remove invalid doxygen 2024-10-01 13:04:49 +02:00
akallabeth
1145eb0fc9
[core,gateway] annotate bugprone-sizeof-expression 2024-10-01 13:04:47 +02:00
akallabeth
cf7fd2d340
[channels,rdpecam] fix widening of multiplication result 2024-10-01 13:04:45 +02:00
akallabeth
9a82045bf2
[client,sdl] remove static from sdlDisp::handle_display_event 2024-10-01 13:04:42 +02:00
akallabeth
1cd0d0ab6e
[client,common] use uintptr_t instad of UINT_PTR 2024-10-01 13:04:40 +02:00
akallabeth
a23d45a419
[client,common] make time a 64bit signed integer 2024-10-01 13:04:37 +02:00
akallabeth
953aa6c436
[winpr,sspi] fix kerberos unused parameter warning 2024-10-01 13:04:35 +02:00
akallabeth
94c3253cee
[ci,qa] enable RDPECAM and RDPEAR channels for clang-tidy 2024-10-01 13:04:32 +02:00
akallabeth
b44527387d
[clang-tidy] disable readability-convert-member-functions-to-static 2024-10-01 13:04:29 +02:00
akallabeth
3fe99c87a1
Merge pull request #10695 from akallabeth/cov-fixes
Cov fixes
2024-10-01 12:56:14 +02:00
akallabeth
490ca0453b
[winpr,stream] use Stream_BufferAs instead of casting 2024-10-01 10:34:42 +02:00
akallabeth
11b7633dc0
[channels] use Stream_BufferAs
For WTSVirtualChannelRead and WTSVirtualChannelWrite use Stream_BufferAs
to cast to correct type.
2024-10-01 10:28:13 +02:00
akallabeth
55177e0e46
[channels,rdpsnd] remove dead code 2024-10-01 10:18:48 +02:00
akallabeth
8ddb678639
[channels,cliprdr] fix server side send routine 2024-10-01 10:16:18 +02:00
akallabeth
a85068d42e
[core,gateway] allow websocket write up to UINT32_MAX 2024-10-01 10:14:03 +02:00
akallabeth
47c5070805
Merge pull request #10635 from akallabeth/initialize-variables
Initialize variables
2024-09-30 16:04:20 +02:00
akallabeth
508238711c
Merge pull request #10676 from akallabeth/cmake-file-to-hex
Cmake file to hex
2024-09-30 15:58:18 +02:00
akallabeth
fd099d38c7
Merge pull request #10688 from akallabeth/settings-fix
Settings fix
2024-09-30 15:55:51 +02:00
akallabeth
ba47e1936f
[uwac] add strerror_r detection and use 2024-09-30 15:41:52 +02:00
akallabeth
a820912a24
[winpr,utils] fix sterror_r detection and use 2024-09-30 15:41:50 +02:00
akallabeth
f95f873c58
[ci,tidy] fix ci preload file
the option is named ENABLE_WARNING_VERBOSE to enable verbose warnings.
2024-09-30 15:41:47 +02:00
akallabeth
aa47e58f11
[core,settings] disable clang-tidy warning
we allocate a UINT32** using calloc and casting it. This allows freeing
this up with free but yields some warnings. Disable for this specific
case
2024-09-30 15:41:45 +02:00
akallabeth
ce30f80d2c
[client,common] disable clang-tidy for function
change_lock moves ownership of allocated CliprdrLocalStream to
file->local_streams. Do not complain about possible memory leak (false
positive)
2024-09-30 15:41:42 +02:00
akallabeth
53942081a1
[ci,tidy] use CFLAGS from cmake verbose warnings 2024-09-30 15:41:36 +02:00
akallabeth
98e11c69c1
[winpr,ncrypt] add pragma to disable warning 2024-09-30 15:41:34 +02:00
akallabeth
c319541f0d
[core,settings] add unit test
Test cases for freerdp_settings_check_client_after_preconnect
2024-09-30 15:41:31 +02:00
akallabeth
d71c9c566a
[core,settings] monitor configuration check
* fix origin check, might not be primary monitor
* fix a memory leak
2024-09-30 15:41:23 +02:00
akallabeth
fffabcaab1
[primitives,opencl] Use CMake to include opencl code
* Use CMake to convert opencl source file to C constant
* Mark opencl sources as headers and add to CMake to show in IDE
2024-09-30 10:50:42 +02:00
akallabeth
fe590801a1
[cmake] replace custom file2hex tool
Use CMake to read file and convert to C array of hex values
2024-09-30 10:50:36 +02:00
David Fort
b891228279
Merge pull request #10693 from akallabeth/abi-fixes
[channels,rdpear] default to OFF
2024-09-30 10:20:19 +02:00
akallabeth
f3055f9644
Merge pull request #10642 from akallabeth/warn-fixes-again
fix a few more warnings
2024-09-30 10:05:20 +02:00
akallabeth
2973ff7004
[channels,rdpear] default to OFF
Since the channel was introduced late in the 3.x series require users to
explicitly enable it to not break existing build setups.
2024-09-30 09:42:45 +02:00
akallabeth
dd98b20f4a
[core,utils] improve utils_str_is_empty 2024-09-30 09:32:15 +02:00
akallabeth
55a5fe26fb
[common,test] remove redundant cast 2024-09-30 09:32:12 +02:00
akallabeth
9d478c2ce7
[winpr,crt] fix redundant casts 2024-09-30 09:32:04 +02:00
akallabeth
1947f28a70 [codec,fdk] fix use of strcat 2024-09-30 09:31:36 +02:00
akallabeth
3825fe8135 [warnings] fix Wunreachable-code-break 2024-09-30 09:31:36 +02:00
akallabeth
f529345d84 [warnings] fix Wcast-qual 2024-09-30 09:31:36 +02:00
David Fort
51b179b9c7
Merge pull request #10687 from akallabeth/man-grab-keyboard
[client,common] improve grab description
2024-09-27 22:37:32 +02:00
akallabeth
6e6f50c088
[client,common] improve grab description
Better describe what +grab-keyboard and +grab-mouse do.
2024-09-27 13:39:00 +02:00
akallabeth
c470b23795
Merge pull request #10672 from akallabeth/multimon-warn
Multimon warn
2024-09-27 10:44:06 +02:00
Martin Fleisz
9ec3d9dc0b
Merge pull request #10679 from akallabeth/rdpei-no-thread
Rdpei no thread
2024-09-27 09:58:44 +02:00
Armin Novak
1bc188158b
[ci,preload] enable verbose warnings 2024-09-27 09:44:43 +02:00
akallabeth
cf809e6388
[core,settings] add settings validation
after client side preconnect validate the settings.
Currently checks for some monitor layout limitations are implemented
2024-09-27 09:44:40 +02:00
akallabeth
3e7a7fdcad
[channels,rdpei] implement channel without thread
* implement channel without thread (compile time option)
* use dynamic logger
* add some missing parameter and stream checks
2024-09-27 09:32:22 +02:00
akallabeth
9f454bea85
Merge pull request #10684 from akallabeth/redirect-bandwidth-auto
[core,mcs] unify message channel handling
2024-09-27 09:12:01 +02:00
akallabeth
f400b9a602
[core,client] fix freerdp_channels_check_fds
unify freerdp_channels_check_fds and
freerdp_channels_process_pending_messages as they both do the same
thing.
2024-09-26 17:01:14 +02:00
akallabeth
ab88e79a36
[core,mcs] unify message channel handling 2024-09-26 16:57:27 +02:00
akallabeth
2fe0435e79
Merge pull request #10680 from akallabeth/redirect-bandwidth-auto
[core,connection] handle message channel in state
2024-09-26 15:14:16 +02:00
akallabeth
5e13d5bf16
[core,connection] handle message channel in state
When in demand active it is possible that we can receive message channel
messages. In case we receive one switch parsing to the appropriate
handlers.
2024-09-26 14:38:59 +02:00
akallabeth
8cf0dd4359
Merge pull request #10682 from akallabeth/cleanup
[revert] delete accidentally committed files
2024-09-26 10:55:09 +02:00
akallabeth
3e09d4cfc1
[ci,abi] rename working directory
since the old working directory checker had been accidentally checked in
use a new one to avoid clashes during build.
2024-09-26 10:16:41 +02:00
akallabeth
776b0e68b5
[revert] delete accidentally committed files 2024-09-26 09:09:07 +02:00
Martin Fleisz
64bf1c9a97
Merge pull request #10678 from akallabeth/compile-fix
Compile fix
2024-09-25 10:52:33 +02:00
Armin Novak
66b6a90cc7
[client,x11] fix xf_GetWindowProperty arguments
Use BYTE* as argument and cast later to desired type
2024-09-25 10:31:38 +02:00
Armin Novak
9fc7e5bfd9
[cmake] default ENABLE_WARNING_VERBOSE=OFF 2024-09-25 10:28:49 +02:00
akallabeth
cfc56e936a
Merge pull request #10675 from akallabeth/clang-tidy-customize
Clang tidy customize
2024-09-25 09:05:17 +02:00
David Fort
609d04deab
Merge pull request #10671 from akallabeth/workarea-fix
[client,x11] fix reading of work area
2024-09-25 07:18:54 +02:00
akallabeth
5e998bb078
[winpr,platfom] fix WINPR_PRAGMA_DIAG_IGNORED_UNUSED_MACRO 2024-09-24 20:35:28 +02:00
akallabeth
ff31004b98
[clang-tidy] disable cppcoreguidelines-macro-usage
This check does not help us as:
* We need some stringification macros even in C++
* The whole API is C so macros are all over the place
2024-09-24 20:35:13 +02:00
akallabeth
2e1ea335f3
Merge pull request #10674 from akallabeth/unused-eliminate
Unused eliminate
2024-09-24 20:07:34 +02:00
akallabeth
f414bef5cb
[codec,dsp] fix freerdp_dsp_context_free
abort early on NULL argument
2024-09-24 19:45:23 +02:00
akallabeth
0d8764263f
[client,sdl] eliminate unused variables 2024-09-24 19:45:20 +02:00
akallabeth
b1cc0a3191
[proxy,modules] eliminate unused variables 2024-09-24 19:45:16 +02:00
akallabeth
01d565398e
[client,x11] fix reading of work area
https://specifications.freedesktop.org/wm-spec/1.4/ar01s03.html
_NET_CURRENT_DESKTOP might not be supported by a window manager. Ignore
failures there and just take the first monitor dimensions.
2024-09-24 13:07:22 +02:00
akallabeth
469f75a314
[codec,ncrush] fix possible overflow 2024-09-24 11:39:45 +02:00
akallabeth
89e6f357b5
[utils,smartcard] fix possible integer overflow 2024-09-24 11:34:02 +02:00
akallabeth
1f3e6decf2
[client,common] fix possible integer overflow 2024-09-24 11:31:40 +02:00
akallabeth
3d210d815d
[client,X11] fix sign of shifted type 2024-09-24 11:30:23 +02:00
akallabeth
0fe89241f8
[core,client] add argument checks & assertions
* freerdp_get_event_handles
* freerdp_channels_process_pending_messages
2024-09-24 11:08:38 +02:00
akallabeth
26003e59cc
[va_list] initialize with ={0}; 2024-09-24 11:06:18 +02:00
akallabeth
fcdbc05979
Merge pull request #10663 from akallabeth/client-channel-event-process-api
[core,client] add channel poll registration API
2024-09-24 11:05:09 +02:00
akallabeth
82a43ef4dc
[core,client] add channel poll registration API
Add a new API that allows channels to register/unregister an
event-handle along with a callback function to be called by the RDP main
thread.
This allows background processing of channel specifics without the need
for a channel specific thread.
2024-09-24 10:10:52 +02:00
akallabeth
193e985063
Merge pull request #10666 from hardening/sdl3_fix2
sdl3: various fixes with the clipboard
2024-09-24 10:08:27 +02:00
akallabeth
7ccc794176
Merge pull request #10668 from akallabeth/ffmpeg-fix
[cmake,ffmpeg] fix version detection
2024-09-24 10:07:42 +02:00
akallabeth
c766c13103
[cmake,ffmpeg] fix version detection
If not detected by pkg-config fall back on header file parsing to
extract the version of the FFmpeg component.
2024-09-24 09:47:46 +02:00
David Fort
57c703cf67 sdl3: various fixes with the clipboard
There were various invalid checks with function return values. The patch also
fixes a deadlock between the SDL clipboard data function and the FreeRDP
thread.
2024-09-23 15:35:11 +02:00
Martin Fleisz
5380a743b5
Merge pull request #10664 from akallabeth/audin-fixes
Audin fixes
2024-09-23 12:22:41 +02:00
akallabeth
4b60f0651c
[channels] Fix PulseAudio assertions/NULL checks 2024-09-23 12:01:13 +02:00
akallabeth
ae3330d63d
[codec,dsp] reorganize experimental codecs
* Remove ALAW/µULAW from sound channels
* Make everything except PCM and AAC experimental
2024-09-23 12:01:11 +02:00
akallabeth
ce2605fad2
[codec,dsp] fix FDK-AAC memory leak 2024-09-23 12:00:55 +02:00
akallabeth
b350b0039e
Merge pull request #10662 from JohnWoo22/neon_combine_fix
fix neon-based chroma filter
2024-09-23 10:54:27 +02:00
JohnWoo22
69163f91ee fix neon-based chroma filter 2024-09-23 14:01:17 +08:00
akallabeth
7fc4f528c0
Merge pull request #10654 from akallabeth/unused-macros
[warnings] remove or comment unused macros
2024-09-20 19:23:45 +02:00
akallabeth
239440e28d
[warnings] remove or comment unused macros 2024-09-20 18:49:38 +02:00
akallabeth
ed942f8c20
[warnings,c++] deactivate -Wexit-time-destructors
This warning can be ignored as on all supported platforms memory, file
and network resources are cleared up on program termination.
2024-09-20 17:35:52 +02:00
Martin Fleisz
5bcd737548
Merge pull request #10651 from akallabeth/disable-language-extension-warn
[compiler,warnings] disable -Wlanguage-extension-token
2024-09-20 14:07:11 +02:00
Norbert Federa
d3a7629734
Merge pull request #10629 from akallabeth/rail-modal
[client,X11] Fix RAILS modal dialog handling
2024-09-20 13:38:46 +02:00
akallabeth
516cf54c75
[compiler,warnings] disable -Wlanguage-extension-token
Expression Statements are not supported by ISO C but we require it for
certain macros. Disable this warning as it just yields false positives.
2024-09-20 13:34:24 +02:00
David Fort
6660119422
Merge pull request #10650 from akallabeth/winpr-errno
[winpr,utils] fix winpr_strerror argument types
2024-09-20 12:57:56 +02:00
akallabeth
69527e117a
[client,X11] update _NET_WM_STATE for WS_EX_TOPMOST
* Set _NET_WM_STATE_ABOVE if WS_EX_TOPMOST is set and WS_EX_TOOLWINDOW
  clear for a window style
* Clear _NET_WM_STATE_ABOVE in all other cases
2024-09-20 11:33:29 +02:00
akallabeth
d0c1e6055f
[client,X11] add missing _NET_WM_STATE* atoms 2024-09-20 11:33:26 +02:00
akallabeth
0a24f12281
[client,X11] update window style
* if WINDOW_ORDER_STATE_NEW is not set also update
2024-09-20 11:31:34 +02:00
akallabeth
fd3c7633d6
[client,X11] fix rails modal windows
xf_XSetTransientForHint of windows of type
(WS_EX_CONTROLPARENT | WS_EX_TOOLWINDOW | WS_EX_DLGMODALFRAME)
and parent window set
2024-09-20 11:31:32 +02:00
akallabeth
c8e6b1b71f
[client,x11] log rail WINDOW_STATE_ORDER 2024-09-20 11:31:30 +02:00
akallabeth
2b1abcd550
[client,x11] add helper util x11_error_to_string
The helper function x11_error_to_string stringifies a X11 error return
code.
2024-09-20 11:31:27 +02:00
akallabeth
f67e641cce
[client,X11] add helper functions for rail window style
* window_styles_to_string
* window_styles_ex_to_string
2024-09-20 11:31:24 +02:00
akallabeth
e79aaf4d82
[ci,abi-checker] suppress winpr_strerror parameter change
The change is not 100% clean but does not break ABI (but might create
some unnecessary warnings in 3rd party code)
2024-09-20 11:11:08 +02:00
akallabeth
42e3c6fff8
[winpr,utils] fix winpr_strerror argument types
errno is of type int, so use a signed INT32 as argument type to avoid
warings with sign conversions
2024-09-20 10:57:21 +02:00
akallabeth
f86f70a022
Merge pull request #10637 from akallabeth/dealloc-fix
[warnings] fix mismatched-dealloc
2024-09-20 10:50:20 +02:00
akallabeth
7a607dbc53
Merge pull request #10630 from akallabeth/disable-ctad-maybe-unuspported
[build,c++] add CXXCompilerFlags to (un)set warnings
2024-09-20 10:48:56 +02:00
akallabeth
9e416ed002
Merge pull request #10648 from akallabeth/sdl3-api-update
[client,sdl] update to current sdl3-api
2024-09-20 10:45:27 +02:00
akallabeth
699fc70941
[client,sdl] update to current sdl3-api 2024-09-20 10:19:29 +02:00
David Fort
80623095a0
Merge pull request #10647 from akallabeth/kbd-range-checks
[locale,keyboard] fix index range checks
2024-09-20 10:15:05 +02:00
Armin Novak
107a8d9f48
[compiler] disable C++ warnings
Projects are set to require C++ 17, so disable all warnings complaining
about compatibility with previous versions of the standard.
2024-09-20 09:17:22 +02:00
Armin Novak
02b98e9287
[client,sdl] use constexpr instead of defines 2024-09-20 09:17:03 +02:00
Armin Novak
c509aabc08
[cmake] disable -Wdisabled-macro-expansion
this warning does not yield useful results for FreeRDP, disable by
default.
2024-09-20 09:16:33 +02:00
Armin Novak
96052ca2fb
[build,c++] add CXXCompilerFlags to set warnings
Just like with the C components and CompilerFlags.cmake add a
configuration for C++ that disables specific warnings only found in C++
code.
2024-09-20 09:16:30 +02:00
akallabeth
ffd40983ac
[locale,keyboard] fix index range checks 2024-09-20 08:28:56 +02:00
Martin Fleisz
e2d1938886
Merge pull request #10644 from FreeRDP/revert-10643-rdg
Revert "[core,gateway] read leftover http body in the rdg IN channel."
2024-09-19 13:56:35 +02:00
Vic Lee
35ad7e7d0d
Revert "[core,gateway] read leftover http body in the rdg IN channel." 2024-09-19 19:38:29 +08:00
akallabeth
33fcc04263
Merge pull request #10643 from llyzs/rdg
[core,gateway] read leftover http body in the rdg IN channel.
2024-09-19 13:21:26 +02:00
Vic Lee
56535c9663 [core,gateway] read leftover http body in the rdg IN channel. 2024-09-19 18:29:54 +08:00
Martin Fleisz
8cd12a87fd
Merge pull request #10639 from akallabeth/kbd-layout-fix
Kbd layout fix
2024-09-19 11:34:48 +02:00
Martin Fleisz
183be60bac
Merge pull request #10623 from akallabeth/warn-fixes-stream
Warn fixes stream
2024-09-19 09:49:19 +02:00
akallabeth
632e2180f7
[winpr,stream] rewrite stream read functions
Use a loop to shift in bytes to avoid casts.
2024-09-19 09:06:20 +02:00
Armin Novak
46457a5033
[winpr,stream] Add Stream_BufferAs macro
* Add Stream_BufferAs, Stream_ConstBufferAs, Stream_GetBufferAs and
  Stream_GetPointerAs to get a pointer to the stream pointer or buffer
  casted to a specific type.
* Use WINPR_STREAM_CAST in these new macros for proper cast according to
  C or C++
2024-09-19 09:06:13 +02:00
akallabeth
c5e8326d07
Merge pull request #10640 from akallabeth/sdl-hicpp
[client,sdl] fix class constructors and operators
2024-09-19 08:26:52 +02:00
akallabeth
84719a4d83
[client,sdl] fix class constructors and operators
delete unused move/copy constructors and operators
2024-09-18 23:33:50 +02:00
akallabeth
564656166e
[locale,keyboard] add unit tests for functions 2024-09-18 21:31:16 +02:00
akallabeth
8d46de743e
Merge pull request #10638 from akallabeth/tidy-branch-clone
[clang-tidy] deactivate bugprone-branch-clone check
2024-09-18 21:22:13 +02:00
akallabeth
7ae1f07aa8
[locale,keyboard] fix missing input validation 2024-09-18 21:17:28 +02:00
akallabeth
afde8e779b
[locale,keyboard] fix loading of keyboard locales
if keyboard locales should be loaded from a file also load the layouts
2024-09-18 21:17:21 +02:00
David Fort
37271d01fa
Merge pull request #10634 from akallabeth/warn-fixes-cov
[utils,smartcard] return after free
2024-09-18 21:13:58 +02:00
Armin Novak
98f2f69f60
[clang-tidy] deactivate bugprone-branch-clone check
The check triggers on switch cases running the same function and, more
importantly, on our macro CommandLineSwitchStart. Not usable for this
project, deactivating the check.
2024-09-18 16:14:55 +02:00
Martin Fleisz
33a7bee4f9
Merge pull request #10617 from akallabeth/sdl-scope-guard
Sdl scope guard
2024-09-18 15:41:22 +02:00
Armin Novak
c7c84682e1
[warnings] fix mismatched-dealloc
Some allocator functions have an error path where the corresponding free
function is called. Since the memory in the allocator function was
allocated using malloc/calloc the free function does not match. Silence
warnings with pragma macros
2024-09-18 15:35:28 +02:00
Armin Novak
b4755a58dc
[utils,smartcard] return after free
In smartcard_ListReadersA_Call first free up memory and then return in
case of an error
2024-09-18 14:32:45 +02:00
Martin Fleisz
c16e5ffcc2
Merge pull request #10631 from akallabeth/warn-fixes-cov
Warn fixes cov
2024-09-18 14:16:10 +02:00
Armin Novak
fbbda2259d
[clang-tidy] deactivate cppcoreguidelines-pro-type-reinterpret-cast
we do noeed these casts for compatibility with C void* usage. Deactivate
this check to reduce noise.
2024-09-18 13:14:19 +02:00
Armin Novak
fdd8a5cedd
[codec,progressive] fix result cast in progressive_rfx_srl_read 2024-09-18 13:14:19 +02:00
Armin Novak
3905ef0b01
[client,sdl] split sdl_client_thread_run
the function can easily be split into three funcions covering a specific
part of the thread loop. Makes the whole thing less complex and easier
to read.
2024-09-18 13:01:46 +02:00
akallabeth
8ef4b2aefa
[client,SDL] move thread cleanup to own function
The cleanup code for the RDP thread of the SDL clients grew quite
complex. Move to a function to reduce complexity and make the main
thread more readable again.
2024-09-18 11:48:35 +02:00
akallabeth
b7601ec755
[client,SDL] remove goto usage, replace with RAII
* use std::uniqe_ptr to clean up malloced strings
* use ScopeGuard to run cleanup code whenever the function is exited
2024-09-18 11:48:35 +02:00
akallabeth
ed2c5e9a5b
[client,sdl] add scope guard
add a class wrapping a cleanup function called when the class instance
is out of scope. useful to clean up C resources in a lambda function
2024-09-18 11:48:34 +02:00
Armin Novak
769b225278
[utils,smartcard] fix size checks 2024-09-18 11:47:02 +02:00
Armin Novak
bed6e7968e
[winpr,utils] fix plausibility checks in IniFile_Load_File 2024-09-18 11:47:01 +02:00
Armin Novak
65f6541f67
[server,proxy] fix plausibility checks in pf_config_get_uint32 2024-09-18 11:47:01 +02:00
Armin Novak
7b8ddb89c7
[codec,planar] fix parameter type of functions 2024-09-18 11:47:01 +02:00
Armin Novak
d55dfa316f
[server,proxy] fix unchecked return 2024-09-18 11:47:01 +02:00
Armin Novak
58ea63fd84
[winpr,path] fix comparison of unsigned < 0 2024-09-18 11:47:01 +02:00
Armin Novak
deec4df8c0
[proxy,module] move list in dyn-channel-dump instead of copy 2024-09-18 11:46:56 +02:00
Martin Fleisz
e6b4bb0e76
Merge pull request #10627 from llyzs/rpc
[core,gateway] migrate rpc gateway to use new transport layer.
2024-09-18 09:58:07 +02:00
akallabeth
e2fbab750b
Merge pull request #10625 from akallabeth/bsd-fix
[winpr,library] implement GetModuleFileNameA
2024-09-18 09:45:23 +02:00
Vic Lee
5f37b54847 [core,gateway] migrate rpc gateway to use new transport layer. 2024-09-18 15:39:34 +08:00
akallabeth
b738cf01b9
Merge pull request #10626 from akallabeth/mac-bundle-fix
[build,mac] require cJSON
2024-09-17 21:13:49 +02:00
akallabeth
b62249402a [build,mac] require cJSON
we build with cJSON, so enforce it during build. Prevents other
installed libraries to be considered.
2024-09-17 20:23:11 +02:00
akallabeth
347ac5a941
[winpr,library] implement GetModuleFileNameA 2024-09-17 18:01:10 +02:00
akallabeth
4d8a3a22e2
Merge pull request #10622 from akallabeth/warn-fx
[warnings] fix shorten-64-to-32
2024-09-17 17:13:33 +02:00
akallabeth
586f40631f
[warnings] fix shorten-64-to-32 2024-09-17 16:13:48 +02:00
akallabeth
6fb3120c0b
[clang-tidy] disable modernize-avoid-c-arrays
same as with similar hicpp and cppcoreguidelines check disable for our
project
2024-09-17 16:13:33 +02:00
akallabeth
accb4eae75
Merge pull request #10621 from akallabeth/warn-fx
Warn fixes
2024-09-17 13:24:00 +02:00
akallabeth
9278a0adb8
[clang-tidy] fix typo in deactivated check 2024-09-17 12:58:13 +02:00
akallabeth
0e97a51181
[build,mac] disable CHANNEL_RDPEAR
we don't have a MIT-KRB5 library ready on mac os, disable for the time
being.
2024-09-17 12:57:45 +02:00
akallabeth
618e02a65e
[cmake] fix SWScale library variable name 2024-09-17 12:57:43 +02:00
akallabeth
7f52be7d75
[codec,dsp] fix build WITH_FAAC 2024-09-17 12:57:40 +02:00
akallabeth
b388739a0c
[build,mac] fix ignore paths
Use CMAKE_IGNORE_PREFIX_PATH to ignore macports/homebrew/... libraries
when building a mac os bundle
2024-09-17 12:57:37 +02:00
akallabeth
328b7433a4
[server,proxy] fix unchecked return values 2024-09-17 12:57:34 +02:00
akallabeth
84c7fbe922
Merge pull request #10620 from akallabeth/clang-tidy-refine
[clang-tidy] disable cppcoreguidelines-pro-bounds-pointer-arithmetic
2024-09-17 12:24:58 +02:00
akallabeth
b66bc796f4
Merge pull request #10612 from hardening/sdl3_fix
SDL3 client: improve the treatment of clipboard data requests
2024-09-17 12:09:25 +02:00
Martin Fleisz
d3f284505d
Merge pull request #10618 from akallabeth/proxy-nonblock-fix
[core,proxy] fix nonblocking BIO reads
2024-09-17 11:57:21 +02:00
akallabeth
5281b7a320
[clang-tidy] disable cppcoreguidelines-pro-bounds-pointer-arithmetic
the check is not really helpful as all it points out is use of argc/argv
or some handling of C API stuff
2024-09-17 11:47:29 +02:00
David Fort
688f450fc2 SDL3 client: improve the treatment of clipboard data requests
This patch adds a success flag on clipboard data requests, so that we can react
correctly in the SDL handler. I've also made some errors non fatal like if you requests
a kind of data that doesn't exist the client should not terminateit's for that.
2024-09-17 11:37:48 +02:00
David Fort
6c05b54e4f
Merge pull request #10619 from akallabeth/clang-tidy-refine
[clang-tidy] deactivate some C++ checks not fitting
2024-09-17 11:12:24 +02:00
Martin Fleisz
cd70c73e39
Merge pull request #10615 from akallabeth/asn1-int
[winpr,asn1] fix sign extraction for ASN1 integer
2024-09-17 11:08:53 +02:00
akallabeth
a3b658f677
[clang-tidy] deactivate some C++ checks not fitting
* cppcoreguidelines-avoid-c-arrays: most of our code is in C, so the C++
  components must use these to call the library functions
* modernize-pass-by-value: not compatible with the lowest supported C++
  standard of the project
2024-09-17 10:46:21 +02:00
akallabeth
c7efbf5b8e
[core,proxy] fix nonblocking BIO reads
* In case of non-blocking BIO layers the proxy read functions bailed
  out with an error. Retry reading in that case unless the
  TcpConnectTimeout is exceeded
* Terminate proxy read operations if rdpContext::abortEvent is set
2024-09-17 10:37:19 +02:00
akallabeth
ca260e13bb
[winpr,asn1] fix sign extraction for ASN1 integer
ASN1 integer might not be full 32bit integers, so extract the sign from
the first byte and append 0x80000000 after the rest of the integer was
successfully read.
2024-09-17 10:03:50 +02:00
akallabeth
6c88d89566
Merge pull request #10616 from hardening/rail_text_scale
rails: add missing functions client implementation
2024-09-16 19:56:30 +02:00
David Fort
8cc9e5f4e9 rails: add missing functions client implementation
The client side callbacks for textScale and CaretBlinkRate were not implemented.
2024-09-16 18:55:25 +02:00
akallabeth
8e1a2e3645
Merge pull request #10610 from akallabeth/vcapitype
[windows,32bit] fix VCAPITYPE consistency
2024-09-16 15:35:17 +02:00
akallabeth
f2e90eca34
[windows,32bit] fix VCAPITYPE consistency
Fixes #10581
2024-09-16 14:15:59 +02:00
akallabeth
073f1ee642
Merge pull request #10609 from akallabeth/warn
Fix unused return values
2024-09-16 12:03:31 +02:00
akallabeth
befa4233ad
[warnings] fixed bugprone-not-null-terminated-result 2024-09-16 08:22:42 +02:00
akallabeth
a19305569d
[assert] fix ULONG_MAX use
most of the time this was used to check ULONG limits. Replace with
correct UINT32_MAX
2024-09-16 08:22:40 +02:00
akallabeth
bb242b9a89
[return checks] fix use of WaitForSingleObject 2024-09-16 08:22:37 +02:00
akallabeth
965d231e49
[return checks] fix use of CloseHandle 2024-09-16 08:22:31 +02:00
akallabeth
cd18dea174
[return checks] fix use of unicode functions 2024-09-16 06:48:26 +02:00
akallabeth
f655843260
[return checks] fix use of rdpSettings getter/setter 2024-09-16 06:48:23 +02:00
akallabeth
c0d06c782b
[return checks] fix missing checks
* Stream_EnsureRemainingCapacity
* rdp_client_transition_to_state
2024-09-16 06:48:19 +02:00
akallabeth
07ea37d1d7
[return checks] fix use of CommandLineParseArgumentsA 2024-09-16 06:48:16 +02:00
akallabeth
4c8f6383ae
[return checks] fix use of freerdp_interruptible_getc 2024-09-16 06:48:13 +02:00
akallabeth
4d2197eab0
[return checks] fix use of TerminateThread 2024-09-16 06:48:11 +02:00
akallabeth
94020c183c
[return checks] fix use of ResetEvent 2024-09-16 06:48:09 +02:00
akallabeth
7c8c14294f
[return checks] fix use of ReleaseMutex 2024-09-16 06:48:06 +02:00
akallabeth
7d67b8e204
[return checks] fix use of SetEvent 2024-09-16 06:47:58 +02:00
akallabeth
80e0c68dca
Merge pull request #10608 from akallabeth/warn
Warnings fix apple related stuff
2024-09-15 20:39:38 +02:00
akallabeth
0d5bc92a2b
[warnings] fix apple iOS/macos 2024-09-15 19:47:13 +02:00
akallabeth
869bfd5e86
[client,android] mark includes SYSTEM 2024-09-15 19:47:03 +02:00
akallabeth
039e24bf48
Merge pull request #10607 from akallabeth/warn
Warnings fixed
2024-09-15 10:43:54 +02:00
akallabeth
0de75b305c
[warnings] fix unchecked return 2024-09-15 10:19:56 +02:00
akallabeth
1bd6d70057
[warnings] fix some warnings on mac os 2024-09-15 10:06:22 +02:00
akallabeth
a4a7019f97
[channels,rdpdr] fix uninitialized warnings 2024-09-15 09:58:41 +02:00
akallabeth
f7726ed7b6
[server,shadow] improve command line error logging
print an error message indicating where the parsing failed.
2024-09-15 09:21:38 +02:00
akallabeth
ba41d5e532
[warnings] fix unchecked return 2024-09-15 09:08:02 +02:00
akallabeth
687f946999
[channels,rdpear] fix length checks for 32bit size_t 2024-09-15 09:07:53 +02:00
akallabeth
f1be630637
[server,proxy] fix unchecked return 2024-09-15 09:07:49 +02:00
akallabeth
8a3f2be769
[rdtk] improve rdtk_font_load_descriptor_file
do simpler and better error handling
2024-09-15 09:07:38 +02:00
akallabeth
ca1791cfe8
Merge pull request #10606 from akallabeth/warn-fix
Warn fix
2024-09-14 21:44:34 +02:00
akallabeth
8b6091a007
[winpr,wtsapi] improve API usage
* Mark WTSVirtualChannelOpen and WTSVirtualChannelOpenEx with
  WINPR_ATTR_MALLOC to enforce compiler checks for resource cleanup
* Fix unused result warnings, use the result or cast to (void) where not
  requierd
2024-09-14 21:29:31 +02:00
akallabeth
a1cef8dd85
[warnings] silence and fix unused results 2024-09-14 21:29:28 +02:00
akallabeth
65de25205b
[winpr,env] add missing WINPR_ATTR_MALLOC 2024-09-14 21:29:26 +02:00
akallabeth
9cfd748b63
[core,nla] nla_read_TSRemoteGuardPackageCred
* fix maybe uninitialized arguments
* fix return in case of invalid packet
2024-09-14 21:29:24 +02:00
akallabeth
3460f64f57
[client,common] fix possible NULL dereference 2024-09-14 21:29:21 +02:00
akallabeth
2bcf2c50eb
[channels,rdpear] fix krb5 inclusion
* do not expose the krb5 include path in interface library, it is
  private to the object library
* fix include krb5.h instead of krb5/krb5.h
2024-09-14 21:29:18 +02:00
akallabeth
6327b77461
[winpr,crypto] fix type warnings in test case 2024-09-14 17:39:38 +02:00
akallabeth
7295f8a3b8
Merge pull request #10601 from akallabeth/warn-fix
[warnings] fix a bunch of them
2024-09-14 12:21:36 +02:00
akallabeth
0b9d35235b
[channels,rdpear] fix leak in rdpear_prepare_response 2024-09-14 08:31:29 +02:00
akallabeth
dbe92795e3
[winpr,kerberos] fix possible NULL argument to strdup 2024-09-14 08:31:01 +02:00
akallabeth
d5b41bb8a0
[warnings] fix casts
* Add macro WINPR_REINTERPRET_CAST to cast (checked) from type A to B
* Fix cast warnings
2024-09-14 08:24:51 +02:00
akallabeth
01c6447963
[clang-tidy] disable clang-analyzer-optin.performance.Padding
this is not a bug but a performance suggestion test. We don´t want these
mixed in with actual issues
2024-09-14 08:24:48 +02:00
akallabeth
5a711f5ae4
[winpr,collections] fix cast to float 2024-09-14 08:24:45 +02:00
akallabeth
d7f6cf90b4
[core,nla] add missing static for function 2024-09-14 08:24:43 +02:00
akallabeth
5f2ed9b8ce
[crypto,tls] explicitly cast function pointer 2024-09-14 08:24:40 +02:00
akallabeth
f0a73e3e9c
[channels,rdpear] fix inconsistencies in ndr.c/h 2024-09-14 08:24:38 +02:00
akallabeth
1c161b0270
[channels,rdpear] elimiate warnings 2024-09-14 08:24:35 +02:00
akallabeth
70b597ce1e
[utils,passphrase] fix unused result warning 2024-09-14 08:24:32 +02:00
akallabeth
71080e61b0
[warnings] fix a bunch of them
* fix uninitialized variable warnings
 * modivy ndr_context_* functions to utilize WINPR_ATTR_MALLOC
 * build_krbtgt use winpr_asprintf
 * add proper Stream_Write_UINT64_BE
2024-09-14 08:24:28 +02:00
akallabeth
3895cf9fd3
Merge pull request #10603 from akallabeth/strtok-replace
[strtok] replace function with strtok_s
2024-09-13 21:31:54 +02:00
akallabeth
16cec716e0
[strtok] replace function with strtok_s
Since strtok is not thread safe replace it with strtok_s (WinPR wrapper
around strtok_r for systems not supporting the ISO function names)
2024-09-13 21:19:17 +02:00
akallabeth
f1cddd78f9
Merge pull request #10602 from akallabeth/reserved-fix
[winpr,include] fix reserved-identifier warnings
2024-09-13 16:42:30 +02:00
akallabeth
d2641ea55f
[winpr,include] fix reserved-identifier warnings
* Remove symbols where possible
* Use #pragma where the symbols are implementing ISO or windows
  functions
2024-09-13 14:30:33 +02:00
akallabeth
7ef9345743
Merge pull request #10549 from hardening/rcg2
core, channels: client-side remote credential guard
2024-09-13 08:24:14 +02:00
akallabeth
166441c4ee
Merge pull request #10599 from akallabeth/more-docs
More docs
2024-09-12 22:15:26 +02:00
akallabeth
163aec7e2b
[warnings] fix documentation command unknown 2024-09-12 21:21:41 +02:00
akallabeth
afff514ca7
[compiler] add WINPR_ATTR_MALLOC
Add WINPR_ATTR_MALLOC checks to allocating functions to help compilers
find memory leaks or allocation mismatches
2024-09-12 20:09:22 +02:00
akallabeth
fb5934007a
[doxygen] add basic documentation for new API
* Add basic documentation for new functions/structs/data types since
  3.0.0
2024-09-12 20:09:19 +02:00
akallabeth
98f22d49b9 [CMake] add public headers as INTERFACE target 2024-09-12 18:54:40 +02:00
akallabeth
aa72746cda
Merge pull request #10597 from akallabeth/some-more-warnings
Some more warnings
2024-09-12 17:11:41 +02:00
akallabeth
c84655cd62
[warnings] remove const params
Avoid const TYPE* const type declarations
2024-09-12 14:29:25 +02:00
akallabeth
a1a1fc8658
[warnings] fix mismatches between declaration and implementation 2024-09-12 13:32:44 +02:00
akallabeth
7ebefc505f
[warnings] fix some msbuild warnings 2024-09-12 13:32:41 +02:00
akallabeth
b29c141c39
[client,cmdline] fix COMMAND_LINE_ARGUMENT_A arguments
* The project expects COMMAND_LINE_ARGUMENT_A arguments, so fix
  COMMAND_LINE_ARGUMENT macro usage. (affects windows API)
2024-09-12 13:30:10 +02:00
akallabeth
f74fd1ab0f
[warnings] silence unused macro warnings
* Add WINPR_PRAGMA_DIAG_IGNORED_UNUSED_MACRO
* Silence usages that
2024-09-12 13:30:08 +02:00
akallabeth
f62325d443
[winpr] silence -Wreserved-identifier
* Add macro WINPR_PRAGMA_DIAG_IGNORED_RESERVED_IDENTIFIER
* Silence use in wtypes.h.in to avoid false positives
2024-09-12 13:30:05 +02:00
akallabeth
7aa80cb751
[documentation] update
* Fix wrong tag @version, replace with @since
* Document some functions
2024-09-12 13:30:03 +02:00
akallabeth
2638d9d894
[warnings] fix casts 2024-09-12 13:30:00 +02:00
akallabeth
adc4f2abf8
[warnings] fix unused variables 2024-09-12 13:29:58 +02:00
akallabeth
29697ca68d
[winpr,ncryt] fix a memory leak
NCryptP11EnumKeys did leak memory under certain conditions
2024-09-12 13:29:55 +02:00
akallabeth
773eed8878
[client,sdl] use auto for variable declaration 2024-09-12 13:29:53 +02:00
akallabeth
6481993305
[winpr,ncrypt] do not abort test if NCryptEnumKeys fails 2024-09-12 13:29:50 +02:00
akallabeth
f9141fb94b
[winpr,ncrypt] improve logging 2024-09-12 13:29:48 +02:00
akallabeth
e00661d338
[warnings] fix dead store warnings 2024-09-12 13:29:46 +02:00
akallabeth
c9b0c9ecd5
[warnings] remove unused variables 2024-09-12 10:08:10 +02:00
akallabeth
898cb5782c
Merge pull request #10595 from akallabeth/some-more-warnings
Some more warnings
2024-09-12 10:05:16 +02:00
akallabeth
fa9fff6ed0
[winpr,clipboard] properly define guard function 2024-09-12 09:09:00 +02:00
akallabeth
b2d58de1da
[client,X11] fix Wtautological-constant-out-of-range-compare 2024-09-12 09:08:58 +02:00
akallabeth
6f756fd1be
[clang-tidy] disable readability-suspicious-call-argument
we only get false positives from this check, so deemed useless for our
use case
2024-09-12 09:08:56 +02:00
akallabeth
cc6850bf21
[warnings] fix format nonliteral
add pragma to suppress format nonliteral warnings where appropriate
2024-09-12 09:08:53 +02:00
akallabeth
8a990644c0
[warnings] fix missing NULL assert/check 2024-09-12 09:08:51 +02:00
akallabeth
2ae0c456b4
[client,sdl] fix float casts 2024-09-12 09:08:49 +02:00
akallabeth
0f00e37884
[clang-tidy] disable hicpp-no-assembler
we need assembler code for some critical spots, so this check is useless
for our use case.
2024-09-11 23:42:01 +02:00
akallabeth
66153045be
[winpr,timezone] Include TimeZoneNameMap as header
* Update tzextract to generate header
* Update TimeZoneNameMapUtils to include header
2024-09-11 23:41:58 +02:00
akallabeth
384cd284d8
[warnings] use WINPR_CAST_CONST_AWAY
on locations that require (ugly) const to non const casts usw
WINPR_CAST_CONST_AWAY to do proper compiler specific casts to avoid
warnings
2024-09-11 23:41:50 +02:00
akallabeth
0de5430578
Merge pull request #10594 from akallabeth/sdl3-fix
Sdl3 fix
2024-09-11 22:39:08 +02:00
akallabeth
2175428df5
[client,SDL] default webview to off
The AAD webview is currently not working as expected, disable until
resolved.
2024-09-11 22:23:33 +02:00
akallabeth
3682e11e55
[primitives,test] use same parameter names
use the same parameter names for declaration and implementation
2024-09-11 22:20:35 +02:00
akallabeth
993756e575
[client,sdl] fix SDL3 compilation error 2024-09-11 21:50:30 +02:00
akallabeth
1f917ca46f
Merge pull request #10593 from akallabeth/warnings-more-more-more
Warnings more more more
2024-09-11 21:49:16 +02:00
akallabeth
265246cdfc
[core,activation] allocate buffer with calloc 2024-09-11 21:03:20 +02:00
akallabeth
06097575a4
[client,sdl] fix redundant initializer 2024-09-11 20:50:36 +02:00
akallabeth
ae95b66922
[warnings] fix portability [cm]alloc size 0 2024-09-11 20:50:33 +02:00
akallabeth
31ef07ead7
[warnings] fix tautological unsigned zero compare 2024-09-11 20:50:30 +02:00
akallabeth
8ba7b65725
[winpr,secapi] add invalid value to KERB_LOGON_SUBMIT_TYPE 2024-09-11 20:50:27 +02:00
akallabeth
11671bcd5b
[warnings] fix unreachable code return 2024-09-11 20:50:24 +02:00
akallabeth
a1be46e5dd
[warning] fix function declarations
use same names in declaration and implementation
2024-09-11 20:50:21 +02:00
akallabeth
eb70b1756b
[winpr,wlog] fix GNU variadic macro 2024-09-11 20:50:17 +02:00
akallabeth
eec69bde0f
[client,sdl] fix c++ string find, use char overload 2024-09-11 20:50:14 +02:00
akallabeth
62e52b30c8
[utils,passphrase] fix missing char to int cast 2024-09-11 20:49:44 +02:00
akallabeth
861f699d92
[uwac] fix uwac seat functions
change arguments to match prototypes
2024-09-11 20:49:03 +02:00
akallabeth
953b2664c0
[opencl,primitives] fix const warning 2024-09-11 20:48:52 +02:00
akallabeth
bf4953d288
[codec,h264] fix documentation unknown 2024-09-11 20:48:49 +02:00
akallabeth
403ee7ad4c
[core,activation] simplify rdp_write_client_persistent_key_list_pdu 2024-09-11 20:48:46 +02:00
akallabeth
e864fed61f
[uwac] disable clang-tidy for generated files 2024-09-11 20:48:43 +02:00
akallabeth
9fed64eb0d
[client,SDL] SdlEventUpdateTriggerGuard
Delete copy & move assingment operators
2024-09-11 20:48:39 +02:00
akallabeth
c427d0cfb2
[cmake] add helper to dump target properties 2024-09-11 20:48:32 +02:00
David Fort
a4bd5ba886 core, channels: client-side remote credential guard
This patch implements the client-side part of the remote credential guard feature
as described in MS-RDPEAR. The 2 main changes are: shipping the TSRemoteGuardaCreds in
NLA, and implement the rdpear channel that allows LSASS to remote all the calls to
our client. For now it's UNIX only as the windows implementation would be implemented
in a completely different way.
To test, you may establish you ccache and then connect with (RCG enabled on the server):
	xfreerdp /remoteGuard /u:<user> /d:<domain> /v<server>

That should log you in, and in the session you should not be asked for credentials when
doing mstsc /remoteGuard /v:<other server>.
2024-09-11 17:15:11 +02:00
akallabeth
9c52238d24
Merge pull request #10590 from akallabeth/dynamic-resizing-to-bool
[client,common] change /dynamic-resizing to BOOL option
2024-09-11 11:27:51 +02:00
Armin Novak
17c209c0f9
[client,common] change /dynamic-resizing to BOOL option
Allows to use +-/ prefixes to enable/disable the option. Brought up on
matrix channel for uses with RDP files that enable the option. Now it
can be disabled by adding -dynamic-resolution on command line.
2024-09-11 11:06:21 +02:00
akallabeth
b66486ed23
Merge pull request #10587 from FreeRDP/timezone-patches-1726031205
[timezones] Update definitions
2024-09-11 09:51:38 +02:00
akallabeth
398efacb10 Update timezone definitions 2024-09-11 05:06:45 +00:00
akallabeth
9d10923524
Merge pull request #10580 from akallabeth/more-warn-fixes
More warn fixes
2024-09-10 17:07:12 +02:00
akallabeth
8793d5a843
Merge pull request #10582 from akallabeth/doxygen
Doxygen
2024-09-10 15:26:09 +02:00
akallabeth
21d0088b95
[clang-tidy] disable performance-avoid-endl
this warning is not required in our case as we do not have code that
requires high performance utilizing std::endl (output to std::cout or
std::cerr)
2024-09-10 14:43:17 +02:00
akallabeth
b7553d5f41
[clang-tidy] disable cppcoreguidelines-no-malloc,hicpp-no-malloc
The project is mostly C so the C++ components are expected to wrap the C
allocation. This check does only produce false positives in our use
case.
2024-09-10 14:43:14 +02:00
akallabeth
edf6ab89f7
[warnings] fix dead store 2024-09-10 14:43:11 +02:00
akallabeth
674e84cbf3
[channels,location] fix cast warning 2024-09-10 14:43:08 +02:00
akallabeth
c1918ac189
[winpr,wlog] fix cast warning 2024-09-10 14:42:52 +02:00
akallabeth
529ce7534b
[cmake,compiler] disable -Wswitch-enum warning
the warning is quite useless as we do not always list all enumerations
in a switch.
2024-09-10 14:42:44 +02:00
akallabeth
189abc73f3
[client,sdl] fix missing field initializer warnings 2024-09-10 14:42:42 +02:00
akallabeth
3ab6d2f918
[proxy,modules] fix unchecked return 2024-09-10 14:42:39 +02:00
akallabeth
a085b0d228
[winpr,comm] fix compiler warnings 2024-09-10 14:42:28 +02:00
akallabeth
ba7465abf5
Merge pull request #10585 from akallabeth/x11-clip-cache-fix
[client,x11] fix clipboard cache
2024-09-10 14:31:25 +02:00
akallabeth
64438a4028
Merge pull request #10584 from akallabeth/client-minimize-shortcut
Client minimize shortcut
2024-09-10 14:26:36 +02:00
akallabeth
fcdd03a020
[client,x11] fix clipboard cache
Use new function format_to_cache_slot to convert a clipboard format to a
valid key value for wHashTable. This avoids issues with our synthesized
CF_RAW format (value 0) which is an invalid key for wHashTable
2024-09-10 13:35:21 +02:00
akallabeth
2a641aa834
[client,sdl3] update to new API 2024-09-10 12:46:27 +02:00
akallabeth
215f798665
[client,x11] add minimize shortcut 2024-09-10 12:29:12 +02:00
akallabeth
d93d9765b3
[client,sdl] add minimize shortcut 2024-09-10 12:28:36 +02:00
akallabeth
f891bd3646
[docs] add doxygen comments for 3.0 API 2024-09-10 08:31:30 +02:00
akallabeth
801c825e2b
update-doxyfile 2024-09-10 08:31:19 +02:00
Martin Fleisz
86bfade4dc
Merge pull request #10579 from akallabeth/transport_cb_doc
[core,transport] follow up to #10576
2024-09-09 14:15:15 +02:00
akallabeth
4253426e48
[core,transport] follow up to #10576
document the behaviour and reference the place it is used to avoid
confusion on future code review
2024-09-09 13:43:43 +02:00
akallabeth
cec6fef1de
Merge pull request #10575 from akallabeth/ffmpeg-detect-update
Ffmpeg detect update
2024-09-09 12:59:15 +02:00
akallabeth
3fa3772038
Merge pull request #10577 from akallabeth/scale-desktop
[client,common] properly abort on invalid scale-desktop
2024-09-09 12:58:26 +02:00
akallabeth
306af4070c
[client,common] properly abort on invalid scale-desktop 2024-09-09 12:37:22 +02:00
Martin Fleisz
a92a13d74c
Merge pull request #10576 from llyzs/fix_ssl_cb
[core,transport] fix ssl info callback function signature and some wa…
2024-09-09 12:33:58 +02:00
akallabeth
52ee2e4668
[cmake] unify ffmpeg and swscale detection 2024-09-09 12:20:17 +02:00
akallabeth
0bbf0b6e80
[ci] add avformat to dependencies 2024-09-09 11:59:52 +02:00
Vic Lee
929e4bdf8d [core,transport] fix ssl info callback function signature and some warnings. 2024-09-09 17:42:14 +08:00
akallabeth
e23115c54f
[codec,dsp] fix and simplify avcodec version check 2024-09-09 11:23:19 +02:00
akallabeth
9738fc40f3
Merge pull request #10548 from akallabeth/serial-port
[BSD] build-serial-port
2024-09-09 09:41:12 +02:00
akallabeth
d1490e3c12
[packaging,nightly] add avformat to dependencies 2024-09-09 09:38:07 +02:00
akallabeth
073426d4c1
[cmake,ffmpeg] update CMake detection script 2024-09-09 08:52:11 +02:00
akallabeth
02d9d56536
Merge pull request #10563 from llyzs/transport_io
Add new transport io layer design and support custom socket.
2024-09-06 15:18:20 +02:00
akallabeth
6a64fe121b
Merge pull request #10569 from akallabeth/fprintf-void
Fprintf void
2024-09-06 10:44:32 +02:00
David Fort
b6f094da4e
Merge pull request #10570 from akallabeth/rdpgfx-debug
[rdpgfx,client] debug caps version as string
2024-09-06 10:42:40 +02:00
akallabeth
db8e340604
[rdpgfx,client] debug caps version as string 2024-09-06 09:35:23 +02:00
akallabeth
fbd9aae501
Merge pull request #10567 from akallabeth/client-common-improve
[client,common] extended parser
2024-09-06 09:24:59 +02:00
akallabeth
97a9f3238f
[clang-tidy] disable cppcoreguidelines-interfaces-global-init
this guideline is for C++ code. The same issue does not apply for C code
so these warnings are just noise outside of our C++ subprojects.
2024-09-06 09:22:28 +02:00
akallabeth
082c46ba64
[proxy,modules] require C++ 17
Unify required C++ standard and require C++ 17 for all modules. It does
not make a lot of sense to have different standard requirements in the
same project.
2024-09-06 09:20:28 +02:00
akallabeth
2170cc65e3
[warnings] cast return of fprintf (void)
fprintf returns a value. Not using it is mostly fine, but it generates
noise when compiling with all warnings on, so cast to (void)
2024-09-06 09:16:21 +02:00
akallabeth
1e1e9a445b
[utils,gfx] add rdpgfx_caps_version_str 2024-09-06 08:38:37 +02:00
akallabeth
b26ab2f069
[client,common] extended parser 2024-09-06 08:23:06 +02:00
akallabeth
590fbcf005
Merge pull request #10564 from hardening/sdl3_fix
sdl3: fix build with last version of SDL3
2024-09-05 21:51:44 +02:00
akallabeth
749023bacb
Merge pull request #10555 from akallabeth/cast-fix-tls
[crypto,tls] simplify function pointer cast
2024-09-05 17:18:27 +02:00
Vic Lee
ae05778644 [core,transport] add new transport io layer design and support custom socket. 2024-09-05 20:59:21 +08:00
David Fort
3a9a820092 sdl3: fix build with last version of SDL3 2024-09-05 14:57:11 +02:00
David Fort
d0cfd3b502
Merge pull request #10561 from akallabeth/clang-tidy-macro
[clang-tidy] disable bugprone-macro-parentheses
2024-09-05 09:25:53 +02:00
akallabeth
ec26c8c168
[clang-tidy] disable bugprone-macro-parentheses
this check has too many false positives (when the macro arguments are
types for example) so disable this.
2024-09-05 08:45:02 +02:00
akallabeth
7d48aee829
Merge pull request #10556 from akallabeth/stream-api-improve
[winpr,stream] add returning stream read/peek
2024-09-05 08:40:15 +02:00
akallabeth
8fd724b7b6
Merge pull request #10560 from akallabeth/warn-fix
Warn fix
2024-09-05 08:39:53 +02:00
akallabeth
c670eda6eb
Merge pull request #10559 from akallabeth/clip-endian
[winpr,clipboard] use endian safe bitmap read/write
2024-09-04 22:24:55 +02:00
akallabeth
b9202bd0b1 [clang-tidy] disable cert-dcl50-cpp
we do want to use variadic macros in C++ code as we interface with C
2024-09-04 22:20:59 +02:00
akallabeth
e3f94e6622 nodiscard 2024-09-04 22:17:35 +02:00
akallabeth
64a0d87c98 fix missing prototype 2024-09-04 22:15:38 +02:00
akallabeth
798421e883 fix missing static for functions 2024-09-04 22:12:32 +02:00
akallabeth
9ae37b094f fix implicit widening of multiplication result 2024-09-04 22:01:09 +02:00
akallabeth
8b92e17e60 modernize includes 2024-09-04 22:00:12 +02:00
akallabeth
b980bf2e14
[winpr,clipboard] use endian safe bitmap read/write 2024-09-04 21:56:44 +02:00
akallabeth
6a1c3b4545
[function pointer] use macro for GetProcAddress
Cast all results of GetProcAddress with WINPR_FUNC_PTR_CAST
2024-09-04 21:31:48 +02:00
akallabeth
889ae65a1f
[warnings] add WINPR_CAST_CONST_PTR_AWAY
simple macro casting a const pointer to a non const one.
2024-09-04 20:55:17 +02:00
akallabeth
245afb706c
[function pointers] unify casts with macro 2024-09-04 20:06:45 +02:00
akallabeth
1a9766e190
[warnings] fix function pointer casts 2024-09-04 20:06:43 +02:00
akallabeth
9776cc109e
[crypto,tls] simplify function pointer cast 2024-09-04 20:06:40 +02:00
akallabeth
a82821b756
[winpr,stream] fix return value
signed int functions should not return unsigned values
2024-09-04 13:17:50 +02:00
akallabeth
d959121b2f
[winpr,stream] add returning stream read/peek
To make use easier add Stream functions that return the value read
instead of taking it as argument.
2024-09-04 13:17:43 +02:00
akallabeth
9c6126c470
[winpr,comm] build generic serial-port support
* Disable linux specific code if build on *BSD
* Build stub to just return NULL for unsupported platforms
2024-09-04 12:50:49 +02:00
akallabeth
e37dffaca4
[crypto,tls] disable linter warning
the argument is #ifdefed, so some configurations produce a warning
2024-09-04 12:50:46 +02:00
akallabeth
0eb0cff367
[winpr,utils] fix integer size warnings 2024-09-04 12:50:43 +02:00
akallabeth
5aff241096
Merge pull request #10554 from akallabeth/tidy-silence
Tidy silence
2024-09-04 10:35:22 +02:00
akallabeth
9df86daf28
[winpr,comm] add missing includes 2024-09-04 10:14:07 +02:00
akallabeth
5e123735fa
[warnings] fixed sign-compare 2024-09-04 10:14:05 +02:00
akallabeth
3eb905cfb1
Merge pull request #10553 from akallabeth/tables-fn-fix
[channels] fix function pointer casts
2024-09-04 10:13:02 +02:00
akallabeth
b6e72c7674
Merge pull request #10551 from akallabeth/arch-fixes
Arch fixes
2024-09-04 09:56:35 +02:00
akallabeth
2fc791fe9b [client,X11] fix shadowed variable 2024-09-04 09:45:00 +02:00
akallabeth
3e933203e2 [crypto,tls] fix bad-function-cast
do silence the compiler warning and add a comment why we do that.
2024-09-04 09:41:53 +02:00
akallabeth
ff62730419
[channels] fix function pointer casts
* Cast freerdp_load_channel_addin_entry return with a union (removes the
  incompatible function pointer cast warnings)
* Typedef function pointers in tables.h
2024-09-04 09:12:41 +02:00
akallabeth
c851dfcb7f
Merge pull request #10546 from akallabeth/sign-compare-fix
Sign compare fix
2024-09-04 09:11:50 +02:00
akallabeth
ebbfe598dc
[winpr,utils] unify bitmap reading
* clipboard synthesizer needs to read the bitmap header, use the function
  from utils/image
* check bitmap header in utils/image and abort if wrong
2024-09-04 09:07:18 +02:00
akallabeth
c5f346488f
[crypto,tls] revert const argument
with some build options this needs to be writeable.
2024-09-04 09:03:21 +02:00
akallabeth
16d6c3b795
[clang-tidy] disable modernize-return-braced-init-list
this check does not work well with older C++ standards
2024-09-03 17:41:02 +02:00
akallabeth
9a027833b9
[warnings] fix misplaced widening cast 2024-09-03 17:40:55 +02:00
akallabeth
fe6d861a5c
[channels] fix VCAPITYPE for all channel entry points 2024-09-03 17:26:58 +02:00
akallabeth
491c884c7a
[cmake] remove casts from tables.c 2024-09-03 15:15:08 +02:00
akallabeth
b77d6e8550
[channels] fix function pointer casts
* Cast freerdp_load_channel_addin_entry return with a union (removes the
  incompatible function pointer cast warnings)
* Typedef function pointers in tables.h
2024-09-03 15:13:58 +02:00
akallabeth
f3d84d4557
[warnings] use ARRAYSIZE macro 2024-09-03 15:10:58 +02:00
akallabeth
baa70d1ab6
[warnings] fix compare integers of different signs 2024-09-03 15:10:46 +02:00
akallabeth
cbeded839d
Merge pull request #10545 from akallabeth/warn-cleanups
Warn cleanups
2024-09-03 13:22:40 +02:00
akallabeth
a89aefa8d4
[winpr,smartcard] disable linter warnings
* silenced readability-non-const-parameter warnings that can not be
  changeddue to API requirements
2024-09-03 13:07:16 +02:00
akallabeth
734d4ce43e
[rdtk] fix integer cast warnings 2024-09-03 12:56:21 +02:00
akallabeth
ca5a8e0625
[ci,clang-tidy] disable cppcoreguidelines-macro-to-enum 2024-09-03 12:56:13 +02:00
akallabeth
42b078a59d
[emu,scard] smartcard emulation cleanup
* Fix readability-non-const-parameter (disable lint, API requires these
  to be non const)
* Return an appropriate error for functions returning
  SCARD_E_UNSUPPORTED_FEATURE if there is a parameter wrong
* Remove unused functions
2024-09-03 12:24:55 +02:00
akallabeth
5a4a1a40ad
fix declaration and implementation parameter names 2024-09-03 12:24:53 +02:00
akallabeth
f7fd817d1c
[warnings] fix redundant casting 2024-09-03 12:24:51 +02:00
akallabeth
72ae7fb54f
[nolint] add cert-dcl37-c,cert-dcl51-cpp 2024-09-03 12:24:48 +02:00
akallabeth
852e0c1450
[common,assistance] fix shadowed variable 2024-09-03 12:17:33 +02:00
akallabeth
cbae4155fb
[client,SDL] delete unused copy & move constructors 2024-09-03 12:17:20 +02:00
akallabeth
96bdd58226
Merge pull request #10544 from akallabeth/double-fixes
Double fixes
2024-09-03 08:55:13 +02:00
Armin Novak
fe4cb6de65
[warnings] fix float/double warnings 2024-09-02 16:20:20 +02:00
Armin Novak
7c537d681f [winpr,file] mark winpr_fopen with WINPR_ATTR_MALLOC
enable allocator/deallocator checks for FILE* created by this function
2024-09-02 14:39:53 +02:00
akallabeth
654e107ade
Merge pull request #10543 from akallabeth/wfixes
[codec,dsp] fix ffmpeg warnings
2024-09-02 14:30:22 +02:00
Armin Novak
4b62174c4f
[winpr,platform] fix unknown-warning-option 2024-09-02 14:13:10 +02:00
Armin Novak
11a9c010f9
[winpr] wtypes NOLINT
Silence linter for basic type definitions that use reserved identifiers
2024-09-02 13:56:07 +02:00
Armin Novak
5791b2a5aa
[codec,dsp] fix ffmpeg warnings 2024-09-02 13:39:12 +02:00
akallabeth
6d8d4ddb1a
Merge pull request #10541 from akallabeth/warn-pedantic
Warn pedantic
2024-08-31 11:33:24 +02:00
akallabeth
6fb7bfd043
[winpr,unwind] fix _Unwind_GetLanguageSpecificData
The function has various return value definitions (void* or uintptr_t)
and no proper API versioning. So cast to the expected type regardless of
actual definition and silence linter for this specific line.
2024-08-31 11:17:54 +02:00
akallabeth
e756c90569
[warnings] clang-tidy suppress warnings
* Suppress NOLINT(bugprone-suspicious-include)
* Suppress __STDC_WANT_LIB_EXT1__ 1 // NOLINT(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
2024-08-30 22:03:47 +02:00
akallabeth
1dea19ac5f
[warnings] clang-tidy suppress warnings
* Suppress NOLINT(bugprone-suspicious-include)
* Suppress __STDC_WANT_LIB_EXT1__ 1 // NOLINT(bugprone-reserved-identifier,cert-dcl37-c,cert-dcl51-cpp)
2024-08-30 16:01:11 +02:00
akallabeth
5887f8a558
[warnings] suppress warnings
Some warnings can not be solved as they depend on external libraries or
limitations of the C standard.
Suppress these warnings selectively
2024-08-30 15:40:16 +02:00
akallabeth
36fbed25c9
[winpr,include] define warning ignore macros
Define new macros to ignore specific compiler warnings:
* WINPR_PRAGMA_DIAG_IGNORED_OVERLENGTH_STRINGS
* WINPR_PRAGMA_DIAG_IGNORED_QUALIFIERS
2024-08-30 15:40:13 +02:00
akallabeth
3674c5c2f7
[common,assistance] eliminate pedantic cast warnings 2024-08-30 15:40:10 +02:00
akallabeth
7c1fd71b7b
[uwac] elminate pedantic warnings from defines 2024-08-30 15:40:08 +02:00
akallabeth
48aaa53a84
[codec,dsp] fix restrict warning 2024-08-30 15:40:06 +02:00
akallabeth
7d3b2aebfd
[warnings] silence WINPR_FALLTHROGH 2024-08-30 15:40:03 +02:00
akallabeth
190929c018
[warnings] fix function pointer casts 2024-08-30 15:40:01 +02:00
Martin Fleisz
d02a30e377
Merge pull request #10540 from akallabeth/wasm
[winpr,comm] do not compile with EMSCRIPTEN
2024-08-30 09:33:08 +02:00
akallabeth
f60e386f3e
[winpr,comm] do not compile with EMSCRIPTEN 2024-08-30 09:12:51 +02:00
akallabeth
e1d0efa817
Merge pull request #10532 from akallabeth/release-3.8.0
Release 3.8.0
2024-08-30 08:53:55 +02:00
akallabeth
ab9ae66a8d
Merge pull request #10537 from akallabeth/warnings-for-release
[warnings] revert some mismatching function declarations
2024-08-30 08:53:43 +02:00
akallabeth
f22018302f
[warnings] revert some mismatching function declarations 2024-08-30 08:39:30 +02:00
akallabeth
605d390dba
Merge pull request #10535 from akallabeth/clang-tidy-fixes
Clang tidy fixes
2024-08-29 17:31:50 +02:00
akallabeth
ec73265268
[channels,rail] fix unused variable warnings 2024-08-29 17:13:57 +02:00
akallabeth
b53146150c
Revert "[ci,clang-tidy] use .clang-tidy file"
This reverts commit 113810e45b.
2024-08-29 17:13:55 +02:00
akallabeth
ba9897f8b7
[warnings] replace rand() function use 2024-08-29 17:13:53 +02:00
akallabeth
bd637c6cd1
[warnings] fix various clang-tidy warnings 2024-08-29 17:13:50 +02:00
akallabeth
f3596b950a
3.8.1-dev0 cycle 2024-08-29 16:52:44 +02:00
akallabeth
d277e494c6
release-3.8.0 2024-08-29 16:52:41 +02:00
akallabeth
a18287694e
changelog 3.8.0 2024-08-29 16:52:39 +02:00
akallabeth
500495dc00
[warnings] fix SDL3 related issues 2024-08-29 16:03:51 +02:00
akallabeth
cc626276d0
[warnings] integer cast and checks 2024-08-29 15:49:33 +02:00
akallabeth
ceae258e37
[warnings] fix clang-tidy issues in clients 2024-08-29 15:34:27 +02:00
akallabeth
47e40dd7a5
[warnings] fix clang-tidy issues in channels 2024-08-29 15:34:25 +02:00
akallabeth
36c3184a0f
[warnings] fix clang-tidy issues in libfreerdp 2024-08-29 15:34:22 +02:00
akallabeth
92e416610a
[warnings] fix clang-tidy issues in rdtk 2024-08-29 15:20:47 +02:00
akallabeth
457d6f7578
[warnings] fix clang-tidy issues in uwac 2024-08-29 15:20:45 +02:00
akallabeth
24cd7828c9
[warnings] fix clang-tidy issues in server 2024-08-29 15:20:42 +02:00
akallabeth
6a3564407e
[warnings] fix clang-tidy issues in winpr 2024-08-29 15:20:39 +02:00
akallabeth
c44f89bc68
[clang-tidy] disable google-readability-todo 2024-08-29 15:13:38 +02:00
akallabeth
b91c768867
Merge pull request #10531 from akallabeth/warning-fixes-cast
Warning fixes cast
2024-08-29 12:26:05 +02:00
akallabeth
9c9d74e920
[warnings] fix redundant casts 2024-08-29 12:03:09 +02:00
akallabeth
91cb77a85e
[warnings] fix uninitialized variable warnings 2024-08-29 11:43:26 +02:00
akallabeth
1b352bf09a
Merge pull request #10519 from akallabeth/warning-fixes-implicit-int
[warnings] fix implicit widening conversion
2024-08-29 11:42:14 +02:00
akallabeth
af813a0929
[cmake,clang-tidy] do not use explicit .clang-tidy
if not explicitly added the nearest .clang-tidy file to the compiled
source is used.
2024-08-29 11:18:36 +02:00
akallabeth
6a5d6d0514
[ci,clang-tidy] disable uninitialize va_list warning 2024-08-29 10:47:28 +02:00
akallabeth
15456e1ee1
[warnings] fix implicit widening conversion 2024-08-29 10:47:20 +02:00
akallabeth
4439240fd3
Merge pull request #10525 from akallabeth/warn-fixes-err33-c
[warnings] fix cert-err33-c
2024-08-29 10:35:57 +02:00
akallabeth
5443a934a9
Merge pull request #10529 from akallabeth/android-fix
Android fix
2024-08-29 10:20:12 +02:00
akallabeth
1d33095500
[warnings] fix cert-err33-c
Fix unused return values, cast to void if on purpose
2024-08-29 10:19:27 +02:00
akallabeth
622fcc7025
[warnings] fix types and guards
Fix some broken define guards and a wrong return type
2024-08-29 09:53:48 +02:00
akallabeth
1e24fcd9a4
[cmake,android] check compiler flags
Check -mfloat-abi=softfp supported before use. This workaround is for
older NDK versions that do not properly set this in the toolchain file.
Newer NDK versions changed compiler no longer supporting that flag.
2024-08-29 09:53:39 +02:00
David Fort
7503efed27
Merge pull request #10528 from akallabeth/winpr-perf
Winpr perf
2024-08-29 09:05:16 +02:00
akallabeth
3b8dc5c183
[cmake] move WITH_VERBOSE_WINPR_ASSERT
Since the definition is common to FreeRDP and WinPR move it to
CommonConfigOptions
2024-08-29 08:44:39 +02:00
akallabeth
efde29f362
[winpr,utils] Set Queue_Enqueue only once
In #10527 performance was measured and SetEvent did take a lot of time
in these measurements. The reset is only required once though, so use a
more fine grained trigger condition.
2024-08-29 08:30:32 +02:00
akallabeth
d0addb52bd
[winpr,utils] Reset CountdownEvent_AddCount only once
In #10527 performance was measured and ResetEvent did take a lot of time
in these measurements. The reset is only required once though, so use a
more fine grained trigger condition.
2024-08-29 08:30:21 +02:00
akallabeth
eeba99d73e
Merge pull request #10523 from akallabeth/autoreconnect-fix
[core,client] flush pending channel messages
2024-08-28 16:42:05 +02:00
akallabeth
380c5808a0
Merge pull request #10518 from akallabeth/clang-tidy-cleanup
Clang tidy cleanup
2024-08-28 16:36:16 +02:00
akallabeth
4ccfbc96ac
[core,client] flush pending channel messages
on disconnect flush all pending messages to avoid sending on reconnect.
2024-08-28 14:13:28 +02:00
akallabeth
de5b7c8e42
Merge pull request #10521 from akallabeth/warn-fix-uninit
[warnings] fix uninitialized variables
2024-08-28 11:12:11 +02:00
akallabeth
743c923ca7
Merge pull request #10516 from troyrollo/ssh-askpass-support
Add support for getting passwords from ssh-askpass
2024-08-28 11:11:35 +02:00
akallabeth
113810e45b
[ci,clang-tidy] use .clang-tidy file 2024-08-28 10:51:48 +02:00
Armin Novak
03449da9e9
[warnings] fix uninitialized variables 2024-08-28 10:46:40 +02:00
akallabeth
3c6f0491bf
Merge pull request #10520 from akallabeth/warn-init-variables
[warnings] fix cppcoreguidelines-init-variables
2024-08-28 10:45:14 +02:00
Armin Novak
3b1c1e0af1 [warnings] fix cppcoreguidelines-init-variables 2024-08-28 10:15:36 +02:00
akallabeth
8e4f9ad5ac
[utils,passphrase] do not check for SSH_ASKPASS 2024-08-28 10:14:06 +02:00
akallabeth
396b3b51b4
[utils,passphrase] format & clean code 2024-08-28 10:08:30 +02:00
Armin Novak
4a9018ab14
[clang-tidy] cleanup configuration
* Remove unknown AnalyzeTemporaryDtors
* Deactivate some tests contradicting our coding style
2024-08-28 10:01:22 +02:00
Armin Novak
d71af44bb1
[warnings] disable warnings for generated code
* Disable clang-tidy in test build directories
* Disable compiler warnings for test binary directories.

These contain generated code we can not change, so the warnings are just noise
2024-08-28 09:18:30 +02:00
akallabeth
6d994feef6
Merge pull request #10517 from akallabeth/uwac-fix
[uwac] remove broken function attribute
2024-08-28 09:05:59 +02:00
akallabeth
b0afe43d34
[uwac] remove broken function attribute 2024-08-28 08:50:17 +02:00
Troy Rollo
3f0000df0f Add support for getting passwords from ssh-askpass 2024-08-28 13:44:21 +10:00
akallabeth
d6b7e90d69
Merge pull request #10514 from akallabeth/double-free
[channels,rail] fix use after free
2024-08-27 09:25:04 +02:00
Armin Novak
7aae7896ae
[channels,rail] fix use after free 2024-08-27 09:08:15 +02:00
akallabeth
f928f9465b
Merge pull request #10513 from hardening/freerdp_peer_new_fix
core: relax check in freerdp_peer_new
2024-08-27 08:41:49 +02:00
David Fort
f1b299c3e2 core: relax check in freerdp_peer_new
Not all socket kinds have the TCP_NODELAY option (especially local UNIX sockets),
so don't make the setsockopt fatal.
2024-08-26 19:53:49 +02:00
akallabeth
598746a26b
Merge pull request #10511 from akallabeth/rails-simplify
[channels,rail] simplify sending
2024-08-26 14:31:08 +02:00
akallabeth
7f13d1993d
[channels,rail] simplify sending
* Fix #5347: Do not create useless copy of data to send.
2024-08-26 14:14:47 +02:00
akallabeth
00eb86970d
Merge pull request #10510 from akallabeth/serial-cleanup
Serial cleanup
2024-08-26 13:47:10 +02:00
akallabeth
7054b26916
[channels,parallel] compilation checks
* Only compile channel related command line if enabled
* Warn on unsupported platforms
2024-08-26 13:30:30 +02:00
akallabeth
387dabc4dd
[channels,serial] add CMake messages
Inform user about platforms that do not support serial redirection
2024-08-26 13:26:15 +02:00
akallabeth
1ec18ce827
[channels,serial] default to off on APPLE 2024-08-26 13:23:09 +02:00
akallabeth
050eef537a
[client,common] guard /serial argument
only enable if serial redirection support is compiled in
2024-08-26 13:21:13 +02:00
akallabeth
d08e44d883
[channels,serial] only build on linux
* Guard by CMake
* Remove code #ifdef to ease porting
2024-08-26 13:18:52 +02:00
akallabeth
f855fdc66a
Merge pull request #10509 from akallabeth/cmake-system-inc
[cmake] mark dependency includes SYSTEM
2024-08-26 12:40:10 +02:00
akallabeth
eb7d8fdeb0
[channels,serial] improve command line parsing
* Gracefully exit on invalid serial driver
* Gracefully exit on onvalid serial port flags
2024-08-26 12:37:03 +02:00
akallabeth
0b21fddef6
[channels,serial] improve IRP processing logging 2024-08-26 12:37:01 +02:00
akallabeth
df04e4c888
[channels,parallel] unify IRP processing logging 2024-08-26 12:36:58 +02:00
akallabeth
d81dd9d9ff
[winpr,comm] fix stopping of serial threads
Since most unhandled threads get cancelled do not rely on
SERIAL_EV_WINPR_WAITING flag.
2024-08-26 12:36:56 +02:00
akallabeth
221dd7ce1d
[winpr,comm] improve error handling 2024-08-26 12:36:51 +02:00
akallabeth
1ca069c771
[channels,serial] fix IrpThread handling
* Proper terminated threads cleanup
* Proper remaining threads termination on close
2024-08-26 12:35:54 +02:00
akallabeth
348ddf61c0
[channels,serial] delay IRP thread start
wait until irp_thread_func has completed before starting the thread.
This prevents a race condition when accessing the IRP structure which is
freed up once the thread terminates.
2024-08-26 12:35:51 +02:00
akallabeth
9f911bea62
[winpr,comm] cleanup comm_sercx2_sys
* WINPR_ASSERT arugments
* remove use of restricted keywords (variables/functions starting with _)
2024-08-26 12:23:14 +02:00
akallabeth
2a7572e6b3
[winpr,comm] cleanup comm_serial_sys
* WINPR_ASSERT arguments
* remove use of restricted keywords (variables/functions starting with _)
2024-08-26 12:23:11 +02:00
akallabeth
652c5310f2
[channel,serial] cleanup code
* WINPR_ASSERT arugments
* remove use of restricted keywords (variables/functions starting with _)
* Better logging and error checks
2024-08-26 12:23:04 +02:00
akallabeth
56d660f258
[cmake] mark dependency includes SYSTEM
Mark all dependency include paths SYSTEM so warnings from system headers
are excluded from ci warning statistics
2024-08-26 11:10:49 +02:00
akallabeth
36686ba348
Merge pull request #10508 from akallabeth/cov-fix-high
[coverity] fix warnings
2024-08-26 09:51:23 +02:00
akallabeth
679de71056
[core,nla] remove platform guards for PasswordHash
Fixes #10507: do not ask for password if PasswordHash is supplied on
windows.
2024-08-26 09:23:55 +02:00
akallabeth
86e2789d9b
[coverity] fix warnings 2024-08-26 09:19:06 +02:00
akallabeth
2812775c96
Merge pull request #10504 from akallabeth/sdl-monitors
[client,sdl] add support for /monitors argument
2024-08-23 15:03:46 +02:00
akallabeth
95b88baa8f
Merge pull request #10503 from akallabeth/coverity-fix
[coverity] fix some warnings
2024-08-23 14:14:04 +02:00
akallabeth
49dc431045
[client,sdl] add support for /monitors argument 2024-08-23 14:00:47 +02:00
akallabeth
fc6ba9f8f9
Merge pull request #10502 from akallabeth/ci-autoclose
[ci,autoclose] improve detection
2024-08-23 12:40:34 +02:00
akallabeth
ba7fd06ec4
[coverity] fix some warnings
* mostly dead store and identical code branches.
* some possible integer overflows
2024-08-23 12:38:41 +02:00
akallabeth
a3d2c33f96
[ci,autoclose] improve detection
* Increase operations-per-run to 90, 60 is still too low.
* Exempt assigned pull requests and issues
* Exempt pull requests and issues with a milestone
2024-08-23 11:45:40 +02:00
akallabeth
3f5f53d3dc
Merge pull request #10501 from akallabeth/ci-autoclose
[ci,autoclose] increase operations per run
2024-08-23 11:15:35 +02:00
akallabeth
fb57a96eba [ci,autoclose] increase operations per run 2024-08-23 11:00:58 +02:00
David Fort
c7b519472b
Merge pull request #10494 from fifthdegree/asn1_int_fix
Fix ASN.1 integer decoding
2024-08-21 22:46:37 +02:00
Isaac Klein
3fb7bd92cc Don't accept 0-length ASN.1 integers for decoding 2024-08-21 14:02:26 -04:00
akallabeth
73b7401bbb
Merge pull request #10498 from akallabeth/solid-fill
Solid fill
2024-08-21 15:44:53 +02:00
Armin Novak
8f55f33951
[gdi,bitmap] initialize buffer solid black 2024-08-21 15:14:43 +02:00
Armin Novak
502640caca
[gdi,gfx] SolidFill always use alpha 0xff 2024-08-21 15:13:53 +02:00
akallabeth
20986e927f
Merge pull request #10496 from akallabeth/warn_fixes
Warn fixes
2024-08-21 10:19:28 +02:00
Armin Novak
17d44e847f
[coverity] fix various warnings 2024-08-21 09:47:34 +02:00
Armin Novak
fe76bafd57 [channels,drive] fix out of bound access 2024-08-21 09:20:25 +02:00
Isaac Klein
9c413abee1 Fix ASN.1 integer decoding
Treat ASN.1 encoded integers with a leading zero byte and the MSB of the
second byte set as non-negative
2024-08-20 19:14:02 -04:00
akallabeth
0fe5831187
Merge pull request #10491 from akallabeth/tcp_probe_addrinfo
[core,tcp] retry all DNS entries until success
2024-08-20 14:08:06 +02:00
akallabeth
79abff4329
Merge pull request #10492 from akallabeth/sdl-dialog-msg
[client,sdl] remove tab from dialog messages
2024-08-20 13:54:51 +02:00
akallabeth
37008506c2
[client,sdl] remove tab from dialog messages 2024-08-20 13:31:41 +02:00
akallabeth
7fe1164d26
Merge pull request #10490 from akallabeth/desktop-resize-deadlock
Desktop resize deadlock
2024-08-20 13:28:04 +02:00
akallabeth
1265498b1f
Merge pull request #10489 from akallabeth/verify-cert-improve
Verify cert improve
2024-08-20 13:13:57 +02:00
akallabeth
4286a4c164
[core,tcp] retry all DNS entries until success
When resolving some DNS name with getaddrinfo try all returned entries
matching the configuration (IPv4|IPv6|any) until the socket can be
connected. Fixes #5335
2024-08-20 13:10:12 +02:00
akallabeth
37f9d8a930
[client,wayland] improve VerifyCertificate message
* Use FreeRDP_CertificateCallbackPreferPEM for callbacks
2024-08-20 12:42:59 +02:00
akallabeth
d5d3d8501e
[client,x11] improve VerifyCertificate message
* Use FreeRDP_CertificateCallbackPreferPEM for callbacks
2024-08-20 12:42:57 +02:00
akallabeth
7ea8e63a39
[client,sample] improve VerifyCertificate message
* Use FreeRDP_CertificateCallbackPreferPEM for callbacks
2024-08-20 12:42:54 +02:00
akallabeth
39e8c077d4
[client,sdl] improve VerifyCertificate message
* Use FreeRDP_CertificateCallbackPreferPEM for callbacks
* Add notBefore and notAfter dates to callback messages
2024-08-20 12:42:51 +02:00
akallabeth
e95a813560
[client,common] unify PEM ceritificate string
* Unify PEM data extraction
* Add notBefore and notAfter dates to certificate callback messages
2024-08-20 12:42:49 +02:00
akallabeth
c2d30a07e9
[crypto,cert] add getter for notBefore and notAfter
Add getters for ceritificate dates notBefore and notAfter. Returns the
date as RFC822 string.
2024-08-20 12:42:46 +02:00
akallabeth
dcbeedb4d4
[client,x11] fix a possible deadlock on desktop resize 2024-08-20 12:41:17 +02:00
David Fort
ddde8f26e8
Merge pull request #10488 from akallabeth/gdi-resize
[core,update] ensure EndPaint before DesktopResize
2024-08-20 11:33:29 +02:00
akallabeth
63d87dcf18
[core,update] ensure EndPaint before DesktopResize
When DesktopResize is called EndPaint might not have been. Ensure the
update-lock is released and data flushed before resizing.
2024-08-20 09:54:56 +02:00
akallabeth
a863bc0bf4
Merge pull request #10485 from akallabeth/issue-close-modify
[ci,issue-close] extend period, add wip label
2024-08-19 13:29:22 +02:00
akallabeth
03794e4679
[ci,issue-close] extend period, add wip label 2024-08-19 13:04:06 +02:00
akallabeth
82835026d3
Merge pull request #10484 from akallabeth/clip_unit_test
Clip unit test
2024-08-19 12:06:16 +02:00
akallabeth
4b7727bd4e
[winpr,utils] fix PNG bpp extraction 2024-08-19 11:50:15 +02:00
akallabeth
7f84bd5c81
[winpr,utils] fix image stride calculation 2024-08-19 11:50:11 +02:00
akallabeth
7dfdadbe53
[winpr,clipboard] add image clipboard tests 2024-08-19 11:50:07 +02:00
akallabeth
bc4022eb3b
Merge pull request #10482 from akallabeth/issue-autoclose
[ci,issues] add workflow to autoclose stale issues
2024-08-16 15:01:39 +02:00
akallabeth
b80e33ff70
[ci,issues] add workflow to autoclose stale issues 2024-08-16 14:23:23 +02:00
Martin Fleisz
9f18768483
Merge pull request #10480 from akallabeth/ignore_empty_string_in_rdp_file
[client,common] ignore empty strings for channels
2024-08-14 15:33:49 +02:00
Armin Novak
1f95865907
[client,common] ignore empty strings for channels
Ignore empty strings when parsing redirection channel arguments
2024-08-14 14:31:58 +02:00
Martin Fleisz
8f5a20923c
Merge pull request #10477 from akallabeth/cliprdr_packet_format_list_new
[channels,cliprdr] refactor cliprdr_packet_format_list_new
2024-08-14 09:40:38 +02:00
akallabeth
1e19ccd76d
[channels,cliprdr] refactor cliprdr_packet_format_list_new
* Simplify function
* Add missing arguments for ASCII names
2024-08-14 09:19:51 +02:00
Martin Fleisz
92b547e91e
Merge pull request #10474 from akallabeth/accepted-key-fix
[crypto,tls] fix AcceptedKey checks
2024-08-14 08:47:10 +02:00
akallabeth
dac0ae4976
[crypto,cert] extend certificate store API
Use the certificate PEM without trustchain in the local trust store, but
keep the full PEM with chain for the user facing callbacks.
2024-08-13 15:56:08 +02:00
akallabeth
1f806f35db
Merge pull request #10476 from hardening/cliprdr_log_fix
cliprdr: fix message of error code log
2024-08-13 15:36:53 +02:00
David Fort
6e2cc358ba cliprdr: fix message of error code log 2024-08-13 15:08:30 +02:00
akallabeth
4523c4ec78
Merge pull request #10472 from akallabeth/clip-rdp-2-rdp-fix
Clip rdp 2 rdp fix
2024-08-13 08:27:35 +02:00
akallabeth
22fb6aad31
[crypto,tls] fix AcceptedKey checks
* Add freerdp_certificate_get_pem_ex to extract PEM for cert only
* Compare only certificate without certificate chain
* Store only certificate PEM without chain for later comparison
2024-08-13 07:40:07 +02:00
akallabeth
d4ecd16477
Merge pull request #10471 from hardening/sdl3_build
[sdl3] fix build against last SDL3
2024-08-12 16:10:25 +02:00
akallabeth
1dd9f32e76
Merge pull request #10470 from akallabeth/timzeone_generator_no_format
[winpr,timezone] disable clang-format for WindowsZones
2024-08-12 15:55:44 +02:00
Armin Novak
14c85bafd3
[client,x11] fix RAW clipboard copy 2024-08-12 15:55:26 +02:00
Armin Novak
83b253dc84
[channels,cliprdr] fix cliprdr_packet_format_list_new
* Fix length calculations
* Fix format name write, skip empty strings
2024-08-12 13:23:33 +02:00
David Fort
4e6f7fb989 [sdl3] fix build against last SDL3 2024-08-12 11:50:02 +02:00
Armin Novak
b2e15b5f75
[winpr,timezone] disable clang-format for WindowsZones 2024-08-12 10:49:10 +02:00
1088 changed files with 29341 additions and 14691 deletions

View File

@ -21,31 +21,67 @@ Checks: >
-altera-id-dependent-backward-branch,
-altera-struct-pack-align,
-altera-unroll-loops,
-cppcoreguidelines-interfaces-global-init,
-bugprone-easily-swappable-parameters,
-bugprone-assignment-in-if-condition,
-bugprone-branch-clone,
-bugprone-macro-parentheses,
-cert-dcl16-c,
-cert-env33-c,
-cert-dcl50-cpp,
-clang-analyzer-optin.performance.Padding,
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
-clang-analyzer-valist.Uninitialized,
-cppcoreguidelines-pro-bounds-array-to-pointer-decay,
-cppcoreguidelines-owning-memory,
-cppcoreguidelines-avoid-c-arrays,
-cppcoreguidelines-avoid-do-while,
-cppcoreguidelines-avoid-magic-numbers,
-cppcoreguidelines-avoid-non-const-global-variables,
-cppcoreguidelines-macro-to-enum,
-cppcoreguidelines-macro-usage,
-cppcoreguidelines-pro-type-vararg,
-cppcoreguidelines-pro-type-reinterpret-cast,
-cppcoreguidelines-pro-bounds-pointer-arithmetic,
-cppcoreguidelines-no-malloc,
-google-readability-braces-around-statements,
-google-readability-todo,
-hicpp-avoid-c-arrays,
-hicpp-braces-around-statements,
-hicpp-no-array-decay,
-hicpp-no-assembler,
-hicpp-multiway-paths-covered,
-hicpp-signed-bitwise,
-hicpp-uppercase-literal-suffix,
-hicpp-vararg,
-hicpp-no-malloc,
-llvm-header-guard,
-llvm-include-order,
-llvm-qualified-auto,
-llvm-else-after-return,
-readability-else-after-return,
-readability-avoid-nested-conditional-operator,
-modernize-use-trailing-return-type,
-modernize-return-braced-init-list,
-modernize-macro-to-enum,
-modernize-pass-by-value,
-modernize-avoid-c-arrays,
-readability-braces-around-statements,
-readability-convert-member-functions-to-static,
-readability-function-cognitive-complexity,
-readability-identifier-length,
-readability-implicit-bool-conversion,
-readability-magic-numbers,
-readability-math-missing-parentheses,
-readability-misleading-indentation,
-readability-qualified-auto,
-readability-suspicious-call-argument,
-readability-string-compare,
-readability-uppercase-literal-suffix,
-performance-no-int-to-ptr
-performance-no-int-to-ptr,
-performance-avoid-endl
WarningsAsErrors: ''
HeaderFilterRegex: ''
AnalyzeTemporaryDtors: false
FormatStyle: file
User: nin
CheckOptions:

View File

@ -38,13 +38,13 @@ jobs:
xserver-xorg-dev \
libswscale-dev \
libswresample-dev \
libavformat-dev \
libavutil-dev \
libavcodec-dev \
libcups2-dev \
libpulse-dev \
libasound2-dev \
libpcsclite-dev \
xsltproc \
libxcb-cursor-dev \
libxcursor-dev \
libcairo2-dev \
@ -65,7 +65,6 @@ jobs:
libcairo2-dev \
libsoxr-dev \
libsdl2-dev \
docbook-xsl \
libkrb5-dev \
libcjson-dev \
libsdl2-ttf-dev \
@ -84,11 +83,11 @@ jobs:
- name: "Prepare configuration"
run: |
mkdir -p checker
cp ci/cmake-preloads/config-abi.txt checker/
cp scripts/abi-suppr.txt checker/
curl https://gist.githubusercontent.com/akallabeth/aa35caed0d39241fa17c3dc8a0539ea3/raw/ef12f8c720ac6be51aa1878710e2502b1b39cf4c/check-abi -o checker/check-abi
chmod +x checker/check-abi
mkdir -p abi-checker
cp ci/cmake-preloads/config-abi.txt abi-checker/
cp scripts/abi-suppr.txt abi-checker/
curl https://gist.githubusercontent.com/akallabeth/aa35caed0d39241fa17c3dc8a0539ea3/raw/ef12f8c720ac6be51aa1878710e2502b1b39cf4c/check-abi -o abi-checker/check-abi
chmod +x abi-checker/check-abi
echo "GITHUB_BASE_REF=$GITHUB_BASE_REF"
echo "GITHUB_HEAD_REF=$GITHUB_HEAD_REF"
echo "API_BASE_REF=${{ inputs.API_BASE_REF || '3.0.0' }}"
@ -100,4 +99,4 @@ jobs:
BASE_REF: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event_name == 'workflow_dispatch' && inputs.API_BASE_REF || '3.0.0' }}
run: |
echo "BASE_REF=$BASE_REF"
./checker/check-abi -s checker/abi-suppr.txt --parameters="-Cchecker/config-abi.txt" $BASE_REF $(git rev-parse HEAD)
./abi-checker/check-abi -s abi-checker/abi-suppr.txt --parameters="-Cabi-checker/config-abi.txt" $BASE_REF $(git rev-parse HEAD)

View File

@ -27,7 +27,7 @@ jobs:
distro: ubuntu22.04
steps:
- uses: actions/checkout@v4
- uses: uraimo/run-on-arch-action@master
- uses: uraimo/run-on-arch-action@v2.8.1
name: "Run tests"
id: build
with:
@ -52,8 +52,6 @@ jobs:
libpulse-dev \
libasound2-dev \
libpcsclite-dev \
xsltproc \
libxml2-dev \
libxcb-cursor-dev \
libxcursor-dev \
libcairo2-dev \
@ -74,7 +72,6 @@ jobs:
libsdl2-dev \
libsdl2-ttf-dev \
libsdl2-image-dev \
docbook-xsl \
libkrb5-dev \
libcjson-dev \
libpkcs11-helper1-dev \

View File

@ -16,7 +16,7 @@ jobs:
split_workflow: true
clang_tidy_checks: ''
# List of packages to install
apt_packages: libkrb5-dev,libxkbcommon-dev,libxkbfile-dev,libx11-dev,libwayland-dev,libxrandr-dev,libxi-dev,libxrender-dev,libxext-dev,libxinerama-dev,libxfixes-dev,libxcursor-dev,libxv-dev,libxdamage-dev,libxtst-dev,libcups2-dev,libcairo2-dev,libpcsclite-dev,libasound2-dev,libswscale-dev,libpulse-dev,libavcodec-dev,libavutil-dev,libfuse3-dev,libswresample-dev,libusb-1.0-0-dev,libudev-dev,libdbus-glib-1-dev,libpam0g-dev,uuid-dev,libxml2-dev,libcjson-dev,libsdl2-2.0-0,libsdl2-dev,libsdl2-ttf-dev,libsdl2-image-dev,libsystemd-dev,liburiparser-dev,libopus-dev,libwebp-dev,libjpeg-dev,libpng-dev,xsltproc,docbook-xsl,libgsm1-dev,libfaac-dev,libfaad-dev,libsoxr-dev,opencl-c-headers,opencl-headers,ocl-icd-opencl-dev,libssl-dev,libv4l-dev
apt_packages: libkrb5-dev,libxkbcommon-dev,libxkbfile-dev,libx11-dev,libwayland-dev,libxrandr-dev,libxi-dev,libxrender-dev,libxext-dev,libxinerama-dev,libxfixes-dev,libxcursor-dev,libxv-dev,libxdamage-dev,libxtst-dev,libcups2-dev,libcairo2-dev,libpcsclite-dev,libasound2-dev,libswscale-dev,libpulse-dev,libavformat-dev,libavcodec-dev,libavutil-dev,libfuse3-dev,libswresample-dev,libusb-1.0-0-dev,libudev-dev,libdbus-glib-1-dev,libpam0g-dev,uuid-dev,libcjson-dev,libsdl2-2.0-0,libsdl2-dev,libsdl2-ttf-dev,libsdl2-image-dev,libsystemd-dev,liburiparser-dev,libopus-dev,libwebp-dev,libjpeg-dev,libpng-dev,libgsm1-dev,libfaac-dev,libfaad-dev,libsoxr-dev,opencl-c-headers,opencl-headers,ocl-icd-opencl-dev,libssl-dev,libv4l-dev
# CMake command to run in order to generate compile_commands.json
build_dir: tidy

View File

@ -86,6 +86,7 @@ jobs:
xserver-xorg-dev \
libswscale-dev \
libswresample-dev \
libavformat-dev \
libavutil-dev \
libavcodec-dev \
libcups2-dev \
@ -93,7 +94,6 @@ jobs:
libpulse-dev \
libasound2-dev \
libpcsclite-dev \
xsltproc \
libxcb-cursor-dev \
libxcursor-dev \
libcairo2-dev \
@ -115,7 +115,6 @@ jobs:
libcairo2-dev \
libsoxr-dev \
libsdl2-dev \
docbook-xsl \
libkrb5-dev \
libcjson-dev \
libsdl2-ttf-dev \

View File

@ -5,6 +5,7 @@ on:
schedule:
- cron: "0 0 * * *"
workflow_dispatch:
branches: [ master, stable* ]
permissions:
contents: read
@ -19,71 +20,33 @@ jobs:
run: |
sudo apt-get update
sudo apt-get install -y \
libxrandr-dev \
libxinerama-dev \
libusb-1.0-0-dev \
xserver-xorg-dev \
libswscale-dev \
libswresample-dev \
libavutil-dev \
libavcodec-dev \
libcups2-dev \
libpulse-dev \
libasound2-dev \
libpcsclite-dev \
libv4l-dev \
xsltproc \
libxcb-cursor-dev \
libxcursor-dev \
libcairo2-dev \
libfaac-dev \
libfaad-dev \
libjpeg-dev \
libgsm1-dev \
devscripts \
ninja-build \
libxfixes-dev \
libxkbcommon-dev \
libwayland-dev \
libpam0g-dev \
libxdamage-dev \
libxcb-damage0-dev \
equivs \
ccache \
libxtst-dev \
libfuse3-dev \
libsystemd-dev \
libcairo2-dev \
libsoxr-dev \
libsdl2-dev \
docbook-xsl \
libkrb5-dev \
libcjson-dev \
libsdl2-ttf-dev \
libsdl2-image-dev \
libwebkit2gtk-4.0-dev \
clang \
libopus-dev \
libwebp-dev \
libpng-dev \
libjpeg-dev \
liburiparser-dev
clang
sudo mk-build-deps --install packaging/deb/freerdp-nightly/control
- name: Download Coverity build tool
run: |
wget -c -N https://scan.coverity.com/download/linux64 --post-data "token=${{ secrets.COVERITY_SCAN_TOKEN }}&project=FreeRDP" -O coverity_tool.tar.gz
mkdir coverity_tool
tar xzf coverity_tool.tar.gz --strip 1 -C coverity_tool
- name: Build with Coverity build tool
run: |
export PATH=`pwd`/coverity_tool/bin:$PATH
export CC=/usr/bin/clang
export CXX=/usr/bin/clang++
cov-configure --template --compiler clang --comptype clangcc
# in source build is used to help coverity to determine relative file path
cmake \
-GNinja \
-C ci/cmake-preloads/config-coverity.txt \
-DALLOW_IN_SOURCE_BUILD=true \
-B. \
-DCOVERITY_BUILD=ON \
-Bcov-build \
-S.
cov-build --dir cov-int cmake --build .
cov-build --dir cov-int cmake --build cov-build
- name: Submit build result to Coverity Scan
run: |

View File

@ -37,7 +37,7 @@ jobs:
dry-run: false
sanitizer: ${{ matrix.sanitizer }}
- name: Upload crash
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4.3.6
if: failure() && steps.build.outcome == 'success'
with:
name: ${{ matrix.sanitizer }}-artifacts

29
.github/workflows/issue-autoclose.yml vendored Normal file
View File

@ -0,0 +1,29 @@
name: Close inactive issues
on:
workflow_dispatch:
schedule:
- cron: "33 3 * * *"
jobs:
close-issues:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/stale@v5
with:
days-before-stale: 30
days-before-close: 30
operations-per-run: 90
exempt-all-milestones: true
exempt-assignees: true
exempt-issue-labels: "wip,pinned,help-wanted,blocker,feature"
exempt-pr-labels: "wip,pinned,help-wanted,blocker,feature"
stale-issue-label: "stale"
stale-issue-message: "This issue is stale because it has been open for 30 days with no activity."
close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale."
days-before-pr-stale: -1
days-before-pr-close: -1
repo-token: ${{ secrets.GITHUB_TOKEN }}

View File

@ -33,7 +33,9 @@ jobs:
run: build\Release\tzextract.exe winpr\libwinpr\timezone
- name: Format code
run: |
clang-format -i --style=file:.clang-format winpr/libwinpr/timezone/WindowsZones.c
clang-format -i --style=file:.clang-format winpr/libwinpr/timezone/TimeZoneNameMap.c
clang-format -i --style=file:.clang-format winpr/libwinpr/timezone/TimeZoneNameMap_static.h
clang-format -i --style=file:.clang-format winpr/libwinpr/timezone/TimeZoneNameMap.json
- name: Create Pull Request
id: cpr

2
.gitignore vendored
View File

@ -1,3 +1,5 @@
**/CMakeCache.txt
**/CMakeFiles
build
checker
abi-checker

View File

@ -1,56 +0,0 @@
sudo: required
dist: trusty
os: linux
language: c
compiler:
- gcc
matrix:
include:
- os: linux
compiler: gcc
- os: linux
compiler: clang
exclude:
- compiler: gcc
addons:
apt:
packages:
- gdb
- libx11-dev
- libxrandr-dev
- libxi-dev
- libxv-dev
- libcups2-dev
- libxdamage-dev
- libxcursor-dev
- libxext-dev
- libxinerama-dev
- libxkbcommon-dev
- libxkbfile-dev
- libxml2-dev
- libasound2-dev
- libgstreamer1.0-dev
- libgstreamer-plugins-base1.0-dev
- libpulse-dev
- libpcsclite-dev
- libgsm1-dev
- libavcodec-dev
- libavutil-dev
- libxext-dev
- ninja-build
- libsystemd-dev
- libwayland-dev
before_script:
- ulimit -c unlimited -S
script:
- sudo hostname travis-ci.local
- cmake -G Ninja -C ci/cmake-preloads/config-linux-all.txt -D CMAKE_BUILD_TYPE=Debug .
- make
- make test

View File

@ -56,6 +56,11 @@ if (NOT WIN32 AND NOT ANDROID)
option(WITH_X11 "build X11 client/server" ${OPT_DEFAULT_VAL})
endif()
# Enable coverity related pragma definitions
if (COVERITY_BUILD)
add_compile_definitions(COVERITY_BUILD)
endif()
# Include our extra modules
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/)
@ -84,6 +89,7 @@ include(CMakePackageConfigHelpers)
include(InstallFreeRDPMan)
include(GetGitRevisionDescription)
include(SetFreeRDPCMakeInstallDir)
include(Doxygen)
# Soname versioning
set(BUILD_NUMBER 0)
@ -92,7 +98,7 @@ if ($ENV{BUILD_NUMBER})
endif()
set(VERSION_REGEX "^(.*)([0-9]+)\\.([0-9]+)\\.([0-9]+)-?(.*)")
set(RAW_VERSION_STRING "3.7.1-dev0")
set(RAW_VERSION_STRING "3.9.1-dev0")
if(EXISTS "${PROJECT_SOURCE_DIR}/.source_tag")
file(READ ${PROJECT_SOURCE_DIR}/.source_tag RAW_VERSION_STRING)
elseif(USE_VERSION_FROM_GIT_TAG)
@ -188,14 +194,14 @@ endif(CMAKE_CROSSCOMPILING)
# Turn on solution folders (2.8.4+)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
option(EXPORT_ALL_SYMBOLS "Export all symbols form library" OFF)
if(BUILD_TESTING)
set(EXPORT_ALL_SYMBOLS TRUE)
set(CTEST_OUTPUT_ON_FAILURE TRUE)
add_definitions(-DBUILD_TESTING)
elseif(NOT DEFINED EXPORT_ALL_SYMBOLS)
set(EXPORT_ALL_SYMBOLS FALSE)
option(CTEST_OUTPUT_ON_FAILURE ON "show verbose output on CTest failures")
if(BUILD_TESTING_INTERNAL)
set(EXPORT_ALL_SYMBOLS ON CACHE BOOL "testing default" FORCE)
add_definitions(-DBUILD_TESTING_INTERNAL)
elseif(BUILD_TESTING)
set(EXPORT_ALL_SYMBOLS OFF CACHE BOOL "testing default" FORCE)
else()
option(EXPORT_ALL_SYMBOLS "Export all symbols form library" OFF)
endif()
if (EXPORT_ALL_SYMBOLS)
@ -238,22 +244,6 @@ if(CMAKE_COMPILER_IS_GNUCC)
endif()
endif()
# When building with Unix Makefiles and doing any release builds
# try to set __FILE__ to relative paths via a make specific macro
if (CMAKE_GENERATOR MATCHES "Unix Makefile*")
if(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
string(TOUPPER ${CMAKE_BUILD_TYPE} UPPER_BUILD_TYPE)
CHECK_C_COMPILER_FLAG (-Wno-builtin-macro-redefined Wno-builtin-macro-redefined)
if(Wno-builtin-macro-redefined)
set(CMAKE_C_FLAGS_${UPPER_BUILD_TYPE} "${CMAKE_C_FLAGS_${UPPER_BUILD_TYPE}} -Wno-builtin-macro-redefined -D__FILE__='\"$(subst ${PROJECT_BINARY_DIR}/,,$(subst ${PROJECT_SOURCE_DIR}/,,$(abspath $<)))\"'")
endif()
endif()
endif()
if(CMAKE_COMPILER_IS_CLANG)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-c11-extensions -Wno-gnu")
endif()
set(THREAD_PREFER_PTHREAD_FLAG TRUE)
if(NOT IOS)
@ -262,12 +252,6 @@ endif()
# Enable address sanitizer, where supported and when required
if(CMAKE_COMPILER_IS_CLANG OR CMAKE_COMPILER_IS_GNUCC)
CHECK_C_COMPILER_FLAG ("-fno-omit-frame-pointer" fno-omit-frame-pointer)
if (fno-omit-frame-pointer)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer")
endif()
set(CMAKE_REQUIRED_LINK_OPTIONS_SAVED ${CMAKE_REQUIRED_LINK_OPTIONS})
file(WRITE ${PROJECT_BINARY_DIR}/foo.txt "")
if(WITH_SANITIZE_ADDRESS)
@ -422,8 +406,13 @@ if(ANDROID)
endif()
if(ANDROID_ABI STREQUAL arm64-v8a)
# https://github.com/android/ndk/issues/910
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfloat-abi=softfp")
include (CheckCCompilerFlag)
check_c_compiler_flag("-mfloat-abi=softfp" ABI_SOFTFP_SUPPORTED)
if (ABI_SOFTFP_SUPPORTED)
# https://github.com/android/ndk/issues/910
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfloat-abi=softfp")
endif()
endif()
if("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
@ -491,10 +480,6 @@ set(PCSC_FEATURE_TYPE "RECOMMENDED")
set(PCSC_FEATURE_PURPOSE "smart card")
set(PCSC_FEATURE_DESCRIPTION "smart card device redirection")
set(FFMPEG_FEATURE_TYPE "RECOMMENDED")
set(FFMPEG_FEATURE_PURPOSE "multimedia")
set(FFMPEG_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback")
set(OPENH264_FEATURE_TYPE "OPTIONAL")
set(OPENH264_FEATURE_PURPOSE "codec")
set(OPENH264_FEATURE_DESCRIPTION "use OpenH264 library")
@ -526,11 +511,9 @@ set(SOXR_FEATURE_DESCRIPTION "SOX audio resample library")
if(WIN32)
set(WAYLAND_FEATURE_TYPE "DISABLED")
set(PCSC_FEATURE_TYPE "DISABLED")
set(FFMPEG_FEATURE_TYPE "OPTIONAL")
endif()
if(APPLE)
set(FFMPEG_FEATURE_TYPE "OPTIONAL")
set(WAYLAND_FEATURE_TYPE "DISABLED")
if(IOS)
set(PCSC_FEATURE_TYPE "DISABLED")
@ -547,7 +530,7 @@ find_feature(Wayland ${WAYLAND_FEATURE_TYPE} ${WAYLAND_FEATURE_PURPOSE} ${WAYLAN
option(WITH_LIBRESSL "build with LibreSSL" OFF)
if (WITH_LIBRESSL)
find_package(LibreSSL REQUIRED)
include_directories(${LibreSSL_INCLUDE_DIRS})
include_directories(SYSTEM ${LibreSSL_INCLUDE_DIRS})
set(OPENSSL_INCLUDE_DIR ${LIBRESSL_INCLUDE_DIR})
set(OPENSSL_LIBRARIES ${LIBRESSL_LIBRARIES})
set(OPENSSL_CRYPTO_LIBRARIES ${LIBRESSL_LIBRARIES})
@ -563,11 +546,9 @@ endif()
find_feature(PCSC ${PCSC_FEATURE_TYPE} ${PCSC_FEATURE_PURPOSE} ${PCSC_FEATURE_DESCRIPTION})
if (WITH_DSP_FFMPEG OR WITH_VIDEO_FFMPEG OR WITH_FFMPEG)
set(FFMPEG_FEATURE_TYPE "REQUIRED" )
find_package(FFmpeg REQUIRED COMPONENTS AVUTIL AVCODEC)
endif()
find_feature(FFmpeg ${FFMPEG_FEATURE_TYPE} ${FFMPEG_FEATURE_PURPOSE} ${FFMPEG_FEATURE_DESCRIPTION})
find_feature(OpenH264 ${OPENH264_FEATURE_TYPE} ${OPENH264_FEATURE_PURPOSE} ${OPENH264_FEATURE_DESCRIPTION})
find_feature(OpenCL ${OPENCL_FEATURE_TYPE} ${OPENCL_FEATURE_PURPOSE} ${OPENCL_FEATURE_DESCRIPTION})
find_feature(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRIPTION})
@ -583,29 +564,6 @@ endif (WITH_OPENH264 AND NOT WITH_OPENH264_LOADING)
# Version check, if we have detected FFMPEG but the version is too old
# deactivate it as sound backend.
if (WITH_DSP_FFMPEG)
# Deactivate FFmpeg backend for sound, if the version is too old.
# See libfreerdp/codec/dsp_ffmpeg.h
file(STRINGS "${AVCODEC_INCLUDE_DIR}/libavcodec/version.h" AV_VERSION_FILE REGEX "LIBAVCODEC_VERSION_M[A-Z]+[\t ]*[0-9]+")
if (EXISTS "${AVCODEC_INCLUDE_DIR}/libavcodec/version_major.h")
file(STRINGS "${AVCODEC_INCLUDE_DIR}/libavcodec/version_major.h" AV_VERSION_FILE2 REGEX "LIBAVCODEC_VERSION_M[A-Z]+[\t ]*[0-9]+")
list(APPEND AV_VERSION_FILE ${AV_VERSION_FILE2})
endif()
FOREACH(item ${AV_VERSION_FILE})
STRING(REGEX MATCH "LIBAVCODEC_VERSION_M[A-Z]+[\t ]*[0-9]+" litem ${item})
IF(litem)
string(REGEX REPLACE "[ \t]+" ";" VSPLIT_LINE ${litem})
list(LENGTH VSPLIT_LINE VSPLIT_LINE_LEN)
if (NOT "${VSPLIT_LINE_LEN}" EQUAL "2")
message(ERROR "invalid entry in libavcodec version header ${item}")
endif(NOT "${VSPLIT_LINE_LEN}" EQUAL "2")
list(GET VSPLIT_LINE 0 VNAME)
list(GET VSPLIT_LINE 1 VVALUE)
set(${VNAME} ${VVALUE})
ENDIF(litem)
ENDFOREACH(item ${AV_VERSION_FILE})
set(AVCODEC_VERSION "${LIBAVCODEC_VERSION_MAJOR}.${LIBAVCODEC_VERSION_MINOR}.${LIBAVCODEC_VERSION_MICRO}")
if (AVCODEC_VERSION VERSION_LESS "57.48.101")
message(WARNING "FFmpeg version detected (${AVCODEC_VERSION}) is too old. (Require at least 57.48.101 for sound). Deactivating")
set(WITH_DSP_FFMPEG OFF)
@ -620,7 +578,7 @@ set(WITH_OPENH264 ${OPENH264_FOUND})
if(OPENSSL_FOUND)
add_definitions("-DWITH_OPENSSL")
message(STATUS "Using OpenSSL Version: ${OPENSSL_VERSION}")
include_directories(${OPENSSL_INCLUDE_DIR})
include_directories(SYSTEM ${OPENSSL_INCLUDE_DIR})
endif()
if(MBEDTLS_FOUND)
@ -682,7 +640,7 @@ if(ANDROID)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -pg")
set(PROFILER_LIBRARIES
"${FREERDP_EXTERNAL_PROFILER_PATH}/obj/local/${ANDROID_ABI}/libandroid-ndk-profiler.a")
include_directories("${FREERDP_EXTERNAL_PROFILER_PATH}")
include_directories(SYSTEM "${FREERDP_EXTERNAL_PROFILER_PATH}")
endif()
endif()
@ -690,7 +648,7 @@ endif()
include(CTest)
if(BUILD_TESTING)
if(BUILD_TESTING_INTERNAL OR BUILD_TESTING)
enable_testing()
if(MSVC)
@ -702,13 +660,6 @@ endif()
include(CommonConfigOptions)
# WinPR
# We want to control the winpr assert for the whole project
option(WITH_VERBOSE_WINPR_ASSERT "Compile with verbose WINPR_ASSERT." ON)
if (WITH_VERBOSE_WINPR_ASSERT)
add_definitions(-DWITH_VERBOSE_WINPR_ASSERT)
endif()
if (FREERDP_UNIFIED_BUILD)
add_subdirectory(winpr)
if (WITH_WAYLAND)
@ -725,7 +676,7 @@ if (FREERDP_UNIFIED_BUILD)
include_directories(${PROJECT_BINARY_DIR}/winpr/include)
else()
find_package(WinPR 3 REQUIRED)
include_directories(${WinPR_INCLUDE_DIR})
include_directories(SYSTEM ${WinPR_INCLUDE_DIR})
endif()
option(WITH_AAD "Compile with support for Azure AD authentication" ${WITH_WINPR_JSON})
@ -740,7 +691,7 @@ include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
if(WITH_THIRD_PARTY)
add_subdirectory(third-party)
if (NOT "${THIRD_PARTY_INCLUDES}" STREQUAL "")
include_directories(${THIRD_PARTY_INCLUDES})
include_directories(SYSTEM ${THIRD_PARTY_INCLUDES})
endif()
endif()
@ -776,7 +727,7 @@ endif()
set(FREERDP_BUILD_CONFIG_LIST "")
GET_CMAKE_PROPERTY(res VARIABLES)
FOREACH(var ${res})
IF (var MATCHES "^WITH_*|^BUILD_TESTING|^WINPR_HAVE_*")
IF (var MATCHES "^WITH_*|^BUILD_TESTING*|^WINPR_HAVE_*")
LIST(APPEND FREERDP_BUILD_CONFIG_LIST "${var}=${${var}}")
ENDIF()
ENDFOREACH()

View File

@ -1,3 +1,57 @@
# 2024-10-21 Version 3.9.0
We're proud to present the newest release of FreeRDP.
This one brings some major code cleanup (we've addressed lots of clang-tidy
warnings) as well as some highly anticipated new features.
We also did update the API documentation quite a bit (still incomplete though,
help always welcome ;))
So, what is new:
* Support for RDPEAR (remote credential guard) /remoteGuard option for non windows clients
* Global configuration file support, allowing to configure certificate
accept/ignore/... default settings for all users
* Simplified manpage generation, eliminates docbook and xmlto dependencies
speeding up builds
* New API for client channels to run tasks on RDP thread
* New extended transport layer API
* RDPECAM MJPEG support
* the first updates of timezone definitions from our automated ci
Noteworthy changes:
* Fix bugs in SSE4.1/AVX2 image copy (#10720)
* Add warnings for invalid monitor settings during connect (#10672)
* Fix ALSA microphone support (#10664)
* Fix modal windows in RAILS mode (#10629)
* Update experimental SDL3 client (SDL3 API should now have been stabilized,
various pull requests)
* Fix keyboard layouts, the external JSON did miss a few (#10639)
For a complete and detailed change log since the last release run:
git log 3.9.0...3.8.0
# 2024-08-30 Version 3.8.0
This is a bugfix release. Due to additional exports required by a bugfix the minor version was incremented
Noteworthy changes:
* Reduce number of warnings on CI build (make dependency includes SYSTEM) (#10509)
* Fix possible crashes with P11 certificate parsing (#10462, #10463)
* Various clipboard related fixes (#10472, #10476, #10477, #10480, #10484)
* Fix a race condition on DesktopResize (xfreerdp) (#10488)
* Improve certificate warnings (#10489)
* Try all possible resolved IP addresses for a DNS name on connect (#10491)
* Fix an issue with GFX SolidFill alpha data (#10498)
* Various fixes for SDL clients (#10504, #10492, #10471)
* Fix serial and parallel redirection crashes (#10510)
* Fix android build issues with NDK 27 (#10529)
* Improve performance of some WinPR primitives (#10528)
* Fix an issue with autoreconnect (#10523)
* Support ssh-askpass like password reading (#10516)
* Lots of code cleanups to reduce clang-tidy warnings (#10531, #10525, #10521, #10520, #10519, #10518)
For a complete and detailed change log since the last release run:
git log 3.8.0...3.7.0
# 2024-08-08 Version 3.7.0
This release has accumulated quite a number of changes. Along bugfixes for 3.6.3 it also

View File

@ -175,7 +175,7 @@ static const IWTSVirtualChannelCallback ainput_functions = { ainput_on_data_rece
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(UINT ainput_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
FREERDP_ENTRY_POINT(UINT VCAPITYPE ainput_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
{
return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, AINPUT_DVC_CHANNEL_NAME,
sizeof(AINPUT_PLUGIN), sizeof(GENERIC_CHANNEL_CALLBACK),

View File

@ -176,8 +176,8 @@ static UINT ainput_server_send_version(ainput_server* ainput)
Stream_Write_UINT32(s, AINPUT_VERSION_MAJOR); /* Version (4 bytes) */
Stream_Write_UINT32(s, AINPUT_VERSION_MINOR); /* Version (4 bytes) */
WINPR_ASSERT(Stream_GetPosition(s) <= ULONG_MAX);
if (!WTSVirtualChannelWrite(ainput->ainput_channel, (PCHAR)Stream_Buffer(s),
WINPR_ASSERT(Stream_GetPosition(s) <= UINT32_MAX);
if (!WTSVirtualChannelWrite(ainput->ainput_channel, Stream_BufferAs(s, char),
(ULONG)Stream_GetPosition(s), &written))
{
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
@ -292,7 +292,7 @@ static DWORD WINAPI ainput_server_thread_func(LPVOID arg)
}
}
WTSVirtualChannelClose(ainput->ainput_channel);
(void)WTSVirtualChannelClose(ainput->ainput_channel);
ainput->ainput_channel = NULL;
if (error && ainput->context.rdpcontext)
@ -327,7 +327,7 @@ static UINT ainput_server_open(ainput_server_context* context)
if (!ainput->thread)
{
WLog_ERR(TAG, "CreateEvent failed!");
CloseHandle(ainput->stopEvent);
(void)CloseHandle(ainput->stopEvent);
ainput->stopEvent = NULL;
return ERROR_INTERNAL_ERROR;
}
@ -351,7 +351,7 @@ static UINT ainput_server_close(ainput_server_context* context)
if (!ainput->externalThread && ainput->thread)
{
SetEvent(ainput->stopEvent);
(void)SetEvent(ainput->stopEvent);
if (WaitForSingleObject(ainput->thread, INFINITE) == WAIT_FAILED)
{
@ -360,8 +360,8 @@ static UINT ainput_server_close(ainput_server_context* context)
return error;
}
CloseHandle(ainput->thread);
CloseHandle(ainput->stopEvent);
(void)CloseHandle(ainput->thread);
(void)CloseHandle(ainput->stopEvent);
ainput->thread = NULL;
ainput->stopEvent = NULL;
}
@ -369,7 +369,7 @@ static UINT ainput_server_close(ainput_server_context* context)
{
if (ainput->state != AINPUT_INITIAL)
{
WTSVirtualChannelClose(ainput->ainput_channel);
(void)WTSVirtualChannelClose(ainput->ainput_channel);
ainput->ainput_channel = NULL;
ainput->state = AINPUT_INITIAL;
}
@ -467,7 +467,7 @@ static UINT ainput_process_message(ainput_server* ainput)
goto out;
}
if (WTSVirtualChannelRead(ainput->ainput_channel, 0, (PCHAR)Stream_Buffer(s),
if (WTSVirtualChannelRead(ainput->ainput_channel, 0, Stream_BufferAs(s, char),
(ULONG)Stream_Capacity(s), &ActualBytesReturned) == FALSE)
{
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");

View File

@ -30,6 +30,6 @@ set(${MODULE_PREFIX}_LIBS
)
include_directories(..)
include_directories(${ALSA_INCLUDE_DIRS})
include_directories(SYSTEM ${ALSA_INCLUDE_DIRS})
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")

View File

@ -75,12 +75,6 @@ static snd_pcm_format_t audin_alsa_format(UINT32 wFormatTag, UINT32 bitPerChanne
return SND_PCM_FORMAT_UNKNOWN;
}
case WAVE_FORMAT_ALAW:
return SND_PCM_FORMAT_A_LAW;
case WAVE_FORMAT_MULAW:
return SND_PCM_FORMAT_MU_LAW;
default:
return SND_PCM_FORMAT_UNKNOWN;
}
@ -121,16 +115,19 @@ static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_hand
static DWORD WINAPI audin_alsa_thread_func(LPVOID arg)
{
int error = 0;
DWORD error = CHANNEL_RC_OK;
BYTE* buffer = NULL;
snd_pcm_t* capture_handle = NULL;
AudinALSADevice* alsa = (AudinALSADevice*)arg;
DWORD status = 0;
WINPR_ASSERT(alsa);
WLog_Print(alsa->log, WLOG_DEBUG, "in");
if ((error = snd_pcm_open(&capture_handle, alsa->device_name, SND_PCM_STREAM_CAPTURE, 0)) < 0)
snd_pcm_t* capture_handle = NULL;
const int rc = snd_pcm_open(&capture_handle, alsa->device_name, SND_PCM_STREAM_CAPTURE, 0);
if (rc < 0)
{
WLog_Print(alsa->log, WLOG_ERROR, "snd_pcm_open (%s)", snd_strerror(error));
WLog_Print(alsa->log, WLOG_ERROR, "snd_pcm_open (%s)", snd_strerror(rc));
error = CHANNEL_RC_INITIALIZATION_ERROR;
goto out;
}
@ -154,35 +151,43 @@ static DWORD WINAPI audin_alsa_thread_func(LPVOID arg)
while (1)
{
size_t frames = alsa->frames_per_packet;
status = WaitForSingleObject(alsa->stopEvent, 0);
const DWORD status = WaitForSingleObject(alsa->stopEvent, 0);
if (status == WAIT_FAILED)
{
error = GetLastError();
WLog_Print(alsa->log, WLOG_ERROR, "WaitForSingleObject failed with error %ld!", error);
WLog_Print(alsa->log, WLOG_ERROR, "WaitForSingleObject failed with error %" PRIu32 "!",
error);
break;
}
if (status == WAIT_OBJECT_0)
break;
error = snd_pcm_readi(capture_handle, buffer, frames);
if (error == 0)
continue;
if (error == -EPIPE)
{
snd_pcm_recover(capture_handle, error, 0);
continue;
}
else if (error < 0)
{
WLog_Print(alsa->log, WLOG_ERROR, "snd_pcm_readi (%s)", snd_strerror(error));
WLog_Print(alsa->log, WLOG_DEBUG, "alsa->stopEvent requests termination");
break;
}
error = alsa->receive(&alsa->aformat, buffer, (long)error * alsa->bytes_per_frame,
snd_pcm_sframes_t framesRead = snd_pcm_readi(capture_handle, buffer, frames);
if (framesRead == 0)
continue;
if (framesRead == -EPIPE)
{
const int res = snd_pcm_recover(capture_handle, (int)framesRead, 0);
if (res < 0)
WLog_Print(alsa->log, WLOG_WARN, "snd_pcm_recover (%s)", snd_strerror(res));
continue;
}
else if (framesRead < 0)
{
WLog_Print(alsa->log, WLOG_ERROR, "snd_pcm_readi (%s)", snd_strerror((int)framesRead));
error = ERROR_INTERNAL_ERROR;
break;
}
error = alsa->receive(&alsa->aformat, buffer, (long)framesRead * alsa->bytes_per_frame,
alsa->user_data);
if (error)
@ -196,7 +201,11 @@ static DWORD WINAPI audin_alsa_thread_func(LPVOID arg)
free(buffer);
if (capture_handle)
snd_pcm_close(capture_handle);
{
const int res = snd_pcm_close(capture_handle);
if (res < 0)
WLog_Print(alsa->log, WLOG_WARN, "snd_pcm_close (%s)", snd_strerror(res));
}
out:
WLog_Print(alsa->log, WLOG_DEBUG, "out");
@ -299,7 +308,7 @@ static UINT audin_alsa_open(IAudinDevice* device, AudinReceive receive, void* us
return CHANNEL_RC_OK;
error_out:
CloseHandle(alsa->stopEvent);
(void)CloseHandle(alsa->stopEvent);
alsa->stopEvent = NULL;
return ERROR_INTERNAL_ERROR;
}
@ -319,7 +328,7 @@ static UINT audin_alsa_close(IAudinDevice* device)
if (alsa->stopEvent)
{
SetEvent(alsa->stopEvent);
(void)SetEvent(alsa->stopEvent);
if (WaitForSingleObject(alsa->thread, INFINITE) == WAIT_FAILED)
{
@ -329,9 +338,9 @@ static UINT audin_alsa_close(IAudinDevice* device)
return error;
}
CloseHandle(alsa->stopEvent);
(void)CloseHandle(alsa->stopEvent);
alsa->stopEvent = NULL;
CloseHandle(alsa->thread);
(void)CloseHandle(alsa->thread);
alsa->thread = NULL;
}
@ -350,7 +359,7 @@ static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, const ADDIN_ARG
int status = 0;
DWORD flags = 0;
const COMMAND_LINE_ARGUMENT_A* arg = NULL;
AudinALSADevice* alsa = (AudinALSADevice*)device;
AudinALSADevice* alsa = device;
COMMAND_LINE_ARGUMENT_A audin_alsa_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>",
NULL, NULL, -1, NULL, "audio device name" },
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } };
@ -390,8 +399,8 @@ static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, const ADDIN_ARG
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(
UINT alsa_freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints))
FREERDP_ENTRY_POINT(UINT VCAPITYPE alsa_freerdp_audin_client_subsystem_entry(
PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints))
{
const ADDIN_ARGV* args = NULL;
AudinALSADevice* alsa = NULL;

View File

@ -113,7 +113,7 @@ static UINT audin_channel_write_and_free(AUDIN_CHANNEL_CALLBACK* callback, wStre
return ERROR_INTERNAL_ERROR;
Stream_SealLength(out);
WINPR_ASSERT(Stream_Length(out) <= ULONG_MAX);
WINPR_ASSERT(Stream_Length(out) <= UINT32_MAX);
const UINT error = callback->channel->Write(callback->channel, (ULONG)Stream_Length(out),
Stream_Buffer(out), NULL);
@ -810,9 +810,9 @@ static UINT audin_load_device_plugin(AUDIN_PLUGIN* audin, const char* name, cons
FREERDP_AUDIN_DEVICE_ENTRY_POINTS entryPoints = { 0 };
UINT error = ERROR_INTERNAL_ERROR;
const PFREERDP_AUDIN_DEVICE_ENTRY entry =
(const PFREERDP_AUDIN_DEVICE_ENTRY)freerdp_load_channel_addin_entry(AUDIN_CHANNEL_NAME,
name, NULL, 0);
PVIRTUALCHANNELENTRY pvce = freerdp_load_channel_addin_entry(AUDIN_CHANNEL_NAME, name, NULL, 0);
PFREERDP_AUDIN_DEVICE_ENTRY entry = WINPR_FUNC_PTR_CAST(pvce, PFREERDP_AUDIN_DEVICE_ENTRY);
if (entry == NULL)
{
@ -827,7 +827,8 @@ static UINT audin_load_device_plugin(AUDIN_PLUGIN* audin, const char* name, cons
entryPoints.args = args;
entryPoints.rdpcontext = audin->rdpcontext;
if ((error = entry(&entryPoints)))
error = entry(&entryPoints);
if (error)
{
WLog_Print(audin->log, WLOG_ERROR, "%s entry returned error %" PRIu32 ".", name, error);
return error;
@ -940,12 +941,12 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, const ADDIN_ARGV* args)
}
CommandLineSwitchCase(arg, "rate")
{
long val = strtol(arg->Value, NULL, 0);
unsigned long val = strtoul(arg->Value, NULL, 0);
if ((errno != 0) || (val < INT32_MIN) || (val > INT32_MAX))
if ((errno != 0) || (val == 0) || (val > UINT32_MAX))
return FALSE;
audin->fixed_format->nSamplesPerSec = val;
audin->fixed_format->nSamplesPerSec = (UINT32)val;
}
CommandLineSwitchCase(arg, "channel")
{
@ -968,7 +969,7 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, const ADDIN_ARGV* args)
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(UINT audin_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
FREERDP_ENTRY_POINT(UINT VCAPITYPE audin_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
{
struct SubsystemEntry
{

View File

@ -34,6 +34,6 @@ set(${MODULE_PREFIX}_LIBS
)
include_directories(..)
include_directories(${MAC_INCLUDE_DIRS})
include_directories(SYSTEM ${MAC_INCLUDE_DIRS})
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")

View File

@ -295,8 +295,8 @@ static UINT audin_ios_free(IAudinDevice *device)
return CHANNEL_RC_OK;
}
FREERDP_ENTRY_POINT(
UINT ios_freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints))
FREERDP_ENTRY_POINT(UINT VCAPITYPE ios_freerdp_audin_client_subsystem_entry(
PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints))
{
DWORD errCode;
char errString[1024];

View File

@ -36,6 +36,6 @@ set(${MODULE_PREFIX}_LIBS
)
include_directories(..)
include_directories(${MAC_INCLUDE_DIRS})
include_directories(SYSTEM ${MAC_INCLUDE_DIRS})
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")

View File

@ -380,8 +380,8 @@ static UINT audin_mac_parse_addin_args(AudinMacDevice *device, const ADDIN_ARGV
return CHANNEL_RC_OK;
}
FREERDP_ENTRY_POINT(
UINT mac_freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints))
FREERDP_ENTRY_POINT(UINT VCAPITYPE mac_freerdp_audin_client_subsystem_entry(
PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints))
{
DWORD errCode;
char errString[1024];

View File

@ -31,6 +31,6 @@ set(${MODULE_PREFIX}_LIBS
)
include_directories(..)
include_directories(${OpenSLES_INCLUDE_DIRS})
include_directories(SYSTEM ${OpenSLES_INCLUDE_DIRS})
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")

View File

@ -292,7 +292,7 @@ static UINT audin_opensles_parse_addin_args(AudinOpenSLESDevice* device, const A
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(UINT opensles_freerdp_audin_client_subsystem_entry(
FREERDP_ENTRY_POINT(UINT VCAPITYPE opensles_freerdp_audin_client_subsystem_entry(
PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints))
{
const ADDIN_ARGV* args;

View File

@ -31,11 +31,12 @@ set(${MODULE_PREFIX}_LIBS
include_directories(..)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${OSS_INCLUDE_DIRS})
configure_file(
include_directories(SYSTEM ${OSS_INCLUDE_DIRS})
cleaning_configure_file(
${CMAKE_SOURCE_DIR}/cmake/oss-includes.h.in
${CMAKE_CURRENT_BINARY_DIR}/oss-includes.h
@ONLY
)
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")

View File

@ -85,15 +85,14 @@ static UINT32 audin_oss_get_format(const AUDIO_FORMAT* format)
case 16:
return AFMT_S16_LE;
default:
break;
}
break;
case WAVE_FORMAT_ALAW:
return AFMT_A_LAW;
case WAVE_FORMAT_MULAW:
return AFMT_MU_LAW;
default:
break;
}
return 0;
@ -160,8 +159,8 @@ static DWORD WINAPI audin_oss_thread_func(LPVOID arg)
if (oss->dev_unit != -1)
{
sprintf_s(dev_name, (PATH_MAX - 1), "/dev/dsp%i", oss->dev_unit);
sprintf_s(mixer_name, PATH_MAX - 1, "/dev/mixer%i", oss->dev_unit);
(void)sprintf_s(dev_name, (PATH_MAX - 1), "/dev/dsp%i", oss->dev_unit);
(void)sprintf_s(mixer_name, PATH_MAX - 1, "/dev/mixer%i", oss->dev_unit);
}
WLog_INFO(TAG, "open: %s", dev_name);
@ -309,7 +308,7 @@ static UINT audin_oss_open(IAudinDevice* device, AudinReceive receive, void* use
if (!(oss->thread = CreateThread(NULL, 0, audin_oss_thread_func, oss, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
CloseHandle(oss->stopEvent);
(void)CloseHandle(oss->stopEvent);
oss->stopEvent = NULL;
return ERROR_INTERNAL_ERROR;
}
@ -332,7 +331,7 @@ static UINT audin_oss_close(IAudinDevice* device)
if (oss->stopEvent != NULL)
{
SetEvent(oss->stopEvent);
(void)SetEvent(oss->stopEvent);
if (WaitForSingleObject(oss->thread, INFINITE) == WAIT_FAILED)
{
@ -341,9 +340,9 @@ static UINT audin_oss_close(IAudinDevice* device)
return error;
}
CloseHandle(oss->stopEvent);
(void)CloseHandle(oss->stopEvent);
oss->stopEvent = NULL;
CloseHandle(oss->thread);
(void)CloseHandle(oss->thread);
oss->thread = NULL;
}
@ -386,7 +385,7 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice* device, const ADDIN_ARGV*
char* eptr = NULL;
DWORD flags = 0;
const COMMAND_LINE_ARGUMENT_A* arg = NULL;
AudinOSSDevice* oss = (AudinOSSDevice*)device;
AudinOSSDevice* oss = device;
COMMAND_LINE_ARGUMENT_A audin_oss_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>",
NULL, NULL, -1, NULL, "audio device name" },
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } };
@ -445,8 +444,8 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice* device, const ADDIN_ARGV*
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(
UINT oss_freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints))
FREERDP_ENTRY_POINT(UINT VCAPITYPE oss_freerdp_audin_client_subsystem_entry(
PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints))
{
const ADDIN_ARGV* args = NULL;
AudinOSSDevice* oss = NULL;

View File

@ -30,6 +30,6 @@ set(${MODULE_PREFIX}_LIBS
)
include_directories(..)
include_directories(${PULSEAUDIO_INCLUDE_DIR})
include_directories(SYSTEM ${PULSEAUDIO_INCLUDE_DIR})
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")

View File

@ -112,9 +112,6 @@ static void audin_pulse_context_state_callback(pa_context* context, void* userda
switch (state)
{
case PA_CONTEXT_READY:
pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
case PA_CONTEXT_FAILED:
case PA_CONTEXT_TERMINATED:
pa_threaded_mainloop_signal(pulse->mainloop, 0);
@ -283,14 +280,6 @@ static UINT audin_pulse_set_format(IAudinDevice* device, const AUDIO_FORMAT* for
break;
case WAVE_FORMAT_ALAW: /* A-LAW */
sample_spec.format = PA_SAMPLE_ALAW;
break;
case WAVE_FORMAT_MULAW: /* U-LAW */
sample_spec.format = PA_SAMPLE_ULAW;
break;
default:
return ERROR_INTERNAL_ERROR;
}
@ -303,15 +292,14 @@ static UINT audin_pulse_set_format(IAudinDevice* device, const AUDIO_FORMAT* for
static void audin_pulse_stream_state_callback(pa_stream* stream, void* userdata)
{
AudinPulseDevice* pulse = (AudinPulseDevice*)userdata;
WINPR_ASSERT(pulse);
pa_stream_state_t state = pa_stream_get_state(stream);
WLog_Print(pulse->log, WLOG_DEBUG, "stream state %s", pulse_stream_state_string(state));
switch (state)
{
case PA_STREAM_READY:
pa_threaded_mainloop_signal(pulse->mainloop, 0);
break;
case PA_STREAM_FAILED:
case PA_STREAM_TERMINATED:
pa_threaded_mainloop_signal(pulse->mainloop, 0);
@ -405,7 +393,9 @@ static UINT audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u
buffer_attr.prebuf = (UINT32)-1;
buffer_attr.minreq = (UINT32)-1;
/* 500ms latency */
buffer_attr.fragsize = pulse->bytes_per_frame * pulse->frames_per_packet;
const size_t frag = pulse->bytes_per_frame * pulse->frames_per_packet;
WINPR_ASSERT(frag <= UINT32_MAX);
buffer_attr.fragsize = (uint32_t)frag;
if (buffer_attr.fragsize % pulse->format.nBlockAlign)
buffer_attr.fragsize +=
@ -420,7 +410,7 @@ static UINT audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u
return pa_context_errno(pulse->context);
}
for (;;)
while (pulse->stream)
{
state = pa_stream_get_state(pulse->stream);
@ -455,7 +445,7 @@ static UINT audin_pulse_parse_addin_args(AudinPulseDevice* device, const ADDIN_A
int status = 0;
DWORD flags = 0;
const COMMAND_LINE_ARGUMENT_A* arg = NULL;
AudinPulseDevice* pulse = (AudinPulseDevice*)device;
AudinPulseDevice* pulse = device;
COMMAND_LINE_ARGUMENT_A audin_pulse_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>",
NULL, NULL, -1, NULL, "audio device name" },
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } };
@ -496,7 +486,7 @@ static UINT audin_pulse_parse_addin_args(AudinPulseDevice* device, const ADDIN_A
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(UINT pulse_freerdp_audin_client_subsystem_entry(
FREERDP_ENTRY_POINT(UINT VCAPITYPE pulse_freerdp_audin_client_subsystem_entry(
PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints))
{
const ADDIN_ARGV* args = NULL;

View File

@ -30,7 +30,7 @@ set(${MODULE_PREFIX}_LIBS
)
include_directories(..)
include_directories(${SNDIO_INCLUDE_DIRS})
include_directories(SYSTEM ${SNDIO_INCLUDE_DIRS})
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")

View File

@ -204,7 +204,7 @@ static UINT audin_sndio_open(IAudinDevice* device, AudinReceive receive, void* u
sndio, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed");
CloseHandle(sndio->stopEvent);
(void)CloseHandle(sndio->stopEvent);
sndio->stopEvent = NULL;
return ERROR_INTERNAL_ERROR;
}
@ -227,7 +227,7 @@ static UINT audin_sndio_close(IAudinDevice* device)
if (sndio->stopEvent != NULL)
{
SetEvent(sndio->stopEvent);
(void)SetEvent(sndio->stopEvent);
if (WaitForSingleObject(sndio->thread, INFINITE) == WAIT_FAILED)
{
@ -236,9 +236,9 @@ static UINT audin_sndio_close(IAudinDevice* device)
return error;
}
CloseHandle(sndio->stopEvent);
(void)CloseHandle(sndio->stopEvent);
sndio->stopEvent = NULL;
CloseHandle(sndio->thread);
(void)CloseHandle(sndio->thread);
sndio->thread = NULL;
}
@ -309,7 +309,7 @@ static UINT audin_sndio_parse_addin_args(AudinSndioDevice* device, ADDIN_ARGV* a
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(UINT sndio_freerdp_audin_client_subsystem_entry(
FREERDP_ENTRY_POINT(UINT VCAPITYPE sndio_freerdp_audin_client_subsystem_entry(
PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints))
{
ADDIN_ARGV* args;

View File

@ -29,6 +29,7 @@
#include <mmsystem.h>
#include <winpr/crt.h>
#include <winpr/wtsapi.h>
#include <winpr/cmdline.h>
#include <freerdp/freerdp.h>
#include <freerdp/addin.h>
@ -176,7 +177,6 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg)
if (!winmm->hWaveIn)
{
MMRESULT rc;
rc = waveInOpen(&winmm->hWaveIn, WAVE_MAPPER, winmm->pwfx_cur, (DWORD_PTR)waveInProc,
(DWORD_PTR)winmm,
CALLBACK_FUNCTION | WAVE_MAPPED_DEFAULT_COMMUNICATION_DEVICE);
@ -293,7 +293,7 @@ static UINT audin_winmm_close(IAudinDevice* device)
if (!winmm)
return ERROR_INVALID_PARAMETER;
SetEvent(winmm->stopEvent);
(void)SetEvent(winmm->stopEvent);
status = WaitForSingleObject(winmm->thread, INFINITE);
if (status == WAIT_FAILED)
@ -304,8 +304,8 @@ static UINT audin_winmm_close(IAudinDevice* device)
return error;
}
CloseHandle(winmm->thread);
CloseHandle(winmm->stopEvent);
(void)CloseHandle(winmm->thread);
(void)CloseHandle(winmm->stopEvent);
winmm->thread = NULL;
winmm->stopEvent = NULL;
winmm->receive = NULL;
@ -436,7 +436,7 @@ static UINT audin_winmm_open(IAudinDevice* device, AudinReceive receive, void* u
if (!(winmm->thread = CreateThread(NULL, 0, audin_winmm_thread_func, winmm, 0, NULL)))
{
WLog_Print(winmm->log, WLOG_ERROR, "CreateThread failed!");
CloseHandle(winmm->stopEvent);
(void)CloseHandle(winmm->stopEvent);
winmm->stopEvent = NULL;
return ERROR_INTERNAL_ERROR;
}
@ -491,7 +491,7 @@ static UINT audin_winmm_parse_addin_args(AudinWinmmDevice* device, const ADDIN_A
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(UINT winmm_freerdp_audin_client_subsystem_entry(
FREERDP_ENTRY_POINT(UINT VCAPITYPE winmm_freerdp_audin_client_subsystem_entry(
PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints))
{
const ADDIN_ARGV* args;

View File

@ -378,8 +378,8 @@ static DWORD WINAPI audin_server_thread_func(LPVOID arg)
if (!Stream_EnsureRemainingCapacity(s, BytesReturned))
break;
WINPR_ASSERT(Stream_Capacity(s) <= ULONG_MAX);
if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR)Stream_Buffer(s),
WINPR_ASSERT(Stream_Capacity(s) <= UINT32_MAX);
if (WTSVirtualChannelRead(audin->audin_channel, 0, Stream_BufferAs(s, char),
(ULONG)Stream_Capacity(s), &BytesReturned) == FALSE)
{
WLog_Print(audin->log, WLOG_ERROR, "WTSVirtualChannelRead failed!");
@ -430,7 +430,7 @@ static DWORD WINAPI audin_server_thread_func(LPVOID arg)
out_capacity:
Stream_Free(s, TRUE);
out:
WTSVirtualChannelClose(audin->audin_channel);
(void)WTSVirtualChannelClose(audin->audin_channel);
audin->audin_channel = NULL;
if (error && audin->context.rdpcontext)
@ -489,7 +489,7 @@ static BOOL audin_server_open(audin_server_context* context)
CreateThread(NULL, 0, audin_server_thread_func, (void*)audin, 0, NULL)))
{
WLog_Print(audin->log, WLOG_ERROR, "CreateThread failed!");
CloseHandle(audin->stopEvent);
(void)CloseHandle(audin->stopEvent);
audin->stopEvent = NULL;
return FALSE;
}
@ -516,7 +516,7 @@ static BOOL audin_server_close(audin_server_context* context)
if (audin->thread)
{
SetEvent(audin->stopEvent);
(void)SetEvent(audin->stopEvent);
if (WaitForSingleObject(audin->thread, INFINITE) == WAIT_FAILED)
{
@ -525,15 +525,15 @@ static BOOL audin_server_close(audin_server_context* context)
return FALSE;
}
CloseHandle(audin->thread);
CloseHandle(audin->stopEvent);
(void)CloseHandle(audin->thread);
(void)CloseHandle(audin->stopEvent);
audin->thread = NULL;
audin->stopEvent = NULL;
}
if (audin->audin_channel)
{
WTSVirtualChannelClose(audin->audin_channel);
(void)WTSVirtualChannelClose(audin->audin_channel);
audin->audin_channel = NULL;
}
@ -569,10 +569,8 @@ static UINT audin_server_packet_send(audin_server_context* context, wStream* s)
WINPR_ASSERT(s);
const size_t pos = Stream_GetPosition(s);
if (pos > UINT32_MAX)
return ERROR_INVALID_PARAMETER;
if (!WTSVirtualChannelWrite(audin->audin_channel, (PCHAR)Stream_Buffer(s), (UINT32)pos,
WINPR_ASSERT(pos <= UINT32_MAX);
if (!WTSVirtualChannelWrite(audin->audin_channel, Stream_BufferAs(s, char), (UINT32)pos,
&written))
{
WLog_Print(audin->log, WLOG_ERROR, "WTSVirtualChannelWrite failed!");

View File

@ -2,6 +2,8 @@
# FreeRDP cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
# Copyright 2024 Armin Novak <anovak@thincast.com>
# Copyright 2024 Thincast Technologies GmbH
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -29,23 +31,13 @@ if(CHANNEL_STATIC_CLIENT_ENTRIES)
list(REMOVE_DUPLICATES CHANNEL_STATIC_CLIENT_ENTRIES)
endif()
set(CLIENT_STATIC_TYPEDEFS "#if __GNUC__\n")
set(CLIENT_STATIC_TYPEDEFS "${CLIENT_STATIC_TYPEDEFS}#pragma GCC diagnostic push\n")
set(CLIENT_STATIC_TYPEDEFS "${CLIENT_STATIC_TYPEDEFS}#pragma GCC diagnostic ignored \"-Wstrict-prototypes\"\n")
set(CLIENT_STATIC_TYPEDEFS "${CLIENT_STATIC_TYPEDEFS}#endif\n")
set(CLIENT_STATIC_TYPEDEFS "${CLIENT_STATIC_TYPEDEFS}typedef UINT (*static_entry_fkt)();\n")
set(CLIENT_STATIC_TYPEDEFS "${CLIENT_STATIC_TYPEDEFS}typedef UINT (*static_addin_fkt)();\n")
set(CLIENT_STATIC_TYPEDEFS "${CLIENT_STATIC_TYPEDEFS}#if __GNUC__\n")
set(CLIENT_STATIC_TYPEDEFS "${CLIENT_STATIC_TYPEDEFS}#pragma GCC diagnostic pop\n")
set(CLIENT_STATIC_TYPEDEFS "${CLIENT_STATIC_TYPEDEFS}#endif\n")
foreach(STATIC_ENTRY ${CHANNEL_STATIC_CLIENT_ENTRIES})
foreach(STATIC_MODULE ${CHANNEL_STATIC_CLIENT_MODULES})
foreach(ENTRY ${${STATIC_MODULE}_CLIENT_ENTRY})
if(${ENTRY} STREQUAL ${STATIC_ENTRY})
set(STATIC_MODULE_NAME ${${STATIC_MODULE}_CLIENT_NAME})
set(STATIC_MODULE_CHANNEL ${${STATIC_MODULE}_CLIENT_CHANNEL})
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${STATIC_MODULE_NAME})
list(APPEND ${MODULE_PREFIX}_LIBS ${STATIC_MODULE_NAME})
set(ENTRY_POINT_NAME "${STATIC_MODULE_CHANNEL}_${ENTRY}")
if(${ENTRY} STREQUAL "VirtualChannelEntry")
@ -53,32 +45,54 @@ foreach(STATIC_ENTRY ${CHANNEL_STATIC_CLIENT_ENTRIES})
elseif(${ENTRY} STREQUAL "VirtualChannelEntryEx")
set(ENTRY_POINT_IMPORT "extern BOOL VCAPITYPE ${ENTRY_POINT_NAME}(PCHANNEL_ENTRY_POINTS,PVOID);")
elseif(${ENTRY} MATCHES "DVCPluginEntry$")
set(ENTRY_POINT_IMPORT "extern UINT ${ENTRY_POINT_NAME}(IDRDYNVC_ENTRY_POINTS* pEntryPoints);")
set(ENTRY_POINT_IMPORT "extern UINT VCAPITYPE ${ENTRY_POINT_NAME}(IDRDYNVC_ENTRY_POINTS* pEntryPoints);")
elseif(${ENTRY} MATCHES "DeviceServiceEntry$")
set(ENTRY_POINT_IMPORT "extern UINT ${ENTRY_POINT_NAME}(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints);")
set(ENTRY_POINT_IMPORT "extern UINT VCAPITYPE ${ENTRY_POINT_NAME}(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints);")
else()
set(ENTRY_POINT_IMPORT "extern UINT ${ENTRY_POINT_NAME}(void);")
set(ENTRY_POINT_IMPORT "extern UINT VCAPITYPE ${ENTRY_POINT_NAME}(void);")
endif()
set(${STATIC_ENTRY}_IMPORTS "${${STATIC_ENTRY}_IMPORTS}\n${ENTRY_POINT_IMPORT}")
set(${STATIC_ENTRY}_TABLE "${${STATIC_ENTRY}_TABLE}\n\t{ \"${STATIC_MODULE_CHANNEL}\", (static_entry_fkt)${ENTRY_POINT_NAME} },")
string(APPEND ${STATIC_ENTRY}_IMPORTS "\n${ENTRY_POINT_IMPORT}")
string(APPEND ${STATIC_ENTRY}_TABLE "\n\t{ \"${STATIC_MODULE_CHANNEL}\", ${ENTRY_POINT_NAME} },")
endif()
endforeach()
endforeach()
endforeach()
set(CLIENT_STATIC_ENTRY_TABLES_LIST "${CLIENT_STATIC_ENTRY_TABLES_LIST}\nextern const STATIC_ENTRY_TABLE CLIENT_STATIC_ENTRY_TABLES[];\nconst STATIC_ENTRY_TABLE CLIENT_STATIC_ENTRY_TABLES[] =\n{")
string(APPEND CLIENT_STATIC_ENTRY_TABLES_LIST "\nextern const STATIC_ENTRY_TABLE CLIENT_STATIC_ENTRY_TABLES[];\n")
string(APPEND CLIENT_STATIC_ENTRY_TABLES_LIST "const STATIC_ENTRY_TABLE CLIENT_STATIC_ENTRY_TABLES[] =\n{")
foreach(STATIC_ENTRY ${CHANNEL_STATIC_CLIENT_ENTRIES})
set(CLIENT_STATIC_ENTRY_IMPORTS "${CLIENT_STATIC_ENTRY_IMPORTS}\n${${STATIC_ENTRY}_IMPORTS}")
set(CLIENT_STATIC_ENTRY_TABLES "${CLIENT_STATIC_ENTRY_TABLES}\nextern const STATIC_ENTRY CLIENT_${STATIC_ENTRY}_TABLE[];\nconst STATIC_ENTRY CLIENT_${STATIC_ENTRY}_TABLE[] =\n{")
set(CLIENT_STATIC_ENTRY_TABLES "${CLIENT_STATIC_ENTRY_TABLES}\n${${STATIC_ENTRY}_TABLE}")
set(CLIENT_STATIC_ENTRY_TABLES "${CLIENT_STATIC_ENTRY_TABLES}\n\t{ NULL, NULL }\n};")
set(CLIENT_STATIC_ENTRY_TABLES_LIST "${CLIENT_STATIC_ENTRY_TABLES_LIST}\n\t{ \"${STATIC_ENTRY}\", CLIENT_${STATIC_ENTRY}_TABLE },")
if(${STATIC_ENTRY} STREQUAL "VirtualChannelEntry")
set(CLIENT_STATIC_ENTRY_TYPE "STATIC_ENTRY_VC")
set(CLIENT_STATIC_ENTRY_INITIALIZER ".csevc")
elseif(${STATIC_ENTRY} STREQUAL "VirtualChannelEntryEx")
set(CLIENT_STATIC_ENTRY_TYPE "STATIC_ENTRY_VCEX")
set(CLIENT_STATIC_ENTRY_INITIALIZER ".csevcex")
elseif(${STATIC_ENTRY} MATCHES "DVCPluginEntry$")
set(CLIENT_STATIC_ENTRY_TYPE "STATIC_ENTRY_DVC")
set(CLIENT_STATIC_ENTRY_INITIALIZER ".csedvc")
elseif(${STATIC_ENTRY} MATCHES "DeviceServiceEntry$")
set(CLIENT_STATIC_ENTRY_TYPE "STATIC_ENTRY_DSE")
set(CLIENT_STATIC_ENTRY_INITIALIZER ".csedse")
else()
set(CLIENT_STATIC_ENTRY_TYPE "STATIC_ENTRY")
set(CLIENT_STATIC_ENTRY_INITIALIZER ".cse")
endif()
string(APPEND CLIENT_STATIC_ENTRY_TABLES "\nextern const ${CLIENT_STATIC_ENTRY_TYPE} CLIENT_${STATIC_ENTRY}_TABLE[];\n")
string(APPEND CLIENT_STATIC_ENTRY_TABLES "const ${CLIENT_STATIC_ENTRY_TYPE} CLIENT_${STATIC_ENTRY}_TABLE[] =\n{")
string(APPEND CLIENT_STATIC_ENTRY_TABLES "\n${${STATIC_ENTRY}_TABLE}")
string(APPEND CLIENT_STATIC_ENTRY_TABLES "\n\t{ NULL, NULL }\n};")
string(APPEND CLIENT_STATIC_ENTRY_TABLES_LIST "\n\t{ \"${STATIC_ENTRY}\", { ${CLIENT_STATIC_ENTRY_INITIALIZER} = CLIENT_${STATIC_ENTRY}_TABLE } },")
endforeach()
set(CLIENT_STATIC_ENTRY_TABLES_LIST "${CLIENT_STATIC_ENTRY_TABLES_LIST}\n\t{ NULL, NULL }\n};")
string(APPEND CLIENT_STATIC_ENTRY_TABLES_LIST "\n\t{ NULL, { .cse = NULL } }\n};")
set(CLIENT_STATIC_ADDIN_TABLE "extern const STATIC_ADDIN_TABLE CLIENT_STATIC_ADDIN_TABLE[];\n")
string(APPEND CLIENT_STATIC_ADDIN_TABLE "const STATIC_ADDIN_TABLE CLIENT_STATIC_ADDIN_TABLE[] =\n{")
set(CLIENT_STATIC_ADDIN_TABLE "extern const STATIC_ADDIN_TABLE CLIENT_STATIC_ADDIN_TABLE[];\nconst STATIC_ADDIN_TABLE CLIENT_STATIC_ADDIN_TABLE[] =\n{")
foreach(STATIC_MODULE ${CHANNEL_STATIC_CLIENT_MODULES})
set(STATIC_MODULE_NAME ${${STATIC_MODULE}_CLIENT_NAME})
set(STATIC_MODULE_CHANNEL ${${STATIC_MODULE}_CLIENT_CHANNEL})
@ -98,26 +112,38 @@ foreach(STATIC_MODULE ${CHANNEL_STATIC_CLIENT_MODULES})
endif()
string(LENGTH "${STATIC_SUBSYSTEM_TYPE}" _type_length)
set(SUBSYSTEM_MODULE_NAME "${STATIC_MODULE_NAME}-${STATIC_SUBSYSTEM}")
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${SUBSYSTEM_MODULE_NAME})
list(APPEND ${MODULE_PREFIX}_LIBS ${SUBSYSTEM_MODULE_NAME})
if(_type_length GREATER 0)
set(STATIC_SUBSYSTEM_ENTRY "${STATIC_SUBSYSTEM_NAME}_freerdp_${STATIC_MODULE_CHANNEL}_client_${STATIC_SUBSYSTEM_TYPE}_subsystem_entry")
else()
set(STATIC_SUBSYSTEM_ENTRY "${STATIC_SUBSYSTEM_NAME}_freerdp_${STATIC_MODULE_CHANNEL}_client_subsystem_entry")
endif()
set(SUBSYSTEM_TABLE "${SUBSYSTEM_TABLE}\n\t{ \"${STATIC_SUBSYSTEM_NAME}\", \"${STATIC_SUBSYSTEM_TYPE}\", ${STATIC_SUBSYSTEM_ENTRY} },")
set(SUBSYSTEM_IMPORT "extern UINT ${STATIC_SUBSYSTEM_ENTRY}(void*);")
set(CLIENT_STATIC_SUBSYSTEM_IMPORTS "${CLIENT_STATIC_SUBSYSTEM_IMPORTS}\n${SUBSYSTEM_IMPORT}")
string(APPEND SUBSYSTEM_TABLE "\n\t{ \"${STATIC_SUBSYSTEM_NAME}\", \"${STATIC_SUBSYSTEM_TYPE}\", ${STATIC_SUBSYSTEM_ENTRY} },")
set(SUBSYSTEM_IMPORT "extern UINT VCAPITYPE ${STATIC_SUBSYSTEM_ENTRY}(void*);")
string(APPEND CLIENT_STATIC_SUBSYSTEM_IMPORTS "\n${SUBSYSTEM_IMPORT}")
endforeach()
set(SUBSYSTEM_TABLE "${SUBSYSTEM_TABLE}\n\t{ NULL, NULL, NULL }\n};")
set(CLIENT_STATIC_SUBSYSTEM_TABLES "${CLIENT_STATIC_SUBSYSTEM_TABLES}\n${SUBSYSTEM_TABLE}")
string(APPEND SUBSYSTEM_TABLE "\n\t{ NULL, NULL, NULL }\n};")
string(APPEND CLIENT_STATIC_SUBSYSTEM_TABLES "\n${SUBSYSTEM_TABLE}")
foreach(ENTRY ${${STATIC_MODULE}_CLIENT_ENTRY})
set (ENTRY_POINT_NAME ${STATIC_MODULE_CHANNEL}_${ENTRY})
set(CLIENT_STATIC_ADDIN_TABLE "${CLIENT_STATIC_ADDIN_TABLE}\n\t{ \"${STATIC_MODULE_CHANNEL}\", \"${ENTRY}\", (static_addin_fkt)${ENTRY_POINT_NAME}, ${SUBSYSTEM_TABLE_NAME} },")
if(${ENTRY} STREQUAL "VirtualChannelEntry")
set(ENTRY_INITIALIZER ".csevc")
elseif(${ENTRY} STREQUAL "VirtualChannelEntryEx")
set(ENTRY_INITIALIZER ".csevcex")
elseif(${ENTRY} MATCHES "DVCPluginEntry$")
set(ENTRY_INITIALIZER ".csedvc")
elseif(${ENTRY} MATCHES "DeviceServiceEntry$")
set(ENTRY_INITIALIZER ".csedse")
else()
set(ENTRY_INITIALIZER ".cse")
endif()
string(APPEND CLIENT_STATIC_ADDIN_TABLE "\n\t{ \"${STATIC_MODULE_CHANNEL}\", \"${ENTRY}\", { ${ENTRY_INITIALIZER} = ${ENTRY_POINT_NAME} }, ${SUBSYSTEM_TABLE_NAME} },")
endforeach()
endforeach()
set(CLIENT_STATIC_ADDIN_TABLE "${CLIENT_STATIC_ADDIN_TABLE}\n\t{ NULL, NULL, NULL, NULL }\n};")
string(APPEND CLIENT_STATIC_ADDIN_TABLE "\n\t{ NULL, NULL, { .cse = NULL }, NULL }\n};")
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tables.c.in ${CMAKE_CURRENT_BINARY_DIR}/tables.c)
cleaning_configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tables.c.in ${CMAKE_CURRENT_BINARY_DIR}/tables.c)
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} freerdp winpr)

View File

@ -48,16 +48,15 @@ static void* freerdp_channels_find_static_entry_in_table(const STATIC_ENTRY_TABL
const char* identifier)
{
size_t index = 0;
const STATIC_ENTRY* pEntry = (const STATIC_ENTRY*)&table->table[index++];
const STATIC_ENTRY* pEntry = &table->table.cse[index++];
while (pEntry->entry != NULL)
{
static_entry_fn_t fkt = pEntry->entry;
if (strcmp(pEntry->name, identifier) == 0)
{
return (void*)pEntry->entry;
}
return WINPR_FUNC_PTR_CAST(fkt, void*);
pEntry = (const STATIC_ENTRY*)&table->table[index++];
pEntry = &table->table.cse[index++];
}
return NULL;
@ -68,7 +67,7 @@ void* freerdp_channels_client_find_static_entry(const char* name, const char* id
size_t index = 0;
const STATIC_ENTRY_TABLE* pEntry = &CLIENT_STATIC_ENTRY_TABLES[index++];
while (pEntry->table != NULL)
while (pEntry->table.cse != NULL)
{
if (strcmp(pEntry->name, name) == 0)
{
@ -111,7 +110,7 @@ static FREERDP_ADDIN** freerdp_channels_list_client_static_addins(LPCSTR pszName
goto error_out;
}
sprintf_s(pAddin->cName, ARRAYSIZE(pAddin->cName), "%s", table->name);
(void)sprintf_s(pAddin->cName, ARRAYSIZE(pAddin->cName), "%s", table->name);
pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
pAddin->dwFlags |= FREERDP_ADDIN_STATIC;
pAddin->dwFlags |= FREERDP_ADDIN_NAME;
@ -128,8 +127,9 @@ static FREERDP_ADDIN** freerdp_channels_list_client_static_addins(LPCSTR pszName
goto error_out;
}
sprintf_s(pAddin->cName, ARRAYSIZE(pAddin->cName), "%s", table->name);
sprintf_s(pAddin->cSubsystem, ARRAYSIZE(pAddin->cSubsystem), "%s", subsystems[j].name);
(void)sprintf_s(pAddin->cName, ARRAYSIZE(pAddin->cName), "%s", table->name);
(void)sprintf_s(pAddin->cSubsystem, ARRAYSIZE(pAddin->cSubsystem), "%s",
subsystems[j].name);
pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
pAddin->dwFlags |= FREERDP_ADDIN_STATIC;
pAddin->dwFlags |= FREERDP_ADDIN_NAME;
@ -190,23 +190,23 @@ static FREERDP_ADDIN** freerdp_channels_list_dynamic_addins(LPCSTR pszName, LPCS
if (pszName && pszSubsystem && pszType)
{
sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX "%s-client-%s-%s.%s",
pszName, pszSubsystem, pszType, pszExtension);
(void)sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX "%s-client-%s-%s.%s",
pszName, pszSubsystem, pszType, pszExtension);
}
else if (pszName && pszType)
{
sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX "%s-client-?-%s.%s",
pszName, pszType, pszExtension);
(void)sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX "%s-client-?-%s.%s",
pszName, pszType, pszExtension);
}
else if (pszName)
{
sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX "%s-client*.%s", pszName,
pszExtension);
(void)sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX "%s-client*.%s",
pszName, pszExtension);
}
else
{
sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX "?-client*.%s",
pszExtension);
(void)sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX "?-client*.%s",
pszExtension);
}
cchPattern = strnlen(pszPattern, cchPattern);
@ -473,7 +473,7 @@ PVIRTUALCHANNELENTRY freerdp_channels_load_static_addin_entry(LPCSTR pszName, LP
{
if (strncmp(table->name, pszName, MAX_PATH) == 0)
{
if (type && strncmp(table->type, type, MAX_PATH))
if (type && (strncmp(table->type, type, MAX_PATH) != 0))
continue;
if (pszSubsystem != NULL)
@ -487,15 +487,15 @@ PVIRTUALCHANNELENTRY freerdp_channels_load_static_addin_entry(LPCSTR pszName, LP
0) || /* we only want to know if strnlen is > 0 */
(strncmp(subsystems->name, pszSubsystem, MAX_PATH) == 0))
{
static_subsystem_entry_fn_t fkt = subsystems->entry;
if (pszType)
{
if (strncmp(subsystems->type, pszType, MAX_PATH) == 0)
return (PVIRTUALCHANNELENTRY)subsystems->entry;
return WINPR_FUNC_PTR_CAST(fkt, PVIRTUALCHANNELENTRY);
}
else
{
return (PVIRTUALCHANNELENTRY)subsystems->entry;
}
return WINPR_FUNC_PTR_CAST(fkt, PVIRTUALCHANNELENTRY);
}
}
}
@ -507,7 +507,7 @@ PVIRTUALCHANNELENTRY freerdp_channels_load_static_addin_entry(LPCSTR pszName, LP
return NULL;
}
return (PVIRTUALCHANNELENTRY)table->entry;
return table->entry.csevc;
}
}
}
@ -567,10 +567,10 @@ static DWORD WINAPI channel_client_thread_proc(LPVOID userdata)
if (error && internals->ctx)
{
char msg[128];
_snprintf(msg, 127,
"%s_virtual_channel_client_thread reported an"
" error",
internals->channel_name);
(void)_snprintf(msg, 127,
"%s_virtual_channel_client_thread reported an"
" error",
internals->channel_name);
setChannelError(internals->ctx, error, msg);
}
ExitThread(error);
@ -594,7 +594,7 @@ static void channel_client_handler_free(msg_proc_internals* internals)
return;
if (internals->thread)
CloseHandle(internals->thread);
(void)CloseHandle(internals->thread);
MessageQueue_Free(internals->queue);
Stream_Free(internals->data_in, TRUE);
free(internals->channel_name);
@ -696,7 +696,8 @@ UINT channel_client_post_message(void* MsgsHandle, LPVOID pData, UINT32 dataLeng
if (Stream_Capacity(data_in) != Stream_GetPosition(data_in))
{
char msg[128];
_snprintf(msg, 127, "%s_plugin_process_received: read error", internals->channel_name);
(void)_snprintf(msg, 127, "%s_plugin_process_received: read error",
internals->channel_name);
WLog_ERR(TAG, msg);
return ERROR_INTERNAL_ERROR;
}

View File

@ -25,9 +25,9 @@
${CLIENT_STATIC_TYPEDEFS}
${CLIENT_STATIC_ENTRY_IMPORTS}
${CLIENT_STATIC_SUBSYSTEM_IMPORTS}
${CLIENT_STATIC_ENTRY_TABLES}
${CLIENT_STATIC_ENTRY_TABLES_LIST}
${CLIENT_STATIC_SUBSYSTEM_IMPORTS}
${CLIENT_STATIC_SUBSYSTEM_TABLES}
${CLIENT_STATIC_ADDIN_TABLE}

View File

@ -18,36 +18,87 @@
*/
#include <winpr/platform.h>
#include <winpr/wtsapi.h>
#include <freerdp/svc.h>
#include <freerdp/dvc.h>
#include <freerdp/channels/rdpdr.h>
/* The 'entry' function pointers have variable arguments. */
WINPR_PRAGMA_DIAG_PUSH
WINPR_PRAGMA_DIAG_IGNORED_STRICT_PROTOTYPES
typedef UINT(VCAPITYPE* static_entry_fn_t)();
typedef struct
{
const char* name;
UINT (*entry)();
static_entry_fn_t entry;
} STATIC_ENTRY;
typedef BOOL(VCAPITYPE* static_entry_vc_fn_t)(PCHANNEL_ENTRY_POINTS);
typedef struct
{
const char* name;
const STATIC_ENTRY* table;
static_entry_vc_fn_t entry;
} STATIC_ENTRY_VC;
typedef BOOL(VCAPITYPE* static_entry_vcex_fn_t)(PCHANNEL_ENTRY_POINTS, PVOID);
typedef struct
{
const char* name;
static_entry_vcex_fn_t entry;
} STATIC_ENTRY_VCEX;
typedef UINT(VCAPITYPE* static_entry_dvc_fn_t)(IDRDYNVC_ENTRY_POINTS*);
typedef struct
{
const char* name;
static_entry_dvc_fn_t entry;
} STATIC_ENTRY_DVC;
typedef UINT(VCAPITYPE* static_entry_dse_fn_t)(PDEVICE_SERVICE_ENTRY_POINTS);
typedef struct
{
const char* name;
static_entry_dse_fn_t entry;
} STATIC_ENTRY_DSE;
typedef union
{
const STATIC_ENTRY* cse;
const STATIC_ENTRY_VC* csevc;
const STATIC_ENTRY_VCEX* csevcex;
const STATIC_ENTRY_DVC* csedvc;
const STATIC_ENTRY_DSE* csedse;
} static_entry_u;
typedef union
{
static_entry_fn_t cse;
static_entry_vc_fn_t csevc;
static_entry_vcex_fn_t csevcex;
static_entry_dvc_fn_t csedvc;
static_entry_dse_fn_t csedse;
} static_entry_fn_u;
typedef struct
{
const char* name;
static_entry_u table;
} STATIC_ENTRY_TABLE;
typedef UINT(VCAPITYPE* static_subsystem_entry_fn_t)(void*);
typedef struct
{
const char* name;
const char* type;
UINT (*entry)();
static_subsystem_entry_fn_t entry;
} STATIC_SUBSYSTEM_ENTRY;
typedef struct
{
const char* name;
const char* type;
UINT (*entry)();
static_entry_fn_u entry;
const STATIC_SUBSYSTEM_ENTRY* table;
} STATIC_ADDIN_TABLE;

View File

@ -98,7 +98,8 @@ CLIPRDR_FORMAT_LIST cliprdr_filter_format_list(const CLIPRDR_FORMAT_LIST* list,
}
}
}
filtered.numFormats = wpos;
WINPR_ASSERT(wpos <= UINT32_MAX);
filtered.numFormats = (UINT32)wpos;
return filtered;
}

View File

@ -38,8 +38,8 @@
#include "cliprdr_format.h"
#include "../cliprdr_common.h"
const char* type_FileGroupDescriptorW = "FileGroupDescriptorW";
const char* type_FileContents = "FileContents";
const char type_FileGroupDescriptorW[] = "FileGroupDescriptorW";
const char type_FileContents[] = "FileContents";
CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr)
{
@ -59,17 +59,17 @@ CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr)
*/
static UINT cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* s)
{
size_t pos = 0;
UINT32 dataLen = 0;
UINT status = CHANNEL_RC_OK;
WINPR_ASSERT(cliprdr);
WINPR_ASSERT(s);
pos = Stream_GetPosition(s);
dataLen = pos - 8;
const size_t pos = Stream_GetPosition(s);
const size_t dataLen = pos - 8;
WINPR_ASSERT(dataLen <= UINT32_MAX);
Stream_SetPosition(s, 4);
Stream_Write_UINT32(s, dataLen);
Stream_Write_UINT32(s, (UINT32)dataLen);
Stream_SetPosition(s, pos);
WLog_DBG(TAG, "Cliprdr Sending (%" PRIu32 " bytes)", dataLen + 8);
@ -677,7 +677,7 @@ static UINT cliprdr_client_format_list(CliprdrClientContext* context,
}
cliprdr->initialFormatListSent = TRUE;
s = cliprdr_packet_format_list_new(&filterList, cliprdr->useLongFormatNames);
s = cliprdr_packet_format_list_new(&filterList, cliprdr->useLongFormatNames, FALSE);
cliprdr_free_format_list(&filterList);
if (!s)
@ -790,13 +790,10 @@ cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context,
static UINT cliprdr_client_format_data_request(CliprdrClientContext* context,
const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest)
{
wStream* s = NULL;
cliprdrPlugin* cliprdr = NULL;
WINPR_ASSERT(context);
WINPR_ASSERT(formatDataRequest);
cliprdr = (cliprdrPlugin*)context->handle;
cliprdrPlugin* cliprdr = (cliprdrPlugin*)context->handle;
WINPR_ASSERT(cliprdr);
const UINT32 mask =
@ -806,8 +803,8 @@ static UINT cliprdr_client_format_data_request(CliprdrClientContext* context,
WLog_WARN(TAG, "remote -> local copy disabled, ignoring request");
return CHANNEL_RC_OK;
}
s = cliprdr_packet_new(CB_FORMAT_DATA_REQUEST, 0, 4);
wStream* s = cliprdr_packet_new(CB_FORMAT_DATA_REQUEST, 0, 4);
if (!s)
{
WLog_ERR(TAG, "cliprdr_packet_new failed!");
@ -815,7 +812,8 @@ static UINT cliprdr_client_format_data_request(CliprdrClientContext* context,
}
Stream_Write_UINT32(s, formatDataRequest->requestedFormatId); /* requestedFormatId (4 bytes) */
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatDataRequest");
WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatDataRequest(0x%08" PRIx32 ")",
formatDataRequest->requestedFormatId);
return cliprdr_packet_send(cliprdr, s);
}
@ -828,21 +826,18 @@ static UINT
cliprdr_client_format_data_response(CliprdrClientContext* context,
const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse)
{
wStream* s = NULL;
cliprdrPlugin* cliprdr = NULL;
WINPR_ASSERT(context);
WINPR_ASSERT(formatDataResponse);
cliprdr = (cliprdrPlugin*)context->handle;
cliprdrPlugin* cliprdr = (cliprdrPlugin*)context->handle;
WINPR_ASSERT(cliprdr);
const UINT32 mask =
freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask);
WINPR_ASSERT((mask & (CLIPRDR_FLAG_LOCAL_TO_REMOTE | CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES)) != 0);
WINPR_ASSERT(
(freerdp_settings_get_uint32(context->rdpcontext->settings, FreeRDP_ClipboardFeatureMask) &
(CLIPRDR_FLAG_LOCAL_TO_REMOTE | CLIPRDR_FLAG_LOCAL_TO_REMOTE_FILES)) != 0);
s = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE, formatDataResponse->common.msgFlags,
formatDataResponse->common.dataLen);
wStream* s = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE, formatDataResponse->common.msgFlags,
formatDataResponse->common.dataLen);
if (!s)
{
@ -972,6 +967,8 @@ static VOID VCAPITYPE cliprdr_virtual_channel_open_event_ex(LPVOID lpUserParam,
case CHANNEL_EVENT_USER:
break;
default:
break;
}
if (error && cliprdr && cliprdr->context->rdpcontext)
@ -1091,7 +1088,8 @@ static VOID VCAPITYPE cliprdr_virtual_channel_init_event_ex(LPVOID lpUserParam,
WLog_ERR(TAG,
"cliprdr_virtual_channel_event_terminated failed with error %" PRIu32 "!",
error);
break;
default:
break;
}
@ -1120,8 +1118,8 @@ FREERDP_ENTRY_POINT(BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS p
cliprdr->channelDef.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP |
CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL;
sprintf_s(cliprdr->channelDef.name, ARRAYSIZE(cliprdr->channelDef.name),
CLIPRDR_SVC_CHANNEL_NAME);
(void)sprintf_s(cliprdr->channelDef.name, ARRAYSIZE(cliprdr->channelDef.name),
CLIPRDR_SVC_CHANNEL_NAME);
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*)pEntryPoints;
WINPR_ASSERT(pEntryPointsEx);

View File

@ -55,7 +55,7 @@ typedef struct
CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr);
UINT cliprdr_send_error_response(cliprdrPlugin* cliprdr, UINT16 type);
extern const char* type_FileGroupDescriptorW;
extern const char* type_FileContents;
extern const char type_FileGroupDescriptorW[];
extern const char type_FileContents[];
#endif /* FREERDP_CHANNEL_CLIPRDR_CLIENT_MAIN_H */

View File

@ -32,6 +32,8 @@ static const char* CB_MSG_TYPE_STR(UINT32 type)
{
switch (type)
{
case CB_TYPE_NONE:
return "CB_TYPE_NONE";
case CB_MONITOR_READY:
return "CB_MONITOR_READY";
case CB_FORMAT_LIST:
@ -61,7 +63,7 @@ static const char* CB_MSG_TYPE_STR(UINT32 type)
const char* CB_MSG_TYPE_STRING(UINT16 type, char* buffer, size_t size)
{
_snprintf(buffer, size, "%s [0x%04" PRIx16 "]", CB_MSG_TYPE_STR(type), type);
(void)_snprintf(buffer, size, "%s [0x%04" PRIx16 "]", CB_MSG_TYPE_STR(type), type);
return buffer;
}
@ -75,16 +77,11 @@ const char* CB_MSG_FLAGS_STRING(UINT16 msgFlags, char* buffer, size_t size)
winpr_str_append("CB_ASCII_NAMES", buffer, size, "|");
const size_t len = strnlen(buffer, size);
if (len > 0)
{
/* remove trailing | */
buffer[len - 1] = '\0';
}
else
if (!len)
winpr_str_append("NONE", buffer, size, "");
char val[32] = { 0 };
_snprintf(val, sizeof(val), "[0x%04" PRIx16 "]", msgFlags);
(void)_snprintf(val, sizeof(val), "[0x%04" PRIx16 "]", msgFlags);
winpr_str_append(val, buffer, size, "|");
return buffer;
}
@ -242,141 +239,76 @@ wStream* cliprdr_packet_file_contents_response_new(const CLIPRDR_FILE_CONTENTS_R
}
wStream* cliprdr_packet_format_list_new(const CLIPRDR_FORMAT_LIST* formatList,
BOOL useLongFormatNames)
BOOL useLongFormatNames, BOOL useAsciiNames)
{
wStream* s = NULL;
size_t formatNameSize = 0;
char* szFormatName = NULL;
WCHAR* wszFormatName = NULL;
BOOL asciiNames = FALSE;
CLIPRDR_FORMAT* format = NULL;
UINT32 length = 0;
WINPR_ASSERT(formatList);
if (formatList->common.msgType != CB_FORMAT_LIST)
WLog_WARN(TAG, "called with invalid type %08" PRIx32, formatList->common.msgType);
if (!useLongFormatNames)
if (useLongFormatNames && useAsciiNames)
WLog_WARN(TAG, "called with invalid arguments useLongFormatNames=true && "
"useAsciiNames=true. useAsciiNames requires "
"useLongFormatNames=false, ignoring argument.");
const UINT32 length = formatList->numFormats * 36;
const size_t formatNameCharSize =
(useLongFormatNames || !useAsciiNames) ? sizeof(WCHAR) : sizeof(CHAR);
wStream* s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length);
if (!s)
{
length = formatList->numFormats * 36;
s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length);
if (!s)
{
WLog_ERR(TAG, "cliprdr_packet_new failed!");
return NULL;
}
for (UINT32 index = 0; index < formatList->numFormats; index++)
{
size_t formatNameLength = 0;
format = (CLIPRDR_FORMAT*)&(formatList->formats[index]);
Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */
formatNameSize = 0;
szFormatName = format->formatName;
if (asciiNames)
{
if (szFormatName)
formatNameLength = strnlen(szFormatName, 32);
if (formatNameLength > 31)
formatNameLength = 31;
Stream_Write(s, szFormatName, formatNameLength);
Stream_Zero(s, 32 - formatNameLength);
}
else
{
wszFormatName = NULL;
if (szFormatName)
{
wszFormatName = ConvertUtf8ToWCharAlloc(szFormatName, &formatNameSize);
if (!wszFormatName)
{
Stream_Free(s, TRUE);
return NULL;
}
formatNameSize += 1; /* append terminating '\0' */
}
if (formatNameSize > 15)
formatNameSize = 15;
/* size in bytes instead of wchar */
formatNameSize *= sizeof(WCHAR);
if (wszFormatName)
Stream_Write(s, wszFormatName, (size_t)formatNameSize);
Stream_Zero(s, (size_t)(32 - formatNameSize));
free(wszFormatName);
}
}
WLog_ERR(TAG, "cliprdr_packet_new failed!");
return NULL;
}
else
for (UINT32 index = 0; index < formatList->numFormats; index++)
{
length = 0;
for (UINT32 index = 0; index < formatList->numFormats; index++)
const CLIPRDR_FORMAT* format = &(formatList->formats[index]);
const char* szFormatName = format->formatName;
size_t formatNameLength = 0;
if (szFormatName)
formatNameLength = strlen(szFormatName);
size_t formatNameMaxLength = formatNameLength + 1; /* Ensure '\0' termination in output */
if (!Stream_EnsureRemainingCapacity(s,
4 + MAX(32, formatNameMaxLength * formatNameCharSize)))
goto fail;
Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */
if (!useLongFormatNames)
{
format = (CLIPRDR_FORMAT*)&(formatList->formats[index]);
length += 4;
formatNameSize = sizeof(WCHAR);
if (format->formatName)
{
SSIZE_T size = ConvertUtf8ToWChar(format->formatName, NULL, 0);
if (size < 0)
return NULL;
formatNameSize = (size_t)(size + 1) * sizeof(WCHAR);
}
length += (UINT32)formatNameSize;
formatNameMaxLength = useAsciiNames ? 32 : 16;
formatNameLength = MIN(formatNameMaxLength - 1, formatNameLength);
}
s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length);
if (!s)
if (szFormatName && (formatNameLength > 0))
{
WLog_ERR(TAG, "cliprdr_packet_new failed!");
return NULL;
}
for (UINT32 index = 0; index < formatList->numFormats; index++)
{
format = (CLIPRDR_FORMAT*)&(formatList->formats[index]);
Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */
if (format->formatName)
if (useAsciiNames)
{
const size_t cap = Stream_Capacity(s);
const size_t pos = Stream_GetPosition(s);
const size_t rem = cap - pos;
if ((cap < pos) || ((rem / 2) > INT_MAX))
{
Stream_Free(s, TRUE);
return NULL;
}
const size_t len = strnlen(format->formatName, rem / sizeof(WCHAR));
if (Stream_Write_UTF16_String_From_UTF8(s, len + 1, format->formatName, len, TRUE) <
0)
{
Stream_Free(s, TRUE);
return NULL;
}
Stream_Write(s, szFormatName, formatNameLength);
Stream_Zero(s, formatNameMaxLength - formatNameLength);
}
else
{
Stream_Write_UINT16(s, 0);
if (Stream_Write_UTF16_String_From_UTF8(s, formatNameMaxLength, szFormatName,
formatNameLength, TRUE) < 0)
goto fail;
}
}
else
Stream_Zero(s, formatNameMaxLength * formatNameCharSize);
}
return s;
fail:
Stream_Free(s, TRUE);
return NULL;
}
UINT cliprdr_read_unlock_clipdata(wStream* s, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData)
{
if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
@ -473,14 +405,13 @@ UINT cliprdr_read_format_list(wStream* s, CLIPRDR_FORMAT_LIST* formatList, BOOL
}
else if (!useLongFormatNames)
{
const size_t cap = Stream_Capacity(sub1);
formatList->numFormats = (cap / 36);
if ((formatList->numFormats * 36) != cap)
const size_t cap = Stream_Capacity(sub1) / 36ULL;
if (cap > UINT32_MAX)
{
WLog_ERR(TAG, "Invalid short format list length: %" PRIuz "", cap);
return ERROR_INTERNAL_ERROR;
}
formatList->numFormats = (UINT32)cap;
if (formatList->numFormats)
formats = (CLIPRDR_FORMAT*)calloc(formatList->numFormats, sizeof(CLIPRDR_FORMAT));

View File

@ -42,7 +42,7 @@ cliprdr_packet_file_contents_request_new(const CLIPRDR_FILE_CONTENTS_REQUEST* re
FREERDP_LOCAL wStream*
cliprdr_packet_file_contents_response_new(const CLIPRDR_FILE_CONTENTS_RESPONSE* response);
FREERDP_LOCAL wStream* cliprdr_packet_format_list_new(const CLIPRDR_FORMAT_LIST* formatList,
BOOL useLongFormatNames);
BOOL useLongFormatNames, BOOL useAsciiNames);
FREERDP_LOCAL UINT cliprdr_read_lock_clipdata(wStream* s,
CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData);

View File

@ -96,13 +96,9 @@ static UINT cliprdr_server_packet_send(CliprdrServerPrivate* cliprdr, wStream* s
dataLen = (UINT32)(pos - 8);
Stream_SetPosition(s, 4);
Stream_Write_UINT32(s, dataLen);
if (pos > UINT32_MAX)
{
rc = ERROR_INVALID_DATA;
goto fail;
}
status = WTSVirtualChannelWrite(cliprdr->ChannelHandle, (PCHAR)Stream_Buffer(s), (UINT32)pos,
WINPR_ASSERT(pos <= UINT32_MAX);
status = WTSVirtualChannelWrite(cliprdr->ChannelHandle, Stream_BufferAs(s, char), (UINT32)pos,
&written);
rc = status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
fail:
@ -230,7 +226,7 @@ static UINT cliprdr_server_format_list(CliprdrServerContext* context,
cliprdr = (CliprdrServerPrivate*)context->handle;
s = cliprdr_packet_format_list_new(formatList, context->useLongFormatNames);
s = cliprdr_packet_format_list_new(formatList, context->useLongFormatNames, FALSE);
if (!s)
{
WLog_ERR(TAG, "cliprdr_packet_format_list_new failed!");
@ -1355,7 +1351,7 @@ static UINT cliprdr_server_close(CliprdrServerContext* context)
if (cliprdr->ChannelHandle)
{
WTSVirtualChannelClose(cliprdr->ChannelHandle);
(void)WTSVirtualChannelClose(cliprdr->ChannelHandle);
cliprdr->ChannelHandle = NULL;
}
@ -1395,7 +1391,7 @@ static UINT cliprdr_server_start(CliprdrServerContext* context)
if (!(cliprdr->Thread = CreateThread(NULL, 0, cliprdr_server_thread, (void*)context, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
CloseHandle(cliprdr->StopEvent);
(void)CloseHandle(cliprdr->StopEvent);
cliprdr->StopEvent = NULL;
return ERROR_INTERNAL_ERROR;
}
@ -1420,7 +1416,7 @@ static UINT cliprdr_server_stop(CliprdrServerContext* context)
if (cliprdr->StopEvent)
{
SetEvent(cliprdr->StopEvent);
(void)SetEvent(cliprdr->StopEvent);
if (WaitForSingleObject(cliprdr->Thread, INFINITE) == WAIT_FAILED)
{
@ -1429,8 +1425,8 @@ static UINT cliprdr_server_stop(CliprdrServerContext* context)
return error;
}
CloseHandle(cliprdr->Thread);
CloseHandle(cliprdr->StopEvent);
(void)CloseHandle(cliprdr->Thread);
(void)CloseHandle(cliprdr->StopEvent);
}
if (cliprdr->ChannelHandle)

View File

@ -119,8 +119,8 @@ disp_send_display_control_monitor_layout_pdu(GENERIC_CHANNEL_CALLBACK* callback,
current.Height = 8192;
Stream_Write_UINT32(s, current.Flags); /* Flags (4 bytes) */
Stream_Write_UINT32(s, current.Left); /* Left (4 bytes) */
Stream_Write_UINT32(s, current.Top); /* Top (4 bytes) */
Stream_Write_INT32(s, current.Left); /* Left (4 bytes) */
Stream_Write_INT32(s, current.Top); /* Top (4 bytes) */
Stream_Write_UINT32(s, current.Width); /* Width (4 bytes) */
Stream_Write_UINT32(s, current.Height); /* Height (4 bytes) */
Stream_Write_UINT32(s, current.PhysicalWidth); /* PhysicalWidth (4 bytes) */
@ -314,7 +314,7 @@ static const IWTSVirtualChannelCallback disp_callbacks = { disp_on_data_received
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(UINT disp_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
FREERDP_ENTRY_POINT(UINT VCAPITYPE disp_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
{
return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, DISP_DVC_CHANNEL_NAME,
sizeof(DISP_PLUGIN), sizeof(GENERIC_CHANNEL_CALLBACK),

View File

@ -311,7 +311,11 @@ static UINT disp_server_handle_messages(DispServerContext* context)
return CHANNEL_RC_NO_MEMORY;
}
if (WTSVirtualChannelRead(priv->disp_channel, 0, (PCHAR)Stream_Buffer(s), Stream_Capacity(s),
const size_t cap = Stream_Capacity(s);
if (cap > UINT32_MAX)
return CHANNEL_RC_NO_BUFFER;
if (WTSVirtualChannelRead(priv->disp_channel, 0, Stream_BufferAs(s, char), (ULONG)cap,
&BytesReturned) == FALSE)
{
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
@ -412,8 +416,8 @@ static UINT disp_server_open(DispServerContext* context)
priv->SessionId = (DWORD)*pSessionId;
WTSFreeMemory(pSessionId);
priv->disp_channel = (HANDLE)WTSVirtualChannelOpenEx(priv->SessionId, DISP_DVC_CHANNEL_NAME,
WTS_CHANNEL_OPTION_DYNAMIC);
priv->disp_channel =
WTSVirtualChannelOpenEx(priv->SessionId, DISP_DVC_CHANNEL_NAME, WTS_CHANNEL_OPTION_DYNAMIC);
if (!priv->disp_channel)
{
@ -465,7 +469,7 @@ static UINT disp_server_open(DispServerContext* context)
CreateThread(NULL, 0, disp_server_thread_func, (void*)context, 0, NULL)))
{
WLog_ERR(TAG, "CreateEvent failed!");
CloseHandle(priv->stopEvent);
(void)CloseHandle(priv->stopEvent);
priv->stopEvent = NULL;
rc = ERROR_INTERNAL_ERROR;
goto out_close;
@ -474,7 +478,7 @@ static UINT disp_server_open(DispServerContext* context)
return CHANNEL_RC_OK;
out_close:
WTSVirtualChannelClose(priv->disp_channel);
(void)WTSVirtualChannelClose(priv->disp_channel);
priv->disp_channel = NULL;
priv->channelEvent = NULL;
return rc;
@ -488,8 +492,11 @@ static UINT disp_server_packet_send(DispServerContext* context, wStream* s)
WINPR_ASSERT(context);
WINPR_ASSERT(s);
if (!WTSVirtualChannelWrite(context->priv->disp_channel, (PCHAR)Stream_Buffer(s),
Stream_GetPosition(s), &written))
const size_t pos = Stream_GetPosition(s);
WINPR_ASSERT(pos <= UINT32_MAX);
if (!WTSVirtualChannelWrite(context->priv->disp_channel, Stream_BufferAs(s, char), (UINT32)pos,
&written))
{
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
ret = ERROR_INTERNAL_ERROR;
@ -550,7 +557,7 @@ static UINT disp_server_close(DispServerContext* context)
if (priv->thread)
{
SetEvent(priv->stopEvent);
(void)SetEvent(priv->stopEvent);
if (WaitForSingleObject(priv->thread, INFINITE) == WAIT_FAILED)
{
@ -559,15 +566,15 @@ static UINT disp_server_close(DispServerContext* context)
return error;
}
CloseHandle(priv->thread);
CloseHandle(priv->stopEvent);
(void)CloseHandle(priv->thread);
(void)CloseHandle(priv->stopEvent);
priv->thread = NULL;
priv->stopEvent = NULL;
}
if (priv->disp_channel)
{
WTSVirtualChannelClose(priv->disp_channel);
(void)WTSVirtualChannelClose(priv->disp_channel);
priv->disp_channel = NULL;
}

View File

@ -352,16 +352,16 @@ fail:
static UINT dvcman_load_addin(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr,
const ADDIN_ARGV* args, rdpContext* context)
{
PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL;
WINPR_ASSERT(drdynvc);
WINPR_ASSERT(pChannelMgr);
WINPR_ASSERT(args);
WINPR_ASSERT(context);
WLog_Print(drdynvc->log, WLOG_INFO, "Loading Dynamic Virtual Channel %s", args->argv[0]);
pDVCPluginEntry = (PDVC_PLUGIN_ENTRY)freerdp_load_channel_addin_entry(
args->argv[0], NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC);
PVIRTUALCHANNELENTRY pvce =
freerdp_load_channel_addin_entry(args->argv[0], NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC);
PDVC_PLUGIN_ENTRY pDVCPluginEntry = WINPR_FUNC_PTR_CAST(pvce, PDVC_PLUGIN_ENTRY);
if (pDVCPluginEntry)
{
@ -509,6 +509,8 @@ static UINT dvcman_channel_close(DVCMAN_CHANNEL* channel, BOOL perRequest, BOOL
break;
case DVC_CHANNEL_CLOSED:
break;
default:
break;
}
return error;
@ -1371,7 +1373,7 @@ static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cb
"process_close_request: Sp=%d cbChId=%d, ChannelId=%" PRIu32 "", Sp, cbChId,
ChannelId);
channel = (DVCMAN_CHANNEL*)dvcman_get_channel_by_id(drdynvc->channel_mgr, ChannelId, TRUE);
channel = dvcman_get_channel_by_id(drdynvc->channel_mgr, ChannelId, TRUE);
if (!channel)
{
WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_close_request channel %" PRIu32 " not present",
@ -1543,6 +1545,8 @@ static void VCAPITYPE drdynvc_virtual_channel_open_event_ex(LPVOID lpUserParam,
case CHANNEL_EVENT_USER:
break;
default:
break;
}
if (error && drdynvc && drdynvc->rdpcontext)
@ -1770,7 +1774,7 @@ static UINT drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc)
return status;
}
CloseHandle(drdynvc->thread);
(void)CloseHandle(drdynvc->thread);
drdynvc->thread = NULL;
}
else
@ -1997,8 +2001,8 @@ FREERDP_ENTRY_POINT(BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_E
drdynvc->channelDef.options =
CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP;
sprintf_s(drdynvc->channelDef.name, ARRAYSIZE(drdynvc->channelDef.name),
DRDYNVC_SVC_CHANNEL_NAME);
(void)sprintf_s(drdynvc->channelDef.name, ARRAYSIZE(drdynvc->channelDef.name),
DRDYNVC_SVC_CHANNEL_NAME);
drdynvc->state = DRDYNVC_STATE_INITIAL;
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*)pEntryPoints;

View File

@ -97,7 +97,7 @@ static DWORD WINAPI drdynvc_server_thread(LPVOID arg)
}
if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0,
(PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned))
Stream_BufferAs(s, char), Stream_Capacity(s), &BytesReturned))
{
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
break;
@ -138,7 +138,7 @@ static UINT drdynvc_server_start(DrdynvcServerContext* context)
CreateThread(NULL, 0, drdynvc_server_thread, (void*)context, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
CloseHandle(context->priv->StopEvent);
(void)CloseHandle(context->priv->StopEvent);
context->priv->StopEvent = NULL;
return ERROR_INTERNAL_ERROR;
}
@ -154,7 +154,7 @@ static UINT drdynvc_server_start(DrdynvcServerContext* context)
static UINT drdynvc_server_stop(DrdynvcServerContext* context)
{
UINT error = 0;
SetEvent(context->priv->StopEvent);
(void)SetEvent(context->priv->StopEvent);
if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
{
@ -163,7 +163,7 @@ static UINT drdynvc_server_stop(DrdynvcServerContext* context)
return error;
}
CloseHandle(context->priv->Thread);
(void)CloseHandle(context->priv->Thread);
return CHANNEL_RC_OK;
}

View File

@ -45,12 +45,12 @@
#include "drive_file.h"
#ifdef WITH_DEBUG_RDPDR
#define DEBUG_WSTR(msg, wstr) \
do \
{ \
char lpstr[1024] = { 0 }; \
ConvertWCharToUtf8(wstr, lpstr, ARRAYSIZE(lpstr)); \
WLog_DBG(TAG, msg, lpstr); \
#define DEBUG_WSTR(msg, wstr) \
do \
{ \
char lpstr[1024] = { 0 }; \
(void)ConvertWCharToUtf8(wstr, lpstr, ARRAYSIZE(lpstr)); \
WLog_DBG(TAG, msg, lpstr); \
} while (0)
#else
#define DEBUG_WSTR(msg, wstr) \
@ -96,6 +96,9 @@ static BOOL contains_dotdot(const WCHAR* path, size_t base_length, size_t path_l
const WCHAR* dotdot = InitializeConstWCharFromUtf8("..", dotdotbuffer, ARRAYSIZE(dotdotbuffer));
const WCHAR* tst = path;
if (path_length < 2)
return FALSE;
do
{
tst = _wcsstr(tst, dotdot);
@ -122,13 +125,12 @@ static WCHAR* drive_file_combine_fullpath(const WCHAR* base_path, const WCHAR* p
{
BOOL ok = FALSE;
WCHAR* fullpath = NULL;
size_t length = 0;
if (!base_path || (!path && (PathWCharLength > 0)))
goto fail;
const size_t base_path_length = _wcsnlen(base_path, MAX_PATH);
length = base_path_length + PathWCharLength + 1;
const size_t length = base_path_length + PathWCharLength + 1;
fullpath = (WCHAR*)calloc(length, sizeof(WCHAR));
if (!fullpath)
@ -145,7 +147,7 @@ static WCHAR* drive_file_combine_fullpath(const WCHAR* base_path, const WCHAR* p
if (contains_dotdot(&fullpath[base_path_length], base_path_length, PathWCharLength))
{
char abuffer[MAX_PATH] = { 0 };
ConvertWCharToUtf8(&fullpath[base_path_length], abuffer, ARRAYSIZE(abuffer));
(void)ConvertWCharToUtf8(&fullpath[base_path_length], abuffer, ARRAYSIZE(abuffer));
WLog_WARN(TAG, "[rdpdr] received invalid file path '%s' from server, aborting!",
&abuffer[base_path_length]);
@ -359,7 +361,7 @@ BOOL drive_file_free(DRIVE_FILE* file)
if (file->file_handle != INVALID_HANDLE_VALUE)
{
CloseHandle(file->file_handle);
(void)CloseHandle(file->file_handle);
file->file_handle = INVALID_HANDLE_VALUE;
}
@ -390,7 +392,7 @@ fail:
BOOL drive_file_seek(DRIVE_FILE* file, UINT64 Offset)
{
LARGE_INTEGER loffset;
LARGE_INTEGER loffset = { 0 };
if (!file)
return FALSE;
@ -583,7 +585,7 @@ BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, w
if (hFile != INVALID_HANDLE_VALUE)
{
status = GetFileInformationByHandle(hFile, &fileInformation);
CloseHandle(hFile);
(void)CloseHandle(hFile);
if (!status)
goto out_fail;
@ -614,10 +616,10 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
{
INT64 size = 0;
WCHAR* fullpath = NULL;
ULARGE_INTEGER liCreationTime;
ULARGE_INTEGER liLastAccessTime;
ULARGE_INTEGER liLastWriteTime;
ULARGE_INTEGER liChangeTime;
ULARGE_INTEGER liCreationTime = { 0 };
ULARGE_INTEGER liLastAccessTime = { 0 };
ULARGE_INTEGER liLastWriteTime = { 0 };
ULARGE_INTEGER liChangeTime = { 0 };
FILETIME ftCreationTime;
FILETIME ftLastAccessTime;
FILETIME ftLastWriteTime;
@ -626,7 +628,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
FILETIME* pftLastWriteTime = NULL;
UINT32 FileAttributes = 0;
UINT32 FileNameLength = 0;
LARGE_INTEGER liSize;
LARGE_INTEGER liSize = { 0 };
UINT8 delete_pending = 0;
UINT8 ReplaceIfExists = 0;
DWORD attr = 0;
@ -788,7 +790,7 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
if (file->file_handle != INVALID_HANDLE_VALUE)
{
CloseHandle(file->file_handle);
(void)CloseHandle(file->file_handle);
file->file_handle = INVALID_HANDLE_VALUE;
}

View File

@ -470,7 +470,10 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
const size_t volumeLabelLen = (_wcslen(volumeLabel) + 1) * sizeof(WCHAR);
const size_t length = 17ul + volumeLabelLen;
Stream_Write_UINT32(output, length); /* Length */
if ((length > UINT32_MAX) || (volumeLabelLen > UINT32_MAX))
return CHANNEL_RC_NO_BUFFER;
Stream_Write_UINT32(output, (UINT32)length); /* Length */
if (!Stream_EnsureRemainingCapacity(output, length))
{
@ -483,7 +486,7 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
Stream_Write_UINT32(output,
wfad.ftCreationTime.dwHighDateTime); /* VolumeCreationTime */
Stream_Write_UINT32(output, lpNumberOfFreeClusters & 0xffff); /* VolumeSerialNumber */
Stream_Write_UINT32(output, volumeLabelLen); /* VolumeLabelLength */
Stream_Write_UINT32(output, (UINT32)volumeLabelLen); /* VolumeLabelLength */
Stream_Write_UINT8(output, 0); /* SupportsObjects */
/* Reserved(1), MUST NOT be added! */
Stream_Write(output, volumeLabel, volumeLabelLen); /* VolumeLabel (Unicode) */
@ -513,7 +516,11 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
InitializeConstWCharFromUtf8("FAT32", LabelBuffer, ARRAYSIZE(LabelBuffer));
const size_t diskTypeLen = (_wcslen(diskType) + 1) * sizeof(WCHAR);
const size_t length = 12ul + diskTypeLen;
Stream_Write_UINT32(output, length); /* Length */
if ((length > UINT32_MAX) || (diskTypeLen > UINT32_MAX))
return CHANNEL_RC_NO_BUFFER;
Stream_Write_UINT32(output, (UINT32)length); /* Length */
if (!Stream_EnsureRemainingCapacity(output, length))
{
@ -524,7 +531,7 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
Stream_Write_UINT32(output, FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES |
FILE_UNICODE_ON_DISK); /* FileSystemAttributes */
Stream_Write_UINT32(output, MAX_PATH); /* MaximumComponentNameLength */
Stream_Write_UINT32(output, diskTypeLen); /* FileSystemNameLength */
Stream_Write_UINT32(output, (UINT32)diskTypeLen); /* FileSystemNameLength */
Stream_Write(output, diskType, diskTypeLen); /* FileSystemName (Unicode) */
}
break;
@ -822,7 +829,7 @@ static UINT drive_free_int(DRIVE_DEVICE* drive)
if (!drive)
return ERROR_INVALID_PARAMETER;
CloseHandle(drive->thread);
(void)CloseHandle(drive->thread);
ListDictionary_Free(drive->files);
MessageQueue_Free(drive->IrpQueue);
Stream_Free(drive->device.data, TRUE);
@ -945,7 +952,7 @@ static UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
}
Stream_Write_UINT8(drive->device.data, '\0');
drive->device.name = (const char*)Stream_Buffer(drive->device.data);
drive->device.name = Stream_BufferAs(drive->device.data, char);
if (!drive->device.name)
goto out_error;
@ -1009,7 +1016,8 @@ out_error:
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(UINT drive_DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints))
FREERDP_ENTRY_POINT(
UINT VCAPITYPE drive_DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints))
{
RDPDR_DRIVE* drive = NULL;
UINT error = 0;

View File

@ -84,7 +84,7 @@ static const IWTSVirtualChannelCallback echo_callbacks = { echo_on_data_received
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(UINT echo_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
FREERDP_ENTRY_POINT(UINT VCAPITYPE echo_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
{
return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, ECHO_DVC_CHANNEL_NAME,
sizeof(ECHO_PLUGIN), sizeof(GENERIC_CHANNEL_CALLBACK),

View File

@ -219,7 +219,7 @@ static DWORD WINAPI echo_server_thread_func(LPVOID arg)
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
WTSVirtualChannelClose(echo->echo_channel);
(void)WTSVirtualChannelClose(echo->echo_channel);
ExitThread(ERROR_NOT_ENOUGH_MEMORY);
return ERROR_NOT_ENOUGH_MEMORY;
}
@ -239,7 +239,12 @@ static DWORD WINAPI echo_server_thread_func(LPVOID arg)
break;
Stream_SetPosition(s, 0);
WTSVirtualChannelRead(echo->echo_channel, 0, NULL, 0, &BytesReturned);
if (!WTSVirtualChannelRead(echo->echo_channel, 0, NULL, 0, &BytesReturned))
{
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (BytesReturned < 1)
continue;
@ -251,7 +256,7 @@ static DWORD WINAPI echo_server_thread_func(LPVOID arg)
break;
}
if (WTSVirtualChannelRead(echo->echo_channel, 0, (PCHAR)Stream_Buffer(s),
if (WTSVirtualChannelRead(echo->echo_channel, 0, Stream_BufferAs(s, char),
(ULONG)Stream_Capacity(s), &BytesReturned) == FALSE)
{
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
@ -259,8 +264,7 @@ static DWORD WINAPI echo_server_thread_func(LPVOID arg)
break;
}
IFCALLRET(echo->context.Response, error, &echo->context, (BYTE*)Stream_Buffer(s),
BytesReturned);
IFCALLRET(echo->context.Response, error, &echo->context, Stream_Buffer(s), BytesReturned);
if (error)
{
@ -270,7 +274,7 @@ static DWORD WINAPI echo_server_thread_func(LPVOID arg)
}
Stream_Free(s, TRUE);
WTSVirtualChannelClose(echo->echo_channel);
(void)WTSVirtualChannelClose(echo->echo_channel);
echo->echo_channel = NULL;
out:
@ -302,7 +306,7 @@ static UINT echo_server_open(echo_server_context* context)
if (!(echo->thread = CreateThread(NULL, 0, echo_server_thread_func, (void*)echo, 0, NULL)))
{
WLog_ERR(TAG, "CreateEvent failed!");
CloseHandle(echo->stopEvent);
(void)CloseHandle(echo->stopEvent);
echo->stopEvent = NULL;
return ERROR_INTERNAL_ERROR;
}
@ -323,7 +327,7 @@ static UINT echo_server_close(echo_server_context* context)
if (echo->thread)
{
SetEvent(echo->stopEvent);
(void)SetEvent(echo->stopEvent);
if (WaitForSingleObject(echo->thread, INFINITE) == WAIT_FAILED)
{
@ -332,8 +336,8 @@ static UINT echo_server_close(echo_server_context* context)
return error;
}
CloseHandle(echo->thread);
CloseHandle(echo->stopEvent);
(void)CloseHandle(echo->thread);
(void)CloseHandle(echo->stopEvent);
echo->thread = NULL;
echo->stopEvent = NULL;
}

View File

@ -100,7 +100,7 @@ static UINT encomsp_read_unicode_string(wStream* s, ENCOMSP_UNICODE_STRING* str)
if (!Stream_CheckAndLogRequiredLengthOfSize(TAG, s, str->cchString, sizeof(WCHAR)))
return ERROR_INVALID_DATA;
Stream_Read(s, &(str->wString), (str->cchString * 2)); /* String (variable) */
Stream_Read(s, &(str->wString), (sizeof(WCHAR) * str->cchString)); /* String (variable) */
return CHANNEL_RC_OK;
}
@ -1026,13 +1026,13 @@ static VOID VCAPITYPE encomsp_virtual_channel_open_event_ex(LPVOID lpUserParam,
case CHANNEL_EVENT_USER:
break;
default:
break;
}
if (error && encomsp && encomsp->rdpcontext)
setChannelError(encomsp->rdpcontext, error,
"encomsp_virtual_channel_open_event reported an error");
return;
}
static DWORD WINAPI encomsp_virtual_channel_client_thread(LPVOID arg)
@ -1139,7 +1139,7 @@ static UINT encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp)
}
MessageQueue_Free(encomsp->queue);
CloseHandle(encomsp->thread);
(void)CloseHandle(encomsp->thread);
encomsp->queue = NULL;
encomsp->thread = NULL;
@ -1244,8 +1244,8 @@ FREERDP_ENTRY_POINT(BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_E
encomsp->channelDef.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP |
CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL;
sprintf_s(encomsp->channelDef.name, ARRAYSIZE(encomsp->channelDef.name),
ENCOMSP_SVC_CHANNEL_NAME);
(void)sprintf_s(encomsp->channelDef.name, ARRAYSIZE(encomsp->channelDef.name),
ENCOMSP_SVC_CHANNEL_NAME);
CHANNEL_ENTRY_POINTS_FREERDP_EX* pEntryPointsEx =
(CHANNEL_ENTRY_POINTS_FREERDP_EX*)pEntryPoints;
WINPR_ASSERT(pEntryPointsEx);

View File

@ -232,7 +232,12 @@ static DWORD WINAPI encomsp_server_thread(LPVOID arg)
break;
}
WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned);
if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, NULL, 0, &BytesReturned))
{
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
if (BytesReturned < 1)
continue;
@ -244,8 +249,10 @@ static DWORD WINAPI encomsp_server_thread(LPVOID arg)
break;
}
if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR)Stream_Buffer(s),
Stream_Capacity(s), &BytesReturned))
const size_t cap = Stream_Capacity(s);
if ((cap > UINT32_MAX) ||
!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, Stream_BufferAs(s, char),
(ULONG)cap, &BytesReturned))
{
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
error = ERROR_INTERNAL_ERROR;
@ -254,7 +261,7 @@ static DWORD WINAPI encomsp_server_thread(LPVOID arg)
if (Stream_GetPosition(s) >= ENCOMSP_ORDER_HEADER_SIZE)
{
header = (ENCOMSP_ORDER_HEADER*)Stream_Buffer(s);
header = Stream_BufferAs(s, ENCOMSP_ORDER_HEADER);
if (header->Length >= Stream_GetPosition(s))
{
@ -306,7 +313,7 @@ static UINT encomsp_server_start(EncomspServerContext* context)
CreateThread(NULL, 0, encomsp_server_thread, (void*)context, 0, NULL)))
{
WLog_ERR(TAG, "CreateThread failed!");
CloseHandle(context->priv->StopEvent);
(void)CloseHandle(context->priv->StopEvent);
context->priv->StopEvent = NULL;
return ERROR_INTERNAL_ERROR;
}
@ -322,7 +329,7 @@ static UINT encomsp_server_start(EncomspServerContext* context)
static UINT encomsp_server_stop(EncomspServerContext* context)
{
UINT error = CHANNEL_RC_OK;
SetEvent(context->priv->StopEvent);
(void)SetEvent(context->priv->StopEvent);
if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
{
@ -331,8 +338,8 @@ static UINT encomsp_server_stop(EncomspServerContext* context)
return error;
}
CloseHandle(context->priv->Thread);
CloseHandle(context->priv->StopEvent);
(void)CloseHandle(context->priv->Thread);
(void)CloseHandle(context->priv->StopEvent);
return error;
}
@ -364,7 +371,7 @@ void encomsp_server_context_free(EncomspServerContext* context)
if (context)
{
if (context->priv->ChannelHandle != INVALID_HANDLE_VALUE)
WTSVirtualChannelClose(context->priv->ChannelHandle);
(void)WTSVirtualChannelClose(context->priv->ChannelHandle);
free(context->priv);
free(context);

View File

@ -394,7 +394,7 @@ static void terminate_plugin_cb(GENERIC_DYNVC_PLUGIN* base)
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(UINT geometry_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
FREERDP_ENTRY_POINT(UINT VCAPITYPE geometry_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
{
return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, GEOMETRY_DVC_CHANNEL_NAME,
sizeof(GEOMETRY_PLUGIN), sizeof(GENERIC_CHANNEL_CALLBACK),

View File

@ -679,7 +679,7 @@ static UINT gfxredir_server_open(GfxRedirServerContext* context)
CreateThread(NULL, 0, gfxredir_server_thread_func, (void*)context, 0, NULL)))
{
WLog_ERR(TAG, "CreateEvent failed!");
CloseHandle(priv->stopEvent);
(void)CloseHandle(priv->stopEvent);
priv->stopEvent = NULL;
rc = ERROR_INTERNAL_ERROR;
}
@ -705,7 +705,7 @@ static UINT gfxredir_server_close(GfxRedirServerContext* context)
if (priv->thread)
{
SetEvent(priv->stopEvent);
(void)SetEvent(priv->stopEvent);
if (WaitForSingleObject(priv->thread, INFINITE) == WAIT_FAILED)
{
@ -714,8 +714,8 @@ static UINT gfxredir_server_close(GfxRedirServerContext* context)
return error;
}
CloseHandle(priv->thread);
CloseHandle(priv->stopEvent);
(void)CloseHandle(priv->thread);
(void)CloseHandle(priv->stopEvent);
priv->thread = NULL;
priv->stopEvent = NULL;
}

View File

@ -99,12 +99,15 @@ static BOOL location_read_server_ready_pdu(LOCATION_CALLBACK* callback, wStream*
static UINT location_channel_send(IWTSVirtualChannel* channel, wStream* s)
{
const size_t len = Stream_GetPosition(s);
if (len > UINT32_MAX)
return ERROR_INTERNAL_ERROR;
Stream_SetPosition(s, 2);
Stream_Write_UINT32(s, len);
Stream_Write_UINT32(s, (UINT32)len);
WINPR_ASSERT(channel);
WINPR_ASSERT(channel->Write);
return channel->Write(channel, len, Stream_Buffer(s), NULL);
return channel->Write(channel, (UINT32)len, Stream_Buffer(s), NULL);
}
static UINT location_send_client_ready_pdu(const LOCATION_CALLBACK* callback)
@ -138,7 +141,7 @@ static const char* location_version_str(UINT32 version, char* buffer, size_t siz
break;
}
_snprintf(buffer, size, "%s [0x%08" PRIx32 "]", str, version);
(void)_snprintf(buffer, size, "%s [0x%08" PRIx32 "]", str, version);
return buffer;
}
@ -335,11 +338,12 @@ static UINT location_send(LocationClientContext* context, LOCATION_PDUTYPE type,
IWTSVirtualChannel* channel = cb->channel;
WINPR_ASSERT(channel);
LOCATION_CALLBACK* callback = (LOCATION_CALLBACK*)loc->baseDynPlugin.channel_callbacks;
const LOCATION_CALLBACK* callback =
(const LOCATION_CALLBACK*)loc->baseDynPlugin.channel_callbacks;
WINPR_ASSERT(callback);
UINT32 res = ERROR_INTERNAL_ERROR;
va_list ap;
va_list ap = { 0 };
va_start(ap, count);
switch (type)
{
@ -465,7 +469,7 @@ static const IWTSVirtualChannelCallback location_callbacks = { location_on_data_
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(UINT location_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
FREERDP_ENTRY_POINT(UINT VCAPITYPE location_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
{
return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, LOCATION_DVC_CHANNEL_NAME,
sizeof(LOCATION_PLUGIN), sizeof(LOCATION_CALLBACK),

View File

@ -296,7 +296,7 @@ static UINT location_process_message(location_server* location)
goto out;
}
if (WTSVirtualChannelRead(location->location_channel, 0, (PCHAR)Stream_Buffer(s),
if (WTSVirtualChannelRead(location->location_channel, 0, Stream_BufferAs(s, char),
(ULONG)Stream_Capacity(s), &BytesReturned) == FALSE)
{
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
@ -356,6 +356,8 @@ static UINT location_server_context_poll_int(LocationServerContext* context)
case LOCATION_OPENED:
error = location_process_message(location);
break;
default:
break;
}
return error;
@ -423,10 +425,12 @@ static DWORD WINAPI location_server_thread_func(LPVOID arg)
break;
}
break;
default:
break;
}
}
WTSVirtualChannelClose(location->location_channel);
(void)WTSVirtualChannelClose(location->location_channel);
location->location_channel = NULL;
if (error && location->context.rdpcontext)
@ -456,7 +460,7 @@ static UINT location_server_open(LocationServerContext* context)
if (!location->thread)
{
WLog_ERR(TAG, "CreateThread failed!");
CloseHandle(location->stopEvent);
(void)CloseHandle(location->stopEvent);
location->stopEvent = NULL;
return ERROR_INTERNAL_ERROR;
}
@ -475,7 +479,7 @@ static UINT location_server_close(LocationServerContext* context)
if (!location->externalThread && location->thread)
{
SetEvent(location->stopEvent);
(void)SetEvent(location->stopEvent);
if (WaitForSingleObject(location->thread, INFINITE) == WAIT_FAILED)
{
@ -484,8 +488,8 @@ static UINT location_server_close(LocationServerContext* context)
return error;
}
CloseHandle(location->thread);
CloseHandle(location->stopEvent);
(void)CloseHandle(location->thread);
(void)CloseHandle(location->stopEvent);
location->thread = NULL;
location->stopEvent = NULL;
}
@ -493,7 +497,7 @@ static UINT location_server_close(LocationServerContext* context)
{
if (location->state != LOCATION_INITIAL)
{
WTSVirtualChannelClose(location->location_channel);
(void)WTSVirtualChannelClose(location->location_channel);
location->location_channel = NULL;
location->state = LOCATION_INITIAL;
}
@ -541,8 +545,10 @@ static UINT location_server_packet_send(LocationServerContext* context, wStream*
WINPR_ASSERT(location);
WINPR_ASSERT(s);
if (!WTSVirtualChannelWrite(location->location_channel, (PCHAR)Stream_Buffer(s),
Stream_GetPosition(s), &written))
const size_t pos = Stream_GetPosition(s);
WINPR_ASSERT(pos <= UINT32_MAX);
if (!WTSVirtualChannelWrite(location->location_channel, Stream_BufferAs(s, char), (ULONG)pos,
&written))
{
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
error = ERROR_INTERNAL_ERROR;

View File

@ -6,11 +6,19 @@ set(OPTION_SERVER_DEFAULT OFF)
if(WIN32)
set(OPTION_CLIENT_DEFAULT OFF)
set(OPTION_SERVER_DEFAULT OFF)
message("Serial redirection not supported on windows")
endif()
if(APPLE)
set(OPTION_CLIENT_DEFAULT OFF)
set(OPTION_SERVER_DEFAULT OFF)
message("Serial redirection not supported on apple")
endif()
if(ANDROID)
set(OPTION_CLIENT_DEFAULT OFF)
set(OPTION_SERVER_DEFAULT OFF)
message("Serial redirection not supported on android")
endif()
define_channel_options(NAME "parallel" TYPE "device"

View File

@ -53,6 +53,7 @@
#include <freerdp/constants.h>
#include <freerdp/channels/rdpdr.h>
#include <freerdp/channels/log.h>
#include <freerdp/utils/rdpdr_utils.h>
#define TAG CHANNELS_TAG("drive.client")
@ -67,6 +68,7 @@ typedef struct
HANDLE thread;
wMessageQueue* queue;
rdpContext* rdpcontext;
wLog* log;
} PARALLEL_DEVICE;
/**
@ -130,12 +132,7 @@ static UINT parallel_process_irp_close(PARALLEL_DEVICE* parallel, IRP* irp)
WINPR_ASSERT(parallel);
WINPR_ASSERT(irp);
if (close(parallel->file) < 0)
{
}
else
{
}
(void)close(parallel->file);
Stream_Zero(irp->output, 5); /* Padding(5) */
return irp->Complete(irp);
@ -166,13 +163,13 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
if (!buffer)
{
WLog_ERR(TAG, "malloc failed!");
WLog_Print(parallel->log, WLOG_ERROR, "malloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
status = read(parallel->file, buffer, Length);
if (status < 0)
if ((status < 0) || (status > UINT32_MAX))
{
irp->IoStatus = STATUS_UNSUCCESSFUL;
free(buffer);
@ -181,7 +178,7 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
}
else
{
Length = status;
Length = (UINT32)status;
}
Stream_Write_UINT32(irp->output, Length);
@ -190,7 +187,7 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
{
if (!Stream_EnsureRemainingCapacity(irp->output, Length))
{
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
WLog_Print(parallel->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
free(buffer);
return CHANNEL_RC_NO_MEMORY;
}
@ -212,7 +209,6 @@ static UINT parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp)
UINT32 len = 0;
UINT32 Length = 0;
UINT64 Offset = 0;
ssize_t status = 0;
WINPR_ASSERT(parallel);
WINPR_ASSERT(irp);
@ -233,7 +229,7 @@ static UINT parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp)
while (len > 0)
{
status = write(parallel->file, ptr, len);
const ssize_t status = write(parallel->file, ptr, len);
if ((status < 0) || (status > len))
{
@ -272,7 +268,7 @@ static UINT parallel_process_irp_device_control(PARALLEL_DEVICE* parallel, IRP*
*/
static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
{
UINT error = 0;
UINT error = ERROR_INTERNAL_ERROR;
WINPR_ASSERT(parallel);
WINPR_ASSERT(irp);
@ -280,57 +276,42 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
switch (irp->MajorFunction)
{
case IRP_MJ_CREATE:
if ((error = parallel_process_irp_create(parallel, irp)))
{
WLog_ERR(TAG, "parallel_process_irp_create failed with error %" PRIu32 "!", error);
return error;
}
error = parallel_process_irp_create(parallel, irp);
break;
case IRP_MJ_CLOSE:
if ((error = parallel_process_irp_close(parallel, irp)))
{
WLog_ERR(TAG, "parallel_process_irp_close failed with error %" PRIu32 "!", error);
return error;
}
error = parallel_process_irp_close(parallel, irp);
break;
case IRP_MJ_READ:
if ((error = parallel_process_irp_read(parallel, irp)))
{
WLog_ERR(TAG, "parallel_process_irp_read failed with error %" PRIu32 "!", error);
return error;
}
error = parallel_process_irp_read(parallel, irp);
break;
case IRP_MJ_WRITE:
if ((error = parallel_process_irp_write(parallel, irp)))
{
WLog_ERR(TAG, "parallel_process_irp_write failed with error %" PRIu32 "!", error);
return error;
}
error = parallel_process_irp_write(parallel, irp);
break;
case IRP_MJ_DEVICE_CONTROL:
if ((error = parallel_process_irp_device_control(parallel, irp)))
{
WLog_ERR(TAG, "parallel_process_irp_device_control failed with error %" PRIu32 "!",
error);
return error;
}
error = parallel_process_irp_device_control(parallel, irp);
break;
default:
irp->IoStatus = STATUS_NOT_SUPPORTED;
return irp->Complete(irp);
error = irp->Complete(irp);
break;
}
return CHANNEL_RC_OK;
DWORD level = WLOG_TRACE;
if (error)
level = WLOG_WARN;
WLog_Print(parallel->log, level,
"[%s|0x%08" PRIx32 "] completed with %s [0x%08" PRIx32 "] (IoStatus %s [0x%08" PRIx32
"])",
rdpdr_irp_string(irp->MajorFunction), irp->MajorFunction, WTSErrorToString(error),
error, NtStatus2Tag(irp->IoStatus), irp->IoStatus);
return error;
}
static DWORD WINAPI parallel_thread_func(LPVOID arg)
@ -343,7 +324,7 @@ static DWORD WINAPI parallel_thread_func(LPVOID arg)
{
if (!MessageQueue_Wait(parallel->queue))
{
WLog_ERR(TAG, "MessageQueue_Wait failed!");
WLog_Print(parallel->log, WLOG_ERROR, "MessageQueue_Wait failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
@ -351,7 +332,7 @@ static DWORD WINAPI parallel_thread_func(LPVOID arg)
wMessage message = { 0 };
if (!MessageQueue_Peek(parallel->queue, &message, TRUE))
{
WLog_ERR(TAG, "MessageQueue_Peek failed!");
WLog_Print(parallel->log, WLOG_ERROR, "MessageQueue_Peek failed!");
error = ERROR_INTERNAL_ERROR;
break;
}
@ -361,9 +342,11 @@ static DWORD WINAPI parallel_thread_func(LPVOID arg)
IRP* irp = (IRP*)message.wParam;
if ((error = parallel_process_irp(parallel, irp)))
error = parallel_process_irp(parallel, irp);
if (error)
{
WLog_ERR(TAG, "parallel_process_irp failed with error %" PRIu32 "!", error);
WLog_Print(parallel->log, WLOG_ERROR,
"parallel_process_irp failed with error %" PRIu32 "!", error);
break;
}
}
@ -384,9 +367,11 @@ static UINT parallel_irp_request(DEVICE* device, IRP* irp)
{
PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*)device;
WINPR_ASSERT(parallel);
if (!MessageQueue_Post(parallel->queue, NULL, 0, (void*)irp, NULL))
{
WLog_ERR(TAG, "MessageQueue_Post failed!");
WLog_Print(parallel->log, WLOG_ERROR, "MessageQueue_Post failed!");
return ERROR_INTERNAL_ERROR;
}
@ -398,23 +383,30 @@ static UINT parallel_irp_request(DEVICE* device, IRP* irp)
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT parallel_free_int(PARALLEL_DEVICE* parallel)
{
if (parallel)
{
if (!MessageQueue_PostQuit(parallel->queue, 0) ||
(WaitForSingleObject(parallel->thread, INFINITE) == WAIT_FAILED))
{
const UINT error = GetLastError();
WLog_Print(parallel->log, WLOG_ERROR,
"WaitForSingleObject failed with error %" PRIu32 "!", error);
}
(void)CloseHandle(parallel->thread);
Stream_Free(parallel->device.data, TRUE);
MessageQueue_Free(parallel->queue);
}
free(parallel);
return CHANNEL_RC_OK;
}
static UINT parallel_free(DEVICE* device)
{
UINT error = 0;
PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*)device;
if (!MessageQueue_PostQuit(parallel->queue, 0) ||
(WaitForSingleObject(parallel->thread, INFINITE) == WAIT_FAILED))
{
error = GetLastError();
WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error);
return error;
}
CloseHandle(parallel->thread);
Stream_Free(parallel->device.data, TRUE);
MessageQueue_Free(parallel->queue);
free(parallel);
if (device)
return parallel_free_int((PARALLEL_DEVICE*)device);
return CHANNEL_RC_OK;
}
@ -438,26 +430,27 @@ static void parallel_message_free(void* obj)
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(UINT parallel_DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints))
FREERDP_ENTRY_POINT(
UINT VCAPITYPE parallel_DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints))
{
char* name = NULL;
char* path = NULL;
size_t length = 0;
RDPDR_PARALLEL* device = NULL;
PARALLEL_DEVICE* parallel = NULL;
UINT error = 0;
WINPR_ASSERT(pEntryPoints);
device = (RDPDR_PARALLEL*)pEntryPoints->device;
RDPDR_PARALLEL* device = (RDPDR_PARALLEL*)pEntryPoints->device;
WINPR_ASSERT(device);
name = device->device.Name;
path = device->Path;
wLog* log = WLog_Get(TAG);
WINPR_ASSERT(log);
char* name = device->device.Name;
char* path = device->Path;
if (!name || (name[0] == '*') || !path)
{
/* TODO: implement auto detection of parallel ports */
WLog_Print(log, WLOG_WARN, "Autodetection not implemented, no ports will be redirected");
return CHANNEL_RC_INITIALIZATION_ERROR;
}
@ -467,21 +460,22 @@ FREERDP_ENTRY_POINT(UINT parallel_DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINT
if (!parallel)
{
WLog_ERR(TAG, "calloc failed!");
WLog_Print(log, WLOG_ERROR, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
parallel->log = log;
parallel->device.type = RDPDR_DTYP_PARALLEL;
parallel->device.name = name;
parallel->device.IRPRequest = parallel_irp_request;
parallel->device.Free = parallel_free;
parallel->rdpcontext = pEntryPoints->rdpcontext;
length = strlen(name);
const size_t length = strlen(name);
parallel->device.data = Stream_New(NULL, length + 1);
if (!parallel->device.data)
{
WLog_ERR(TAG, "Stream_New failed!");
WLog_Print(parallel->log, WLOG_ERROR, "Stream_New failed!");
error = CHANNEL_RC_NO_MEMORY;
goto error_out;
}
@ -494,7 +488,7 @@ FREERDP_ENTRY_POINT(UINT parallel_DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINT
if (!parallel->queue)
{
WLog_ERR(TAG, "MessageQueue_New failed!");
WLog_Print(parallel->log, WLOG_ERROR, "MessageQueue_New failed!");
error = CHANNEL_RC_NO_MEMORY;
goto error_out;
}
@ -503,16 +497,18 @@ FREERDP_ENTRY_POINT(UINT parallel_DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINT
WINPR_ASSERT(obj);
obj->fnObjectFree = parallel_message_free;
if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)parallel)))
error = pEntryPoints->RegisterDevice(pEntryPoints->devman, &parallel->device);
if (error)
{
WLog_ERR(TAG, "RegisterDevice failed with error %" PRIu32 "!", error);
WLog_Print(parallel->log, WLOG_ERROR, "RegisterDevice failed with error %" PRIu32 "!",
error);
goto error_out;
}
if (!(parallel->thread =
CreateThread(NULL, 0, parallel_thread_func, (void*)parallel, 0, NULL)))
parallel->thread = CreateThread(NULL, 0, parallel_thread_func, parallel, 0, NULL);
if (!parallel->thread)
{
WLog_ERR(TAG, "CreateThread failed!");
WLog_Print(parallel->log, WLOG_ERROR, "CreateThread failed!");
error = ERROR_INTERNAL_ERROR;
goto error_out;
}
@ -520,8 +516,6 @@ FREERDP_ENTRY_POINT(UINT parallel_DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINT
return CHANNEL_RC_OK;
error_out:
MessageQueue_Free(parallel->queue);
Stream_Free(parallel->device.data, TRUE);
free(parallel);
parallel_free_int(parallel);
return error;
}

View File

@ -28,6 +28,6 @@ set(${MODULE_PREFIX}_LIBS
)
include_directories(..)
include_directories(${CUPS_INCLUDE_DIRS})
include_directories(SYSTEM ${CUPS_INCLUDE_DIRS})
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")

View File

@ -65,6 +65,8 @@ static bool is_mac_os_sonoma_or_later(void)
int major = 0;
int minor = 0;
int patch = 0;
// NOLINTNEXTLINE(cert-err34-c)
const int rc = sscanf(str, "%d.%d.%d", &major, &minor, &patch);
if (rc != 3)
{
@ -110,8 +112,9 @@ static void printer_cups_get_printjob_name(char* buf, size_t size, size_t id)
WINPR_ASSERT(buf);
WINPR_ASSERT(size > 0);
sprintf_s(buf, size - 1, "FreeRDP Print %04d-%02d-%02d %02d-%02d-%02d - Job %" PRIdz,
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, id);
(void)sprintf_s(buf, size - 1, "FreeRDP Print %04d-%02d-%02d %02d-%02d-%02d - Job %" PRIuz,
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec,
id);
}
static bool http_status_ok(http_status_t status)
@ -146,10 +149,6 @@ static UINT write_printjob(rdpPrintJob* printjob, const BYTE* data, size_t size)
*/
static UINT printer_cups_write_printjob(rdpPrintJob* printjob, const BYTE* data, size_t size)
{
rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*)printjob;
WINPR_ASSERT(cups_printjob);
return write_printjob(printjob, data, size);
}
@ -365,7 +364,7 @@ static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver)
if (!printers)
return NULL;
for (size_t i = 0; i < num_dests; i++)
for (size_t i = 0; i < (size_t)num_dests; i++)
{
const cups_dest_t* dest = &dests[i];
if (dest->instance == NULL)
@ -431,7 +430,7 @@ static void printer_cups_release_ref_driver(rdpPrinterDriver* driver)
cups_driver->references--;
}
FREERDP_ENTRY_POINT(UINT cups_freerdp_printer_client_subsystem_entry(void* arg))
FREERDP_ENTRY_POINT(UINT VCAPITYPE cups_freerdp_printer_client_subsystem_entry(void* arg))
{
rdpPrinterDriver** ppPrinter = (rdpPrinterDriver**)arg;
if (!ppPrinter)

View File

@ -103,7 +103,6 @@ static BOOL printer_write_setting(const char* path, prn_conf_t type, const void*
DWORD written = 0;
BOOL rc = FALSE;
HANDLE file = NULL;
size_t b64len = 0;
char* base64 = NULL;
const char* name = filemap[type];
char* abs = GetCombinedPath(path, name);
@ -129,8 +128,8 @@ static BOOL printer_write_setting(const char* path, prn_conf_t type, const void*
/* base64 char represents 6bit -> 4*(n/3) is the length which is
* always smaller than 2*n */
b64len = strnlen(base64, 2 * length);
rc = WriteFile(file, base64, b64len, &written, NULL);
const size_t b64len = strnlen(base64, 2 * length);
rc = WriteFile(file, base64, (UINT32)b64len, &written, NULL);
if (b64len != written)
rc = FALSE;
@ -139,7 +138,7 @@ static BOOL printer_write_setting(const char* path, prn_conf_t type, const void*
rc = TRUE;
fail:
CloseHandle(file);
(void)CloseHandle(file);
free(base64);
return rc;
}
@ -194,7 +193,7 @@ static BOOL printer_read_setting(const char* path, prn_conf_t type, void** data,
}
fail:
CloseHandle(file);
(void)CloseHandle(file);
if (rc && (lowSize <= INT_MAX))
{
@ -313,7 +312,12 @@ static BOOL printer_load_from_config(const rdpSettings* settings, rdpPrinter* pr
wlen++;
path = get_printer_config_path(settings, wname, wlen * sizeof(WCHAR));
PrinterNameLen = wlen * sizeof(WCHAR);
{
const size_t plen = wlen * sizeof(WCHAR);
if (plen > UINT32_MAX)
goto fail;
PrinterNameLen = (UINT32)plen;
}
if (!path)
goto fail;
@ -331,7 +335,10 @@ static BOOL printer_load_from_config(const rdpSettings* settings, rdpPrinter* pr
DriverName = ConvertUtf8ToWCharAlloc(printer->driver, &len);
if (!DriverName)
goto fail;
DriverNameLen = (len + 1) * sizeof(WCHAR);
const size_t dlen = (len + 1) * sizeof(WCHAR);
if (dlen > UINT32_MAX)
goto fail;
DriverNameLen = (UINT32)dlen;
}
if (!printer_read_setting(path, PRN_CONF_DATA, &CachedPrinterConfigData, &CachedFieldsLen))
@ -651,7 +658,7 @@ static DWORD WINAPI printer_thread_func(LPVOID arg)
else if (rc != WAIT_OBJECT_0)
continue;
ResetEvent(printer_dev->event);
(void)ResetEvent(printer_dev->event);
irp = (IRP*)InterlockedPopEntrySList(printer_dev->pIrpList);
if (irp == NULL)
@ -690,7 +697,7 @@ static UINT printer_irp_request(DEVICE* device, IRP* irp)
if (printer_dev->async)
{
InterlockedPushEntrySList(printer_dev->pIrpList, &(irp->ItemEntry));
SetEvent(printer_dev->event);
(void)SetEvent(printer_dev->event);
}
else
{
@ -908,7 +915,7 @@ static UINT printer_free(DEVICE* device)
if (printer_dev->async)
{
SetEvent(printer_dev->stopEvent);
(void)SetEvent(printer_dev->stopEvent);
if (WaitForSingleObject(printer_dev->thread, INFINITE) == WAIT_FAILED)
{
@ -929,9 +936,9 @@ static UINT printer_free(DEVICE* device)
irp->Discard(irp);
}
CloseHandle(printer_dev->thread);
CloseHandle(printer_dev->stopEvent);
CloseHandle(printer_dev->event);
(void)CloseHandle(printer_dev->thread);
(void)CloseHandle(printer_dev->stopEvent);
(void)CloseHandle(printer_dev->event);
winpr_aligned_free(printer_dev->pIrpList);
}
@ -972,7 +979,7 @@ static UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrint
if (!printer_dev->device.data)
goto error_out;
sprintf_s(printer_dev->port, sizeof(printer_dev->port), "PRN%" PRIdz, printer->id);
(void)sprintf_s(printer_dev->port, sizeof(printer_dev->port), "PRN%" PRIuz, printer->id);
printer_dev->device.type = RDPDR_DTYP_PRINT;
printer_dev->device.name = printer_dev->port;
printer_dev->device.IRPRequest = printer_irp_request;
@ -1048,19 +1055,14 @@ error_out:
static rdpPrinterDriver* printer_load_backend(const char* backend)
{
typedef UINT (*backend_load_t)(rdpPrinterDriver**);
union
{
PVIRTUALCHANNELENTRY entry;
backend_load_t backend;
} fktconv;
fktconv.entry = freerdp_load_channel_addin_entry("printer", backend, NULL, 0);
if (!fktconv.entry)
typedef UINT(VCAPITYPE * backend_load_t)(rdpPrinterDriver**);
PVIRTUALCHANNELENTRY entry = freerdp_load_channel_addin_entry("printer", backend, NULL, 0);
backend_load_t func = WINPR_FUNC_PTR_CAST(entry, backend_load_t);
if (!func)
return NULL;
rdpPrinterDriver* printer = NULL;
const UINT rc = fktconv.backend(&printer);
const UINT rc = func(&printer);
if (rc != CHANNEL_RC_OK)
return NULL;
@ -1072,7 +1074,8 @@ static rdpPrinterDriver* printer_load_backend(const char* backend)
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(UINT printer_DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints))
FREERDP_ENTRY_POINT(
UINT VCAPITYPE printer_DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints))
{
char* name = NULL;
char* driver_name = NULL;

View File

@ -23,6 +23,7 @@
#include <freerdp/config.h>
#include <winpr/crt.h>
#include <winpr/wtsapi.h>
#include <winpr/string.h>
#include <winpr/windows.h>
@ -436,7 +437,7 @@ static void printer_win_release_ref_driver(rdpPrinterDriver* driver)
win->references--;
}
FREERDP_ENTRY_POINT(UINT win_freerdp_printer_client_subsystem_entry(void* arg))
FREERDP_ENTRY_POINT(UINT VCAPITYPE win_freerdp_printer_client_subsystem_entry(void* arg))
{
rdpPrinterDriver** ppPrinter = (rdpPrinterDriver**)arg;
if (!ppPrinter)

View File

@ -82,8 +82,8 @@ UINT client_rail_server_start_cmd(RailClientContext* context)
freerdp_settings_get_string(settings, FreeRDP_RemoteApplicationCmdLine);
if (RemoteApplicationFile && RemoteApplicationCmdLine)
{
_snprintf(argsAndFile, ARRAYSIZE(argsAndFile), "%s %s", RemoteApplicationCmdLine,
RemoteApplicationFile);
(void)_snprintf(argsAndFile, ARRAYSIZE(argsAndFile), "%s %s", RemoteApplicationCmdLine,
RemoteApplicationFile);
exec.RemoteApplicationArguments = argsAndFile;
}
else if (RemoteApplicationFile)

View File

@ -82,23 +82,13 @@ static UINT rail_send(railPlugin* rail, wStream* s)
*/
UINT rail_send_channel_data(railPlugin* rail, wStream* src)
{
wStream* s = NULL;
size_t length = 0;
if (!rail || !src)
return ERROR_INVALID_PARAMETER;
length = Stream_GetPosition(src);
s = Stream_New(NULL, length);
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
Stream_Free(src, TRUE);
return ERROR_INVALID_PARAMETER;
}
Stream_Write(s, Stream_Buffer(src), length);
return rail_send(rail, s);
return rail_send(rail, src);
}
/**
@ -229,13 +219,7 @@ static UINT rail_send_client_sysparam(RailClientContext* context, RAIL_SYSPARAM_
return error;
}
if ((error = rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSPARAM)))
{
WLog_ERR(TAG, "rail_send_pdu failed with error %" PRIu32 "!", error);
}
Stream_Free(s, TRUE);
return error;
return rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSPARAM);
}
/**
@ -514,6 +498,24 @@ static UINT rail_client_snap_arrange(RailClientContext* context, const RAIL_SNAP
return rail_send_client_snap_arrange_order(rail, snap);
}
static UINT rail_client_text_scale(RailClientContext* context, UINT32 textScale)
{
if (!context || !context->handle)
return ERROR_INVALID_PARAMETER;
railPlugin* rail = (railPlugin*)context->handle;
return rail_send_client_text_scale_order(rail, textScale);
}
static UINT rail_client_caret_blink_rate(RailClientContext* context, UINT32 rate)
{
if (!context || !context->handle)
return ERROR_INVALID_PARAMETER;
railPlugin* rail = (railPlugin*)context->handle;
return rail_send_client_caret_blink_rate_order(rail, rate);
}
static VOID VCAPITYPE rail_virtual_channel_open_event_ex(LPVOID lpUserParam, DWORD openHandle,
UINT event, LPVOID pData,
UINT32 dataLength, UINT32 totalLength,
@ -552,13 +554,13 @@ static VOID VCAPITYPE rail_virtual_channel_open_event_ex(LPVOID lpUserParam, DWO
case CHANNEL_EVENT_USER:
break;
default:
break;
}
if (error && rail && rail->rdpcontext)
setChannelError(rail->rdpcontext, error,
"rail_virtual_channel_open_event reported an error");
return;
}
/**
@ -693,7 +695,7 @@ FREERDP_ENTRY_POINT(BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS p
rail->sendHandshake = TRUE;
rail->channelDef.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP |
CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL;
sprintf_s(rail->channelDef.name, ARRAYSIZE(rail->channelDef.name), RAIL_SVC_CHANNEL_NAME);
(void)sprintf_s(rail->channelDef.name, ARRAYSIZE(rail->channelDef.name), RAIL_SVC_CHANNEL_NAME);
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*)pEntryPoints;
if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)) &&
@ -725,6 +727,8 @@ FREERDP_ENTRY_POINT(BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS p
context->ClientSnapArrange = rail_client_snap_arrange;
context->ClientCloak = rail_client_cloak;
context->ClientCompartmentInfo = rail_client_compartment_info;
context->ClientTextScale = rail_client_text_scale;
context->ClientCaretBlinkRate = rail_client_caret_blink_rate;
rail->rdpcontext = pEntryPointsEx->context;
rail->context = context;
isFreerdp = TRUE;

View File

@ -44,7 +44,10 @@ UINT rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType)
UINT16 orderLength = 0;
if (!rail || !s)
{
Stream_Free(s, TRUE);
return ERROR_INVALID_PARAMETER;
}
orderLength = (UINT16)Stream_GetPosition(s);
Stream_SetPosition(s, 0);
@ -1114,13 +1117,10 @@ UINT rail_order_recv(LPVOID userdata, wStream* s)
*/
UINT rail_send_handshake_order(railPlugin* rail, const RAIL_HANDSHAKE_ORDER* handshake)
{
wStream* s = NULL;
UINT error = 0;
if (!rail || !handshake)
return ERROR_INVALID_PARAMETER;
s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH);
wStream* s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH);
if (!s)
{
@ -1129,9 +1129,7 @@ UINT rail_send_handshake_order(railPlugin* rail, const RAIL_HANDSHAKE_ORDER* han
}
rail_write_handshake_order(s, handshake);
error = rail_send_pdu(rail, s, TS_RAIL_ORDER_HANDSHAKE);
Stream_Free(s, TRUE);
return error;
return rail_send_pdu(rail, s, TS_RAIL_ORDER_HANDSHAKE);
}
/**
@ -1141,13 +1139,10 @@ UINT rail_send_handshake_order(railPlugin* rail, const RAIL_HANDSHAKE_ORDER* han
*/
UINT rail_send_handshake_ex_order(railPlugin* rail, const RAIL_HANDSHAKE_EX_ORDER* handshakeEx)
{
wStream* s = NULL;
UINT error = 0;
if (!rail || !handshakeEx)
return ERROR_INVALID_PARAMETER;
s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH);
wStream* s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH);
if (!s)
{
@ -1156,9 +1151,7 @@ UINT rail_send_handshake_ex_order(railPlugin* rail, const RAIL_HANDSHAKE_EX_ORDE
}
rail_write_handshake_ex_order(s, handshakeEx);
error = rail_send_pdu(rail, s, TS_RAIL_ORDER_HANDSHAKE_EX);
Stream_Free(s, TRUE);
return error;
return rail_send_pdu(rail, s, TS_RAIL_ORDER_HANDSHAKE_EX);
}
/**
@ -1185,11 +1178,14 @@ UINT rail_send_client_status_order(railPlugin* rail, const RAIL_CLIENT_STATUS_OR
error = rail_write_client_status_order(s, clientStatus);
if (error == ERROR_SUCCESS)
error = rail_send_pdu(rail, s, TS_RAIL_ORDER_CLIENTSTATUS);
if (ERROR_SUCCESS != error)
{
Stream_Free(s, TRUE);
return error;
Stream_Free(s, TRUE);
return error;
}
return rail_send_pdu(rail, s, TS_RAIL_ORDER_CLIENTSTATUS);
}
/**
@ -1224,11 +1220,7 @@ UINT rail_send_client_exec_order(railPlugin* rail, UINT16 flags,
goto out;
}
if ((error = rail_send_pdu(rail, s, TS_RAIL_ORDER_EXEC)))
{
WLog_ERR(TAG, "rail_send_pdu failed with error %" PRIu32 "!", error);
goto out;
}
return rail_send_pdu(rail, s, TS_RAIL_ORDER_EXEC);
out:
Stream_Free(s, TRUE);
@ -1258,11 +1250,14 @@ UINT rail_send_client_activate_order(railPlugin* rail, const RAIL_ACTIVATE_ORDER
error = rail_write_client_activate_order(s, activate);
if (error == ERROR_SUCCESS)
error = rail_send_pdu(rail, s, TS_RAIL_ORDER_ACTIVATE);
if (ERROR_SUCCESS != error)
{
Stream_Free(s, TRUE);
return error;
Stream_Free(s, TRUE);
return error;
}
return rail_send_pdu(rail, s, TS_RAIL_ORDER_ACTIVATE);
}
/**
@ -1288,11 +1283,14 @@ UINT rail_send_client_sysmenu_order(railPlugin* rail, const RAIL_SYSMENU_ORDER*
error = rail_write_client_sysmenu_order(s, sysmenu);
if (error == ERROR_SUCCESS)
error = rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSMENU);
if (ERROR_SUCCESS != error)
{
Stream_Free(s, TRUE);
return error;
Stream_Free(s, TRUE);
return error;
}
return rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSMENU);
}
/**
@ -1318,11 +1316,14 @@ UINT rail_send_client_syscommand_order(railPlugin* rail, const RAIL_SYSCOMMAND_O
error = rail_write_client_syscommand_order(s, syscommand);
if (error == ERROR_SUCCESS)
error = rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSCOMMAND);
if (ERROR_SUCCESS != error)
{
Stream_Free(s, TRUE);
return error;
Stream_Free(s, TRUE);
return error;
}
return rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSCOMMAND);
}
/**
@ -1349,11 +1350,14 @@ UINT rail_send_client_notify_event_order(railPlugin* rail,
error = rail_write_client_notify_event_order(s, notifyEvent);
if (ERROR_SUCCESS == error)
error = rail_send_pdu(rail, s, TS_RAIL_ORDER_NOTIFY_EVENT);
if (ERROR_SUCCESS != error)
{
Stream_Free(s, TRUE);
return error;
Stream_Free(s, TRUE);
return error;
}
return rail_send_pdu(rail, s, TS_RAIL_ORDER_NOTIFY_EVENT);
}
/**
@ -1379,11 +1383,14 @@ UINT rail_send_client_window_move_order(railPlugin* rail, const RAIL_WINDOW_MOVE
error = rail_write_client_window_move_order(s, windowMove);
if (error == ERROR_SUCCESS)
error = rail_send_pdu(rail, s, TS_RAIL_ORDER_WINDOWMOVE);
if (ERROR_SUCCESS != error)
{
Stream_Free(s, TRUE);
return error;
Stream_Free(s, TRUE);
return error;
}
return rail_send_pdu(rail, s, TS_RAIL_ORDER_WINDOWMOVE);
}
/**
@ -1410,11 +1417,13 @@ UINT rail_send_client_get_appid_req_order(railPlugin* rail,
error = rail_write_client_get_appid_req_order(s, getAppIdReq);
if (error == ERROR_SUCCESS)
error = rail_send_pdu(rail, s, TS_RAIL_ORDER_GET_APPID_REQ);
if (ERROR_SUCCESS != error)
{
Stream_Free(s, TRUE);
return error;
Stream_Free(s, TRUE);
return error;
}
return rail_send_pdu(rail, s, TS_RAIL_ORDER_GET_APPID_REQ);
}
/**
@ -1444,11 +1453,13 @@ UINT rail_send_client_langbar_info_order(railPlugin* rail,
error = rail_write_langbar_info_order(s, langBarInfo);
if (ERROR_SUCCESS == error)
error = rail_send_pdu(rail, s, TS_RAIL_ORDER_LANGBARINFO);
if (ERROR_SUCCESS != error)
{
Stream_Free(s, TRUE);
return error;
Stream_Free(s, TRUE);
return error;
}
return rail_send_pdu(rail, s, TS_RAIL_ORDER_LANGBARINFO);
}
UINT rail_send_client_languageime_info_order(railPlugin* rail,
@ -1473,11 +1484,13 @@ UINT rail_send_client_languageime_info_order(railPlugin* rail,
error = rail_write_languageime_info_order(s, langImeInfo);
if (ERROR_SUCCESS == error)
error = rail_send_pdu(rail, s, TS_RAIL_ORDER_LANGUAGEIMEINFO);
if (ERROR_SUCCESS != error)
{
Stream_Free(s, TRUE);
return error;
Stream_Free(s, TRUE);
return error;
}
return rail_send_pdu(rail, s, TS_RAIL_ORDER_LANGUAGEIMEINFO);
}
UINT rail_send_client_compartment_info_order(railPlugin* rail,
@ -1502,22 +1515,20 @@ UINT rail_send_client_compartment_info_order(railPlugin* rail,
error = rail_write_compartment_info_order(s, compartmentInfo);
if (ERROR_SUCCESS == error)
error = rail_send_pdu(rail, s, TS_RAIL_ORDER_COMPARTMENTINFO);
Stream_Free(s, TRUE);
return error;
if (ERROR_SUCCESS != error)
{
Stream_Free(s, TRUE);
return error;
}
return rail_send_pdu(rail, s, TS_RAIL_ORDER_COMPARTMENTINFO);
}
UINT rail_send_client_cloak_order(railPlugin* rail, const RAIL_CLOAK* cloak)
{
wStream* s = NULL;
UINT error = 0;
if (!rail || !cloak)
return ERROR_INVALID_PARAMETER;
s = rail_pdu_init(5);
wStream* s = rail_pdu_init(5);
if (!s)
{
@ -1527,16 +1538,11 @@ UINT rail_send_client_cloak_order(railPlugin* rail, const RAIL_CLOAK* cloak)
Stream_Write_UINT32(s, cloak->windowId);
Stream_Write_UINT8(s, cloak->cloak ? 1 : 0);
error = rail_send_pdu(rail, s, TS_RAIL_ORDER_CLOAK);
Stream_Free(s, TRUE);
return error;
return rail_send_pdu(rail, s, TS_RAIL_ORDER_CLOAK);
}
UINT rail_send_client_snap_arrange_order(railPlugin* rail, const RAIL_SNAP_ARRANGE* snap)
{
wStream* s = NULL;
UINT error = 0;
if (!rail)
return ERROR_INVALID_PARAMETER;
@ -1552,7 +1558,7 @@ UINT rail_send_client_snap_arrange_order(railPlugin* rail, const RAIL_SNAP_ARRAN
return rail_send_client_window_move_order(rail, &move);
}
s = rail_pdu_init(12);
wStream* s = rail_pdu_init(12);
if (!s)
{
@ -1565,7 +1571,39 @@ UINT rail_send_client_snap_arrange_order(railPlugin* rail, const RAIL_SNAP_ARRAN
Stream_Write_INT16(s, snap->top);
Stream_Write_INT16(s, snap->right);
Stream_Write_INT16(s, snap->bottom);
error = rail_send_pdu(rail, s, TS_RAIL_ORDER_SNAP_ARRANGE);
Stream_Free(s, TRUE);
return error;
return rail_send_pdu(rail, s, TS_RAIL_ORDER_SNAP_ARRANGE);
}
UINT rail_send_client_text_scale_order(railPlugin* rail, UINT32 textScale)
{
if (!rail)
return ERROR_INVALID_PARAMETER;
wStream* s = rail_pdu_init(4);
if (!s)
{
WLog_ERR(TAG, "rail_pdu_init failed!");
return CHANNEL_RC_NO_MEMORY;
}
Stream_Write_UINT32(s, textScale);
return rail_send_pdu(rail, s, TS_RAIL_ORDER_TEXTSCALEINFO);
}
UINT rail_send_client_caret_blink_rate_order(railPlugin* rail, UINT32 rate)
{
if (!rail)
return ERROR_INVALID_PARAMETER;
wStream* s = rail_pdu_init(4);
if (!s)
{
WLog_ERR(TAG, "rail_pdu_init failed!");
return CHANNEL_RC_NO_MEMORY;
}
Stream_Write_UINT32(s, rate);
return rail_send_pdu(rail, s, TS_RAIL_ORDER_CARETBLINKINFO);
}

View File

@ -56,5 +56,7 @@ UINT rail_send_client_cloak_order(railPlugin* rail, const RAIL_CLOAK* cloak);
UINT rail_send_client_snap_arrange_order(railPlugin* rail, const RAIL_SNAP_ARRANGE* snap);
UINT rail_send_client_compartment_info_order(railPlugin* rail,
const RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo);
UINT rail_send_client_text_scale_order(railPlugin* rail, UINT32 textScale);
UINT rail_send_client_caret_blink_rate_order(railPlugin* rail, UINT32 rate);
#endif /* FREERDP_CHANNEL_RAIL_CLIENT_ORDERS_H */

View File

@ -90,8 +90,8 @@ const char* rail_get_order_type_string(UINT16 orderType)
const char* rail_get_order_type_string_full(UINT16 orderType, char* buffer, size_t length)
{
_snprintf(buffer, length, "%s[0x%04" PRIx16 "]", rail_get_order_type_string(orderType),
orderType);
(void)_snprintf(buffer, length, "%s[0x%04" PRIx16 "]", rail_get_order_type_string(orderType),
orderType);
return buffer;
}
@ -121,8 +121,7 @@ void rail_write_pdu_header(wStream* s, UINT16 orderType, UINT16 orderLength)
wStream* rail_pdu_init(size_t length)
{
wStream* s = NULL;
s = Stream_New(NULL, length + RAIL_PDU_HEADER_LENGTH);
wStream* s = Stream_New(NULL, length + RAIL_PDU_HEADER_LENGTH);
if (!s)
return NULL;
@ -595,7 +594,7 @@ const char* rail_handshake_ex_flags_to_string(UINT32 flags, char* buffer, size_t
if (len < 1)
return NULL;
_snprintf(buffer, len, "{");
(void)_snprintf(buffer, len, "{");
char* fbuffer = &buffer[1];
len--;
@ -613,7 +612,7 @@ const char* rail_handshake_ex_flags_to_string(UINT32 flags, char* buffer, size_t
winpr_str_append("EXTENDED_SPI_2_SUPPORTED", fbuffer, len, "|");
char number[16] = { 0 };
_snprintf(number, sizeof(number), "[0x%08" PRIx32 "]", flags);
(void)_snprintf(number, sizeof(number), "[0x%08" PRIx32 "]", flags);
winpr_str_append(number, buffer, len, "}");
return buffer;
}

View File

@ -69,7 +69,7 @@ UINT rail_write_unicode_string_value(wStream* s, const RAIL_UNICODE_STRING* unic
UINT rail_read_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam, BOOL extendedSpiSupported);
UINT rail_write_sysparam_order(wStream* s, const RAIL_SYSPARAM_ORDER* sysparam,
BOOL extendedSpiSupported);
BOOL rail_is_extended_spi_supported(UINT32 channelsFlags);
BOOL rail_is_extended_spi_supported(UINT32 channelFlags);
const char* rail_get_order_type_string(UINT16 orderType);
const char* rail_get_order_type_string_full(UINT16 orderType, char* buffer, size_t length);

View File

@ -46,7 +46,7 @@ static UINT rail_send(RailServerContext* context, wStream* s, ULONG length)
if (!context)
return CHANNEL_RC_BAD_INIT_HANDLE;
if (!WTSVirtualChannelWrite(context->priv->rail_channel, (PCHAR)Stream_Buffer(s), length,
if (!WTSVirtualChannelWrite(context->priv->rail_channel, Stream_BufferAs(s, char), length,
&written))
{
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
@ -670,14 +670,14 @@ static UINT rail_read_exec_order(wStream* s, RAIL_EXEC_ORDER* exec, char* args[]
if (exeLen > 0)
{
const SSIZE_T len = exeLen / sizeof(WCHAR);
const size_t len = exeLen / sizeof(WCHAR);
exec->RemoteApplicationProgram = args[0] = Stream_Read_UTF16_String_As_UTF8(s, len, NULL);
if (!exec->RemoteApplicationProgram)
goto fail;
}
if (workLen > 0)
{
const SSIZE_T len = workLen / sizeof(WCHAR);
const size_t len = workLen / sizeof(WCHAR);
exec->RemoteApplicationWorkingDir = args[1] =
Stream_Read_UTF16_String_As_UTF8(s, len, NULL);
if (!exec->RemoteApplicationWorkingDir)
@ -685,7 +685,7 @@ static UINT rail_read_exec_order(wStream* s, RAIL_EXEC_ORDER* exec, char* args[]
}
if (argLen > 0)
{
const SSIZE_T len = argLen / sizeof(WCHAR);
const size_t len = argLen / sizeof(WCHAR);
exec->RemoteApplicationArguments = args[2] = Stream_Read_UTF16_String_As_UTF8(s, len, NULL);
if (!exec->RemoteApplicationArguments)
goto fail;
@ -1459,21 +1459,21 @@ static UINT rail_server_start(RailServerContext* context)
return CHANNEL_RC_OK;
out_stop_event:
CloseHandle(context->priv->stopEvent);
(void)CloseHandle(context->priv->stopEvent);
context->priv->stopEvent = NULL;
out_close:
WTSVirtualChannelClose(context->priv->rail_channel);
(void)WTSVirtualChannelClose(context->priv->rail_channel);
context->priv->rail_channel = NULL;
return error;
}
static BOOL rail_server_stop(RailServerContext* context)
{
RailServerPrivate* priv = (RailServerPrivate*)context->priv;
RailServerPrivate* priv = context->priv;
if (priv->thread)
{
SetEvent(priv->stopEvent);
(void)SetEvent(priv->stopEvent);
if (WaitForSingleObject(priv->thread, INFINITE) == WAIT_FAILED)
{
@ -1481,15 +1481,15 @@ static BOOL rail_server_stop(RailServerContext* context)
return FALSE;
}
CloseHandle(priv->thread);
CloseHandle(priv->stopEvent);
(void)CloseHandle(priv->thread);
(void)CloseHandle(priv->stopEvent);
priv->thread = NULL;
priv->stopEvent = NULL;
}
if (priv->rail_channel)
{
WTSVirtualChannelClose(priv->rail_channel);
(void)WTSVirtualChannelClose(priv->rail_channel);
priv->rail_channel = NULL;
}

View File

@ -103,9 +103,9 @@ static int init_external_addin(Plugin* plugin)
}
plugin->hProcess = procInfo.hProcess;
CloseHandle(procInfo.hThread);
CloseHandle(siStartInfo.hStdOutput);
CloseHandle(siStartInfo.hStdInput);
(void)CloseHandle(procInfo.hThread);
(void)CloseHandle(siStartInfo.hStdOutput);
(void)CloseHandle(siStartInfo.hStdInput);
return 0;
}
@ -134,7 +134,7 @@ static DWORD WINAPI copyThread(void* data)
{
DWORD status = WAIT_OBJECT_0;
Plugin* plugin = (Plugin*)data;
size_t const bufsize = 16 * 1024;
size_t const bufsize = 16ULL * 1024ULL;
while (status == WAIT_OBJECT_0)
{
@ -145,7 +145,7 @@ static DWORD WINAPI copyThread(void* data)
if (!buffer)
{
fprintf(stderr, "rdp2tcp copyThread: malloc failed\n");
(void)fprintf(stderr, "rdp2tcp copyThread: malloc failed\n");
goto fail;
}
@ -167,7 +167,7 @@ static DWORD WINAPI copyThread(void* data)
plugin->initHandle, plugin->openHandle, buffer, dwRead, buffer) != CHANNEL_RC_OK)
{
free(buffer);
fprintf(stderr, "rdp2tcp copyThread failed %i\n", (int)dwRead);
(void)fprintf(stderr, "rdp2tcp copyThread failed %i\n", (int)dwRead);
goto fail;
}
@ -175,7 +175,7 @@ static DWORD WINAPI copyThread(void* data)
handles[1] = freerdp_abort_event(plugin->channelEntryPoints.context);
status = WaitForMultipleObjects(2, handles, FALSE, INFINITE);
if (status == WAIT_OBJECT_0)
ResetEvent(plugin->writeComplete);
(void)ResetEvent(plugin->writeComplete);
}
fail:
@ -246,9 +246,11 @@ static void VCAPITYPE VirtualChannelOpenEventEx(LPVOID lpUserParam, DWORD openHa
free(pData);
break;
case CHANNEL_EVENT_WRITE_COMPLETE:
SetEvent(plugin->writeComplete);
(void)SetEvent(plugin->writeComplete);
free(pData);
break;
default:
break;
}
}
@ -261,14 +263,14 @@ static void channel_terminated(Plugin* plugin)
return;
if (plugin->copyThread)
TerminateThread(plugin->copyThread, 0);
(void)TerminateThread(plugin->copyThread, 0);
if (plugin->writeComplete)
CloseHandle(plugin->writeComplete);
(void)CloseHandle(plugin->writeComplete);
CloseHandle(plugin->hStdInputWrite);
CloseHandle(plugin->hStdOutputRead);
(void)CloseHandle(plugin->hStdInputWrite);
(void)CloseHandle(plugin->hStdOutputRead);
TerminateProcess(plugin->hProcess, 0);
CloseHandle(plugin->hProcess);
(void)CloseHandle(plugin->hProcess);
free(plugin->commandline);
free(plugin);
}
@ -312,6 +314,8 @@ static VOID VCAPITYPE VirtualChannelInitEventEx(LPVOID lpUserParam, LPVOID pInit
case CHANNEL_EVENT_TERMINATED:
channel_terminated(plugin);
break;
default:
break;
}
}

View File

@ -19,6 +19,12 @@
define_channel_client("rdpdr")
include (CheckFunctionExists)
check_function_exists(getmntent_r FREERDP_HAVE_GETMNTENT_R)
if (FREERDP_HAVE_GETMNTENT_R)
add_definitions(-DFREERDP_HAVE_GETMNTENT_R)
endif()
set(${MODULE_PREFIX}_SRCS
irp.c
irp.h

View File

@ -185,8 +185,7 @@ static const char PARALLEL_SERVICE_NAME[] = "parallel";
UINT devman_load_device_service(DEVMAN* devman, const RDPDR_DEVICE* device, rdpContext* rdpcontext)
{
const char* ServiceName = NULL;
DEVICE_SERVICE_ENTRY_POINTS ep;
PDEVICE_SERVICE_ENTRY entry = NULL;
DEVICE_SERVICE_ENTRY_POINTS ep = { 0 };
union
{
const RDPDR_DEVICE* cdp;
@ -219,8 +218,9 @@ UINT devman_load_device_service(DEVMAN* devman, const RDPDR_DEVICE* device, rdpC
else
WLog_INFO(TAG, "Loading device service %s (static)", ServiceName);
entry = (PDEVICE_SERVICE_ENTRY)freerdp_load_channel_addin_entry(ServiceName, NULL,
"DeviceServiceEntry", 0);
PVIRTUALCHANNELENTRY pvce =
freerdp_load_channel_addin_entry(ServiceName, NULL, "DeviceServiceEntry", 0);
PDEVICE_SERVICE_ENTRY entry = WINPR_FUNC_PTR_CAST(pvce, PDEVICE_SERVICE_ENTRY);
if (!entry)
{

View File

@ -30,6 +30,7 @@
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <freerdp/freerdp.h>
#include <freerdp/utils/rdpdr_utils.h>
#include "rdpdr_main.h"
@ -38,16 +39,21 @@
#define RDPDR_CAPABILITY_HEADER_LENGTH 8
/* Output device direction general capability set */
static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, wStream* s)
static BOOL rdpdr_write_general_capset(rdpdrPlugin* rdpdr, wStream* s)
{
WINPR_UNUSED(rdpdr);
WINPR_ASSERT(rdpdr);
const RDPDR_CAPABILITY_HEADER header = { CAP_GENERAL_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH + 36,
GENERAL_CAPABILITY_VERSION_02 };
const UINT32 ioCode1 = rdpdr->clientIOCode1 & rdpdr->serverIOCode1;
const UINT32 ioCode2 = rdpdr->clientIOCode2 & rdpdr->serverIOCode2;
rdpdr_write_capset_header(rdpdr->log, s, &header);
if (rdpdr_write_capset_header(rdpdr->log, s, &header) != CHANNEL_RC_OK)
return FALSE;
if (!Stream_EnsureRemainingCapacity(s, 36))
return FALSE;
Stream_Write_UINT32(s, rdpdr->clientOsType); /* osType, ignored on receipt */
Stream_Write_UINT32(s, rdpdr->clientOsVersion); /* osVersion, unused and must be set to zero */
Stream_Write_UINT16(s, rdpdr->clientVersionMajor); /* protocolMajorVersion, must be set to 1 */
@ -62,6 +68,7 @@ static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, wStream* s)
Stream_Write_UINT32(
s, rdpdr->clientSpecialTypeDeviceCap); /* SpecialTypeDeviceCap, number of special devices to
be redirected before logon */
return TRUE;
}
/* Process device direction general capability set */
@ -99,12 +106,12 @@ static UINT rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* s,
}
/* Output printer direction capability set */
static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, wStream* s)
static BOOL rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, wStream* s)
{
WINPR_UNUSED(rdpdr);
const RDPDR_CAPABILITY_HEADER header = { CAP_PRINTER_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH,
PRINT_CAPABILITY_VERSION_01 };
rdpdr_write_capset_header(rdpdr->log, s, &header);
return rdpdr_write_capset_header(rdpdr->log, s, &header) == CHANNEL_RC_OK;
}
/* Process printer direction capability set */
@ -117,12 +124,12 @@ static UINT rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* s,
}
/* Output port redirection capability set */
static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, wStream* s)
static BOOL rdpdr_write_port_capset(rdpdrPlugin* rdpdr, wStream* s)
{
WINPR_UNUSED(rdpdr);
const RDPDR_CAPABILITY_HEADER header = { CAP_PORT_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH,
PORT_CAPABILITY_VERSION_01 };
rdpdr_write_capset_header(rdpdr->log, s, &header);
return rdpdr_write_capset_header(rdpdr->log, s, &header) == CHANNEL_RC_OK;
}
/* Process port redirection capability set */
@ -135,12 +142,12 @@ static UINT rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* s,
}
/* Output drive redirection capability set */
static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, wStream* s)
static BOOL rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, wStream* s)
{
WINPR_UNUSED(rdpdr);
const RDPDR_CAPABILITY_HEADER header = { CAP_DRIVE_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH,
DRIVE_CAPABILITY_VERSION_02 };
rdpdr_write_capset_header(rdpdr->log, s, &header);
return rdpdr_write_capset_header(rdpdr->log, s, &header) == CHANNEL_RC_OK;
}
/* Process drive redirection capability set */
@ -153,12 +160,12 @@ static UINT rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* s,
}
/* Output smart card redirection capability set */
static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s)
static BOOL rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s)
{
WINPR_UNUSED(rdpdr);
const RDPDR_CAPABILITY_HEADER header = { CAP_SMARTCARD_TYPE, RDPDR_CAPABILITY_HEADER_LENGTH,
SMARTCARD_CAPABILITY_VERSION_01 };
rdpdr_write_capset_header(rdpdr->log, s, &header);
return rdpdr_write_capset_header(rdpdr->log, s, &header) == CHANNEL_RC_OK;
}
/* Process smartcard redirection capability set */
@ -187,6 +194,7 @@ UINT rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s)
Stream_Read_UINT16(s, numCapabilities);
Stream_Seek(s, 2); /* pad (2 bytes) */
memset(rdpdr->capabilities, 0, sizeof(rdpdr->capabilities));
for (UINT16 i = 0; i < numCapabilities; i++)
{
RDPDR_CAPABILITY_HEADER header = { 0 };
@ -197,27 +205,31 @@ UINT rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s)
switch (header.CapabilityType)
{
case CAP_GENERAL_TYPE:
rdpdr->capabilities[header.CapabilityType] = TRUE;
status = rdpdr_process_general_capset(rdpdr, s, &header);
break;
case CAP_PRINTER_TYPE:
rdpdr->capabilities[header.CapabilityType] = TRUE;
status = rdpdr_process_printer_capset(rdpdr, s, &header);
break;
case CAP_PORT_TYPE:
rdpdr->capabilities[header.CapabilityType] = TRUE;
status = rdpdr_process_port_capset(rdpdr, s, &header);
break;
case CAP_DRIVE_TYPE:
rdpdr->capabilities[header.CapabilityType] = TRUE;
status = rdpdr_process_drive_capset(rdpdr, s, &header);
break;
case CAP_SMARTCARD_TYPE:
rdpdr->capabilities[header.CapabilityType] = TRUE;
status = rdpdr_process_smartcard_capset(rdpdr, s, &header);
break;
default:
break;
}
@ -235,10 +247,13 @@ UINT rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s)
*/
UINT rdpdr_send_capability_response(rdpdrPlugin* rdpdr)
{
wStream* s = NULL;
WINPR_ASSERT(rdpdr);
s = StreamPool_Take(rdpdr->pool, 256);
WINPR_ASSERT(rdpdr->rdpcontext);
rdpSettings* settings = rdpdr->rdpcontext->settings;
WINPR_ASSERT(settings);
wStream* s = StreamPool_Take(rdpdr->pool, 256);
if (!s)
{
@ -246,14 +261,62 @@ UINT rdpdr_send_capability_response(rdpdrPlugin* rdpdr)
return CHANNEL_RC_NO_MEMORY;
}
const RDPDR_DEVICE* cdrives =
freerdp_device_collection_find_type(settings, RDPDR_DTYP_FILESYSTEM);
const RDPDR_DEVICE* cserial = freerdp_device_collection_find_type(settings, RDPDR_DTYP_SERIAL);
const RDPDR_DEVICE* cparallel =
freerdp_device_collection_find_type(settings, RDPDR_DTYP_PARALLEL);
const RDPDR_DEVICE* csmart =
freerdp_device_collection_find_type(settings, RDPDR_DTYP_SMARTCARD);
const RDPDR_DEVICE* cprinter = freerdp_device_collection_find_type(settings, RDPDR_DTYP_PRINT);
/* Only send capabilities the server announced */
const BOOL drives = cdrives && rdpdr->capabilities[CAP_DRIVE_TYPE];
const BOOL serial = cserial && rdpdr->capabilities[CAP_PORT_TYPE];
const BOOL parallel = cparallel && rdpdr->capabilities[CAP_PORT_TYPE];
const BOOL smart = csmart && rdpdr->capabilities[CAP_SMARTCARD_TYPE];
const BOOL printer = cprinter && rdpdr->capabilities[CAP_PRINTER_TYPE];
UINT16 count = 1;
if (drives)
count++;
if (serial || parallel)
count++;
if (smart)
count++;
if (printer)
count++;
Stream_Write_UINT16(s, RDPDR_CTYP_CORE);
Stream_Write_UINT16(s, PAKID_CORE_CLIENT_CAPABILITY);
Stream_Write_UINT16(s, 5); /* numCapabilities */
Stream_Write_UINT16(s, count); /* numCapabilities */
Stream_Write_UINT16(s, 0); /* pad */
rdpdr_write_general_capset(rdpdr, s);
rdpdr_write_printer_capset(rdpdr, s);
rdpdr_write_port_capset(rdpdr, s);
rdpdr_write_drive_capset(rdpdr, s);
rdpdr_write_smartcard_capset(rdpdr, s);
if (!rdpdr_write_general_capset(rdpdr, s))
goto fail;
if (printer)
{
if (!rdpdr_write_printer_capset(rdpdr, s))
goto fail;
}
if (serial || parallel)
{
if (!rdpdr_write_port_capset(rdpdr, s))
goto fail;
}
if (drives)
{
if (!rdpdr_write_drive_capset(rdpdr, s))
goto fail;
}
if (smart)
{
if (!rdpdr_write_smartcard_capset(rdpdr, s))
goto fail;
}
return rdpdr_send(rdpdr, s);
fail:
Stream_Release(s);
return ERROR_OUTOFMEMORY;
}

View File

@ -27,6 +27,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <winpr/crt.h>
#include <winpr/sysinfo.h>
@ -223,7 +224,7 @@ static BOOL rdpdr_load_drive(rdpdrPlugin* rdpdr, const char* name, const char* p
fail:
freerdp_device_free(drive.device);
return rc;
return rc == CHANNEL_RC_OK;
}
/**
@ -514,19 +515,19 @@ typedef struct
*/
static UINT handle_hotplug(rdpdrPlugin* rdpdr)
{
struct dirent* pDirent;
DIR* pDir;
char fullpath[PATH_MAX];
struct dirent* pDirent = NULL;
char fullpath[PATH_MAX] = { 0 };
char* szdir = (char*)"/Volumes";
struct stat buf;
hotplug_dev dev_array[MAX_USB_DEVICES];
int count;
DEVICE_DRIVE_EXT* device_ext;
struct stat buf = { 0 };
hotplug_dev dev_array[MAX_USB_DEVICES] = { 0 };
int count = 0;
DEVICE_DRIVE_EXT* device_ext = NULL;
ULONG_PTR* keys = NULL;
int size = 0;
UINT error;
UINT error = ERROR_INTERNAL_ERROR;
UINT32 ids[1];
pDir = opendir(szdir);
DIR* pDir = opendir(szdir);
if (pDir == NULL)
{
@ -706,7 +707,7 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg)
out:
if (rdpdr->stopEvent)
{
CloseHandle(rdpdr->stopEvent);
(void)CloseHandle(rdpdr->stopEvent);
rdpdr->stopEvent = NULL;
}
ExitThread(CHANNEL_RC_OK);
@ -737,12 +738,15 @@ static BOOL isAutomountLocation(const char* path)
const char* location = automountLocations[x];
size_t length = 0;
WINPR_PRAGMA_DIAG_PUSH
WINPR_PRAGMA_DIAG_IGNORED_FORMAT_NONLITERAL
if (strstr(location, "%lu"))
snprintf(buffer, sizeof(buffer), location, (unsigned long)uid);
(void)snprintf(buffer, sizeof(buffer), location, (unsigned long)uid);
else if (strstr(location, "%s"))
snprintf(buffer, sizeof(buffer), location, uname);
(void)snprintf(buffer, sizeof(buffer), location, uname);
else
snprintf(buffer, sizeof(buffer), "%s", location);
(void)snprintf(buffer, sizeof(buffer), "%s", location);
WINPR_PRAGMA_DIAG_POP
length = strnlen(buffer, sizeof(buffer));
@ -834,9 +838,25 @@ static UINT handle_platform_mounts_bsd(wLog* log, hotplug_dev* dev_array, size_t
#if defined(__LINUX__) || defined(__linux__)
#include <mntent.h>
static struct mntent* getmntent_x(FILE* f, struct mntent* buffer, char* pathbuffer,
size_t pathbuffersize)
{
#if defined(FREERDP_HAVE_GETMNTENT_R)
WINPR_ASSERT(pathbuffersize <= INT32_MAX);
return getmntent_r(f, buffer, pathbuffer, (int)pathbuffersize);
#else
(void)buffer;
(void)pathbuffer;
(void)pathbuffersize;
return getmntent(f);
#endif
}
static UINT handle_platform_mounts_linux(wLog* log, hotplug_dev* dev_array, size_t* size)
{
FILE* f = NULL;
struct mntent mnt = { 0 };
char pathbuffer[PATH_MAX] = { 0 };
struct mntent* ent = NULL;
f = winpr_fopen("/proc/mounts", "r");
if (f == NULL)
@ -844,11 +864,11 @@ static UINT handle_platform_mounts_linux(wLog* log, hotplug_dev* dev_array, size
WLog_Print(log, WLOG_ERROR, "fopen failed!");
return ERROR_OPEN_FAILED;
}
while ((ent = getmntent(f)) != NULL)
while ((ent = getmntent_x(f, &mnt, pathbuffer, sizeof(pathbuffer))) != NULL)
{
handle_mountpoint(dev_array, size, ent->mnt_dir);
}
fclose(f);
(void)fclose(f);
return ERROR_SUCCESS;
}
#endif
@ -919,6 +939,7 @@ static BOOL hotplug_delete_foreach(ULONG_PTR key, void* element, void* data)
WINPR_ASSERT(arg);
WINPR_ASSERT(arg->rdpdr);
WINPR_ASSERT(arg->dev_array || (arg->dev_array_size == 0));
WINPR_ASSERT(key <= UINT32_MAX);
if (!device_ext || (device_ext->device.type != RDPDR_DTYP_FILESYSTEM) || !device_ext->path ||
!device_ext->automount)
@ -949,7 +970,7 @@ static BOOL hotplug_delete_foreach(ULONG_PTR key, void* element, void* data)
if (!dev_found)
{
UINT error = 0;
UINT32 ids[1] = { key };
UINT32 ids[1] = { (UINT32)key };
WINPR_ASSERT(arg->rdpdr->devman);
devman_unregister_device(arg->rdpdr->devman, (void*)key);
@ -1064,7 +1085,7 @@ out:
if (rdpdr->stopEvent)
{
CloseHandle(rdpdr->stopEvent);
(void)CloseHandle(rdpdr->stopEvent);
rdpdr->stopEvent = NULL;
}
@ -1090,7 +1111,7 @@ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr)
{
#if !defined(_WIN32)
if (rdpdr->stopEvent)
SetEvent(rdpdr->stopEvent);
(void)SetEvent(rdpdr->stopEvent);
#endif
#ifdef __MACOSX__
CFRunLoopStop(rdpdr->runLoop);
@ -1104,7 +1125,7 @@ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr)
return error;
}
CloseHandle(rdpdr->hotplugThread);
(void)CloseHandle(rdpdr->hotplugThread);
rdpdr->hotplugThread = NULL;
}
@ -1157,7 +1178,8 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr)
if (!drive->Path)
continue;
BOOL hotplugAll = strncmp(drive->Path, "*", 2) == 0;
const char wildcard[] = "*";
BOOL hotplugAll = strncmp(drive->Path, wildcard, sizeof(wildcard)) == 0;
BOOL hotplugLater = strncmp(drive->Path, DynamicDrives, sizeof(DynamicDrives)) == 0;
if (hotplugAll || hotplugLater)
@ -1249,7 +1271,7 @@ static UINT rdpdr_send_client_announce_reply(rdpdrPlugin* rdpdr)
Stream_Write_UINT16(s, PAKID_CORE_CLIENTID_CONFIRM); /* PacketId (2 bytes) */
Stream_Write_UINT16(s, rdpdr->clientVersionMajor);
Stream_Write_UINT16(s, rdpdr->clientVersionMinor);
Stream_Write_UINT32(s, (UINT32)rdpdr->clientID);
Stream_Write_UINT32(s, rdpdr->clientID);
return rdpdr_send(rdpdr, s);
}
@ -1296,7 +1318,7 @@ static UINT rdpdr_send_client_name_request(rdpdrPlugin* rdpdr)
Stream_Write_UINT32(s, 0); /* codePage, must be set to zero */
Stream_Write_UINT32(s,
(UINT32)computerNameLenW); /* computerNameLen, including null terminator */
Stream_Write(s, computerNameW, (size_t)computerNameLenW);
Stream_Write(s, computerNameW, computerNameLenW);
free(computerNameW);
return rdpdr_send(rdpdr, s);
}
@ -1626,7 +1648,7 @@ static const char* state_str(size_t count, va_list ap, char* buffer, size_t size
static BOOL rdpdr_state_check(rdpdrPlugin* rdpdr, UINT16 packetid, enum RDPDR_CHANNEL_STATE next,
size_t count, ...)
{
va_list ap;
va_list ap = { 0 };
WINPR_ASSERT(rdpdr);
va_start(ap, count);
@ -1858,8 +1880,7 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s)
*/
UINT rdpdr_send(rdpdrPlugin* rdpdr, wStream* s)
{
UINT status = 0;
rdpdrPlugin* plugin = (rdpdrPlugin*)rdpdr;
rdpdrPlugin* plugin = rdpdr;
if (!s)
{
@ -1874,9 +1895,13 @@ UINT rdpdr_send(rdpdrPlugin* rdpdr, wStream* s)
}
const size_t pos = Stream_GetPosition(s);
rdpdr_dump_send_packet(rdpdr->log, WLOG_TRACE, s, "[rdpdr-channel] send");
status = plugin->channelEntryPoints.pVirtualChannelWriteEx(
plugin->InitHandle, plugin->OpenHandle, Stream_Buffer(s), pos, s);
UINT status = ERROR_INTERNAL_ERROR;
if (pos <= UINT32_MAX)
{
rdpdr_dump_send_packet(rdpdr->log, WLOG_TRACE, s, "[rdpdr-channel] send");
status = plugin->channelEntryPoints.pVirtualChannelWriteEx(
plugin->InitHandle, plugin->OpenHandle, Stream_Buffer(s), (UINT32)pos, s);
}
if (status != CHANNEL_RC_OK)
{
@ -2009,13 +2034,13 @@ static VOID VCAPITYPE rdpdr_virtual_channel_open_event_ex(LPVOID lpUserParam, DW
case CHANNEL_EVENT_USER:
break;
default:
break;
}
if (error && rdpdr && rdpdr->rdpcontext)
setChannelError(rdpdr->rdpcontext, error,
"rdpdr_virtual_channel_open_event_ex reported an error");
return;
}
static DWORD WINAPI rdpdr_virtual_channel_client_thread(LPVOID arg)
@ -2176,7 +2201,7 @@ static UINT rdpdr_virtual_channel_event_disconnected(rdpdrPlugin* rdpdr)
}
if (rdpdr->thread)
CloseHandle(rdpdr->thread);
(void)CloseHandle(rdpdr->thread);
MessageQueue_Free(rdpdr->queue);
rdpdr->queue = NULL;
rdpdr->thread = NULL;
@ -2311,7 +2336,8 @@ FREERDP_ENTRY_POINT(BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS p
rdpdr->channelDef.options =
CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP;
sprintf_s(rdpdr->channelDef.name, ARRAYSIZE(rdpdr->channelDef.name), RDPDR_SVC_CHANNEL_NAME);
(void)sprintf_s(rdpdr->channelDef.name, ARRAYSIZE(rdpdr->channelDef.name),
RDPDR_SVC_CHANNEL_NAME);
rdpdr->sequenceId = 0;
pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*)pEntryPoints;

View File

@ -113,6 +113,7 @@ typedef struct
wStreamPool* pool;
wLog* log;
BOOL async;
BOOL capabilities[6];
} rdpdrPlugin;
BOOL rdpdr_state_advance(rdpdrPlugin* rdpdr, enum RDPDR_CHANNEL_STATE next);

View File

@ -206,7 +206,6 @@ static RDPDR_IRP* rdpdr_server_dequeue_irp(RdpdrServerContext* context, UINT32 c
static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context, wStream* s)
{
BOOL status = 0;
size_t length = 0;
ULONG written = 0;
WINPR_ASSERT(context);
@ -214,8 +213,8 @@ static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context, wStream* s
WINPR_ASSERT(s);
Stream_SealLength(s);
length = Stream_Length(s);
WINPR_ASSERT(length <= ULONG_MAX);
const size_t length = Stream_Length(s);
WINPR_ASSERT(length <= UINT32_MAX);
Stream_SetPosition(s, 0);
if (length >= RDPDR_HEADER_LENGTH)
@ -230,7 +229,7 @@ static UINT rdpdr_seal_send_free_request(RdpdrServerContext* context, wStream* s
rdpdr_packetid_string(header.PacketId), header.PacketId);
}
winpr_HexLogDump(context->priv->log, WLOG_DEBUG, Stream_Buffer(s), Stream_Length(s));
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR)Stream_Buffer(s),
status = WTSVirtualChannelWrite(context->priv->ChannelHandle, Stream_BufferAs(s, char),
(ULONG)length, &written);
Stream_Free(s, TRUE);
return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR;
@ -463,13 +462,9 @@ static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* context
switch (VersionMinor)
{
case RDPDR_MINOR_RDP_VERSION_13:
break;
case RDPDR_MINOR_RDP_VERSION_6_X:
break;
case RDPDR_MINOR_RDP_VERSION_5_2:
break;
case RDPDR_MINOR_RDP_VERSION_5_1:
break;
case RDPDR_MINOR_RDP_VERSION_5_0:
break;
default:
@ -1540,7 +1535,9 @@ static UINT rdpdr_server_receive_io_lock_control_request(RdpdrServerContext* con
WLog_Print(context->priv->log, WLOG_WARN,
"[MS-RDPEFS] 2.2.3.3.12 Server Drive Lock Control Request (DR_DRIVE_LOCK_REQ) "
"not implemented");
"[Lock=0x%08" PRIx32 "]"
"not implemented",
Lock);
WLog_Print(context->priv->log, WLOG_WARN, "TODO");
return CHANNEL_RC_OK;
@ -2079,8 +2076,8 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg)
break;
}
capacity = MIN(Stream_Capacity(s), ULONG_MAX);
if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR)Stream_Buffer(s),
capacity = MIN(Stream_Capacity(s), UINT32_MAX);
if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, Stream_BufferAs(s, char),
(ULONG)capacity, &BytesReturned))
{
WLog_Print(context->priv->log, WLOG_ERROR, "WTSVirtualChannelRead failed!");
@ -2149,7 +2146,7 @@ static UINT rdpdr_server_start(RdpdrServerContext* context)
CreateThread(NULL, 0, rdpdr_server_thread, (void*)context, 0, NULL)))
{
WLog_Print(context->priv->log, WLOG_ERROR, "CreateThread failed!");
CloseHandle(context->priv->StopEvent);
(void)CloseHandle(context->priv->StopEvent);
context->priv->StopEvent = NULL;
return ERROR_INTERNAL_ERROR;
}
@ -2170,7 +2167,7 @@ static UINT rdpdr_server_stop(RdpdrServerContext* context)
if (context->priv->StopEvent)
{
SetEvent(context->priv->StopEvent);
(void)SetEvent(context->priv->StopEvent);
if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED)
{
@ -2180,15 +2177,15 @@ static UINT rdpdr_server_stop(RdpdrServerContext* context)
return error;
}
CloseHandle(context->priv->Thread);
(void)CloseHandle(context->priv->Thread);
context->priv->Thread = NULL;
CloseHandle(context->priv->StopEvent);
(void)CloseHandle(context->priv->StopEvent);
context->priv->StopEvent = NULL;
}
if (context->priv->ChannelHandle)
{
WTSVirtualChannelClose(context->priv->ChannelHandle);
(void)WTSVirtualChannelClose(context->priv->ChannelHandle);
context->priv->ChannelHandle = NULL;
}
return CHANNEL_RC_OK;

View File

@ -0,0 +1,38 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2023 David Fort <contact@hardening-consulting.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
if (NOT IOS AND NOT WIN32 AND NOT ANDROID)
find_package(KRB5)
if(KRB5_FOUND)
define_channel("rdpear")
include_directories(common)
if(WITH_CLIENT_CHANNELS OR WITH_SERVER_CHANNELS)
add_subdirectory(common)
endif()
if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()
#if(WITH_SERVER_CHANNELS)
# add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
#endif()
endif()
endif()

View File

@ -0,0 +1,13 @@
set(OPTION_DEFAULT OFF)
set(OPTION_CLIENT_DEFAULT OFF)
set(OPTION_SERVER_DEFAULT OFF)
define_channel_options(NAME "rdpear" TYPE "dynamic"
DESCRIPTION "Authentication redirection Virtual Channel Extension"
SPECIFICATIONS "[MS-RDPEAR]"
DEFAULT ${OPTION_DEFAULT})
define_channel_client_options(${OPTION_CLIENT_DEFAULT})
define_channel_server_options(${OPTION_SERVER_DEFAULT})

View File

@ -0,0 +1,31 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2023 David Fort <contact@hardening-consulting.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
define_channel_client("rdpear")
set(${MODULE_PREFIX}_SRCS
rdpear_main.c
)
set(${MODULE_PREFIX}_LIBS
winpr
freerdp
rdpear-common
)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")

View File

@ -0,0 +1,989 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Authentication redirection virtual channel
*
* Copyright 2023 David Fort <contact@hardening-consulting.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <krb5.h>
#include <errno.h>
#include <winpr/assert.h>
#include <winpr/wtypes.h>
#include <winpr/crt.h>
#include <winpr/wlog.h>
#include <winpr/print.h>
#include <winpr/asn1.h>
#include <winpr/sspi.h>
#include <winpr/collections.h>
#include <rdpear-common/ndr.h>
#include <rdpear-common/rdpear_common.h>
#include <rdpear-common/rdpear_asn1.h>
#include <freerdp/config.h>
#include <freerdp/freerdp.h>
#include <freerdp/addin.h>
#include <freerdp/client/channels.h>
#include <freerdp/channels/log.h>
#include <freerdp/channels/rdpear.h>
#define TAG CHANNELS_TAG("rdpear.client")
/* defined in libkrb5 */
krb5_error_code encode_krb5_authenticator(const krb5_authenticator* rep, krb5_data** code_out);
krb5_error_code encode_krb5_ap_rep(const krb5_ap_rep* rep, krb5_data** code_out);
typedef struct
{
GENERIC_DYNVC_PLUGIN base;
rdpContext* rdp_context;
krb5_context krbContext;
} RDPEAR_PLUGIN;
static const BYTE payloadHeader[16] = { 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static krb5_error_code RPC_ENCRYPTION_KEY_to_keyblock(krb5_context ctx,
const KERB_RPC_ENCRYPTION_KEY* key,
krb5_keyblock** pkeyblock)
{
WINPR_ASSERT(ctx);
WINPR_ASSERT(key);
WINPR_ASSERT(pkeyblock);
if (!key->reserved3.length)
return KRB5KDC_ERR_NULL_KEY;
krb5_error_code rv =
krb5_init_keyblock(ctx, (krb5_enctype)key->reserved2, key->reserved3.length, pkeyblock);
if (rv)
return rv;
krb5_keyblock* keyblock = *pkeyblock;
memcpy(keyblock->contents, key->reserved3.value, key->reserved3.length);
return rv;
}
static krb5_error_code kerb_do_checksum(krb5_context ctx, const KERB_RPC_ENCRYPTION_KEY* key,
krb5_keyusage kusage, krb5_cksumtype cksumtype,
const KERB_ASN1_DATA* plain, krb5_checksum* out)
{
WINPR_ASSERT(ctx);
WINPR_ASSERT(key);
WINPR_ASSERT(plain);
WINPR_ASSERT(out);
krb5_keyblock* keyblock = NULL;
krb5_data data = { 0 };
krb5_error_code rv = RPC_ENCRYPTION_KEY_to_keyblock(ctx, key, &keyblock);
if (rv)
return rv;
data.data = (char*)plain->Asn1Buffer;
data.length = plain->Asn1BufferHints.count;
rv = krb5_c_make_checksum(ctx, cksumtype, keyblock, kusage, &data, out);
krb5_free_keyblock(ctx, keyblock);
return rv;
}
static krb5_error_code kerb_do_encrypt(krb5_context ctx, const KERB_RPC_ENCRYPTION_KEY* key,
krb5_keyusage kusage, const KERB_ASN1_DATA* plain,
krb5_data* out)
{
WINPR_ASSERT(ctx);
WINPR_ASSERT(key);
WINPR_ASSERT(plain);
WINPR_ASSERT(out);
krb5_keyblock* keyblock = NULL;
krb5_data data = { 0 };
krb5_enc_data enc = { 0 };
size_t elen = 0;
krb5_error_code rv = RPC_ENCRYPTION_KEY_to_keyblock(ctx, key, &keyblock);
if (rv)
return rv;
data.data = (char*)plain->Asn1Buffer;
data.length = plain->Asn1BufferHints.count;
rv = krb5_c_encrypt_length(ctx, keyblock->enctype, data.length, &elen);
if (rv)
goto out;
if (!elen || (elen > UINT32_MAX))
{
rv = KRB5_PARSE_MALFORMED;
goto out;
}
enc.ciphertext.length = (unsigned int)elen;
enc.ciphertext.data = malloc(elen);
if (!enc.ciphertext.data)
{
rv = ENOMEM;
goto out;
}
rv = krb5_c_encrypt(ctx, keyblock, kusage, NULL, &data, &enc);
out->data = enc.ciphertext.data;
out->length = enc.ciphertext.length;
out:
krb5_free_keyblock(ctx, keyblock);
return rv;
}
static krb5_error_code kerb_do_decrypt(krb5_context ctx, const KERB_RPC_ENCRYPTION_KEY* key,
krb5_keyusage kusage, const krb5_data* cipher,
KERB_ASN1_DATA* plain)
{
WINPR_ASSERT(ctx);
WINPR_ASSERT(key);
WINPR_ASSERT(cipher);
WINPR_ASSERT(cipher->length);
WINPR_ASSERT(plain);
krb5_keyblock* keyblock = NULL;
krb5_data data = { 0 };
krb5_enc_data enc = { 0 };
krb5_error_code rv = RPC_ENCRYPTION_KEY_to_keyblock(ctx, key, &keyblock);
if (rv)
return rv;
enc.kvno = KRB5_PVNO;
enc.enctype = (krb5_enctype)key->reserved2;
enc.ciphertext.length = cipher->length;
enc.ciphertext.data = cipher->data;
data.length = cipher->length;
data.data = (char*)malloc(cipher->length);
if (!data.data)
{
rv = ENOMEM;
goto out;
}
rv = krb5_c_decrypt(ctx, keyblock, kusage, NULL, &enc, &data);
plain->Asn1Buffer = (BYTE*)data.data;
plain->Asn1BufferHints.count = data.length;
out:
krb5_free_keyblock(ctx, keyblock);
return rv;
}
static BOOL rdpear_send_payload(RDPEAR_PLUGIN* rdpear, IWTSVirtualChannelCallback* pChannelCallback,
RdpEarPackageType packageType, wStream* payload)
{
GENERIC_CHANNEL_CALLBACK* callback = (GENERIC_CHANNEL_CALLBACK*)pChannelCallback;
BOOL ret = FALSE;
wStream* finalStream = NULL;
SecBuffer cryptedBuffer = { 0 };
wStream* unencodedContent = rdpear_encodePayload(packageType, payload);
if (!unencodedContent)
goto out;
const size_t unencodedLen = Stream_GetPosition(unencodedContent);
#if UINT32_MAX < SIZE_MAX
if (unencodedLen > UINT32_MAX)
goto out;
#endif
SecBuffer inBuffer = { (ULONG)unencodedLen, SECBUFFER_DATA, Stream_Buffer(unencodedContent) };
if (!freerdp_nla_encrypt(rdpear->rdp_context, &inBuffer, &cryptedBuffer))
goto out;
finalStream = Stream_New(NULL, 200);
if (!finalStream)
goto out;
Stream_Write_UINT32(finalStream, 0x4EACC3C8); /* ProtocolMagic (4 bytes) */
Stream_Write_UINT32(finalStream, cryptedBuffer.cbBuffer); /* Length (4 bytes) */
Stream_Write_UINT32(finalStream, 0x00000000); /* Version (4 bytes) */
Stream_Write_UINT32(finalStream, 0x00000000); /* Reserved (4 bytes) */
Stream_Write_UINT64(finalStream, 0); /* TsPkgContext (8 bytes) */
/* payload */
if (!Stream_EnsureRemainingCapacity(finalStream, cryptedBuffer.cbBuffer))
goto out;
Stream_Write(finalStream, cryptedBuffer.pvBuffer, cryptedBuffer.cbBuffer);
const size_t pos = Stream_GetPosition(finalStream);
#if UINT32_MAX < SIZE_MAX
if (pos > UINT32_MAX)
goto out;
#endif
UINT status =
callback->channel->Write(callback->channel, (ULONG)pos, Stream_Buffer(finalStream), NULL);
ret = (status == CHANNEL_RC_OK);
if (!ret)
WLog_DBG(TAG, "rdpear_send_payload=0x%x", status);
out:
sspi_SecBufferFree(&cryptedBuffer);
Stream_Free(unencodedContent, TRUE);
Stream_Free(finalStream, TRUE);
return ret;
}
static BOOL rdpear_prepare_response(NdrContext* rcontext, UINT16 callId, UINT32 status,
NdrContext** pwcontext, wStream* retStream)
{
WINPR_ASSERT(rcontext);
WINPR_ASSERT(pwcontext);
BOOL ret = FALSE;
*pwcontext = NULL;
NdrContext* wcontext = ndr_context_copy(rcontext);
if (!wcontext)
return FALSE;
if (!Stream_EnsureRemainingCapacity(retStream, sizeof(payloadHeader)))
goto out;
Stream_Write(retStream, payloadHeader, sizeof(payloadHeader));
if (!ndr_write_header(wcontext, retStream) || !ndr_start_constructed(wcontext, retStream) ||
!ndr_write_pickle(wcontext, retStream) || /* pickle header */
!ndr_write_uint16(wcontext, retStream, callId) || /* callId */
!ndr_write_uint16(wcontext, retStream, 0x0000) || /* align padding */
!ndr_write_uint32(wcontext, retStream, status) || /* status */
!ndr_write_uint16(wcontext, retStream, callId) || /* callId */
!ndr_write_uint16(wcontext, retStream, 0x0000)) /* align padding */
goto out;
*pwcontext = wcontext;
ret = TRUE;
out:
if (!ret)
ndr_context_destroy(&wcontext);
return ret;
}
static BOOL rdpear_kerb_version(NdrContext* rcontext, wStream* s, UINT32* pstatus, UINT32* pversion)
{
*pstatus = ERROR_INVALID_DATA;
if (!ndr_read_uint32(rcontext, s, pversion))
return TRUE;
WLog_DBG(TAG, "-> KerbNegotiateVersion(v=0x%x)", *pversion);
*pstatus = 0;
return TRUE;
}
static BOOL rdpear_kerb_ComputeTgsChecksum(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext, wStream* s,
UINT32* pstatus, KERB_ASN1_DATA* resp)
{
ComputeTgsChecksumReq req = { 0 };
krb5_checksum checksum = { 0 };
wStream* asn1Payload = NULL;
*pstatus = ERROR_INVALID_DATA;
WLog_DBG(TAG, "-> ComputeTgsChecksum");
if (!ndr_read_ComputeTgsChecksumReq(rcontext, s, NULL, &req) ||
!ndr_treat_deferred_read(rcontext, s))
goto out;
// ComputeTgsChecksumReq_dump(WLog_Get(""), WLOG_DEBUG, &req);
krb5_error_code rv =
kerb_do_checksum(rdpear->krbContext, req.Key, KRB5_KEYUSAGE_TGS_REQ_AUTH_CKSUM,
(krb5_cksumtype)req.ChecksumType, req.requestBody, &checksum);
if (rv)
goto out;
asn1Payload = rdpear_enc_Checksum(req.ChecksumType, &checksum);
if (!asn1Payload)
goto out;
resp->Pdu = 8;
resp->Asn1Buffer = Stream_Buffer(asn1Payload);
const size_t pos = Stream_GetPosition(asn1Payload);
if (pos > UINT32_MAX)
goto out;
resp->Asn1BufferHints.count = (UINT32)pos;
*pstatus = 0;
out:
ndr_destroy_ComputeTgsChecksumReq(rcontext, NULL, &req);
krb5_free_checksum_contents(rdpear->krbContext, &checksum);
Stream_Free(asn1Payload, FALSE);
return TRUE;
}
static BOOL rdpear_kerb_BuildEncryptedAuthData(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext,
wStream* s, UINT32* pstatus, KERB_ASN1_DATA* asn1)
{
BuildEncryptedAuthDataReq req = { 0 };
krb5_data encrypted = { 0 };
wStream* asn1Payload = NULL;
krb5_error_code rv = 0;
*pstatus = ERROR_INVALID_DATA;
WLog_DBG(TAG, "-> BuildEncryptedAuthData");
if (!ndr_read_BuildEncryptedAuthDataReq(rcontext, s, NULL, &req) ||
!ndr_treat_deferred_read(rcontext, s))
goto out;
rv = kerb_do_encrypt(rdpear->krbContext, req.Key, (krb5_keyusage)req.KeyUsage,
req.PlainAuthData, &encrypted);
if (rv)
goto out;
/* do the encoding */
asn1Payload = rdpear_enc_EncryptedData(req.Key->reserved2, &encrypted);
if (!asn1Payload)
goto out;
// WLog_DBG(TAG, "rdpear_kerb_BuildEncryptedAuthData resp=");
// winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(asn1Payload), Stream_GetPosition(asn1Payload));
asn1->Pdu = 6;
asn1->Asn1Buffer = Stream_Buffer(asn1Payload);
const size_t pos = Stream_GetPosition(asn1Payload);
if (pos > UINT32_MAX)
goto out;
asn1->Asn1BufferHints.count = (UINT32)pos;
*pstatus = 0;
out:
krb5_free_data_contents(rdpear->krbContext, &encrypted);
ndr_destroy_BuildEncryptedAuthDataReq(rcontext, NULL, &req);
Stream_Free(asn1Payload, FALSE);
return TRUE;
}
static char* KERB_RPC_UNICODESTR_to_charptr(const RPC_UNICODE_STRING* src)
{
WINPR_ASSERT(src);
return ConvertWCharNToUtf8Alloc(src->Buffer, src->strLength, NULL);
}
static BOOL extractAuthData(const KERB_ASN1_DATA* src, krb5_authdata* authData, BOOL* haveData)
{
WinPrAsn1Decoder dec = { 0 };
WinPrAsn1Decoder dec2 = { 0 };
WinPrAsn1Decoder dec3 = { 0 };
WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, src->Asn1Buffer, src->Asn1BufferHints.count);
BOOL error = FALSE;
WinPrAsn1_INTEGER adType = 0;
WinPrAsn1_OctetString os = { 0 };
*haveData = FALSE;
if (!WinPrAsn1DecReadSequence(&dec, &dec2))
return FALSE;
wStream subStream = WinPrAsn1DecGetStream(&dec2);
if (!Stream_GetRemainingLength(&subStream))
return TRUE;
if (!WinPrAsn1DecReadSequence(&dec2, &dec3))
return FALSE;
if (!WinPrAsn1DecReadContextualInteger(&dec3, 0, &error, &adType) ||
!WinPrAsn1DecReadContextualOctetString(&dec3, 1, &error, &os, FALSE))
return FALSE;
if (os.len > UINT32_MAX)
return FALSE;
authData->ad_type = adType;
authData->length = (unsigned int)os.len;
authData->contents = os.data;
*haveData = TRUE;
return TRUE;
}
static BOOL extractChecksum(const KERB_ASN1_DATA* src, krb5_checksum* dst)
{
WinPrAsn1Decoder dec = { 0 };
WinPrAsn1Decoder dec2 = { 0 };
WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, src->Asn1Buffer, src->Asn1BufferHints.count);
BOOL error = FALSE;
WinPrAsn1_OctetString os;
if (!WinPrAsn1DecReadSequence(&dec, &dec2))
return FALSE;
WinPrAsn1_INTEGER cksumtype = 0;
if (!WinPrAsn1DecReadContextualInteger(&dec2, 0, &error, &cksumtype) ||
!WinPrAsn1DecReadContextualOctetString(&dec2, 1, &error, &os, FALSE))
return FALSE;
if (os.len > UINT32_MAX)
return FALSE;
dst->checksum_type = cksumtype;
dst->length = (unsigned int)os.len;
dst->contents = os.data;
return TRUE;
}
#define FILETIME_TO_UNIX_OFFSET_S 11644473600LL
static LONGLONG krb5_time_to_FILETIME(const krb5_timestamp* ts, krb5_int32 usec)
{
WINPR_ASSERT(ts);
return (((*ts + FILETIME_TO_UNIX_OFFSET_S) * (1000LL * 1000LL) + usec) * 10LL);
}
static void krb5_free_principal_contents(krb5_context ctx, krb5_principal principal)
{
WINPR_ASSERT(principal);
krb5_free_data_contents(ctx, &principal->realm);
krb5_free_data(ctx, principal->data);
}
static BOOL rdpear_kerb_CreateApReqAuthenticator(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext,
wStream* s, UINT32* pstatus,
CreateApReqAuthenticatorResp* resp)
{
krb5_error_code rv = 0;
wStream* asn1EncodedAuth = NULL;
CreateApReqAuthenticatorReq req = { 0 };
krb5_data authenticator = { 0 };
krb5_data* der = NULL;
krb5_keyblock* subkey = NULL;
krb5_principal_data client = { 0 };
*pstatus = ERROR_INVALID_DATA;
WLog_DBG(TAG, "-> CreateApReqAuthenticator");
if (!ndr_read_CreateApReqAuthenticatorReq(rcontext, s, NULL, &req) ||
!ndr_treat_deferred_read(rcontext, s))
goto out;
krb5_authdata authdata = { 0 };
krb5_authdata* authDataPtr[2] = { &authdata, NULL };
BOOL haveData = 0;
if (!extractAuthData(req.AuthData, &authdata, &haveData))
{
WLog_ERR(TAG, "error retrieving auth data");
winpr_HexDump(TAG, WLOG_DEBUG, req.AuthData->Asn1Buffer,
req.AuthData->Asn1BufferHints.count);
goto out;
}
if (req.SkewTime->QuadPart)
{
WLog_ERR(TAG, "!!!!! should handle SkewTime !!!!!");
}
if (req.SubKey)
{
rv = RPC_ENCRYPTION_KEY_to_keyblock(rdpear->krbContext, req.SubKey, &subkey);
if (rv)
{
WLog_ERR(TAG, "error importing subkey");
goto out;
}
}
krb5_authenticator authent = { .checksum = NULL,
.subkey = NULL,
.seq_number = req.SequenceNumber,
.authorization_data = haveData ? authDataPtr : NULL };
client.type = req.ClientName->NameType;
if (req.ClientName->nameHints.count > INT32_MAX)
goto out;
client.length = (krb5_int32)req.ClientName->nameHints.count;
client.data = calloc(req.ClientName->nameHints.count, sizeof(krb5_data));
if (!client.data)
goto out;
for (int i = 0; i < client.length; i++)
{
client.data[i].data = KERB_RPC_UNICODESTR_to_charptr(&req.ClientName->Names[i]);
if (!client.data[i].data)
goto out;
client.data[i].length = (unsigned int)strnlen(client.data[i].data, UINT32_MAX);
}
client.realm.data = KERB_RPC_UNICODESTR_to_charptr(req.ClientRealm);
if (!client.realm.data)
goto out;
client.realm.length = (unsigned int)strnlen(client.realm.data, UINT32_MAX);
authent.client = &client;
krb5_checksum checksum;
krb5_checksum* pchecksum = NULL;
if (req.GssChecksum)
{
if (!extractChecksum(req.GssChecksum, &checksum))
{
WLog_ERR(TAG, "Error getting the checksum");
goto out;
}
pchecksum = &checksum;
}
authent.checksum = pchecksum;
krb5_us_timeofday(rdpear->krbContext, &authent.ctime, &authent.cusec);
rv = encode_krb5_authenticator(&authent, &der);
if (rv)
{
WLog_ERR(TAG, "error encoding authenticator");
goto out;
}
KERB_ASN1_DATA plain_authent = { .Pdu = 0,
.Asn1Buffer = (BYTE*)der->data,
.Asn1BufferHints = { .count = der->length } };
rv = kerb_do_encrypt(rdpear->krbContext, req.EncryptionKey, (krb5_keyusage)req.KeyUsage,
&plain_authent, &authenticator);
if (rv)
{
WLog_ERR(TAG, "error encrypting authenticator");
goto out;
}
asn1EncodedAuth = rdpear_enc_EncryptedData(req.EncryptionKey->reserved2, &authenticator);
if (!asn1EncodedAuth)
{
WLog_ERR(TAG, "error encoding to ASN1");
rv = ENOMEM;
goto out;
}
// WLog_DBG(TAG, "authenticator=");
// winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(asn1EncodedAuth),
// Stream_GetPosition(asn1EncodedAuth));
const size_t size = Stream_GetPosition(asn1EncodedAuth);
if (size > UINT32_MAX)
goto out;
resp->Authenticator.Asn1BufferHints.count = (UINT32)size;
resp->Authenticator.Asn1Buffer = Stream_Buffer(asn1EncodedAuth);
resp->AuthenticatorTime.QuadPart = krb5_time_to_FILETIME(&authent.ctime, authent.cusec);
*pstatus = 0;
out:
resp->Authenticator.Pdu = 6;
resp->KerbProtocolError = rv;
krb5_free_principal_contents(rdpear->krbContext, &client);
krb5_free_data(rdpear->krbContext, der);
krb5_free_data_contents(rdpear->krbContext, &authenticator);
if (subkey)
krb5_free_keyblock(rdpear->krbContext, subkey);
ndr_destroy_CreateApReqAuthenticatorReq(rcontext, NULL, &req);
Stream_Free(asn1EncodedAuth, FALSE);
return TRUE;
}
static BOOL rdpear_findEncryptedData(const KERB_ASN1_DATA* src, int* penctype, krb5_data* data)
{
WinPrAsn1Decoder dec = { 0 };
WinPrAsn1Decoder dec2 = { 0 };
WinPrAsn1Decoder_InitMem(&dec, WINPR_ASN1_DER, src->Asn1Buffer, src->Asn1BufferHints.count);
BOOL error = FALSE;
WinPrAsn1_INTEGER encType = 0;
WinPrAsn1_OctetString os = { 0 };
if (!WinPrAsn1DecReadSequence(&dec, &dec2) ||
!WinPrAsn1DecReadContextualInteger(&dec2, 0, &error, &encType) ||
!WinPrAsn1DecReadContextualOctetString(&dec2, 2, &error, &os, FALSE))
return FALSE;
if (os.len > UINT32_MAX)
return FALSE;
data->data = (char*)os.data;
data->length = (unsigned int)os.len;
*penctype = encType;
return TRUE;
}
static BOOL rdpear_kerb_UnpackKdcReplyBody(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext, wStream* s,
UINT32* pstatus, UnpackKdcReplyBodyResp* resp)
{
UnpackKdcReplyBodyReq req = { 0 };
*pstatus = ERROR_INVALID_DATA;
if (!ndr_read_UnpackKdcReplyBodyReq(rcontext, s, NULL, &req) ||
!ndr_treat_deferred_read(rcontext, s))
goto out;
if (req.StrengthenKey)
{
WLog_ERR(TAG, "StrengthenKey not supported yet");
goto out;
}
WLog_DBG(TAG, "-> UnpackKdcReplyBody: KeyUsage=0x%x PDU=0x%x", req.KeyUsage, req.Pdu);
// WLog_DBG(TAG, "encryptedPayload=");
// winpr_HexDump(TAG, WLOG_DEBUG, req.EncryptedData->Asn1Buffer,
// req.EncryptedData->Asn1BufferHints.count);
krb5_data asn1Data = { 0 };
int encType = 0;
if (!rdpear_findEncryptedData(req.EncryptedData, &encType, &asn1Data) || !asn1Data.length)
goto out;
resp->KerbProtocolError = kerb_do_decrypt(
rdpear->krbContext, req.Key, (krb5_keyusage)req.KeyUsage, &asn1Data, &resp->ReplyBody);
resp->ReplyBody.Pdu = req.Pdu;
*pstatus = 0;
out:
ndr_destroy_UnpackKdcReplyBodyReq(rcontext, NULL, &req);
return TRUE;
}
static BOOL rdpear_kerb_DecryptApReply(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext, wStream* s,
UINT32* pstatus, KERB_ASN1_DATA* resp)
{
DecryptApReplyReq req = { 0 };
*pstatus = ERROR_INVALID_DATA;
if (!ndr_read_DecryptApReplyReq(rcontext, s, NULL, &req) ||
!ndr_treat_deferred_read(rcontext, s))
goto out;
WLog_DBG(TAG, "-> DecryptApReply");
// winpr_HexDump(TAG, WLOG_DEBUG, req.EncryptedReply->Asn1Buffer,
// req.EncryptedReply->Asn1BufferHints.count);
krb5_data asn1Data = { 0 };
int encType = 0;
if (!rdpear_findEncryptedData(req.EncryptedReply, &encType, &asn1Data) || !asn1Data.length)
goto out;
resp->Pdu = 0x31;
krb5_error_code rv =
kerb_do_decrypt(rdpear->krbContext, req.Key, KRB5_KEYUSAGE_AP_REP_ENCPART, &asn1Data, resp);
if (rv != 0)
{
WLog_ERR(TAG, "error decrypting");
goto out;
}
// WLog_DBG(TAG, "response=");
// winpr_HexDump(TAG, WLOG_DEBUG, resp->Asn1Buffer, resp->Asn1BufferHints.count);
*pstatus = 0;
out:
ndr_destroy_DecryptApReplyReq(rcontext, NULL, &req);
return TRUE;
}
static BOOL rdpear_kerb_PackApReply(RDPEAR_PLUGIN* rdpear, NdrContext* rcontext, wStream* s,
UINT32* pstatus, PackApReplyResp* resp)
{
PackApReplyReq req = { 0 };
krb5_data asn1Data = { 0 };
krb5_data* out = NULL;
WLog_DBG(TAG, "-> PackApReply");
*pstatus = ERROR_INVALID_DATA;
if (!ndr_read_PackApReplyReq(rcontext, s, NULL, &req) || !ndr_treat_deferred_read(rcontext, s))
goto out;
krb5_error_code rv = kerb_do_encrypt(rdpear->krbContext, req.SessionKey,
KRB5_KEYUSAGE_AP_REP_ENCPART, req.ReplyBody, &asn1Data);
if (rv)
goto out;
krb5_ap_rep reply;
reply.enc_part.kvno = KRB5_PVNO;
reply.enc_part.enctype = (krb5_enctype)req.SessionKey->reserved2;
reply.enc_part.ciphertext.length = asn1Data.length;
reply.enc_part.ciphertext.data = asn1Data.data;
rv = encode_krb5_ap_rep(&reply, &out);
if (rv)
goto out;
resp->PackedReply = (BYTE*)out->data;
resp->PackedReplyHints.count = out->length;
*pstatus = 0;
out:
free(out);
krb5_free_data_contents(rdpear->krbContext, &asn1Data);
ndr_destroy_PackApReplyReq(rcontext, NULL, &req);
return TRUE;
}
static UINT rdpear_decode_payload(RDPEAR_PLUGIN* rdpear,
IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
{
UINT ret = ERROR_INVALID_DATA;
NdrContext* context = NULL;
NdrContext* wcontext = NULL;
UINT32 status = 0;
UINT32 uint32Resp = 0;
KERB_ASN1_DATA asn1Data = { 0 };
CreateApReqAuthenticatorResp createApReqAuthenticatorResp = { 0 };
UnpackKdcReplyBodyResp unpackKdcReplyBodyResp = { 0 };
PackApReplyResp packApReplyResp = { 0 };
void* resp = NULL;
NdrMessageType respDescr = NULL;
wStream* respStream = Stream_New(NULL, 500);
if (!respStream)
goto out;
Stream_Seek(s, 16); /* skip first 16 bytes */
wStream commandStream = { 0 };
UINT16 callId = 0;
UINT16 callId2 = 0;
context = ndr_read_header(s);
if (!context || !ndr_read_constructed(context, s, &commandStream) ||
!ndr_read_pickle(context, &commandStream) ||
!ndr_read_uint16(context, &commandStream, &callId) ||
!ndr_read_uint16(context, &commandStream, &callId2) || (callId != callId2))
goto out;
ret = CHANNEL_RC_NOT_OPEN;
switch (callId)
{
case RemoteCallKerbNegotiateVersion:
resp = &uint32Resp;
respDescr = ndr_uint32_descr();
if (rdpear_kerb_version(context, &commandStream, &status, &uint32Resp))
ret = CHANNEL_RC_OK;
break;
case RemoteCallKerbCreateApReqAuthenticator:
resp = &createApReqAuthenticatorResp;
respDescr = ndr_CreateApReqAuthenticatorResp_descr();
if (rdpear_kerb_CreateApReqAuthenticator(rdpear, context, &commandStream, &status,
&createApReqAuthenticatorResp))
ret = CHANNEL_RC_OK;
break;
case RemoteCallKerbDecryptApReply:
resp = &asn1Data;
respDescr = ndr_KERB_ASN1_DATA_descr();
if (rdpear_kerb_DecryptApReply(rdpear, context, &commandStream, &status, &asn1Data))
ret = CHANNEL_RC_OK;
break;
case RemoteCallKerbComputeTgsChecksum:
resp = &asn1Data;
respDescr = ndr_KERB_ASN1_DATA_descr();
if (rdpear_kerb_ComputeTgsChecksum(rdpear, context, &commandStream, &status, &asn1Data))
ret = CHANNEL_RC_OK;
break;
case RemoteCallKerbBuildEncryptedAuthData:
resp = &asn1Data;
respDescr = ndr_KERB_ASN1_DATA_descr();
if (rdpear_kerb_BuildEncryptedAuthData(rdpear, context, &commandStream, &status,
&asn1Data))
ret = CHANNEL_RC_OK;
break;
case RemoteCallKerbUnpackKdcReplyBody:
resp = &unpackKdcReplyBodyResp;
respDescr = ndr_UnpackKdcReplyBodyResp_descr();
if (rdpear_kerb_UnpackKdcReplyBody(rdpear, context, &commandStream, &status,
&unpackKdcReplyBodyResp))
ret = CHANNEL_RC_OK;
break;
case RemoteCallKerbPackApReply:
resp = &packApReplyResp;
respDescr = ndr_PackApReplyResp_descr();
if (rdpear_kerb_PackApReply(rdpear, context, &commandStream, &status, &packApReplyResp))
ret = CHANNEL_RC_OK;
break;
case RemoteCallNtlmNegotiateVersion:
WLog_ERR(TAG, "don't wanna support NTLM");
break;
default:
WLog_DBG(TAG, "Unhandled callId=0x%x", callId);
winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(&commandStream, BYTE),
Stream_GetRemainingLength(&commandStream));
break;
}
if (!rdpear_prepare_response(context, callId, status, &wcontext, respStream))
goto out;
if (resp && respDescr)
{
WINPR_ASSERT(respDescr->writeFn);
BOOL r = respDescr->writeFn(wcontext, respStream, NULL, resp) &&
ndr_treat_deferred_write(wcontext, respStream);
if (respDescr->destroyFn)
respDescr->destroyFn(wcontext, NULL, resp);
if (!r)
{
WLog_DBG(TAG, "!writeFn || !ndr_treat_deferred_write");
goto out;
}
}
if (!ndr_end_constructed(wcontext, respStream) ||
!rdpear_send_payload(rdpear, pChannelCallback, RDPEAR_PACKAGE_KERBEROS, respStream))
{
WLog_DBG(TAG, "rdpear_send_payload !!!!!!!!");
goto out;
}
out:
if (context)
ndr_context_destroy(&context);
if (wcontext)
ndr_context_destroy(&wcontext);
if (respStream)
Stream_Free(respStream, TRUE);
return ret;
}
static UINT rdpear_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* s)
{
GENERIC_CHANNEL_CALLBACK* callback = (GENERIC_CHANNEL_CALLBACK*)pChannelCallback;
WINPR_ASSERT(callback);
UINT ret = ERROR_INVALID_DATA;
// winpr_HexDump(TAG, WLOG_DEBUG, Stream_PointerAs(s, BYTE), Stream_GetRemainingLength(s));
if (!Stream_CheckAndLogRequiredLength(TAG, s, 24))
return ERROR_INVALID_DATA;
UINT32 protocolMagic = 0;
UINT32 Length = 0;
UINT32 Version = 0;
Stream_Read_UINT32(s, protocolMagic);
if (protocolMagic != 0x4EACC3C8)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, Length);
Stream_Read_UINT32(s, Version);
if (Version != 0x00000000)
return ERROR_INVALID_DATA;
Stream_Seek(s, 4); /* Reserved (4 bytes) */
Stream_Seek(s, 8); /* TsPkgContext (8 bytes) */
if (!Stream_CheckAndLogRequiredLength(TAG, s, Length))
return ERROR_INVALID_DATA;
SecBuffer inBuffer = { Length, SECBUFFER_TOKEN, Stream_PointerAs(s, void) };
SecBuffer decrypted = { 0 };
RDPEAR_PLUGIN* rdpear = (RDPEAR_PLUGIN*)callback->plugin;
WINPR_ASSERT(rdpear);
if (!freerdp_nla_decrypt(rdpear->rdp_context, &inBuffer, &decrypted))
goto out;
WinPrAsn1Decoder dec = { 0 };
WinPrAsn1Decoder dec2 = { 0 };
wStream decodedStream = { 0 };
Stream_StaticInit(&decodedStream, decrypted.pvBuffer, decrypted.cbBuffer);
WinPrAsn1Decoder_Init(&dec, WINPR_ASN1_DER, &decodedStream);
if (!WinPrAsn1DecReadSequence(&dec, &dec2))
goto out;
WinPrAsn1_OctetString packageName = { 0 };
WinPrAsn1_OctetString payload = { 0 };
BOOL error = 0;
if (!WinPrAsn1DecReadContextualOctetString(&dec2, 1, &error, &packageName, FALSE))
goto out;
if (!WinPrAsn1DecReadContextualOctetString(&dec2, 2, &error, &payload, FALSE))
goto out;
wStream payloadStream = { 0 };
Stream_StaticInit(&payloadStream, payload.data, payload.len);
ret = rdpear_decode_payload(rdpear, pChannelCallback, &payloadStream);
out:
sspi_SecBufferFree(&decrypted);
return ret;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT rdpear_on_open(IWTSVirtualChannelCallback* pChannelCallback)
{
WINPR_UNUSED(pChannelCallback);
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT rdpear_on_close(IWTSVirtualChannelCallback* pChannelCallback)
{
WINPR_UNUSED(pChannelCallback);
return CHANNEL_RC_OK;
}
static void terminate_plugin_cb(GENERIC_DYNVC_PLUGIN* base)
{
WINPR_ASSERT(base);
RDPEAR_PLUGIN* rdpear = (RDPEAR_PLUGIN*)base;
krb5_free_context(rdpear->krbContext);
}
static UINT init_plugin_cb(GENERIC_DYNVC_PLUGIN* base, rdpContext* rcontext, rdpSettings* settings)
{
WINPR_ASSERT(base);
WINPR_UNUSED(settings);
RDPEAR_PLUGIN* rdpear = (RDPEAR_PLUGIN*)base;
rdpear->rdp_context = rcontext;
if (krb5_init_context(&rdpear->krbContext))
return CHANNEL_RC_INITIALIZATION_ERROR;
return CHANNEL_RC_OK;
}
static const IWTSVirtualChannelCallback rdpear_callbacks = { rdpear_on_data_received,
rdpear_on_open, rdpear_on_close,
NULL };
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(UINT rdpear_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
{
return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, RDPEAR_DVC_CHANNEL_NAME,
sizeof(RDPEAR_PLUGIN), sizeof(GENERIC_CHANNEL_CALLBACK),
&rdpear_callbacks, init_plugin_cb, terminate_plugin_cb);
}

View File

@ -0,0 +1,58 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2024 David Fort <contact@hardening-consulting.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
add_library(rdpear-common INTERFACE)
add_library(rdpear-common-obj OBJECT
ndr.c
rdpear_asn1.c
rdpear_common.c
rdpear-common/ndr.h
rdpear-common/rdpear_asn1.h
rdpear-common/rdpear_common.h
)
target_include_directories(rdpear-common
SYSTEM
INTERFACE ${KRB5_INCLUDE_DIRS}
)
target_compile_options(rdpear-common
INTERFACE
${KRB5_CFLAGS}
)
target_link_options(rdpear-common
INTERFACE
${KRB5_LDFLAGS}
)
target_include_directories(rdpear-common-obj
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
)
target_include_directories(rdpear-common-obj
SYSTEM
PRIVATE ${KRB5_INCLUDE_DIRS}
)
target_link_directories(rdpear-common INTERFACE ${KRB5_LIBRARY_DIRS})
target_link_libraries(rdpear-common INTERFACE
${KRB5_LIBRARIES}
$<TARGET_OBJECTS:rdpear-common-obj>
)
channel_install(rdpear-common ${FREERDP_ADDIN_PATH} "FreeRDPTargets")
if (BUILD_TESTING_INTERNAL OR BUILD_TESTING)
add_subdirectory(test)
endif()

View File

@ -0,0 +1,994 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Authentication redirection virtual channel
*
* Copyright 2024 David Fort <contact@hardening-consulting.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/assert.h>
#include <winpr/collections.h>
#include <winpr/wlog.h>
#include <freerdp/log.h>
#include <rdpear-common/ndr.h>
#define TAG FREERDP_TAG("ndr")
#define NDR_MAX_CONSTRUCTS 16
#define NDR_MAX_DEFERRED 50
struct NdrContext_s
{
BYTE version;
BOOL bigEndianDrep;
size_t alignBytes;
int currentLevel;
size_t indentLevels[16];
int constructLevel;
size_t constructs[NDR_MAX_CONSTRUCTS];
wHashTable* refPointers;
size_t ndeferred;
NdrDeferredEntry deferred[NDR_MAX_DEFERRED];
UINT32 refIdCounter;
};
NdrContext* ndr_context_new(BOOL bigEndianDrep, BYTE version)
{
NdrContext* ret = calloc(1, sizeof(*ret));
if (!ret)
return NULL;
ret->version = version;
ret->bigEndianDrep = bigEndianDrep;
ret->alignBytes = 4;
ret->refPointers = HashTable_New(FALSE);
if (!ret->refPointers)
{
free(ret);
return NULL;
}
ndr_context_reset(ret);
return ret;
}
void ndr_context_reset(NdrContext* context)
{
WINPR_ASSERT(context);
context->currentLevel = 0;
context->constructLevel = -1;
memset(context->indentLevels, 0, sizeof(context->indentLevels));
if (context->refPointers)
HashTable_Clear(context->refPointers);
context->ndeferred = 0;
context->refIdCounter = 0x20000;
}
NdrContext* ndr_context_copy(const NdrContext* src)
{
WINPR_ASSERT(src);
NdrContext* ret = calloc(1, sizeof(*ret));
if (!ret)
return NULL;
*ret = *src;
ret->refPointers = HashTable_New(FALSE);
if (!ret->refPointers)
{
free(ret);
return NULL;
}
ndr_context_reset(ret);
return ret;
}
void ndr_context_free(NdrContext* context)
{
if (context)
{
HashTable_Free(context->refPointers);
free(context);
}
}
static void ndr_context_bytes_read(NdrContext* context, size_t len)
{
WINPR_ASSERT(context);
context->indentLevels[context->currentLevel] += len;
}
static void ndr_context_bytes_written(NdrContext* context, size_t len)
{
ndr_context_bytes_read(context, len);
}
NdrContext* ndr_read_header(wStream* s)
{
if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
return NULL;
BYTE version = Stream_Get_UINT8(s);
BYTE drep = Stream_Get_UINT8(s);
UINT16 headerLen = Stream_Get_UINT16(s);
if (headerLen < 4 || !Stream_CheckAndLogRequiredLength(TAG, s, headerLen - 4))
return NULL;
/* skip filler */
Stream_Seek(s, headerLen - 4);
return ndr_context_new((drep != 0x10), version);
}
BOOL ndr_write_header(NdrContext* context, wStream* s)
{
WINPR_ASSERT(context);
if (!Stream_EnsureRemainingCapacity(s, 8))
return FALSE;
Stream_Write_UINT8(s, context->version);
Stream_Write_UINT8(s, context->bigEndianDrep ? 0x00 : 0x10);
Stream_Write_UINT16(s, 0x8); /* header len */
BYTE filler[] = { 0xcc, 0xcc, 0xcc, 0xcc };
Stream_Write(s, filler, sizeof(filler));
return TRUE;
}
BOOL ndr_skip_bytes(NdrContext* context, wStream* s, size_t nbytes)
{
WINPR_ASSERT(context);
if (!Stream_CheckAndLogRequiredLength(TAG, s, nbytes))
return FALSE;
context->indentLevels[context->currentLevel] += nbytes;
Stream_Seek(s, nbytes);
return TRUE;
}
BOOL ndr_read_align(NdrContext* context, wStream* s, size_t sz)
{
WINPR_ASSERT(context);
size_t rest = context->indentLevels[context->currentLevel] % sz;
if (rest)
{
size_t padding = (sz - rest);
if (!Stream_CheckAndLogRequiredLength(TAG, s, padding))
return FALSE;
Stream_Seek(s, padding);
context->indentLevels[context->currentLevel] += padding;
}
return TRUE;
}
BOOL ndr_write_align(NdrContext* context, wStream* s, size_t sz)
{
WINPR_ASSERT(context);
size_t rest = context->indentLevels[context->currentLevel] % sz;
if (rest)
{
size_t padding = (sz - rest);
if (!Stream_EnsureRemainingCapacity(s, padding))
return FALSE;
Stream_Zero(s, padding);
context->indentLevels[context->currentLevel] += padding;
}
return TRUE;
}
BOOL ndr_read_pickle(NdrContext* context, wStream* s)
{
WINPR_ASSERT(context);
UINT32 v = 0;
/* NDR format label */
if (!ndr_read_uint32(context, s, &v) || v != 0x20000)
return FALSE;
return ndr_read_uint32(context, s, &v); // padding
}
BOOL ndr_write_pickle(NdrContext* context, wStream* s)
{
WINPR_ASSERT(context);
/* NDR format label */
if (!ndr_write_uint32(context, s, 0x20000))
return FALSE;
ndr_write_uint32(context, s, 0); /* padding */
return TRUE;
}
BOOL ndr_read_constructed(NdrContext* context, wStream* s, wStream* target)
{
WINPR_ASSERT(context);
UINT32 len = 0;
/* len */
if (!ndr_read_uint32(context, s, &len))
return FALSE;
/* padding */
if (!ndr_skip_bytes(context, s, 4))
return FALSE;
/* payload */
if (!Stream_CheckAndLogRequiredLength(TAG, s, len))
return FALSE;
Stream_StaticInit(target, Stream_PointerAs(s, BYTE), len);
Stream_Seek(s, len);
return TRUE;
}
BOOL ndr_start_constructed(NdrContext* context, wStream* s)
{
WINPR_ASSERT(context);
if (!Stream_EnsureCapacity(s, 8))
return FALSE;
if (context->constructLevel == NDR_MAX_CONSTRUCTS)
return FALSE;
context->constructLevel++;
context->constructs[context->constructLevel] = Stream_GetPosition(s);
Stream_Zero(s, 8);
return TRUE;
}
BOOL ndr_end_constructed(NdrContext* context, wStream* s)
{
WINPR_ASSERT(context);
WINPR_ASSERT(context->constructs);
WINPR_ASSERT(context->constructLevel >= 0);
size_t offset = context->constructs[context->constructLevel];
wStream staticS = { 0 };
Stream_StaticInit(&staticS, Stream_Buffer(s) + offset, 4);
/* len */
const size_t len = Stream_GetPosition(s) - (offset + 8);
if (len > UINT32_MAX)
return FALSE;
if (!ndr_write_uint32(context, &staticS, (UINT32)len))
return FALSE;
return TRUE;
}
static size_t ndr_hintsCount(NdrMessageType msgType, const void* hints)
{
WINPR_ASSERT(msgType);
switch (msgType->arity)
{
case NDR_ARITY_SIMPLE:
return 1;
case NDR_ARITY_ARRAYOF:
WINPR_ASSERT(hints);
return ((const NdrArrayHints*)hints)->count;
case NDR_ARITY_VARYING_ARRAYOF:
WINPR_ASSERT(hints);
return ((const NdrVaryingArrayHints*)hints)->maxLength;
default:
WINPR_ASSERT(0 && "unknown arity");
return 0;
}
}
BOOL ndr_read_uint8(NdrContext* context, wStream* s, BYTE* v)
{
WINPR_ASSERT(context);
if (!Stream_CheckAndLogRequiredLength(TAG, s, 1))
return FALSE;
Stream_Read_UINT8(s, *v);
ndr_context_bytes_read(context, 1);
return TRUE;
}
BOOL ndr_read_uint8_(NdrContext* context, wStream* s, const void* hints, void* v)
{
WINPR_UNUSED(hints);
return ndr_read_uint8(context, s, (BYTE*)v);
}
BOOL ndr_write_uint8(NdrContext* context, wStream* s, BYTE v)
{
if (!Stream_EnsureRemainingCapacity(s, 1))
return FALSE;
Stream_Write_UINT8(s, v);
ndr_context_bytes_written(context, 1);
return TRUE;
}
BOOL ndr_write_uint8_(NdrContext* context, wStream* s, const void* hints, const void* v)
{
WINPR_ASSERT(context);
WINPR_ASSERT(s);
WINPR_ASSERT(v);
WINPR_UNUSED(hints);
return ndr_write_uint8(context, s, *(const BYTE*)v);
}
const static NdrMessageDescr uint8_descr = { NDR_ARITY_SIMPLE, 1, ndr_read_uint8_,
ndr_write_uint8_, NULL, NULL };
NdrMessageType ndr_uint8_descr(void)
{
return &uint8_descr;
}
#define SIMPLE_TYPE_IMPL(UPPERTYPE, LOWERTYPE) \
BOOL ndr_read_##LOWERTYPE(NdrContext* context, wStream* s, UPPERTYPE* v) \
{ \
WINPR_ASSERT(context); \
\
if (!Stream_CheckAndLogRequiredLength(TAG, s, sizeof(UPPERTYPE))) \
return FALSE; \
\
if (!ndr_read_align(context, s, sizeof(UPPERTYPE))) \
return FALSE; \
\
if (context->bigEndianDrep) \
Stream_Read_##UPPERTYPE##_BE(s, *v); \
else \
Stream_Read_##UPPERTYPE(s, *v); \
\
ndr_context_bytes_read(context, sizeof(UPPERTYPE)); \
return TRUE; \
} \
\
BOOL ndr_read_##LOWERTYPE##_(NdrContext* context, wStream* s, const void* hints, void* v) \
{ \
WINPR_UNUSED(hints); \
return ndr_read_##LOWERTYPE(context, s, (UPPERTYPE*)v); \
} \
\
BOOL ndr_write_##LOWERTYPE(NdrContext* context, wStream* s, UPPERTYPE v) \
{ \
if (!ndr_write_align(context, s, sizeof(UPPERTYPE)) || \
!Stream_EnsureRemainingCapacity(s, sizeof(UPPERTYPE))) \
return FALSE; \
\
if (context->bigEndianDrep) \
Stream_Write_##UPPERTYPE##_BE(s, v); \
else \
Stream_Write_##UPPERTYPE(s, v); \
\
ndr_context_bytes_written(context, sizeof(UPPERTYPE)); \
return TRUE; \
} \
\
BOOL ndr_write_##LOWERTYPE##_(NdrContext* context, wStream* s, const void* hints, \
const void* v) \
{ \
WINPR_ASSERT(context); \
WINPR_ASSERT(s); \
WINPR_ASSERT(v); \
WINPR_UNUSED(hints); \
\
return ndr_write_##LOWERTYPE(context, s, *(const UPPERTYPE*)v); \
} \
\
const NdrMessageDescr ndr_##LOWERTYPE##_descr_s = { NDR_ARITY_SIMPLE, \
sizeof(UPPERTYPE), \
ndr_read_##LOWERTYPE##_, \
ndr_write_##LOWERTYPE##_, \
NULL, \
NULL }; \
\
NdrMessageType ndr_##LOWERTYPE##_descr(void) \
{ \
return &ndr_##LOWERTYPE##_descr_s; \
}
SIMPLE_TYPE_IMPL(UINT32, uint32)
SIMPLE_TYPE_IMPL(UINT16, uint16)
SIMPLE_TYPE_IMPL(UINT64, uint64)
#define ARRAY_OF_TYPE_IMPL(TYPE, UPPERTYPE) \
BOOL ndr_read_##TYPE##Array(NdrContext* context, wStream* s, const void* hints, void* v) \
{ \
WINPR_ASSERT(context); \
WINPR_ASSERT(s); \
WINPR_ASSERT(hints); \
return ndr_read_uconformant_array(context, s, hints, ndr_##TYPE##_descr(), v); \
} \
\
BOOL ndr_write_##TYPE##Array(NdrContext* context, wStream* s, const void* hints, \
const void* v) \
{ \
WINPR_ASSERT(context); \
WINPR_ASSERT(s); \
WINPR_ASSERT(hints); \
const NdrArrayHints* ahints = (const NdrArrayHints*)hints; \
return ndr_write_uconformant_array(context, s, ahints->count, ndr_##TYPE##_descr(), v); \
} \
void ndr_destroy_##TYPE##Array(NdrContext* context, const void* hints, void* obj) \
{ \
WINPR_ASSERT(context); \
WINPR_ASSERT(obj); \
WINPR_ASSERT(hints); \
const NdrArrayHints* ahints = (const NdrArrayHints*)hints; \
NdrMessageType descr = ndr_##TYPE##_descr(); \
if (descr->destroyFn) \
{ \
UPPERTYPE* ptr = (UPPERTYPE*)obj; \
for (UINT32 i = 0; i < ahints->count; i++, ptr++) \
descr->destroyFn(context, NULL, ptr); \
} \
} \
\
const NdrMessageDescr ndr_##TYPE##Array_descr_s = { \
NDR_ARITY_ARRAYOF, sizeof(UPPERTYPE), ndr_read_##TYPE##Array, \
ndr_write_##TYPE##Array, ndr_destroy_##TYPE##Array, NULL \
}; \
\
NdrMessageType ndr_##TYPE##Array_descr(void) \
{ \
return &ndr_##TYPE##Array_descr_s; \
} \
\
BOOL ndr_read_##TYPE##VaryingArray(NdrContext* context, wStream* s, const void* hints, \
void* v) \
{ \
WINPR_ASSERT(context); \
WINPR_ASSERT(s); \
WINPR_ASSERT(hints); \
return ndr_read_uconformant_varying_array(context, s, (const NdrVaryingArrayHints*)hints, \
ndr_##TYPE##_descr(), v); \
} \
BOOL ndr_write_##TYPE##VaryingArray(NdrContext* context, wStream* s, const void* hints, \
const void* v) \
{ \
WINPR_ASSERT(context); \
WINPR_ASSERT(s); \
WINPR_ASSERT(hints); \
return ndr_write_uconformant_varying_array(context, s, (const NdrVaryingArrayHints*)hints, \
ndr_##TYPE##_descr(), v); \
} \
\
const NdrMessageDescr ndr_##TYPE##VaryingArray_descr_s = { NDR_ARITY_VARYING_ARRAYOF, \
sizeof(UPPERTYPE), \
ndr_read_##TYPE##VaryingArray, \
ndr_write_##TYPE##VaryingArray, \
NULL, \
NULL }; \
\
NdrMessageType ndr_##TYPE##VaryingArray_descr(void) \
{ \
return &ndr_##TYPE##VaryingArray_descr_s; \
}
ARRAY_OF_TYPE_IMPL(uint8, BYTE)
ARRAY_OF_TYPE_IMPL(uint16, UINT16)
BOOL ndr_read_wchar(NdrContext* context, wStream* s, WCHAR* ptr)
{
return ndr_read_uint16(context, s, (UINT16*)ptr);
}
BOOL ndr_read_uconformant_varying_array(NdrContext* context, wStream* s,
const NdrVaryingArrayHints* hints, NdrMessageType itemType,
void* ptarget)
{
WINPR_ASSERT(context);
WINPR_ASSERT(s);
WINPR_ASSERT(hints);
WINPR_ASSERT(itemType);
WINPR_ASSERT(ptarget);
UINT32 maxCount = 0;
UINT32 offset = 0;
UINT32 length = 0;
if (!ndr_read_uint32(context, s, &maxCount) || !ndr_read_uint32(context, s, &offset) ||
!ndr_read_uint32(context, s, &length))
return FALSE;
if ((length * itemType->itemSize) < hints->length)
return FALSE;
if ((maxCount * itemType->itemSize) < hints->maxLength)
return FALSE;
BYTE* target = (BYTE*)ptarget;
for (UINT32 i = 0; i < length; i++, target += itemType->itemSize)
{
if (!itemType->readFn(context, s, NULL, target))
return FALSE;
}
return ndr_read_align(context, s, 4);
}
BOOL ndr_write_uconformant_varying_array(NdrContext* context, wStream* s,
const NdrVaryingArrayHints* hints, NdrMessageType itemType,
const void* psrc)
{
WINPR_ASSERT(context);
WINPR_ASSERT(s);
WINPR_ASSERT(hints);
WINPR_ASSERT(itemType);
WINPR_ASSERT(psrc);
if (!ndr_write_uint32(context, s, hints->maxLength) || !ndr_write_uint32(context, s, 0) ||
!ndr_write_uint32(context, s, hints->length))
return FALSE;
const BYTE* src = (const BYTE*)psrc;
for (UINT32 i = 0; i < hints->length; i++, src += itemType->itemSize)
{
if (!itemType->writeFn(context, s, NULL, src))
return FALSE;
}
return TRUE;
}
BOOL ndr_read_uconformant_array(NdrContext* context, wStream* s, const NdrArrayHints* hints,
NdrMessageType itemType, void* vtarget)
{
WINPR_ASSERT(context);
WINPR_ASSERT(s);
WINPR_ASSERT(itemType);
WINPR_ASSERT(vtarget);
UINT32 count = 0;
if (!ndr_read_uint32(context, s, &count))
return FALSE;
if ((count * itemType->itemSize < hints->count))
return FALSE;
BYTE* target = (BYTE*)vtarget;
for (UINT32 i = 0; i < count; i++, target += itemType->itemSize)
{
if (!itemType->readFn(context, s, NULL, target))
return FALSE;
}
return ndr_read_align(context, s, /*context->alignBytes*/ 4);
}
BOOL ndr_write_uconformant_array(NdrContext* context, wStream* s, UINT32 len,
NdrMessageType itemType, const BYTE* ptr)
{
WINPR_ASSERT(context);
WINPR_ASSERT(s);
WINPR_ASSERT(itemType);
WINPR_ASSERT(ptr);
size_t toWrite = len * itemType->itemSize;
size_t padding = (4 - (toWrite % 4)) % 4;
if (!ndr_write_uint32(context, s, len) || !Stream_EnsureRemainingCapacity(s, toWrite + padding))
return FALSE;
for (UINT32 i = 0; i < len; i++, ptr += itemType->itemSize)
{
if (!itemType->writeFn(context, s, NULL, ptr))
return FALSE;
}
if (padding)
{
Stream_Zero(s, padding);
ndr_context_bytes_written(context, padding);
}
return TRUE;
}
BOOL ndr_struct_read_fromDescr(NdrContext* context, wStream* s, const NdrStructDescr* descr,
void* target)
{
WINPR_ASSERT(context);
WINPR_ASSERT(s);
WINPR_ASSERT(descr);
WINPR_ASSERT(target);
#define NDR_MAX_STRUCT_DEFERRED 16
NdrDeferredEntry deferreds[NDR_MAX_STRUCT_DEFERRED] = { 0 };
size_t ndeferred = 0;
for (size_t i = 0; i < descr->nfields; i++)
{
const NdrFieldStruct* field = &descr->fields[i];
BYTE* ptr = target;
ptr += field->structOffset;
void* hints = NULL;
if (field->hintsField >= 0)
{
/* computes the address of the hints field if any */
WINPR_ASSERT((size_t)field->hintsField < descr->nfields);
const NdrFieldStruct* hintsField = &descr->fields[field->hintsField];
hints = (BYTE*)target + hintsField->structOffset;
}
switch (field->pointerType)
{
case NDR_NOT_POINTER:
if (!field->typeDescr->readFn(context, s, hints, ptr))
{
WLog_ERR(TAG, "error when reading %s.%s", descr->name, field->name);
return FALSE;
}
break;
case NDR_POINTER:
case NDR_POINTER_NON_NULL:
{
NdrDeferredEntry* deferred = &deferreds[ndeferred];
if (ndeferred >= NDR_MAX_STRUCT_DEFERRED)
{
WLog_ERR(TAG, "too many deferred when calling ndr_read_struct_fromDescr for %s",
descr->name);
return FALSE;
}
deferred->name = field->name;
deferred->hints = hints;
deferred->target = ptr;
deferred->msg = field->typeDescr;
if (!ndr_read_refpointer(context, s, &deferred->ptrId))
{
WLog_ERR(TAG, "error when reading %s.%s", descr->name, field->name);
return FALSE;
}
if (!deferred->ptrId && field->pointerType == NDR_POINTER_NON_NULL)
{
WLog_ERR(TAG, "%s.%s can't be null", descr->name, field->name);
return FALSE;
}
ndeferred++;
break;
}
default:
WLog_ERR(TAG, "%s.%s unknown pointer type 0x%x", descr->name, field->name,
field->pointerType);
return FALSE;
}
}
return ndr_push_deferreds(context, deferreds, ndeferred);
}
BOOL ndr_struct_write_fromDescr(NdrContext* context, wStream* s, const NdrStructDescr* descr,
const void* src)
{
WINPR_ASSERT(context);
WINPR_ASSERT(s);
WINPR_ASSERT(descr);
WINPR_ASSERT(src);
NdrDeferredEntry deferreds[NDR_MAX_STRUCT_DEFERRED] = { 0 };
size_t ndeferred = 0;
for (size_t i = 0; i < descr->nfields; i++)
{
const NdrFieldStruct* field = &descr->fields[i];
const BYTE* ptr = (const BYTE*)src + field->structOffset;
const void* hints = NULL;
if (field->hintsField >= 0)
{
/* computes the address of the hints field if any */
WINPR_ASSERT((size_t)field->hintsField < descr->nfields);
const NdrFieldStruct* hintsField = &descr->fields[field->hintsField];
hints = (const BYTE*)src + hintsField->structOffset;
}
switch (field->pointerType)
{
case NDR_POINTER:
case NDR_POINTER_NON_NULL:
{
ndr_refid ptrId = NDR_PTR_NULL;
BOOL isNew = 0;
ptr = *(WINPR_CAST_CONST_PTR_AWAY(ptr, const void**));
if (!ptr && field->pointerType == NDR_POINTER_NON_NULL)
{
WLog_ERR(TAG, "%s.%s can't be null", descr->name, field->name);
return FALSE;
}
if (!ndr_context_allocatePtr(context, ptr, &ptrId, &isNew))
return FALSE;
if (isNew)
{
NdrDeferredEntry* deferred = &deferreds[ndeferred];
if (ndeferred >= NDR_MAX_STRUCT_DEFERRED)
{
WLog_ERR(TAG,
"too many deferred when calling ndr_read_struct_fromDescr for %s",
descr->name);
return FALSE;
}
deferred->name = field->name;
deferred->hints = WINPR_CAST_CONST_PTR_AWAY(hints, void*);
deferred->target = WINPR_CAST_CONST_PTR_AWAY(ptr, void*);
deferred->msg = field->typeDescr;
ndeferred++;
}
if (!ndr_write_uint32(context, s, ptrId))
return FALSE;
break;
}
case NDR_NOT_POINTER:
if (!field->typeDescr->writeFn(context, s, hints, ptr))
{
WLog_ERR(TAG, "error when writing %s.%s", descr->name, field->name);
return FALSE;
}
break;
default:
break;
}
}
return ndr_push_deferreds(context, deferreds, ndeferred);
}
void ndr_struct_dump_fromDescr(wLog* logger, UINT32 lvl, size_t identLevel,
const NdrStructDescr* descr, const void* obj)
{
char tabArray[30 + 1];
size_t ntabs = (identLevel <= 30) ? identLevel : 30;
memset(tabArray, '\t', ntabs);
tabArray[ntabs] = 0;
WLog_Print(logger, lvl, "%s%s", tabArray, descr->name);
for (size_t i = 0; i < descr->nfields; i++)
{
const NdrFieldStruct* field = &descr->fields[i];
const BYTE* ptr = (const BYTE*)obj + field->structOffset;
switch (field->pointerType)
{
case NDR_POINTER:
case NDR_POINTER_NON_NULL:
ptr = *(WINPR_CAST_CONST_PTR_AWAY(ptr, const void**));
break;
case NDR_NOT_POINTER:
break;
default:
WLog_ERR(TAG, "invalid field->pointerType");
break;
}
WLog_Print(logger, lvl, "%s*%s:", tabArray, field->name);
if (field->typeDescr->dumpFn)
field->typeDescr->dumpFn(logger, lvl, identLevel + 1, ptr);
else
WLog_Print(logger, lvl, "%s\t<no dump function>", tabArray);
}
}
void ndr_struct_destroy(NdrContext* context, const NdrStructDescr* descr, void* pptr)
{
WINPR_ASSERT(context);
WINPR_ASSERT(descr);
WINPR_ASSERT(pptr);
for (size_t i = 0; i < descr->nfields; i++)
{
const NdrFieldStruct* field = &descr->fields[i];
void* ptr = (BYTE*)pptr + field->structOffset;
void* hints = NULL;
if (field->hintsField >= 0)
{
/* computes the address of the hints field if any */
WINPR_ASSERT((size_t)field->hintsField < descr->nfields);
const NdrFieldStruct* hintsField = &descr->fields[field->hintsField];
hints = (BYTE*)pptr + hintsField->structOffset;
}
if (field->pointerType != NDR_NOT_POINTER)
ptr = *(void**)ptr;
if (ptr && field->typeDescr->destroyFn)
field->typeDescr->destroyFn(context, hints, ptr);
if (field->pointerType != NDR_NOT_POINTER)
free(ptr);
}
}
ndr_refid ndr_pointer_refid(const void* ptr)
{
return (ndr_refid)((ULONG_PTR)ptr);
}
BOOL ndr_read_refpointer(NdrContext* context, wStream* s, ndr_refid* refId)
{
return ndr_read_uint32(context, s, refId);
}
typedef struct
{
const void* needle;
ndr_refid* presult;
} FindValueArgs;
static BOOL findValueRefFn(const void* key, void* value, void* parg)
{
WINPR_ASSERT(parg);
FindValueArgs* args = (FindValueArgs*)parg;
if (args->needle == value)
{
*args->presult = (ndr_refid)(UINT_PTR)key;
return FALSE;
}
return TRUE;
}
BOOL ndr_context_allocatePtr(NdrContext* context, const void* ptr, ndr_refid* prefId, BOOL* pnewPtr)
{
WINPR_ASSERT(context);
FindValueArgs findArgs = { ptr, prefId };
if (!HashTable_Foreach(context->refPointers, findValueRefFn, &findArgs))
{
*pnewPtr = FALSE;
return TRUE;
}
*pnewPtr = TRUE;
*prefId = context->refIdCounter + 4;
if (!HashTable_Insert(context->refPointers, (void*)(UINT_PTR)(*prefId), ptr))
return FALSE;
context->refIdCounter += 4;
return TRUE;
}
BOOL ndr_read_pointedMessageEx(NdrContext* context, wStream* s, ndr_refid ptrId,
NdrMessageType descr, void* hints, void** target)
{
WINPR_ASSERT(context);
WINPR_ASSERT(s);
WINPR_ASSERT(descr);
WINPR_ASSERT(target);
*target = NULL;
if (!ptrId)
return TRUE;
void* ret = HashTable_GetItemValue(context->refPointers, (void*)(UINT_PTR)ptrId);
if (!ret)
{
size_t itemCount = ndr_hintsCount(descr, hints);
ret = calloc(itemCount, descr->itemSize);
if (!ret)
return FALSE;
if (!descr->readFn(context, s, hints, ret) ||
!HashTable_Insert(context->refPointers, (void*)(UINT_PTR)ptrId, ret))
{
if (descr->destroyFn)
descr->destroyFn(context, hints, ret);
free(ret);
return FALSE;
}
}
*target = ret;
return TRUE;
}
BOOL ndr_push_deferreds(NdrContext* context, NdrDeferredEntry* deferreds, size_t ndeferred)
{
WINPR_ASSERT(context);
WINPR_ASSERT(deferreds);
if (!ndeferred)
return TRUE;
if (context->ndeferred + ndeferred > NDR_MAX_DEFERRED)
{
WLog_ERR(TAG, "too many deferred");
return FALSE;
}
for (size_t i = ndeferred; i > 0; i--, context->ndeferred++)
{
context->deferred[context->ndeferred] = deferreds[i - 1];
}
return TRUE;
}
BOOL ndr_treat_deferred_read(NdrContext* context, wStream* s)
{
WINPR_ASSERT(context);
WINPR_ASSERT(s);
while (context->ndeferred)
{
NdrDeferredEntry current = context->deferred[context->ndeferred - 1];
context->ndeferred--;
WLog_VRB(TAG, "treating read deferred 0x%x for %s", current.ptrId, current.name);
if (!ndr_read_pointedMessageEx(context, s, current.ptrId, current.msg, current.hints,
(void**)current.target))
{
WLog_ERR(TAG, "error parsing deferred %s", current.name);
return FALSE;
}
}
return TRUE;
}
BOOL ndr_treat_deferred_write(NdrContext* context, wStream* s)
{
WINPR_ASSERT(context);
WINPR_ASSERT(s);
while (context->ndeferred)
{
NdrDeferredEntry current = context->deferred[context->ndeferred - 1];
context->ndeferred--;
WLog_VRB(TAG, "treating write deferred for %s", current.name);
if (!current.msg->writeFn(context, s, current.hints, current.target))
{
WLog_ERR(TAG, "error writing deferred %s", current.name);
return FALSE;
}
}
return TRUE;
}

View File

@ -0,0 +1,217 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Authentication redirection virtual channel
*
* Copyright 2024 David Fort <contact@hardening-consulting.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef CHANNELS_RDPEAR_NDR_H_
#define CHANNELS_RDPEAR_NDR_H_
#include <winpr/stream.h>
#include <freerdp/api.h>
#define NDR_PTR_NULL (0UL)
#define NDR_SIMPLE_TYPE_DECL(LOWER, UPPER) \
BOOL ndr_read_##LOWER(NdrContext* context, wStream* s, UPPER* v); \
BOOL ndr_read_##LOWER##_(NdrContext* context, wStream* s, const void* hints, void* v); \
BOOL ndr_write_##LOWER(NdrContext* context, wStream* s, UPPER v); \
BOOL ndr_write_##LOWER##_(NdrContext* context, wStream* s, const void* hints, const void* v); \
extern const NdrMessageDescr ndr_##LOWER##_descr_s; \
NdrMessageType ndr_##LOWER##_descr(void)
#define NDR_ARRAY_OF_TYPE_DECL(TYPE, UPPERTYPE) \
BOOL ndr_read_##TYPE##Array(NdrContext* context, wStream* s, const void* hints, void* v); \
BOOL ndr_write_##TYPE##Array(NdrContext* context, wStream* s, const void* hints, \
const void* v); \
void ndr_destroy_##TYPE##Array(NdrContext* context, const void* hints, void* obj); \
extern const NdrMessageDescr ndr_##TYPE##Array_descr_s; \
NdrMessageType ndr_##TYPE##Array_descr(void); \
\
BOOL ndr_read_##TYPE##VaryingArray(NdrContext* context, wStream* s, const void* hints, \
void* v); \
BOOL ndr_write_##TYPE##VaryingArray(NdrContext* context, wStream* s, const void* hints, \
const void* v); \
extern const NdrMessageDescr ndr_##TYPE##VaryingArray_descr_s; \
NdrMessageType ndr_##TYPE##VaryingArray_descr(void)
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct NdrContext_s NdrContext;
typedef UINT32 ndr_refid;
typedef BOOL (*NDR_READER_FN)(NdrContext* context, wStream* s, const void* hints, void* target);
typedef BOOL (*NDR_WRITER_FN)(NdrContext* context, wStream* s, const void* hints,
const void* obj);
typedef void (*NDR_DESTROY_FN)(NdrContext* context, const void* hints, void* obj);
typedef void (*NDR_DUMP_FN)(wLog* logger, UINT32 lvl, size_t indentLevel, const void* obj);
/** @brief arity of a message */
typedef enum
{
NDR_ARITY_SIMPLE,
NDR_ARITY_ARRAYOF,
NDR_ARITY_VARYING_ARRAYOF,
} NdrTypeArity;
/** @brief message descriptor */
typedef struct
{
NdrTypeArity arity;
size_t itemSize;
NDR_READER_FN readFn;
NDR_WRITER_FN writeFn;
NDR_DESTROY_FN destroyFn;
NDR_DUMP_FN dumpFn;
} NdrMessageDescr;
typedef const NdrMessageDescr* NdrMessageType;
/** @brief pointer or not and if null is accepted */
typedef enum
{
NDR_NOT_POINTER,
NDR_POINTER_NON_NULL,
NDR_POINTER
} NdrPointerType;
/** @brief descriptor of a field in a structure */
typedef struct
{
const char* name;
size_t structOffset;
NdrPointerType pointerType;
ssize_t hintsField;
NdrMessageType typeDescr;
} NdrFieldStruct;
/** @brief structure descriptor */
typedef struct
{
const char* name;
size_t nfields;
const NdrFieldStruct* fields;
} NdrStructDescr;
/** @brief a deferred pointer */
typedef struct
{
ndr_refid ptrId;
const char* name;
void* hints;
void* target;
NdrMessageType msg;
} NdrDeferredEntry;
void ndr_context_free(NdrContext* context);
static INLINE void ndr_context_destroy(NdrContext** pcontext)
{
WINPR_ASSERT(pcontext);
ndr_context_free(*pcontext);
*pcontext = NULL;
}
WINPR_ATTR_MALLOC(ndr_context_free, 1)
NdrContext* ndr_context_new(BOOL bigEndianDrep, BYTE version);
void ndr_context_reset(NdrContext* context);
WINPR_ATTR_MALLOC(ndr_context_free, 1)
NdrContext* ndr_context_copy(const NdrContext* src);
WINPR_ATTR_MALLOC(ndr_context_free, 1)
NdrContext* ndr_read_header(wStream* s);
BOOL ndr_write_header(NdrContext* context, wStream* s);
NDR_SIMPLE_TYPE_DECL(uint8, UINT8);
NDR_SIMPLE_TYPE_DECL(uint16, UINT16);
NDR_SIMPLE_TYPE_DECL(uint32, UINT32);
NDR_SIMPLE_TYPE_DECL(uint64, UINT64);
NDR_ARRAY_OF_TYPE_DECL(uint8, BYTE);
NDR_ARRAY_OF_TYPE_DECL(uint16, UINT16);
BOOL ndr_skip_bytes(NdrContext* context, wStream* s, size_t nbytes);
BOOL ndr_read_align(NdrContext* context, wStream* s, size_t sz);
BOOL ndr_write_align(NdrContext* context, wStream* s, size_t sz);
BOOL ndr_read_pickle(NdrContext* context, wStream* s);
BOOL ndr_write_pickle(NdrContext* context, wStream* s);
BOOL ndr_read_constructed(NdrContext* context, wStream* s, wStream* target);
BOOL ndr_write_constructed(NdrContext* context, wStream* s, wStream* payload);
BOOL ndr_start_constructed(NdrContext* context, wStream* s);
BOOL ndr_end_constructed(NdrContext* context, wStream* s);
BOOL ndr_read_wchar(NdrContext* context, wStream* s, WCHAR* ptr);
/** @brief hints for a varying conformant array */
typedef struct
{
UINT32 length;
UINT32 maxLength;
} NdrVaryingArrayHints;
BOOL ndr_read_uconformant_varying_array(NdrContext* context, wStream* s,
const NdrVaryingArrayHints* hints,
NdrMessageType itemType, void* ptarget);
BOOL ndr_write_uconformant_varying_array(NdrContext* context, wStream* s,
const NdrVaryingArrayHints* hints,
NdrMessageType itemType, const void* src);
/** @brief hints for a conformant array */
typedef struct
{
UINT32 count;
} NdrArrayHints;
BOOL ndr_read_uconformant_array(NdrContext* context, wStream* s, const NdrArrayHints* hints,
NdrMessageType itemType, void* vtarget);
BOOL ndr_write_uconformant_array(NdrContext* context, wStream* s, UINT32 len,
NdrMessageType itemType, const BYTE* ptr);
BOOL ndr_struct_read_fromDescr(NdrContext* context, wStream* s, const NdrStructDescr* descr,
void* target);
BOOL ndr_struct_write_fromDescr(NdrContext* context, wStream* s, const NdrStructDescr* descr,
const void* src);
void ndr_struct_dump_fromDescr(wLog* logger, UINT32 lvl, size_t identLevel,
const NdrStructDescr* descr, const void* obj);
void ndr_struct_destroy(NdrContext* context, const NdrStructDescr* descr, void* pptr);
ndr_refid ndr_pointer_refid(const void* ptr);
BOOL ndr_read_refpointer(NdrContext* context, wStream* s, UINT32* refId);
BOOL ndr_context_allocatePtr(NdrContext* context, const void* ptr, ndr_refid* prefId,
BOOL* pnewPtr);
BOOL ndr_read_pointedMessageEx(NdrContext* context, wStream* s, ndr_refid ptrId,
NdrMessageType descr, void* hints, void** target);
BOOL ndr_push_deferreds(NdrContext* context, NdrDeferredEntry* deferreds, size_t ndeferred);
BOOL ndr_treat_deferred_read(NdrContext* context, wStream* s);
BOOL ndr_treat_deferred_write(NdrContext* context, wStream* s);
#ifdef __cplusplus
}
#endif
#endif /* CHANNELS_RDPEAR_NDR_H_ */

View File

@ -0,0 +1,31 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* ASN1 routines for RDPEAR
*
* Copyright 2024 David Fort <contact@hardening-consulting.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef RPDEAR_RDPEAR_ASN1_H__
#define RPDEAR_RDPEAR_ASN1_H__
#include <krb5.h>
#include <winpr/stream.h>
wStream* rdpear_enc_Checksum(UINT32 cksumtype, krb5_checksum* csum);
wStream* rdpear_enc_EncryptedData(UINT32 encType, krb5_data* payload);
#endif /* RPDEAR_RDPEAR_ASN1_H__ */

View File

@ -0,0 +1,236 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2023 David Fort <contact@hardening-consulting.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CHANNEL_RDPEAR_COMMON_H
#define FREERDP_CHANNEL_RDPEAR_COMMON_H
#include <winpr/stream.h>
#include <winpr/asn1.h>
#include <winpr/wlog.h>
#include <winpr/sspi.h>
#include <freerdp/api.h>
#include <rdpear-common/ndr.h>
typedef enum
{
RDPEAR_PACKAGE_KERBEROS,
RDPEAR_PACKAGE_NTLM,
RDPEAR_PACKAGE_UNKNOWN
} RdpEarPackageType;
/* RDPEAR 2.2.1.1 */
typedef enum
{
// Start Kerberos remote calls
RemoteCallKerbMinimum = 0x100,
RemoteCallKerbNegotiateVersion = 0x100,
RemoteCallKerbBuildAsReqAuthenticator,
RemoteCallKerbVerifyServiceTicket,
RemoteCallKerbCreateApReqAuthenticator,
RemoteCallKerbDecryptApReply,
RemoteCallKerbUnpackKdcReplyBody,
RemoteCallKerbComputeTgsChecksum,
RemoteCallKerbBuildEncryptedAuthData,
RemoteCallKerbPackApReply,
RemoteCallKerbHashS4UPreauth,
RemoteCallKerbSignS4UPreauthData,
RemoteCallKerbVerifyChecksum,
RemoteCallKerbReserved1,
RemoteCallKerbReserved2,
RemoteCallKerbReserved3,
RemoteCallKerbReserved4,
RemoteCallKerbReserved5,
RemoteCallKerbReserved6,
RemoteCallKerbReserved7,
RemoteCallKerbDecryptPacCredentials,
RemoteCallKerbCreateECDHKeyAgreement,
RemoteCallKerbCreateDHKeyAgreement,
RemoteCallKerbDestroyKeyAgreement,
RemoteCallKerbKeyAgreementGenerateNonce,
RemoteCallKerbFinalizeKeyAgreement,
RemoteCallKerbMaximum = 0x1ff,
// End Kerberos remote calls
// Start NTLM remote calls
RemoteCallNtlmMinimum = 0x200,
RemoteCallNtlmNegotiateVersion = 0x200,
RemoteCallNtlmLm20GetNtlm3ChallengeResponse,
RemoteCallNtlmCalculateNtResponse,
RemoteCallNtlmCalculateUserSessionKeyNt,
RemoteCallNtlmCompareCredentials,
RemoteCallNtlmMaximum = 0x2ff,
// End NTLM remote calls
} RemoteGuardCallId;
FREERDP_LOCAL RdpEarPackageType rdpear_packageType_from_name(WinPrAsn1_OctetString* package);
FREERDP_LOCAL wStream* rdpear_encodePayload(RdpEarPackageType packageType, wStream* payload);
#define RDPEAR_COMMON_MESSAGE_DECL(V) \
FREERDP_LOCAL BOOL ndr_read_##V(NdrContext* context, wStream* s, const void* hints, V* obj); \
FREERDP_LOCAL BOOL ndr_write_##V(NdrContext* context, wStream* s, const void* hints, \
const V* obj); \
FREERDP_LOCAL void ndr_destroy_##V(NdrContext* context, const void* hints, V* obj); \
FREERDP_LOCAL void ndr_dump_##V(wLog* logger, UINT32 lvl, size_t indentLevel, const V* obj); \
FREERDP_LOCAL NdrMessageType ndr_##V##_descr(void)
/** @brief 2.2.1.2.2 KERB_RPC_OCTET_STRING */
typedef struct
{
UINT32 length;
BYTE* value;
} KERB_RPC_OCTET_STRING;
RDPEAR_COMMON_MESSAGE_DECL(KERB_RPC_OCTET_STRING);
/** @brief 2.2.1.2.1 KERB_ASN1_DATA */
typedef struct
{
UINT32 Pdu;
NdrArrayHints Asn1BufferHints;
BYTE* Asn1Buffer;
} KERB_ASN1_DATA;
RDPEAR_COMMON_MESSAGE_DECL(KERB_ASN1_DATA);
/** @brief 2.3.10 RPC_UNICODE_STRING (MS-DTYP) */
typedef struct
{
NdrVaryingArrayHints lenHints;
UINT32 strLength;
WCHAR* Buffer;
} RPC_UNICODE_STRING;
RDPEAR_COMMON_MESSAGE_DECL(RPC_UNICODE_STRING);
/** @brief 2.2.1.2.3 KERB_RPC_INTERNAL_NAME */
typedef struct
{
UINT16 NameType;
NdrArrayHints nameHints;
RPC_UNICODE_STRING* Names;
} KERB_RPC_INTERNAL_NAME;
RDPEAR_COMMON_MESSAGE_DECL(KERB_RPC_INTERNAL_NAME);
/** @brief 2.2.1.2.8 KERB_RPC_ENCRYPTION_KEY */
typedef struct
{
UINT32 reserved1;
UINT32 reserved2;
KERB_RPC_OCTET_STRING reserved3;
} KERB_RPC_ENCRYPTION_KEY;
RDPEAR_COMMON_MESSAGE_DECL(KERB_RPC_ENCRYPTION_KEY);
/** @brief 2.2.2.1.8 BuildEncryptedAuthData */
typedef struct
{
UINT32 KeyUsage;
KERB_RPC_ENCRYPTION_KEY* Key;
KERB_ASN1_DATA* PlainAuthData;
} BuildEncryptedAuthDataReq;
RDPEAR_COMMON_MESSAGE_DECL(BuildEncryptedAuthDataReq);
/** @brief 2.2.2.1.7 ComputeTgsChecksum */
typedef struct
{
KERB_ASN1_DATA* requestBody;
KERB_RPC_ENCRYPTION_KEY* Key;
UINT32 ChecksumType;
} ComputeTgsChecksumReq;
RDPEAR_COMMON_MESSAGE_DECL(ComputeTgsChecksumReq);
/** @brief 2.2.2.1.4 CreateApReqAuthenticator */
typedef struct
{
KERB_RPC_ENCRYPTION_KEY* EncryptionKey;
ULONG SequenceNumber;
KERB_RPC_INTERNAL_NAME* ClientName;
RPC_UNICODE_STRING* ClientRealm;
PLARGE_INTEGER SkewTime;
KERB_RPC_ENCRYPTION_KEY* SubKey; // optional
KERB_ASN1_DATA* AuthData; // optional
KERB_ASN1_DATA* GssChecksum; // optional
ULONG KeyUsage;
} CreateApReqAuthenticatorReq;
RDPEAR_COMMON_MESSAGE_DECL(CreateApReqAuthenticatorReq);
/** @brief 2.2.2.1.4 CreateApReqAuthenticator */
typedef struct
{
LARGE_INTEGER AuthenticatorTime;
KERB_ASN1_DATA Authenticator;
LONG KerbProtocolError;
} CreateApReqAuthenticatorResp;
RDPEAR_COMMON_MESSAGE_DECL(CreateApReqAuthenticatorResp);
/** @brief 2.2.2.1.6 UnpackKdcReplyBody */
typedef struct
{
KERB_ASN1_DATA* EncryptedData;
KERB_RPC_ENCRYPTION_KEY* Key;
KERB_RPC_ENCRYPTION_KEY* StrengthenKey;
ULONG Pdu;
ULONG KeyUsage;
} UnpackKdcReplyBodyReq;
RDPEAR_COMMON_MESSAGE_DECL(UnpackKdcReplyBodyReq);
/** @brief 2.2.2.1.6 UnpackKdcReplyBody */
typedef struct
{
LONG KerbProtocolError;
KERB_ASN1_DATA ReplyBody;
} UnpackKdcReplyBodyResp;
RDPEAR_COMMON_MESSAGE_DECL(UnpackKdcReplyBodyResp);
typedef struct
{
KERB_ASN1_DATA* EncryptedReply;
KERB_RPC_ENCRYPTION_KEY* Key;
} DecryptApReplyReq;
RDPEAR_COMMON_MESSAGE_DECL(DecryptApReplyReq);
typedef struct
{
KERB_ASN1_DATA* Reply;
KERB_ASN1_DATA* ReplyBody;
KERB_RPC_ENCRYPTION_KEY* SessionKey;
} PackApReplyReq;
RDPEAR_COMMON_MESSAGE_DECL(PackApReplyReq);
typedef struct
{
NdrArrayHints PackedReplyHints;
BYTE* PackedReply;
} PackApReplyResp;
RDPEAR_COMMON_MESSAGE_DECL(PackApReplyResp);
#undef RDPEAR_COMMON_MESSAGE_DECL
#endif /* FREERDP_CHANNEL_RDPEAR_COMMON_H */

View File

@ -0,0 +1,104 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* ASN1 routines for RDPEAR
*
* Copyright 2024 David Fort <contact@hardening-consulting.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <rdpear-common/rdpear_asn1.h>
#include <winpr/asn1.h>
wStream* rdpear_enc_Checksum(UINT32 cksumtype, krb5_checksum* csum)
{
/**
* Checksum ::= SEQUENCE {
* cksumtype [0] Int32,
* checksum [1] OCTET STRING
* }
*/
wStream* ret = NULL;
WinPrAsn1Encoder* enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
if (!enc)
return NULL;
if (!WinPrAsn1EncSeqContainer(enc))
goto out;
if (!WinPrAsn1EncContextualInteger(enc, 0, (WinPrAsn1_INTEGER)cksumtype))
goto out;
WinPrAsn1_OctetString octets;
octets.data = (BYTE*)csum->contents;
octets.len = csum->length;
if (!WinPrAsn1EncContextualOctetString(enc, 1, &octets) || !WinPrAsn1EncEndContainer(enc))
goto out;
ret = Stream_New(NULL, 1024);
if (!ret)
goto out;
if (!WinPrAsn1EncToStream(enc, ret))
{
Stream_Free(ret, TRUE);
ret = NULL;
goto out;
}
out:
WinPrAsn1Encoder_Free(&enc);
return ret;
}
wStream* rdpear_enc_EncryptedData(UINT32 encType, krb5_data* payload)
{
/**
* EncryptedData ::= SEQUENCE {
* etype [0] Int32 -- EncryptionType --,
* kvno [1] UInt32 OPTIONAL,
* cipher [2] OCTET STRING -- ciphertext
* }
*/
wStream* ret = NULL;
WinPrAsn1Encoder* enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
if (!enc)
return NULL;
if (!WinPrAsn1EncSeqContainer(enc))
goto out;
if (!WinPrAsn1EncContextualInteger(enc, 0, (WinPrAsn1_INTEGER)encType))
goto out;
WinPrAsn1_OctetString octets;
octets.data = (BYTE*)payload->data;
octets.len = payload->length;
if (!WinPrAsn1EncContextualOctetString(enc, 2, &octets) || !WinPrAsn1EncEndContainer(enc))
goto out;
ret = Stream_New(NULL, 1024);
if (!ret)
goto out;
if (!WinPrAsn1EncToStream(enc, ret))
{
Stream_Free(ret, TRUE);
ret = NULL;
goto out;
}
out:
WinPrAsn1Encoder_Free(&enc);
return ret;
}

View File

@ -0,0 +1,565 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2023 David Fort <contact@hardening-consulting.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <rdpear-common/rdpear_common.h>
#include <rdpear-common/rdpear_asn1.h>
#include <rdpear-common/ndr.h>
#include <stddef.h>
#include <winpr/print.h>
#include <freerdp/channels/log.h>
#define TAG CHANNELS_TAG("rdpear")
static char kerberosPackageName[] = {
'K', 0, 'e', 0, 'r', 0, 'b', 0, 'e', 0, 'r', 0, 'o', 0, 's', 0
};
static char ntlmPackageName[] = { 'N', 0, 'T', 0, 'L', 0, 'M', 0 };
RdpEarPackageType rdpear_packageType_from_name(WinPrAsn1_OctetString* package)
{
if (package->len == sizeof(kerberosPackageName) &&
memcmp(package->data, kerberosPackageName, package->len) == 0)
return RDPEAR_PACKAGE_KERBEROS;
if (package->len == sizeof(ntlmPackageName) &&
memcmp(package->data, ntlmPackageName, package->len) == 0)
return RDPEAR_PACKAGE_NTLM;
return RDPEAR_PACKAGE_UNKNOWN;
}
wStream* rdpear_encodePayload(RdpEarPackageType packageType, wStream* payload)
{
wStream* ret = NULL;
WinPrAsn1Encoder* enc = WinPrAsn1Encoder_New(WINPR_ASN1_DER);
if (!enc)
return NULL;
/* TSRemoteGuardInnerPacket ::= SEQUENCE { */
if (!WinPrAsn1EncSeqContainer(enc))
goto out;
/* packageName [1] OCTET STRING */
WinPrAsn1_OctetString packageOctetString;
switch (packageType)
{
case RDPEAR_PACKAGE_KERBEROS:
packageOctetString.data = (BYTE*)kerberosPackageName;
packageOctetString.len = sizeof(kerberosPackageName);
break;
case RDPEAR_PACKAGE_NTLM:
packageOctetString.data = (BYTE*)ntlmPackageName;
packageOctetString.len = sizeof(ntlmPackageName);
break;
default:
goto out;
}
if (!WinPrAsn1EncContextualOctetString(enc, 1, &packageOctetString))
goto out;
/* buffer [2] OCTET STRING*/
WinPrAsn1_OctetString payloadOctetString = { Stream_GetPosition(payload),
Stream_Buffer(payload) };
if (!WinPrAsn1EncContextualOctetString(enc, 2, &payloadOctetString))
goto out;
/* } */
if (!WinPrAsn1EncEndContainer(enc))
goto out;
ret = Stream_New(NULL, 100);
if (!ret)
goto out;
if (!WinPrAsn1EncToStream(enc, ret))
{
Stream_Free(ret, TRUE);
ret = NULL;
goto out;
}
out:
WinPrAsn1Encoder_Free(&enc);
return ret;
}
#define RDPEAR_SIMPLE_MESSAGE_TYPE(V) \
BOOL ndr_read_##V(NdrContext* context, wStream* s, const void* hints, V* obj) \
{ \
WINPR_UNUSED(hints); \
return ndr_struct_read_fromDescr(context, s, &V##_struct, obj); \
} \
BOOL ndr_write_##V(NdrContext* context, wStream* s, const void* hints, const V* obj) \
{ \
WINPR_UNUSED(hints); \
return ndr_struct_write_fromDescr(context, s, &V##_struct, obj); \
} \
void ndr_destroy_##V(NdrContext* context, const void* hints, V* obj) \
{ \
WINPR_UNUSED(hints); \
ndr_struct_destroy(context, &V##_struct, obj); \
} \
void ndr_dump_##V(wLog* logger, UINT32 lvl, size_t indentLevel, const V* obj) \
{ \
ndr_struct_dump_fromDescr(logger, lvl, indentLevel, &V##_struct, obj); \
} \
\
static BOOL ndr_descr_read_##V(NdrContext* context, wStream* s, const void* hints, void* obj) \
{ \
WINPR_UNUSED(hints); \
return ndr_struct_read_fromDescr(context, s, &V##_struct, obj); \
} \
static BOOL ndr_descr_write_##V(NdrContext* context, wStream* s, const void* hints, \
const void* obj) \
{ \
WINPR_UNUSED(hints); \
return ndr_struct_write_fromDescr(context, s, &V##_struct, obj); \
} \
static void ndr_descr_destroy_##V(NdrContext* context, const void* hints, void* obj) \
{ \
WINPR_UNUSED(hints); \
ndr_struct_destroy(context, &V##_struct, obj); \
} \
static void ndr_descr_dump_##V(wLog* logger, UINT32 lvl, size_t indentLevel, const void* obj) \
{ \
ndr_struct_dump_fromDescr(logger, lvl, indentLevel, &V##_struct, obj); \
} \
\
static NdrMessageDescr ndr_##V##_descr_s = { \
NDR_ARITY_SIMPLE, sizeof(V), ndr_descr_read_##V, ndr_descr_write_##V, \
ndr_descr_destroy_##V, ndr_descr_dump_##V, \
}; \
\
NdrMessageType ndr_##V##_descr(void) \
{ \
return &ndr_##V##_descr_s; \
}
static const NdrFieldStruct KERB_RPC_OCTET_STRING_fields[] = {
{ "Length", offsetof(KERB_RPC_OCTET_STRING, length), NDR_NOT_POINTER, -1, &ndr_uint32_descr_s },
{ "value", offsetof(KERB_RPC_OCTET_STRING, value), NDR_POINTER_NON_NULL, 0,
&ndr_uint8Array_descr_s }
};
static const NdrStructDescr KERB_RPC_OCTET_STRING_struct = { "KERB_RPC_OCTET_STRING", 2,
KERB_RPC_OCTET_STRING_fields };
RDPEAR_SIMPLE_MESSAGE_TYPE(KERB_RPC_OCTET_STRING)
/* ============================= KERB_ASN1_DATA ============================== */
static const NdrFieldStruct KERB_ASN1_DATA_fields[] = {
{ "Pdu", offsetof(KERB_ASN1_DATA, Pdu), NDR_NOT_POINTER, -1, &ndr_uint32_descr_s },
{ "Count", offsetof(KERB_ASN1_DATA, Asn1BufferHints.count), NDR_NOT_POINTER, -1,
&ndr_uint32_descr_s },
{ "Asn1Buffer", offsetof(KERB_ASN1_DATA, Asn1Buffer), NDR_POINTER_NON_NULL, 1,
&ndr_uint8Array_descr_s }
};
static const NdrStructDescr KERB_ASN1_DATA_struct = { "KERB_ASN1_DATA",
ARRAYSIZE(KERB_ASN1_DATA_fields),
KERB_ASN1_DATA_fields };
RDPEAR_SIMPLE_MESSAGE_TYPE(KERB_ASN1_DATA)
/* ============================ RPC_UNICODE_STRING ========================== */
BOOL ndr_read_RPC_UNICODE_STRING(NdrContext* context, wStream* s, const void* hints,
RPC_UNICODE_STRING* res)
{
NdrDeferredEntry bufferDesc = { NDR_PTR_NULL, "RPC_UNICODE_STRING.Buffer", &res->lenHints,
&res->Buffer, ndr_uint16VaryingArray_descr() };
UINT16 Length = 0;
UINT16 MaximumLength = 0;
WINPR_UNUSED(hints);
if (!ndr_read_uint16(context, s, &Length) || !ndr_read_uint16(context, s, &MaximumLength) ||
!ndr_read_refpointer(context, s, &bufferDesc.ptrId) || Length > MaximumLength)
return FALSE;
res->lenHints.length = Length;
res->lenHints.maxLength = MaximumLength;
res->strLength = Length / 2;
return ndr_push_deferreds(context, &bufferDesc, 1);
}
static BOOL ndr_descr_read_RPC_UNICODE_STRING(NdrContext* context, wStream* s, const void* hints,
void* res)
{
return ndr_read_RPC_UNICODE_STRING(context, s, hints, res);
}
#if 0
BOOL ndr_write_RPC_UNICODE_STRING(NdrContext* context, wStream* s, const void* hints,
const RPC_UNICODE_STRING* res)
{
return ndr_write_uint32(context, s, res->lenHints.length) &&
ndr_write_uint32(context, s, res->lenHints.maxLength) /*&&
ndr_write_BYTE_ptr(context, s, (BYTE*)res->Buffer, res->Length)*/
;
}
#endif
void ndr_dump_RPC_UNICODE_STRING(wLog* logger, UINT32 lvl, size_t indentLevel,
const RPC_UNICODE_STRING* obj)
{
WINPR_UNUSED(indentLevel);
WLog_Print(logger, lvl, "\tLength=%d MaximumLength=%d", obj->lenHints.length,
obj->lenHints.maxLength);
winpr_HexLogDump(logger, lvl, obj->Buffer, obj->lenHints.length);
}
static void ndr_descr_dump_RPC_UNICODE_STRING(wLog* logger, UINT32 lvl, size_t indentLevel,
const void* obj)
{
ndr_dump_RPC_UNICODE_STRING(logger, lvl, indentLevel, obj);
}
void ndr_destroy_RPC_UNICODE_STRING(NdrContext* context, const void* hints, RPC_UNICODE_STRING* obj)
{
WINPR_UNUSED(context);
WINPR_UNUSED(hints);
if (!obj)
return;
free(obj->Buffer);
obj->Buffer = NULL;
}
static void ndr_descr_destroy_RPC_UNICODE_STRING(NdrContext* context, const void* hints, void* obj)
{
ndr_destroy_RPC_UNICODE_STRING(context, hints, obj);
}
static const NdrMessageDescr RPC_UNICODE_STRING_descr_s = { NDR_ARITY_SIMPLE,
sizeof(RPC_UNICODE_STRING),
ndr_descr_read_RPC_UNICODE_STRING,
/*ndr_write_RPC_UNICODE_STRING*/ NULL,
ndr_descr_destroy_RPC_UNICODE_STRING,
ndr_descr_dump_RPC_UNICODE_STRING };
NdrMessageType ndr_RPC_UNICODE_STRING_descr(void)
{
return &RPC_UNICODE_STRING_descr_s;
}
/* ========================= RPC_UNICODE_STRING_Array ======================== */
static BOOL ndr_read_RPC_UNICODE_STRING_Array(NdrContext* context, wStream* s, const void* hints,
void* v)
{
WINPR_ASSERT(context);
WINPR_ASSERT(s);
WINPR_ASSERT(hints);
return ndr_read_uconformant_array(context, s, hints, ndr_RPC_UNICODE_STRING_descr(), v);
}
static BOOL ndr_write_RPC_UNICODE_STRING_Array(NdrContext* context, wStream* s, const void* ghints,
const void* v)
{
WINPR_ASSERT(context);
WINPR_ASSERT(s);
WINPR_ASSERT(ghints);
const NdrArrayHints* hints = (const NdrArrayHints*)ghints;
return ndr_write_uconformant_array(context, s, hints->count, ndr_RPC_UNICODE_STRING_descr(), v);
}
static const NdrMessageDescr RPC_UNICODE_STRING_Array_descr_s = {
NDR_ARITY_ARRAYOF,
sizeof(RPC_UNICODE_STRING),
ndr_read_RPC_UNICODE_STRING_Array,
ndr_write_RPC_UNICODE_STRING_Array,
NULL,
NULL
};
static NdrMessageType ndr_RPC_UNICODE_STRING_Array_descr(void)
{
return &RPC_UNICODE_STRING_Array_descr_s;
}
/* ========================== KERB_RPC_INTERNAL_NAME ======================== */
BOOL ndr_read_KERB_RPC_INTERNAL_NAME(NdrContext* context, wStream* s, const void* hints,
KERB_RPC_INTERNAL_NAME* res)
{
WINPR_ASSERT(res);
union
{
RPC_UNICODE_STRING** ppstr;
void* pv;
} cnv;
cnv.ppstr = &res->Names;
NdrDeferredEntry names = { NDR_PTR_NULL, "KERB_RPC_INTERNAL_NAME.Names", &res->nameHints,
cnv.pv, ndr_RPC_UNICODE_STRING_Array_descr() };
UINT16 nameCount = 0;
WINPR_UNUSED(hints);
if (!ndr_read_uint16(context, s, &res->NameType) || !ndr_read_uint16(context, s, &nameCount))
return FALSE;
res->nameHints.count = nameCount;
return ndr_read_refpointer(context, s, &names.ptrId) && ndr_push_deferreds(context, &names, 1);
}
static BOOL ndr_descr_read_KERB_RPC_INTERNAL_NAME(NdrContext* context, wStream* s,
const void* hints, void* res)
{
return ndr_read_KERB_RPC_INTERNAL_NAME(context, s, hints, res);
}
BOOL ndr_write_KERB_RPC_INTERNAL_NAME(NdrContext* context, wStream* s, const void* hints,
const KERB_RPC_INTERNAL_NAME* res)
{
WINPR_UNUSED(context);
WINPR_UNUSED(s);
WINPR_UNUSED(hints);
WINPR_UNUSED(res);
WLog_ERR(TAG, "TODO: implement this");
return FALSE;
}
void ndr_dump_KERB_RPC_INTERNAL_NAME(wLog* logger, UINT32 lvl, size_t indentLevel,
const KERB_RPC_INTERNAL_NAME* obj)
{
WINPR_UNUSED(indentLevel);
WINPR_UNUSED(obj);
WLog_Print(logger, lvl, "TODO: implement this");
}
static void ndr_descr_dump_KERB_RPC_INTERNAL_NAME(wLog* logger, UINT32 lvl, size_t indentLevel,
const void* obj)
{
ndr_dump_KERB_RPC_INTERNAL_NAME(logger, lvl, indentLevel, obj);
}
void ndr_destroy_KERB_RPC_INTERNAL_NAME(NdrContext* context, const void* hints,
KERB_RPC_INTERNAL_NAME* obj)
{
WINPR_UNUSED(hints);
if (!obj)
return;
for (UINT32 i = 0; i < obj->nameHints.count; i++)
ndr_destroy_RPC_UNICODE_STRING(context, NULL, &obj->Names[i]);
free(obj->Names);
obj->Names = NULL;
}
static void ndr_descr_destroy_KERB_RPC_INTERNAL_NAME(NdrContext* context, const void* hints,
void* obj)
{
ndr_destroy_KERB_RPC_INTERNAL_NAME(context, hints, obj);
}
static NdrMessageDescr KERB_RPC_INTERNAL_NAME_descr_s = { NDR_ARITY_SIMPLE,
sizeof(KERB_RPC_INTERNAL_NAME),
ndr_descr_read_KERB_RPC_INTERNAL_NAME,
NULL,
ndr_descr_destroy_KERB_RPC_INTERNAL_NAME,
ndr_descr_dump_KERB_RPC_INTERNAL_NAME };
NdrMessageType ndr_KERB_RPC_INTERNAL_NAME_descr(void)
{
return &KERB_RPC_INTERNAL_NAME_descr_s;
}
/* ========================== KERB_RPC_ENCRYPTION_KEY ======================== */
static const NdrFieldStruct KERB_RPC_ENCRYPTION_KEY_fields[] = {
{ "reserved1", offsetof(KERB_RPC_ENCRYPTION_KEY, reserved1), NDR_NOT_POINTER, -1,
&ndr_uint32_descr_s },
{ "reserved2", offsetof(KERB_RPC_ENCRYPTION_KEY, reserved2), NDR_NOT_POINTER, -1,
&ndr_uint32_descr_s },
{ "reserved3", offsetof(KERB_RPC_ENCRYPTION_KEY, reserved3), NDR_NOT_POINTER, -1,
&ndr_KERB_RPC_OCTET_STRING_descr_s }
};
static const NdrStructDescr KERB_RPC_ENCRYPTION_KEY_struct = {
"KERB_RPC_ENCRYPTION_KEY", ARRAYSIZE(KERB_RPC_ENCRYPTION_KEY_fields),
KERB_RPC_ENCRYPTION_KEY_fields
};
RDPEAR_SIMPLE_MESSAGE_TYPE(KERB_RPC_ENCRYPTION_KEY)
/* ========================== BuildEncryptedAuthDataReq ======================== */
static const NdrFieldStruct BuildEncryptedAuthDataReq_fields[] = {
{ "KeyUsage", offsetof(BuildEncryptedAuthDataReq, KeyUsage), NDR_NOT_POINTER, -1,
&ndr_uint32_descr_s },
{ "key", offsetof(BuildEncryptedAuthDataReq, Key), NDR_POINTER_NON_NULL, -1,
&ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
{ "plainAuthData", offsetof(BuildEncryptedAuthDataReq, PlainAuthData), NDR_POINTER_NON_NULL, -1,
&ndr_KERB_ASN1_DATA_descr_s }
};
static const NdrStructDescr BuildEncryptedAuthDataReq_struct = {
"BuildEncryptedAuthDataReq", ARRAYSIZE(BuildEncryptedAuthDataReq_fields),
BuildEncryptedAuthDataReq_fields
};
RDPEAR_SIMPLE_MESSAGE_TYPE(BuildEncryptedAuthDataReq)
/* ========================== ComputeTgsChecksumReq ======================== */
static const NdrFieldStruct ComputeTgsChecksumReq_fields[] = {
{ "requestBody", offsetof(ComputeTgsChecksumReq, requestBody), NDR_POINTER_NON_NULL, -1,
&ndr_KERB_ASN1_DATA_descr_s },
{ "key", offsetof(ComputeTgsChecksumReq, Key), NDR_POINTER_NON_NULL, -1,
&ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
{ "ChecksumType", offsetof(ComputeTgsChecksumReq, ChecksumType), NDR_NOT_POINTER, -1,
&ndr_uint32_descr_s }
};
static const NdrStructDescr ComputeTgsChecksumReq_struct = {
"ComputeTgsChecksumReq", ARRAYSIZE(ComputeTgsChecksumReq_fields), ComputeTgsChecksumReq_fields
};
RDPEAR_SIMPLE_MESSAGE_TYPE(ComputeTgsChecksumReq)
/* ========================== CreateApReqAuthenticatorReq ======================== */
static const NdrFieldStruct CreateApReqAuthenticatorReq_fields[] = {
{ "EncryptionKey", offsetof(CreateApReqAuthenticatorReq, EncryptionKey), NDR_POINTER_NON_NULL,
-1, &ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
{ "SequenceNumber", offsetof(CreateApReqAuthenticatorReq, SequenceNumber), NDR_NOT_POINTER, -1,
&ndr_uint32_descr_s },
{ "ClientName", offsetof(CreateApReqAuthenticatorReq, ClientName), NDR_POINTER_NON_NULL, -1,
&KERB_RPC_INTERNAL_NAME_descr_s },
{ "ClientRealm", offsetof(CreateApReqAuthenticatorReq, ClientRealm), NDR_POINTER_NON_NULL, -1,
&RPC_UNICODE_STRING_descr_s },
{ "SkewTime", offsetof(CreateApReqAuthenticatorReq, SkewTime), NDR_POINTER_NON_NULL, -1,
&ndr_uint64_descr_s },
{ "SubKey", offsetof(CreateApReqAuthenticatorReq, SubKey), NDR_POINTER, -1,
&ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
{ "AuthData", offsetof(CreateApReqAuthenticatorReq, AuthData), NDR_POINTER_NON_NULL, -1,
&ndr_KERB_ASN1_DATA_descr_s },
{ "GssChecksum", offsetof(CreateApReqAuthenticatorReq, GssChecksum), NDR_POINTER, -1,
&ndr_KERB_ASN1_DATA_descr_s },
{ "KeyUsage", offsetof(CreateApReqAuthenticatorReq, KeyUsage), NDR_NOT_POINTER, -1,
&ndr_uint32_descr_s },
};
static const NdrStructDescr CreateApReqAuthenticatorReq_struct = {
"CreateApReqAuthenticatorReq", ARRAYSIZE(CreateApReqAuthenticatorReq_fields),
CreateApReqAuthenticatorReq_fields
};
RDPEAR_SIMPLE_MESSAGE_TYPE(CreateApReqAuthenticatorReq)
/* ========================== CreateApReqAuthenticatorResp ======================== */
static const NdrFieldStruct CreateApReqAuthenticatorResp_fields[] = {
{ "AuthenticatorTime", offsetof(CreateApReqAuthenticatorResp, AuthenticatorTime),
NDR_NOT_POINTER, -1, &ndr_uint64_descr_s },
{ "Authenticator", offsetof(CreateApReqAuthenticatorResp, Authenticator), NDR_NOT_POINTER, -1,
&ndr_KERB_ASN1_DATA_descr_s },
{ "KerbProtocolError", offsetof(CreateApReqAuthenticatorResp, KerbProtocolError),
NDR_NOT_POINTER, -1, &ndr_uint32_descr_s },
};
static const NdrStructDescr CreateApReqAuthenticatorResp_struct = {
"CreateApReqAuthenticatorResp", ARRAYSIZE(CreateApReqAuthenticatorResp_fields),
CreateApReqAuthenticatorResp_fields
};
RDPEAR_SIMPLE_MESSAGE_TYPE(CreateApReqAuthenticatorResp)
/* ========================== UnpackKdcReplyBodyReq ======================== */
static const NdrFieldStruct UnpackKdcReplyBodyReq_fields[] = {
{ "EncryptedData", offsetof(UnpackKdcReplyBodyReq, EncryptedData), NDR_POINTER_NON_NULL, -1,
&ndr_KERB_ASN1_DATA_descr_s },
{ "Key", offsetof(UnpackKdcReplyBodyReq, Key), NDR_POINTER_NON_NULL, -1,
&ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
{ "StrenghtenKey", offsetof(UnpackKdcReplyBodyReq, StrengthenKey), NDR_POINTER, -1,
&ndr_KERB_RPC_ENCRYPTION_KEY_descr_s },
{ "Pdu", offsetof(UnpackKdcReplyBodyReq, Pdu), NDR_NOT_POINTER, -1, &ndr_uint32_descr_s },
{ "KeyUsage", offsetof(UnpackKdcReplyBodyReq, KeyUsage), NDR_NOT_POINTER, -1,
&ndr_uint32_descr_s },
};
static const NdrStructDescr UnpackKdcReplyBodyReq_struct = {
"UnpackKdcReplyBodyReq", ARRAYSIZE(UnpackKdcReplyBodyReq_fields), UnpackKdcReplyBodyReq_fields
};
RDPEAR_SIMPLE_MESSAGE_TYPE(UnpackKdcReplyBodyReq)
/* ========================== UnpackKdcReplyBodyResp ======================== */
static const NdrFieldStruct UnpackKdcReplyBodyResp_fields[] = {
{ "KerbProtocolError", offsetof(UnpackKdcReplyBodyResp, KerbProtocolError), NDR_NOT_POINTER, -1,
&ndr_uint32_descr_s },
{ "ReplyBody", offsetof(UnpackKdcReplyBodyResp, ReplyBody), NDR_NOT_POINTER, -1,
&ndr_KERB_ASN1_DATA_descr_s }
};
static const NdrStructDescr UnpackKdcReplyBodyResp_struct = {
"UnpackKdcReplyBodyResp", ARRAYSIZE(UnpackKdcReplyBodyResp_fields),
UnpackKdcReplyBodyResp_fields
};
RDPEAR_SIMPLE_MESSAGE_TYPE(UnpackKdcReplyBodyResp)
/* ========================== DecryptApReplyReq ======================== */
static const NdrFieldStruct DecryptApReplyReq_fields[] = {
{ "EncryptedReply", offsetof(DecryptApReplyReq, EncryptedReply), NDR_POINTER_NON_NULL, -1,
&ndr_KERB_ASN1_DATA_descr_s },
{ "Key", offsetof(DecryptApReplyReq, Key), NDR_POINTER_NON_NULL, -1,
&ndr_KERB_RPC_ENCRYPTION_KEY_descr_s }
};
static const NdrStructDescr DecryptApReplyReq_struct = { "DecryptApReplyReq",
ARRAYSIZE(DecryptApReplyReq_fields),
DecryptApReplyReq_fields };
RDPEAR_SIMPLE_MESSAGE_TYPE(DecryptApReplyReq)
/* ========================== PackApReplyReq ======================== */
static const NdrFieldStruct PackApReplyReq_fields[] = {
{ "Reply", offsetof(PackApReplyReq, Reply), NDR_POINTER_NON_NULL, -1,
&ndr_KERB_ASN1_DATA_descr_s },
{ "ReplyBody", offsetof(PackApReplyReq, ReplyBody), NDR_POINTER_NON_NULL, -1,
&ndr_KERB_ASN1_DATA_descr_s },
{ "SessionKey", offsetof(PackApReplyReq, SessionKey), NDR_POINTER_NON_NULL, -1,
&ndr_KERB_RPC_ENCRYPTION_KEY_descr_s }
};
static const NdrStructDescr PackApReplyReq_struct = { "PackApReplyReq",
ARRAYSIZE(PackApReplyReq_fields),
PackApReplyReq_fields };
RDPEAR_SIMPLE_MESSAGE_TYPE(PackApReplyReq)
/* ========================== PackApReplyResp ======================== */
static const NdrFieldStruct PackApReplyResp_fields[] = {
{ "PackedReplySize", offsetof(PackApReplyResp, PackedReplyHints), NDR_NOT_POINTER, -1,
&ndr_uint32_descr_s },
{ "PackedReply", offsetof(PackApReplyResp, PackedReply), NDR_POINTER_NON_NULL, 0,
&ndr_uint8Array_descr_s },
};
static const NdrStructDescr PackApReplyResp_struct = { "PackApReplyResp",
ARRAYSIZE(PackApReplyResp_fields),
PackApReplyResp_fields };
RDPEAR_SIMPLE_MESSAGE_TYPE(PackApReplyResp)

View File

@ -0,0 +1,40 @@
set(MODULE_NAME "TestRdpear")
set(MODULE_PREFIX "TEST_RDPEAR")
set(TEST_RDPEAR_DRIVER TestRdpear.c)
disable_warnings_for_directory(${CMAKE_CURRENT_BINARY_DIR})
set(TEST_RDPEAR_TESTS
TestNdr.c
)
if (BUILD_TESTING_INTERNAL)
list(APPEND TEST_RDPEAR_TESTS
TestNdrEar.c
)
endif()
create_test_sourcelist(TEST_RDPEAR_SRCS
TestRdpear.c
${TEST_RDPEAR_TESTS}
)
add_executable(${MODULE_NAME} ${TEST_RDPEAR_SRCS})
add_definitions(-DTESTING_OUTPUT_DIRECTORY="${PROJECT_BINARY_DIR}")
add_definitions(-DTESTING_SRC_DIRECTORY="${PROJECT_SOURCE_DIR}")
target_link_libraries(${MODULE_NAME} freerdp winpr freerdp-client)
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
foreach(test ${${MODULE_PREFIX}_TESTS})
get_filename_component(TestName ${test} NAME_WE)
add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
endforeach()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/Rdpear/Test")

View File

@ -0,0 +1,39 @@
#include <rdpear-common/ndr.h>
int TestNdr(int argc, char* argv[])
{
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
int retCode = -2;
NdrContext* context = ndr_context_new(FALSE, 1);
if (!context)
return -1;
BYTE payload[] = {
// == conformant array ==
0x02, 0x00, 0x00, 0x00, // (nitems)
0x30, 0x00, // content
0x00, 0x00 // (padding)
};
wStream staticS;
wStream* s = Stream_StaticInit(&staticS, payload, sizeof(payload));
BYTE* target = NULL;
NdrArrayHints hints = { 2 };
NdrDeferredEntry e = { 0x020028, "arrayContent", &hints, &target, ndr_uint8Array_descr() };
if (!ndr_push_deferreds(context, &e, 1))
goto out;
if (!ndr_treat_deferred_read(context, s))
goto out;
NdrMessageType descr = ndr_uint8Array_descr();
descr->destroyFn(context, &hints, target);
free(target);
retCode = 0;
out:
ndr_context_destroy(&context);
return retCode;
}

View File

@ -0,0 +1,381 @@
#include <winpr/print.h>
#include <rdpear-common/ndr.h>
#include <rdpear-common/rdpear_common.h>
#ifndef MAX
#define MAX(a, b) ((a) > (b)) ? (a) : (b)
#endif
#ifndef MIN
#define MIN(a, b) ((a) < (b)) ? (a) : (b)
#endif
static BYTE nextValue(BYTE old, INT32 offset, char symbol, char startSymbol)
{
const INT32 uold = 16 * old;
const INT32 diff = symbol - startSymbol;
const INT32 res = uold + diff + offset;
return (BYTE)MIN(MAX(0, res), UINT8_MAX);
}
static BYTE* parseHexBlock(const char* str, size_t* plen)
{
WINPR_ASSERT(str);
WINPR_ASSERT(plen);
BYTE* ret = malloc(strlen(str) / 2);
BYTE* dest = ret;
const char* ptr = str;
BYTE tmp = 0;
size_t nchars = 0;
size_t len = 0;
for (; *ptr; ptr++)
{
switch (*ptr)
{
case ' ':
case '\n':
case '\t':
if (nchars)
{
WLog_ERR("", "error parsing hex block, unpaired char");
free(ret);
return NULL;
}
break;
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
tmp = nextValue(tmp, 0, *ptr, '0');
nchars++;
if (nchars == 2)
{
*dest = tmp;
dest++;
len++;
tmp = 0;
nchars = 0;
}
break;
case 'a':
case 'b':
case 'c':
case 'd':
case 'e':
case 'f':
tmp = nextValue(tmp, 10, *ptr, 'a');
nchars++;
if (nchars == 2)
{
*dest = tmp;
dest++;
len++;
tmp = 0;
nchars = 0;
}
break;
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
tmp = nextValue(tmp, 10, *ptr, 'A');
nchars++;
if (nchars == 2)
{
*dest = tmp;
dest++;
len++;
tmp = 0;
nchars = 0;
}
break;
default:
WLog_ERR("", "invalid char in hex block");
free(ret);
return NULL;
}
}
*plen = len;
return ret;
}
static int TestNdrEarWrite(int argc, char* argv[])
{
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
int rc = -1;
BYTE buffer[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
KERB_ASN1_DATA asn1 = { 7, { 16 }, buffer };
wStream* s = Stream_New(NULL, 100);
if (!s)
return -1;
NdrContext* context = ndr_context_new(FALSE, 1);
if (!context)
goto fail;
if (!ndr_write_KERB_ASN1_DATA(context, s, NULL, &asn1))
goto fail;
if (!ndr_treat_deferred_write(context, s))
goto fail;
// winpr_HexDump("", WLOG_DEBUG, Stream_Buffer(s), Stream_GetPosition(s));
rc = 0;
fail:
ndr_context_destroy(&context);
Stream_Free(s, TRUE);
return rc;
}
static int TestNdrEarRead(int argc, char* argv[])
{
WINPR_UNUSED(argc);
WINPR_UNUSED(argv);
int retCode = -2;
/* ====================================================================== */
NdrContext* context = ndr_context_new(FALSE, 1);
if (!context)
return -1;
wStream staticS = { 0 };
wStream* s = NULL;
#if 0
BYTE payload[] = {
0x00, 0x00, 0x00, 0x00, // (PduType)
0x02, 0x00, 0x00, 0x00, // (Length)
0x28, 0x00, 0x02, 0x00, // (Asn1Buffer)
// == conformant array ==
0x02, 0x00, 0x00, 0x00, // (nitems)
0x30, 0x00, // content
0x00, 0x00 // (padding)
};
s = Stream_StaticInit(&staticS, payload, sizeof(payload));
KERB_ASN1_DATA asn1 = { 0 };
if (!ndr_read_KERB_ASN1_DATA(context, s, NULL, &asn1) || !ndr_treat_deferred_read(context, s) ||
asn1.Asn1BufferHints.count != 2 || *asn1.Asn1Buffer != 0x30)
goto out;
KERB_ASN1_DATA_destroy(context, &asn1);
ndr_context_reset(context);
/* ====================================================================== */
BYTE payload2[] = {
// ------------ a RPC_UNICODE_STRING: Administrateur -------------------------
0x1c, 0x00, // (Length)
0x1e, 0x00, // (MaximumLength)
0x1c, 0x00, 0x02, 0x00, // (Buffer ptr)
// == conformant array ==
0x0f, 0x00, 0x00, 0x00, // (maximum count)
0x00, 0x00, 0x00, 0x00, // (offset)
0x0e, 0x00, 0x00, 0x00, // (length)
0x48, 0x00, 0x41, 0x00, 0x52, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x49, 0x00, 0x4e,
0x00, 0x47, 0x00, 0x33, 0x00, 0x2e, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x00, 0x00,
0x00, 0x00
};
retCode = -3;
s = Stream_StaticInit(&staticS, payload2, sizeof(payload2));
RPC_UNICODE_STRING unicode = { 0 };
if (!ndr_read_RPC_UNICODE_STRING(context, s, NULL, &unicode) || !ndr_treat_deferred_read(context, s))
goto out;
RPC_UNICODE_STRING_destroy(context, &unicode);
ndr_context_reset(context);
/* ====================================================================== */
BYTE payload3[] = {
// ------------ an KERB_RPC_INTERNAL_NAME: HARDENING3.COM -------------------------
0x01, 0x00, // (NameType)
0x01, 0x00, // (NameCount)
0x10, 0x00, 0x02, 0x00, // (Names)
// == conformant array ==
0x01, 0x00, 0x00, 0x00, // (nitems)
// = RPC_UNICODE_STRING =
0x1c, 0x00, // (Length)
0x1e, 0x00, // (MaximumLength)
0x14, 0x00, 0x02, 0x00, /// (Buffer ptr)
// == Uni-dimensional Conformant-varying Array ==
0x0f, 0x00, 0x00, 0x00, // (maximum count)
0x00, 0x00, 0x00, 0x00, // (offset)
0x0e, 0x00, 0x00, 0x00, // (length)
0x41, 0x00, 0x64, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74,
0x00, 0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x75, 0x00, 0x72, 0x00, 0x00, 0x00,
0x00, 0x00
};
KERB_RPC_INTERNAL_NAME intName = { 0 };
retCode = -4;
s = Stream_StaticInit(&staticS, payload3, sizeof(payload3));
if (!ndr_read_KERB_RPC_INTERNAL_NAME(context, s, NULL, &intName) || !ndr_treat_deferred_read(context, s))
goto out;
KERB_RPC_INTERNAL_NAME_destroy(context, &intName);
ndr_context_reset(context);
#endif
/* ====================================================================== */
#if 0
BYTE payload4[] = {
0x03, 0x01, 0x03, 0x01, // unionId / unionId
0x04, 0x00, 0x02, 0x00, // (EncryptionKey ptr)
0xf8, 0xca, 0x95, 0x11, // (SequenceNumber)
0x0c, 0x00, 0x02, 0x00, // (ClientName ptr)
0x18, 0x00, 0x02, 0x00, // (ClientRealm ptr)
0x20, 0x00, 0x02, 0x00, // (SkewTime ptr)
0x00, 0x00, 0x00, 0x00, // (SubKey ptr)
0x24, 0x00, 0x02, 0x00, // (AuthData ptr)
0x2c, 0x00, 0x02, 0x00, // (GssChecksum ptr)
0x07, 0x00, 0x00, 0x00, // (KeyUsage)
// === EncryptionKey ===
0x40, 0xe9, 0x12, 0xdf, // reserved1
0x12, 0x00, 0x00, 0x00, // reserved2
// KERB_RPC_OCTET_STRING
0x4c, 0x00, 0x00, 0x00, // (length)
0x08, 0x00, 0x02, 0x00, // (value ptr)
// == conformant array ==
0x4c, 0x00, 0x00, 0x00, // (length)
0xc4, 0x41, 0xee, 0x34,
0x82, 0x2b, 0x29, 0x61, 0xe2, 0x96, 0xb5, 0x75, 0x61, 0x2d, 0xbf, 0x86, 0x01, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x89, 0x08, 0x60, 0x2e,
0x30, 0x3e, 0xfe, 0x56, 0x11, 0xf0, 0x31, 0xf2, 0xd6, 0x2e, 0x3d, 0x33, 0xfe, 0xce, 0x56, 0x12,
0xbf, 0xb2, 0xe5, 0x86, 0x29, 0x8d, 0x29, 0x74, 0x1f, 0x8a, 0xf9, 0xb9, 0x8c, 0xd4, 0x86, 0x3a,
0x21, 0x92, 0xb2, 0x07, 0x95, 0x4b, 0xea, 0xee,
//=== ClientName - KERB_RPC_INTERNAL_NAME ===
0x01, 0x00, // (NameType)
0x01, 0x00, // (NameCount)
0x10, 0x00, 0x02, 0x00, // (Names)
0x01, 0x00, 0x00, 0x00, // (nitems)
// = RPC_UNICODE_STRING =
0x1c, 0x00, // (Length)
0x1e, 0x00, // (MaximumLength)
0x14, 0x00, 0x02, 0x00, //(Buffer ptr)
// == Uni-dimensional Conformant-varying Array ==
0x0f, 0x00, 0x00, 0x00, // (maximum count)
0x00, 0x00, 0x00, 0x00, // (offset)
0x0e, 0x00, 0x00, 0x00, // (length)
0x41, 0x00, 0x64, 0x00, 0x6d, 0x00, 0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00,
0x72, 0x00, 0x61, 0x00, 0x74, 0x00, 0x65, 0x00, 0x75, 0x00, 0x72, 0x00,
// === ClientRealm - RPC_UNICODE_STRING ===
0x1c, 0x00, // (Length)
0x1e, 0x00, // (MaximumLength)
0x1c, 0x00, 0x02, 0x00, // (Buffer ptr)
// == Uni-dimensional conformant varying array ==
0x0f, 0x00, 0x00, 0x00, // (maximum count)
0x00, 0x00, 0x00, 0x00, // (offset)
0x0e, 0x00, 0x00, 0x00, // (length)
0x48, 0x00, 0x41, 0x00, 0x52, 0x00, 0x44, 0x00, 0x45, 0x00, 0x4e, 0x00, 0x49, 0x00, 0x4e, 0x00,
0x47, 0x00, 0x33, 0x00, 0x2e, 0x00, 0x43, 0x00, 0x4f, 0x00, 0x4d, 0x00,
0x00, 0x00, 0x00, 0x00, // padding
// == SkewTime ==
0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
// === AuthData - KERB_ASN1_DATA ==
0x00, 0x00, 0x00, 0x00, // (PduType)
0x02, 0x00, 0x00, 0x00, // (Length)
0x28, 0x00, 0x02, 0x00, // (Asn1Buffer)
// == conformant array ==
0x02, 0x00, 0x00, 0x00, // (nitems)
0x30, 0x00,
0x00, 0x00, // (padding)
// === GssChecksum - KERB_ASN1_DATA ===
0x08, 0x00, 0x00, 0x00, // (PduType)
0x1b, 0x00, 0x00, 0x00, // (Length)
0x30, 0x00, 0x02, 0x00, // (Asn1Buffer)
// == conformant array ==
0x1b, 0x00, 0x00, 0x00, // (length)
0x30, 0x19,
0xa0, 0x03,
0x02, 0x01, 0x07,
0xa1, 0x12,
0x04, 0x10, 0xb9, 0x4f, 0xcd, 0xae, 0xd9, 0xa8, 0xff, 0x49, 0x69, 0x5a, 0xd1,
0x1d, 0x38, 0x49, 0xb6, 0x92, 0x00
};
size_t sizeofPayload4 = sizeof(payload4);
#endif
#if 1
size_t sizeofPayload4 = 0;
BYTE* payload4 = parseHexBlock("03 01 03 01 \
04 00 02 00 38 9e ef 6b 0c 00 02 00 18 00 02 00 \
20 00 02 00 00 00 00 00 24 00 02 00 2c 00 02 00 \
07 00 00 00 13 8a a5 a8 12 00 00 00 20 00 00 00 \
08 00 02 00 20 00 00 00 c9 03 42 a8 17 8f d9 c4 \
9b d2 c4 6e 73 64 98 7b 90 f5 9a 28 77 8e ca de \
29 2e a3 8d 8a 56 36 d5 01 00 01 00 10 00 02 00 \
01 00 00 00 1c 00 1e 00 14 00 02 00 0f 00 00 00 \
00 00 00 00 0e 00 00 00 41 00 64 00 6d 00 69 00 \
6e 00 69 00 73 00 74 00 72 00 61 00 74 00 65 00 \
75 00 72 00 1c 00 1e 00 1c 00 02 00 0f 00 00 00 \
00 00 00 00 0e 00 00 00 48 00 41 00 52 00 44 00 \
45 00 4e 00 49 00 4e 00 47 00 33 00 2e 00 43 00 \
4f 00 4d 00 00 00 00 00 00 00 00 00 00 00 00 00 \
02 00 00 00 28 00 02 00 02 00 00 00 30 00 00 00 \
08 00 00 00 1b 00 00 00 30 00 02 00 1b 00 00 00 \
30 19 a0 03 02 01 07 a1 12 04 10 e4 aa ff 2b 93 \
97 4c f2 5c 0b 49 85 72 92 94 54 00",
&sizeofPayload4);
if (!payload4)
goto out;
#endif
CreateApReqAuthenticatorReq createApReqAuthenticatorReq = { 0 };
s = Stream_StaticInit(&staticS, payload4, sizeofPayload4);
if (!ndr_skip_bytes(context, s, 4) || /* skip union id */
!ndr_read_CreateApReqAuthenticatorReq(context, s, NULL, &createApReqAuthenticatorReq) ||
!ndr_treat_deferred_read(context, s) || createApReqAuthenticatorReq.KeyUsage != 7 ||
!createApReqAuthenticatorReq.EncryptionKey || createApReqAuthenticatorReq.SubKey ||
!createApReqAuthenticatorReq.ClientName ||
createApReqAuthenticatorReq.ClientName->nameHints.count != 1 ||
!createApReqAuthenticatorReq.ClientRealm || !createApReqAuthenticatorReq.AuthData ||
createApReqAuthenticatorReq.AuthData->Asn1BufferHints.count != 2 ||
!createApReqAuthenticatorReq.SkewTime ||
createApReqAuthenticatorReq.SkewTime->QuadPart != 0)
goto out;
ndr_destroy_CreateApReqAuthenticatorReq(context, NULL, &createApReqAuthenticatorReq);
ndr_context_reset(context);
/* ============ successful end of test =============== */
retCode = 0;
out:
free(payload4);
ndr_context_destroy(&context);
return retCode;
}
int TestNdrEar(int argc, char* argv[])
{
const int rc = TestNdrEarWrite(argc, argv);
if (rc)
return rc;
return TestNdrEarRead(argc, argv);
}

View File

@ -22,7 +22,7 @@ if(NOT WITH_SWSCALE OR NOT WITH_FFMPEG)
endif()
# currently camera redirect client supported for platforms with Video4Linux only
find_package(SWScale REQUIRED)
find_package(FFmpeg REQUIRED COMPONENTS SWSCALE)
find_package(V4L)
if(V4L_FOUND)
set(WITH_V4L ON)
@ -31,7 +31,17 @@ else()
message(FATAL_ERROR "libv4l-dev required for CHANNEL_RDPECAM_CLIENT")
endif()
include_directories(${SWScale_INCLUDE_DIR})
option(RDPECAM_INPUT_FORMAT_H264 "[MS-RDPECAM] Enable H264 camera format (passthrough)" ON)
if(RDPECAM_INPUT_FORMAT_H264)
add_definitions("-DWITH_INPUT_FORMAT_H264")
endif()
option(RDPECAM_INPUT_FORMAT_MJPG "[MS-RDPECAM] Enable MJPG camera format" ON)
if(RDPECAM_INPUT_FORMAT_MJPG)
add_definitions("-DWITH_INPUT_FORMAT_MJPG")
endif()
include_directories(SYSTEM ${SWSCALE_INCLUDE_DIRS})
set(${MODULE_PREFIX}_SRCS
camera_device_enum_main.c
@ -42,7 +52,7 @@ set(${MODULE_PREFIX}_SRCS
set(${MODULE_PREFIX}_LIBS
freerdp
winpr
${SWScale_LIBRARY}
${SWSCALE_LIBRARIES}
${FFMPEG_LIBRARIES}
)

View File

@ -25,6 +25,10 @@
#include <stdlib.h>
#include <string.h>
#if defined(WITH_INPUT_FORMAT_MJPG)
#include <libavcodec/avcodec.h>
#endif
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
@ -54,7 +58,7 @@
* for sample responses. Excessive size is to make sure any sample
* will fit in, even with highest resolution.
*/
#define ECAM_SAMPLE_RESPONSE_BUFFER_SIZE (1024 * 4050)
#define ECAM_SAMPLE_RESPONSE_BUFFER_SIZE (1024ULL * 4050ULL)
typedef struct s_ICamHal ICamHal;
@ -94,8 +98,15 @@ typedef struct
wStream* sampleRespBuffer;
H264_CONTEXT* h264;
#if defined(WITH_INPUT_FORMAT_MJPG)
AVCodecContext* avContext;
AVPacket* avInputPkt;
AVFrame* avOutFrame;
#endif
/* sws_scale */
struct SwsContext* sws;
int srcLineSizes[4];
} CameraDeviceStream;
@ -160,7 +171,7 @@ typedef struct
typedef FREERDP_CAMERA_HAL_ENTRY_POINTS* PFREERDP_CAMERA_HAL_ENTRY_POINTS;
/* entry point called by addin manager */
typedef UINT (*PFREERDP_CAMERA_HAL_ENTRY)(PFREERDP_CAMERA_HAL_ENTRY_POINTS pEntryPoints);
typedef UINT(VCAPITYPE* PFREERDP_CAMERA_HAL_ENTRY)(PFREERDP_CAMERA_HAL_ENTRY_POINTS pEntryPoints);
/* common functions */
UINT ecam_channel_send_generic_msg(CameraPlugin* ecam, GENERIC_CHANNEL_CALLBACK* hchannel,
@ -171,8 +182,10 @@ UINT ecam_channel_write(CameraPlugin* ecam, GENERIC_CHANNEL_CALLBACK* hchannel,
wStream* out, BOOL freeStream);
/* ecam device interface */
void ecam_dev_destroy(CameraDevice* dev);
WINPR_ATTR_MALLOC(ecam_dev_destroy, 1)
CameraDevice* ecam_dev_create(CameraPlugin* ecam, const char* deviceId, const char* deviceName);
void ecam_dev_destroy(void* dev);
/* video encoding interface */
BOOL ecam_encoder_context_init(CameraDeviceStream* stream);

View File

@ -316,6 +316,12 @@ static UINT ecam_on_new_channel_connection(IWTSListenerCallback* pListenerCallba
return CHANNEL_RC_OK;
}
static void ecam_dev_destroy_pv(void* obj)
{
CameraDevice* dev = obj;
ecam_dev_destroy(dev);
}
/**
* Function description
*
@ -349,7 +355,7 @@ static UINT ecam_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage
wObject* obj = HashTable_ValueObject(ecam->devices);
WINPR_ASSERT(obj);
obj->fnObjectFree = ecam_dev_destroy;
obj->fnObjectFree = ecam_dev_destroy_pv;
ecam->hlistener = (GENERIC_LISTENER_CALLBACK*)calloc(1, sizeof(GENERIC_LISTENER_CALLBACK));
@ -468,11 +474,14 @@ static UINT ecam_load_hal_plugin(CameraPlugin* ecam, const char* name, const ADD
FREERDP_CAMERA_HAL_ENTRY_POINTS entryPoints = { 0 };
UINT error = ERROR_INTERNAL_ERROR;
const PFREERDP_CAMERA_HAL_ENTRY entry =
(const PFREERDP_CAMERA_HAL_ENTRY)freerdp_load_channel_addin_entry(RDPECAM_CHANNEL_NAME,
name, NULL, 0);
union
{
PVIRTUALCHANNELENTRY pvce;
const PFREERDP_CAMERA_HAL_ENTRY entry;
} cnv;
cnv.pvce = freerdp_load_channel_addin_entry(RDPECAM_CHANNEL_NAME, name, NULL, 0);
if (entry == NULL)
if (cnv.entry == NULL)
{
WLog_ERR(TAG,
"freerdp_load_channel_addin_entry did not return any function pointers for %s ",
@ -485,7 +494,8 @@ static UINT ecam_load_hal_plugin(CameraPlugin* ecam, const char* name, const ADD
entryPoints.args = args;
entryPoints.ecam = ecam;
if ((error = entry(&entryPoints)))
error = cnv.entry(&entryPoints);
if (error)
{
WLog_ERR(TAG, "%s entry returned error %" PRIu32 ".", name, error);
return error;
@ -500,7 +510,7 @@ static UINT ecam_load_hal_plugin(CameraPlugin* ecam, const char* name, const ADD
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(UINT rdpecam_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
FREERDP_ENTRY_POINT(UINT VCAPITYPE rdpecam_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
{
UINT error = CHANNEL_RC_INITIALIZATION_ERROR;

View File

@ -24,11 +24,16 @@
#define TAG CHANNELS_TAG("rdpecam-device.client")
/* supported formats in preference order:
* passthrough, I420 (used as input for H264 encoder), other YUV based, RGB based
* H264, MJPG, I420 (used as input for H264 encoder), other YUV based, RGB based
*/
static const CAM_MEDIA_FORMAT_INFO supportedFormats[] = {
/* inputFormat, outputFormat */
{ CAM_MEDIA_FORMAT_H264, CAM_MEDIA_FORMAT_H264 }, /* passthrough: comment out to disable */
/* inputFormat, outputFormat */
#if defined(WITH_INPUT_FORMAT_H264)
{ CAM_MEDIA_FORMAT_H264, CAM_MEDIA_FORMAT_H264 }, /* passthrough */
#endif
#if defined(WITH_INPUT_FORMAT_MJPG)
{ CAM_MEDIA_FORMAT_MJPG, CAM_MEDIA_FORMAT_H264 },
#endif
{ CAM_MEDIA_FORMAT_I420, CAM_MEDIA_FORMAT_H264 },
{ CAM_MEDIA_FORMAT_YUY2, CAM_MEDIA_FORMAT_H264 },
{ CAM_MEDIA_FORMAT_NV12, CAM_MEDIA_FORMAT_H264 },
@ -37,11 +42,6 @@ static const CAM_MEDIA_FORMAT_INFO supportedFormats[] = {
};
static const size_t nSupportedFormats = ARRAYSIZE(supportedFormats);
/**
* Function description
*
* @return void
*/
static void ecam_dev_write_media_type(wStream* s, CAM_MEDIA_TYPE_DESCRIPTION* mediaType)
{
WINPR_ASSERT(mediaType);
@ -56,11 +56,6 @@ static void ecam_dev_write_media_type(wStream* s, CAM_MEDIA_TYPE_DESCRIPTION* me
Stream_Write_UINT8(s, mediaType->Flags);
}
/**
* Function description
*
* @return TRUE if success
*/
static BOOL ecam_dev_read_media_type(wStream* s, CAM_MEDIA_TYPE_DESCRIPTION* mediaType)
{
WINPR_ASSERT(mediaType);
@ -76,11 +71,6 @@ static BOOL ecam_dev_read_media_type(wStream* s, CAM_MEDIA_TYPE_DESCRIPTION* med
return TRUE;
}
/**
* Function description
*
* @return void
*/
static void ecam_dev_print_media_type(CAM_MEDIA_TYPE_DESCRIPTION* mediaType)
{
WINPR_ASSERT(mediaType);
@ -149,7 +139,7 @@ static UINT ecam_dev_sample_captured_callback(CameraDevice* dev, int streamIndex
}
else /* passthrough */
{
encodedSample = (BYTE*)sample;
encodedSample = WINPR_CAST_CONST_PTR_AWAY(sample, BYTE*);
encodedSize = size;
}
@ -163,11 +153,6 @@ static UINT ecam_dev_sample_captured_callback(CameraDevice* dev, int streamIndex
return ecam_dev_send_sample_response(dev, streamIndex, encodedSample, encodedSize);
}
/**
* Function description
*
* @return void
*/
static void ecam_dev_stop_stream(CameraDevice* dev, size_t streamIndex)
{
WINPR_ASSERT(dev);
@ -493,7 +478,7 @@ static UINT ecam_dev_process_media_type_list_request(CameraDevice* dev,
stream->formats = supportedFormats[formatIndex];
/* replacing inputFormat with outputFormat in mediaTypes before sending response */
for (int i = 0; i < nMediaTypes; i++)
for (size_t i = 0; i < nMediaTypes; i++)
{
mediaTypes[i].Format = streamOutputFormat(stream);
mediaTypes[i].Flags = CAM_MEDIA_TYPE_DESCRIPTION_FLAG_DecodingRequired;
@ -794,11 +779,9 @@ CameraDevice* ecam_dev_create(CameraPlugin* ecam, const char* deviceId, const ch
*
* OBJECT_FREE_FN for devices hash table value
*
* @return void
*/
void ecam_dev_destroy(void* obj)
void ecam_dev_destroy(CameraDevice* dev)
{
CameraDevice* dev = (CameraDevice*)obj;
if (!dev)
return;
@ -817,5 +800,4 @@ void ecam_dev_destroy(void* obj)
ecam_dev_stop_stream(dev, i);
free(dev);
return;
}

View File

@ -18,6 +18,7 @@
*/
#include <winpr/assert.h>
#include <winpr/winpr.h>
#include "camera.h"
@ -86,6 +87,60 @@ static enum AVPixelFormat ecamToAVPixFormat(CAM_MEDIA_FORMAT ecamFormat)
}
}
/**
* Function description
* initialize libswscale
*
* @return success/failure
*/
static BOOL ecam_init_sws_context(CameraDeviceStream* stream, enum AVPixelFormat pixFormat)
{
WINPR_ASSERT(stream);
if (stream->sws)
return TRUE;
/* replacing deprecated JPEG formats, still produced by decoder */
switch (pixFormat)
{
case AV_PIX_FMT_YUVJ411P:
pixFormat = AV_PIX_FMT_YUV411P;
break;
case AV_PIX_FMT_YUVJ420P:
pixFormat = AV_PIX_FMT_YUV420P;
break;
case AV_PIX_FMT_YUVJ422P:
pixFormat = AV_PIX_FMT_YUV422P;
break;
case AV_PIX_FMT_YUVJ440P:
pixFormat = AV_PIX_FMT_YUV440P;
break;
case AV_PIX_FMT_YUVJ444P:
pixFormat = AV_PIX_FMT_YUV444P;
break;
default:
break;
}
const int width = (int)stream->currMediaType.Width;
const int height = (int)stream->currMediaType.Height;
stream->sws = sws_getContext(width, height, pixFormat, width, height, AV_PIX_FMT_YUV420P, 0,
NULL, NULL, NULL);
if (!stream->sws)
{
WLog_ERR(TAG, "sws_getContext failed");
return FALSE;
}
return TRUE;
}
/**
* Function description
*
@ -96,26 +151,71 @@ static BOOL ecam_encoder_compress_h264(CameraDeviceStream* stream, const BYTE* s
{
UINT32 dstSize = 0;
BYTE* srcSlice[4] = { 0 };
int srcLineSizes[4] = { 0 };
BYTE* yuv420pData[3] = { 0 };
UINT32 yuv420pStride[3] = { 0 };
prim_size_t size = { 0 };
size.width = stream->currMediaType.Width;
size.height = stream->currMediaType.Height;
prim_size_t size = { stream->currMediaType.Width, stream->currMediaType.Height };
CAM_MEDIA_FORMAT inputFormat = streamInputFormat(stream);
enum AVPixelFormat pixFormat = ecamToAVPixFormat(inputFormat);
enum AVPixelFormat pixFormat = AV_PIX_FMT_NONE;
#if defined(WITH_INPUT_FORMAT_MJPG)
if (inputFormat == CAM_MEDIA_FORMAT_MJPG)
{
stream->avInputPkt->data = WINPR_CAST_CONST_PTR_AWAY(srcData, uint8_t*);
WINPR_ASSERT(srcSize <= INT32_MAX);
stream->avInputPkt->size = (int)srcSize;
if (avcodec_send_packet(stream->avContext, stream->avInputPkt) < 0)
{
WLog_ERR(TAG, "avcodec_send_packet failed");
return FALSE;
}
if (avcodec_receive_frame(stream->avContext, stream->avOutFrame) < 0)
{
WLog_ERR(TAG, "avcodec_receive_frame failed");
return FALSE;
}
for (size_t i = 0; i < 4; i++)
{
srcSlice[i] = stream->avOutFrame->data[i];
srcLineSizes[i] = stream->avOutFrame->linesize[i];
}
/* get pixFormat produced by MJPEG decoder */
pixFormat = stream->avContext->pix_fmt;
}
else
#endif
{
pixFormat = ecamToAVPixFormat(inputFormat);
if (av_image_fill_linesizes(srcLineSizes, pixFormat, (int)size.width) < 0)
{
WLog_ERR(TAG, "av_image_fill_linesizes failed");
return FALSE;
}
if (av_image_fill_pointers(srcSlice, pixFormat, (int)size.height,
WINPR_CAST_CONST_PTR_AWAY(srcData, BYTE*), srcLineSizes) < 0)
{
WLog_ERR(TAG, "av_image_fill_pointers failed");
return FALSE;
}
}
/* get buffers for YUV420P */
if (h264_get_yuv_buffer(stream->h264, stream->srcLineSizes[0], size.width, size.height,
yuv420pData, yuv420pStride) < 0)
if (h264_get_yuv_buffer(stream->h264, srcLineSizes[0], size.width, size.height, yuv420pData,
yuv420pStride) < 0)
return FALSE;
/* convert from source format to YUV420P */
if (av_image_fill_pointers(srcSlice, pixFormat, (int)size.height, (BYTE*)srcData,
stream->srcLineSizes) < 0)
if (!ecam_init_sws_context(stream, pixFormat))
return FALSE;
const BYTE* cSrcSlice[4] = { srcSlice[0], srcSlice[1], srcSlice[2], srcSlice[3] };
if (sws_scale(stream->sws, cSrcSlice, stream->srcLineSizes, 0, (int)size.height, yuv420pData,
if (sws_scale(stream->sws, cSrcSlice, srcLineSizes, 0, (int)size.height, yuv420pData,
(int*)yuv420pStride) <= 0)
return FALSE;
@ -135,12 +235,28 @@ static BOOL ecam_encoder_compress_h264(CameraDeviceStream* stream, const BYTE* s
static void ecam_encoder_context_free_h264(CameraDeviceStream* stream)
{
WINPR_ASSERT(stream);
if (stream->sws)
{
sws_freeContext(stream->sws);
stream->sws = NULL;
}
#if defined(WITH_INPUT_FORMAT_MJPG)
if (stream->avOutFrame)
av_frame_free(&stream->avOutFrame); /* sets to NULL */
if (stream->avInputPkt)
{
stream->avInputPkt->data = NULL;
stream->avInputPkt->size = 0;
av_packet_free(&stream->avInputPkt); /* sets to NULL */
}
if (stream->avContext)
avcodec_free_context(&stream->avContext); /* sets to NULL */
#endif
if (stream->h264)
{
h264_context_free(stream->h264);
@ -148,6 +264,61 @@ static void ecam_encoder_context_free_h264(CameraDeviceStream* stream)
}
}
#if defined(WITH_INPUT_FORMAT_MJPG)
/**
* Function description
*
* @return success/failure
*/
static BOOL ecam_init_mjpeg_decoder(CameraDeviceStream* stream)
{
WINPR_ASSERT(stream);
const AVCodec* avcodec = avcodec_find_decoder(AV_CODEC_ID_MJPEG);
if (!avcodec)
{
WLog_ERR(TAG, "avcodec_find_decoder failed to find MJPEG codec");
return FALSE;
}
stream->avContext = avcodec_alloc_context3(avcodec);
if (!stream->avContext)
{
WLog_ERR(TAG, "avcodec_alloc_context3 failed");
return FALSE;
}
stream->avContext->width = stream->currMediaType.Width;
stream->avContext->height = stream->currMediaType.Height;
/* AV_EF_EXPLODE flag is to abort decoding on minor error detection,
* return error, so we can skip corrupted frames, if any */
stream->avContext->err_recognition |= AV_EF_EXPLODE;
if (avcodec_open2(stream->avContext, avcodec, NULL) < 0)
{
WLog_ERR(TAG, "avcodec_open2 failed");
return FALSE;
}
stream->avInputPkt = av_packet_alloc();
if (!stream->avInputPkt)
{
WLog_ERR(TAG, "av_packet_alloc failed");
return FALSE;
}
stream->avOutFrame = av_frame_alloc();
if (!stream->avOutFrame)
{
WLog_ERR(TAG, "av_frame_alloc failed");
return FALSE;
}
return TRUE;
}
#endif
/**
* Function description
*
@ -156,6 +327,7 @@ static void ecam_encoder_context_free_h264(CameraDeviceStream* stream)
static BOOL ecam_encoder_context_init_h264(CameraDeviceStream* stream)
{
WINPR_ASSERT(stream);
if (!stream->h264)
stream->h264 = h264_context_new(TRUE);
@ -189,30 +361,10 @@ static BOOL ecam_encoder_context_init_h264(CameraDeviceStream* stream)
if (!h264_context_set_option(stream->h264, H264_CONTEXT_OPTION_QP, 0))
goto fail;
/* initialize libswscale */
{
const int width = (int)stream->currMediaType.Width;
const int height = (int)stream->currMediaType.Height;
CAM_MEDIA_FORMAT inputFormat = streamInputFormat(stream);
enum AVPixelFormat pixFormat = ecamToAVPixFormat(inputFormat);
if (av_image_fill_linesizes(stream->srcLineSizes, pixFormat, width) < 0)
{
WLog_ERR(TAG, "av_image_fill_linesizes failed");
goto fail;
}
if (!stream->sws)
{
stream->sws = sws_getContext(width, height, pixFormat, width, height,
AV_PIX_FMT_YUV420P, 0, NULL, NULL, NULL);
}
if (!stream->sws)
{
WLog_ERR(TAG, "sws_getContext failed");
goto fail;
}
}
#if defined(WITH_INPUT_FORMAT_MJPG)
if (streamInputFormat(stream) == CAM_MEDIA_FORMAT_MJPG && !ecam_init_mjpeg_decoder(stream))
goto fail;
#endif
return TRUE;

View File

@ -27,6 +27,7 @@
#include <linux/videodev2.h>
#include "camera.h"
#include <winpr/handle.h>
#define TAG CHANNELS_TAG("rdpecam-v4l.client")
@ -77,15 +78,17 @@ static UINT cam_v4l_stream_stop(CamV4lStream* stream);
*
* @return NULL-terminated fourcc string
*/
static const char* cam_v4l_get_fourcc_str(unsigned int fourcc)
static const char* cam_v4l_get_fourcc_str(unsigned int fourcc, char* buffer, size_t size)
{
static char buf[5] = { 0 };
buf[0] = (fourcc & 0xFF);
buf[1] = (fourcc >> 8) & 0xFF;
buf[2] = (fourcc >> 16) & 0xFF;
buf[3] = (fourcc >> 24) & 0xFF;
buf[4] = 0;
return buf;
if (size < 5)
return NULL;
buffer[0] = (char)(fourcc & 0xFF);
buffer[1] = (char)((fourcc >> 8) & 0xFF);
buffer[2] = (char)((fourcc >> 16) & 0xFF);
buffer[3] = (char)((fourcc >> 24) & 0xFF);
buffer[4] = '\0';
return buffer;
}
/**
@ -142,10 +145,9 @@ static BOOL cam_v4l_format_supported(int fd, UINT32 format)
*/
static int cam_v4l_open_device(const char* deviceId, int flags)
{
UINT n;
char device[20];
char device[20] = { 0 };
int fd = -1;
struct v4l2_capability cap;
struct v4l2_capability cap = { 0 };
if (!deviceId)
return -1;
@ -153,9 +155,9 @@ static int cam_v4l_open_device(const char* deviceId, int flags)
if (0 == strncmp(deviceId, "/dev/video", 10))
return open(deviceId, flags);
for (n = 0; n < 64; n++)
for (UINT n = 0; n < 64; n++)
{
snprintf(device, sizeof(device), "/dev/video%d", n);
(void)_snprintf(device, sizeof(device), "/dev/video%" PRIu32, n);
if ((fd = open(device, flags)) == -1)
continue;
@ -188,19 +190,19 @@ static INT16 cam_v4l_get_media_type_descriptions(ICamHal* hal, const char* devic
CAM_MEDIA_TYPE_DESCRIPTION* mediaTypes,
size_t* nMediaTypes)
{
int fd;
size_t maxMediaTypes = *nMediaTypes;
size_t nTypes = 0;
int formatIndex;
BOOL formatFound = FALSE;
if ((fd = cam_v4l_open_device(deviceId, O_RDONLY)) == -1)
int fd = cam_v4l_open_device(deviceId, O_RDONLY);
if (fd == -1)
{
WLog_ERR(TAG, "Unable to open device %s", deviceId);
return -1;
}
for (formatIndex = 0; formatIndex < nSupportedFormats; formatIndex++)
size_t formatIndex = 0;
for (; formatIndex < nSupportedFormats; formatIndex++)
{
UINT32 pixelFormat = ecamToV4L2PixFormat(supportedFormats[formatIndex].inputFormat);
WINPR_ASSERT(pixelFormat != 0);
@ -243,9 +245,11 @@ static INT16 cam_v4l_get_media_type_descriptions(ICamHal* hal, const char* devic
mediaTypes->PixelAspectRatioNumerator = mediaTypes->PixelAspectRatioDenominator = 1;
char fourccstr[5] = { 0 };
WLog_DBG(TAG, "Camera format: %s, width: %u, height: %u, fps: %u/%u",
cam_v4l_get_fourcc_str(pixelFormat), mediaTypes->Width, mediaTypes->Height,
mediaTypes->FrameRateNumerator, mediaTypes->FrameRateDenominator);
cam_v4l_get_fourcc_str(pixelFormat, fourccstr, ARRAYSIZE(fourccstr)),
mediaTypes->Width, mediaTypes->Height, mediaTypes->FrameRateNumerator,
mediaTypes->FrameRateDenominator);
mediaTypes++;
nTypes++;
@ -268,7 +272,9 @@ error:
*nMediaTypes = nTypes;
close(fd);
return formatIndex;
if (formatIndex > INT16_MAX)
return -1;
return (INT16)formatIndex;
}
/**
@ -279,16 +285,15 @@ error:
static UINT cam_v4l_enumerate(ICamHal* ihal, ICamHalEnumCallback callback, CameraPlugin* ecam,
GENERIC_CHANNEL_CALLBACK* hchannel)
{
UINT n, count = 0;
char device[20];
int fd = -1;
struct v4l2_capability cap;
char *deviceName, *deviceId;
UINT count = 0;
for (n = 0; n < 64; n++)
for (UINT n = 0; n < 64; n++)
{
snprintf(device, sizeof(device), "/dev/video%d", n);
if ((fd = open(device, O_RDONLY)) == -1)
char device[20] = { 0 };
struct v4l2_capability cap = { 0 };
(void)_snprintf(device, sizeof(device), "/dev/video%" PRIu32, n);
int fd = open(device, O_RDONLY);
if (fd == -1)
continue;
/* query device capabilities and make sure this is a video capture device */
@ -299,12 +304,10 @@ static UINT cam_v4l_enumerate(ICamHal* ihal, ICamHalEnumCallback callback, Camer
}
count++;
deviceName = (char*)cap.card;
const char* deviceName = (char*)cap.card;
const char* deviceId = device;
if (cap.bus_info[0] != 0) /* may not be available in all drivers */
deviceId = (char*)cap.bus_info;
else
deviceId = device;
IFCALL(callback, ecam, hchannel, deviceId, deviceName);
@ -314,18 +317,13 @@ static UINT cam_v4l_enumerate(ICamHal* ihal, ICamHalEnumCallback callback, Camer
return count;
}
/**
* Function description
*
* @return void
*/
static void cam_v4l_stream_free_buffers(CamV4lStream* stream)
{
if (!stream || !stream->buffers)
return;
/* unmap buffers */
for (int i = 0; i < stream->nBuffers; i++)
for (size_t i = 0; i < stream->nBuffers; i++)
{
if (stream->buffers[i].length && stream->buffers[i].start != MAP_FAILED)
{
@ -336,7 +334,6 @@ static void cam_v4l_stream_free_buffers(CamV4lStream* stream)
free(stream->buffers);
stream->buffers = NULL;
stream->nBuffers = 0;
return;
}
/**
@ -420,7 +417,7 @@ static UINT cam_v4l_stream_capture_thread(void* param)
do
{
int retVal;
int retVal = 0;
struct pollfd pfd = { 0 };
pfd.fd = fd;
@ -473,11 +470,6 @@ static UINT cam_v4l_stream_capture_thread(void* param)
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return void
*/
void cam_v4l_stream_close_device(CamV4lStream* stream)
{
if (stream->fd != -1)
@ -532,16 +524,15 @@ UINT cam_v4l_stream_stop(CamV4lStream* stream)
if (stream->captureThread)
{
WaitForSingleObject(stream->captureThread, INFINITE);
CloseHandle(stream->captureThread);
(void)WaitForSingleObject(stream->captureThread, INFINITE);
(void)CloseHandle(stream->captureThread);
stream->captureThread = NULL;
}
EnterCriticalSection(&stream->lock);
/* stop streaming */
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(stream->fd, VIDIOC_STREAMOFF, &type) < 0)
{
WLog_ERR(TAG, "Failure in VIDIOC_STREAMOFF, errno %d", errno);
@ -616,7 +607,8 @@ static UINT cam_v4l_stream_start(ICamHal* ihal, CameraDevice* dev, int streamInd
}
/* trying to set frame rate, if driver supports it */
struct v4l2_streamparm sp1 = { 0 }, sp2 = { 0 };
struct v4l2_streamparm sp1 = { 0 };
struct v4l2_streamparm sp2 = { 0 };
sp1.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(stream->fd, VIDIOC_G_PARM, &sp1) < 0 ||
!(sp1.parm.capture.capability & V4L2_CAP_TIMEPERFRAME))
@ -648,8 +640,7 @@ static UINT cam_v4l_stream_start(ICamHal* ihal, CameraDevice* dev, int streamInd
stream->streaming = TRUE;
/* start streaming */
enum v4l2_buf_type type;
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (ioctl(stream->fd, VIDIOC_STREAMON, &type) < 0)
{
WLog_ERR(TAG, "Failure in VIDIOC_STREAMON, errno %d", errno);
@ -665,9 +656,11 @@ static UINT cam_v4l_stream_start(ICamHal* ihal, CameraDevice* dev, int streamInd
return CAM_ERROR_CODE_OutOfMemory;
}
char fourccstr[5] = { 0 };
WLog_INFO(TAG, "Camera format: %s, width: %u, height: %u, fps: %u/%u",
cam_v4l_get_fourcc_str(pixelFormat), mediaType->Width, mediaType->Height,
mediaType->FrameRateNumerator, mediaType->FrameRateDenominator);
cam_v4l_get_fourcc_str(pixelFormat, fourccstr, ARRAYSIZE(fourccstr)),
mediaType->Width, mediaType->Height, mediaType->FrameRateNumerator,
mediaType->FrameRateDenominator);
return CHANNEL_RC_OK;
}
@ -694,7 +687,6 @@ static UINT cam_v4l_stream_stop_by_device_id(ICamHal* ihal, const char* deviceId
*
* OBJECT_FREE_FN for streams hash table value
*
* @return void
*/
void cam_v4l_stream_free(void* obj)
{
@ -706,8 +698,6 @@ void cam_v4l_stream_free(void* obj)
DeleteCriticalSection(&stream->lock);
free(stream);
return;
}
/**
@ -734,8 +724,8 @@ static UINT cam_v4l_free(ICamHal* ihal)
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(
UINT v4l_freerdp_rdpecam_client_subsystem_entry(PFREERDP_CAMERA_HAL_ENTRY_POINTS pEntryPoints))
FREERDP_ENTRY_POINT(UINT VCAPITYPE v4l_freerdp_rdpecam_client_subsystem_entry(
PFREERDP_CAMERA_HAL_ENTRY_POINTS pEntryPoints))
{
UINT ret = CHANNEL_RC_OK;
WINPR_ASSERT(pEntryPoints);

View File

@ -287,7 +287,7 @@ static UINT enumerator_process_message(enumerator_server* enumerator)
goto out;
}
if (WTSVirtualChannelRead(enumerator->enumerator_channel, 0, (PCHAR)Stream_Buffer(s),
if (WTSVirtualChannelRead(enumerator->enumerator_channel, 0, Stream_BufferAs(s, char),
(ULONG)Stream_Capacity(s), &BytesReturned) == FALSE)
{
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
@ -348,6 +348,8 @@ static UINT enumerator_server_context_poll_int(CamDevEnumServerContext* context)
case ENUMERATOR_OPENED:
error = enumerator_process_message(enumerator);
break;
default:
break;
}
return error;
@ -415,10 +417,12 @@ static DWORD WINAPI enumerator_server_thread_func(LPVOID arg)
break;
}
break;
default:
break;
}
}
WTSVirtualChannelClose(enumerator->enumerator_channel);
(void)WTSVirtualChannelClose(enumerator->enumerator_channel);
enumerator->enumerator_channel = NULL;
if (error && enumerator->context.rdpcontext)
@ -449,7 +453,7 @@ static UINT enumerator_server_open(CamDevEnumServerContext* context)
if (!enumerator->thread)
{
WLog_ERR(TAG, "CreateThread failed!");
CloseHandle(enumerator->stopEvent);
(void)CloseHandle(enumerator->stopEvent);
enumerator->stopEvent = NULL;
return ERROR_INTERNAL_ERROR;
}
@ -468,7 +472,7 @@ static UINT enumerator_server_close(CamDevEnumServerContext* context)
if (!enumerator->externalThread && enumerator->thread)
{
SetEvent(enumerator->stopEvent);
(void)SetEvent(enumerator->stopEvent);
if (WaitForSingleObject(enumerator->thread, INFINITE) == WAIT_FAILED)
{
@ -477,8 +481,8 @@ static UINT enumerator_server_close(CamDevEnumServerContext* context)
return error;
}
CloseHandle(enumerator->thread);
CloseHandle(enumerator->stopEvent);
(void)CloseHandle(enumerator->thread);
(void)CloseHandle(enumerator->stopEvent);
enumerator->thread = NULL;
enumerator->stopEvent = NULL;
}
@ -486,7 +490,7 @@ static UINT enumerator_server_close(CamDevEnumServerContext* context)
{
if (enumerator->state != ENUMERATOR_INITIAL)
{
WTSVirtualChannelClose(enumerator->enumerator_channel);
(void)WTSVirtualChannelClose(enumerator->enumerator_channel);
enumerator->enumerator_channel = NULL;
enumerator->state = ENUMERATOR_INITIAL;
}
@ -531,8 +535,10 @@ static UINT enumerator_server_packet_send(CamDevEnumServerContext* context, wStr
UINT error = CHANNEL_RC_OK;
ULONG written = 0;
if (!WTSVirtualChannelWrite(enumerator->enumerator_channel, (PCHAR)Stream_Buffer(s),
Stream_GetPosition(s), &written))
const size_t len = Stream_GetPosition(s);
WINPR_ASSERT(len <= UINT32_MAX);
if (!WTSVirtualChannelWrite(enumerator->enumerator_channel, Stream_BufferAs(s, char),
(UINT32)len, &written))
{
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
error = ERROR_INTERNAL_ERROR;

View File

@ -426,7 +426,7 @@ static UINT device_process_message(device_server* device)
goto out;
}
if (WTSVirtualChannelRead(device->device_channel, 0, (PCHAR)Stream_Buffer(s),
if (WTSVirtualChannelRead(device->device_channel, 0, Stream_BufferAs(s, char),
(ULONG)Stream_Capacity(s), &BytesReturned) == FALSE)
{
WLog_ERR(TAG, "WTSVirtualChannelRead failed!");
@ -501,6 +501,8 @@ static UINT device_server_context_poll_int(CameraDeviceServerContext* context)
case CAMERA_DEVICE_OPENED:
error = device_process_message(device);
break;
default:
break;
}
return error;
@ -568,10 +570,12 @@ static DWORD WINAPI device_server_thread_func(LPVOID arg)
break;
}
break;
default:
break;
}
}
WTSVirtualChannelClose(device->device_channel);
(void)WTSVirtualChannelClose(device->device_channel);
device->device_channel = NULL;
if (error && device->context.rdpcontext)
@ -601,7 +605,7 @@ static UINT device_server_open(CameraDeviceServerContext* context)
if (!device->thread)
{
WLog_ERR(TAG, "CreateThread failed!");
CloseHandle(device->stopEvent);
(void)CloseHandle(device->stopEvent);
device->stopEvent = NULL;
return ERROR_INTERNAL_ERROR;
}
@ -620,7 +624,7 @@ static UINT device_server_close(CameraDeviceServerContext* context)
if (!device->externalThread && device->thread)
{
SetEvent(device->stopEvent);
(void)SetEvent(device->stopEvent);
if (WaitForSingleObject(device->thread, INFINITE) == WAIT_FAILED)
{
@ -629,8 +633,8 @@ static UINT device_server_close(CameraDeviceServerContext* context)
return error;
}
CloseHandle(device->thread);
CloseHandle(device->stopEvent);
(void)CloseHandle(device->thread);
(void)CloseHandle(device->stopEvent);
device->thread = NULL;
device->stopEvent = NULL;
}
@ -638,7 +642,7 @@ static UINT device_server_close(CameraDeviceServerContext* context)
{
if (device->state != CAMERA_DEVICE_INITIAL)
{
WTSVirtualChannelClose(device->device_channel);
(void)WTSVirtualChannelClose(device->device_channel);
device->device_channel = NULL;
device->state = CAMERA_DEVICE_INITIAL;
}
@ -704,8 +708,10 @@ static UINT device_server_packet_send(CameraDeviceServerContext* context, wStrea
WINPR_ASSERT(context);
WINPR_ASSERT(s);
if (!WTSVirtualChannelWrite(device->device_channel, (PCHAR)Stream_Buffer(s),
Stream_GetPosition(s), &written))
const size_t len = Stream_GetPosition(s);
WINPR_ASSERT(len <= UINT32_MAX);
if (!WTSVirtualChannelWrite(device->device_channel, Stream_BufferAs(s, char), (UINT32)len,
&written))
{
WLog_ERR(TAG, "WTSVirtualChannelWrite failed!");
error = ERROR_INTERNAL_ERROR;

View File

@ -30,3 +30,4 @@ set(${MODULE_PREFIX}_LIBS
include_directories(..)
add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")

View File

@ -24,6 +24,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
@ -41,6 +42,8 @@
#include "rdpei_main.h"
#define RDPEI_TAG CHANNELS_TAG("rdpei.client")
/**
* Touch Input
* http://msdn.microsoft.com/en-us/library/windows/desktop/dd562197/
@ -84,9 +87,13 @@ typedef struct
CRITICAL_SECTION lock;
rdpContext* rdpcontext;
HANDLE thread;
HANDLE event;
UINT64 lastPollEventTime;
BOOL running;
BOOL async;
} RDPEI_PLUGIN;
/**
@ -197,7 +204,8 @@ static UINT rdpei_add_frame(RdpeiClientContext* context)
UINT error = rdpei_send_frame(context, &frame);
if (error != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "rdpei_send_frame failed with error %" PRIu32 "!", error);
WLog_Print(rdpei->base.log, WLOG_ERROR,
"rdpei_send_frame failed with error %" PRIu32 "!", error);
return error;
}
}
@ -210,23 +218,30 @@ static UINT rdpei_add_frame(RdpeiClientContext* context)
* @return 0 on success, otherwise a Win32 error code
*/
static UINT rdpei_send_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s, UINT16 eventId,
UINT32 pduLength)
size_t pduLength)
{
UINT status = 0;
if (!callback || !s || !callback->channel || !callback->channel->Write || !callback->plugin)
if (!callback || !s || !callback->channel || !callback->channel->Write)
return ERROR_INTERNAL_ERROR;
if (pduLength > UINT32_MAX)
return ERROR_INVALID_PARAMETER;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)callback->plugin;
if (!rdpei)
return ERROR_INTERNAL_ERROR;
Stream_SetPosition(s, 0);
Stream_Write_UINT16(s, eventId); /* eventId (2 bytes) */
Stream_Write_UINT32(s, pduLength); /* pduLength (4 bytes) */
Stream_Write_UINT32(s, (UINT32)pduLength); /* pduLength (4 bytes) */
Stream_SetPosition(s, Stream_Length(s));
status = callback->channel->Write(callback->channel, (UINT32)Stream_Length(s), Stream_Buffer(s),
NULL);
#ifdef WITH_DEBUG_RDPEI
WLog_DBG(TAG,
"rdpei_send_pdu: eventId: %" PRIu16 " (%s) length: %" PRIu32 " status: %" PRIu32 "",
eventId, rdpei_eventid_string(eventId), pduLength, status);
WLog_Print(rdpei->base.log, WLOG_DEBUG,
"rdpei_send_pdu: eventId: %" PRIu16 " (%s) length: %" PRIu32 " status: %" PRIu32 "",
eventId, rdpei_eventid_string(eventId), pduLength, status);
#endif
return status;
}
@ -284,12 +299,23 @@ static UINT rdpei_write_pen_frame(wStream* s, const RDPINPUT_PEN_FRAME* frame)
return CHANNEL_RC_OK;
}
static UINT rdpei_send_pen_event_pdu(GENERIC_CHANNEL_CALLBACK* callback, UINT32 frameOffset,
const RDPINPUT_PEN_FRAME* frames, UINT16 count)
static UINT rdpei_send_pen_event_pdu(GENERIC_CHANNEL_CALLBACK* callback, size_t frameOffset,
const RDPINPUT_PEN_FRAME* frames, size_t count)
{
UINT status = 0;
wStream* s = NULL;
WINPR_ASSERT(callback);
if (frameOffset > UINT32_MAX)
return ERROR_INVALID_PARAMETER;
if (count > UINT16_MAX)
return ERROR_INVALID_PARAMETER;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)callback->plugin;
if (!rdpei)
return ERROR_INTERNAL_ERROR;
if (!frames || (count == 0))
return ERROR_INTERNAL_ERROR;
@ -297,7 +323,7 @@ static UINT rdpei_send_pen_event_pdu(GENERIC_CHANNEL_CALLBACK* callback, UINT32
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
WLog_Print(rdpei->base.log, WLOG_ERROR, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -306,14 +332,16 @@ static UINT rdpei_send_pen_event_pdu(GENERIC_CHANNEL_CALLBACK* callback, UINT32
* the time that has elapsed (in milliseconds) from when the oldest touch frame
* was generated to when it was encoded for transmission by the client.
*/
rdpei_write_4byte_unsigned(s, frameOffset); /* encodeTime (FOUR_BYTE_UNSIGNED_INTEGER) */
rdpei_write_2byte_unsigned(s, count); /* (frameCount) TWO_BYTE_UNSIGNED_INTEGER */
rdpei_write_4byte_unsigned(s,
(UINT32)frameOffset); /* encodeTime (FOUR_BYTE_UNSIGNED_INTEGER) */
rdpei_write_2byte_unsigned(s, (UINT16)count); /* (frameCount) TWO_BYTE_UNSIGNED_INTEGER */
for (UINT16 x = 0; x < count; x++)
for (size_t x = 0; x < count; x++)
{
if ((status = rdpei_write_pen_frame(s, &frames[x])))
{
WLog_ERR(TAG, "rdpei_write_pen_frame failed with error %" PRIu32 "!", status);
WLog_Print(rdpei->base.log, WLOG_ERROR,
"rdpei_write_pen_frame failed with error %" PRIu32 "!", status);
Stream_Free(s, TRUE);
return status;
}
@ -410,18 +438,58 @@ static UINT rdpei_add_pen_frame(RdpeiClientContext* context)
return CHANNEL_RC_OK;
}
static UINT rdpei_update(RdpeiClientContext* context)
static UINT rdpei_update(wLog* log, RdpeiClientContext* context)
{
UINT error = rdpei_add_frame(context);
if (error != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "rdpei_add_frame failed with error %" PRIu32 "!", error);
WLog_Print(log, WLOG_ERROR, "rdpei_add_frame failed with error %" PRIu32 "!", error);
return error;
}
return rdpei_add_pen_frame(context);
}
static BOOL rdpei_poll_run_unlocked(rdpContext* context, void* userdata)
{
RDPEI_PLUGIN* rdpei = userdata;
WINPR_ASSERT(rdpei);
WINPR_ASSERT(context);
const UINT64 now = GetTickCount64();
/* Send an event every ~20ms */
if ((now < rdpei->lastPollEventTime) || (now - rdpei->lastPollEventTime < 20ULL))
return TRUE;
rdpei->lastPollEventTime = now;
const UINT error = rdpei_update(rdpei->base.log, rdpei->context);
(void)ResetEvent(rdpei->event);
if (error != CHANNEL_RC_OK)
{
WLog_Print(rdpei->base.log, WLOG_ERROR, "rdpei_add_frame failed with error %" PRIu32 "!",
error);
setChannelError(context, error, "rdpei_add_frame reported an error");
return FALSE;
}
return TRUE;
}
static BOOL rdpei_poll_run(rdpContext* context, void* userdata)
{
RDPEI_PLUGIN* rdpei = userdata;
WINPR_ASSERT(rdpei);
EnterCriticalSection(&rdpei->lock);
BOOL rc = rdpei_poll_run_unlocked(context, userdata);
LeaveCriticalSection(&rdpei->lock);
return rc;
}
static DWORD WINAPI rdpei_periodic_update(LPVOID arg)
{
DWORD status = 0;
@ -450,23 +518,12 @@ static DWORD WINAPI rdpei_periodic_update(LPVOID arg)
if (status == WAIT_FAILED)
{
error = GetLastError();
WLog_ERR(TAG, "WaitForMultipleObjects failed with error %" PRIu32 "!", error);
WLog_Print(rdpei->base.log, WLOG_ERROR,
"WaitForMultipleObjects failed with error %" PRIu32 "!", error);
break;
}
EnterCriticalSection(&rdpei->lock);
error = rdpei_update(context);
if (error != CHANNEL_RC_OK)
{
WLog_ERR(TAG, "rdpei_add_frame failed with error %" PRIu32 "!", error);
break;
}
if (status == WAIT_OBJECT_0)
ResetEvent(rdpei->event);
LeaveCriticalSection(&rdpei->lock);
error = rdpei_poll_run(rdpei->rdpcontext, rdpei);
}
out:
@ -509,7 +566,7 @@ static UINT rdpei_send_cs_ready_pdu(GENERIC_CHANNEL_CALLBACK* callback)
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
WLog_Print(rdpei->base.log, WLOG_ERROR, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -523,25 +580,36 @@ static UINT rdpei_send_cs_ready_pdu(GENERIC_CHANNEL_CALLBACK* callback)
return status;
}
static void rdpei_print_contact_flags(UINT32 contactFlags)
#if defined(WITH_DEBUG_RDPEI)
static void rdpei_print_contact_flags(wLog* log, UINT32 contactFlags)
{
if (contactFlags & RDPINPUT_CONTACT_FLAG_DOWN)
WLog_DBG(TAG, " RDPINPUT_CONTACT_FLAG_DOWN");
WLog_Print(log, WLOG_DEBUG, " RDPINPUT_CONTACT_FLAG_DOWN");
if (contactFlags & RDPINPUT_CONTACT_FLAG_UPDATE)
WLog_DBG(TAG, " RDPINPUT_CONTACT_FLAG_UPDATE");
WLog_Print(log, WLOG_DEBUG, " RDPINPUT_CONTACT_FLAG_UPDATE");
if (contactFlags & RDPINPUT_CONTACT_FLAG_UP)
WLog_DBG(TAG, " RDPINPUT_CONTACT_FLAG_UP");
WLog_Print(log, WLOG_DEBUG, " RDPINPUT_CONTACT_FLAG_UP");
if (contactFlags & RDPINPUT_CONTACT_FLAG_INRANGE)
WLog_DBG(TAG, " RDPINPUT_CONTACT_FLAG_INRANGE");
WLog_Print(log, WLOG_DEBUG, " RDPINPUT_CONTACT_FLAG_INRANGE");
if (contactFlags & RDPINPUT_CONTACT_FLAG_INCONTACT)
WLog_DBG(TAG, " RDPINPUT_CONTACT_FLAG_INCONTACT");
WLog_Print(log, WLOG_DEBUG, " RDPINPUT_CONTACT_FLAG_INCONTACT");
if (contactFlags & RDPINPUT_CONTACT_FLAG_CANCELED)
WLog_DBG(TAG, " RDPINPUT_CONTACT_FLAG_CANCELED");
WLog_Print(log, WLOG_DEBUG, " RDPINPUT_CONTACT_FLAG_CANCELED");
}
#endif
static INT16 bounded(INT32 val)
{
if (val < INT16_MIN)
return INT16_MIN;
if (val > INT16_MAX)
return INT16_MAX;
return (INT16)val;
}
/**
@ -549,15 +617,15 @@ static void rdpei_print_contact_flags(UINT32 contactFlags)
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
static UINT rdpei_write_touch_frame(wLog* log, wStream* s, RDPINPUT_TOUCH_FRAME* frame)
{
int rectSize = 2;
RDPINPUT_CONTACT_DATA* contact = NULL;
if (!s || !frame)
return ERROR_INTERNAL_ERROR;
#ifdef WITH_DEBUG_RDPEI
WLog_DBG(TAG, "contactCount: %" PRIu32 "", frame->contactCount);
WLog_DBG(TAG, "frameOffset: 0x%016" PRIX64 "", frame->frameOffset);
WLog_Print(log, WLOG_DEBUG, "contactCount: %" PRIu32 "", frame->contactCount);
WLog_Print(log, WLOG_DEBUG, "frameOffset: 0x%016" PRIX64 "", frame->frameOffset);
#endif
rdpei_write_2byte_unsigned(s,
frame->contactCount); /* contactCount (TWO_BYTE_UNSIGNED_INTEGER) */
@ -570,7 +638,7 @@ static UINT rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
if (!Stream_EnsureRemainingCapacity(s, (size_t)frame->contactCount * 64))
{
WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!");
WLog_Print(log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -578,19 +646,20 @@ static UINT rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame)
{
contact = &frame->contacts[index];
contact->fieldsPresent |= CONTACT_DATA_CONTACTRECT_PRESENT;
contact->contactRectLeft = contact->x - rectSize;
contact->contactRectTop = contact->y - rectSize;
contact->contactRectRight = contact->x + rectSize;
contact->contactRectBottom = contact->y + rectSize;
contact->contactRectLeft = bounded(contact->x - rectSize);
contact->contactRectTop = bounded(contact->y - rectSize);
contact->contactRectRight = bounded(contact->x + rectSize);
contact->contactRectBottom = bounded(contact->y + rectSize);
#ifdef WITH_DEBUG_RDPEI
WLog_DBG(TAG, "contact[%" PRIu32 "].contactId: %" PRIu32 "", index, contact->contactId);
WLog_DBG(TAG, "contact[%" PRIu32 "].fieldsPresent: %" PRIu32 "", index,
contact->fieldsPresent);
WLog_DBG(TAG, "contact[%" PRIu32 "].x: %" PRId32 "", index, contact->x);
WLog_DBG(TAG, "contact[%" PRIu32 "].y: %" PRId32 "", index, contact->y);
WLog_DBG(TAG, "contact[%" PRIu32 "].contactFlags: 0x%08" PRIX32 "", index,
contact->contactFlags);
rdpei_print_contact_flags(contact->contactFlags);
WLog_Print(log, WLOG_DEBUG, "contact[%" PRIu32 "].contactId: %" PRIu32 "", index,
contact->contactId);
WLog_Print(log, WLOG_DEBUG, "contact[%" PRIu32 "].fieldsPresent: %" PRIu32 "", index,
contact->fieldsPresent);
WLog_Print(log, WLOG_DEBUG, "contact[%" PRIu32 "].x: %" PRId32 "", index, contact->x);
WLog_Print(log, WLOG_DEBUG, "contact[%" PRIu32 "].y: %" PRId32 "", index, contact->y);
WLog_Print(log, WLOG_DEBUG, "contact[%" PRIu32 "].contactFlags: 0x%08" PRIX32 "", index,
contact->contactFlags);
rdpei_print_contact_flags(log, contact->contactFlags);
#endif
Stream_Write_UINT8(s, contact->contactId); /* contactId (1 byte) */
/* fieldsPresent (TWO_BYTE_UNSIGNED_INTEGER) */
@ -637,13 +706,10 @@ static UINT rdpei_send_touch_event_pdu(GENERIC_CHANNEL_CALLBACK* callback,
RDPINPUT_TOUCH_FRAME* frame)
{
UINT status = 0;
wStream* s = NULL;
UINT32 pduLength = 0;
RDPEI_PLUGIN* rdpei = NULL;
WINPR_ASSERT(callback);
rdpei = (RDPEI_PLUGIN*)callback->plugin;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)callback->plugin;
if (!rdpei || !rdpei->rdpcontext)
return ERROR_INTERNAL_ERROR;
if (freerdp_settings_get_bool(rdpei->rdpcontext->settings, FreeRDP_SuspendInput))
@ -652,12 +718,12 @@ static UINT rdpei_send_touch_event_pdu(GENERIC_CHANNEL_CALLBACK* callback,
if (!frame)
return ERROR_INTERNAL_ERROR;
pduLength = 64 + (frame->contactCount * 64);
s = Stream_New(NULL, pduLength);
size_t pduLength = 64ULL + (64ULL * frame->contactCount);
wStream* s = Stream_New(NULL, pduLength);
if (!s)
{
WLog_ERR(TAG, "Stream_New failed!");
WLog_Print(rdpei->base.log, WLOG_ERROR, "Stream_New failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -670,16 +736,17 @@ static UINT rdpei_send_touch_event_pdu(GENERIC_CHANNEL_CALLBACK* callback,
s, (UINT32)frame->frameOffset); /* encodeTime (FOUR_BYTE_UNSIGNED_INTEGER) */
rdpei_write_2byte_unsigned(s, 1); /* (frameCount) TWO_BYTE_UNSIGNED_INTEGER */
if ((status = rdpei_write_touch_frame(s, frame)))
status = rdpei_write_touch_frame(rdpei->base.log, s, frame);
if (status)
{
WLog_ERR(TAG, "rdpei_write_touch_frame failed with error %" PRIu32 "!", status);
WLog_Print(rdpei->base.log, WLOG_ERROR,
"rdpei_write_touch_frame failed with error %" PRIu32 "!", status);
Stream_Free(s, TRUE);
return status;
}
Stream_SealLength(s);
pduLength = Stream_Length(s);
status = rdpei_send_pdu(callback, s, EVENTID_TOUCH, pduLength);
status = rdpei_send_pdu(callback, s, EVENTID_TOUCH, Stream_Length(s));
Stream_Free(s, TRUE);
return status;
}
@ -693,20 +760,19 @@ static UINT rdpei_recv_sc_ready_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream*
{
UINT32 features = 0;
UINT32 protocolVersion = 0;
RDPEI_PLUGIN* rdpei = NULL;
if (!callback || !callback->plugin)
return ERROR_INTERNAL_ERROR;
rdpei = (RDPEI_PLUGIN*)callback->plugin;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)callback->plugin;
if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
if (!Stream_CheckAndLogRequiredLengthWLog(rdpei->base.log, s, 4))
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, protocolVersion); /* protocolVersion (4 bytes) */
if (protocolVersion >= RDPINPUT_PROTOCOL_V300)
{
if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
if (!Stream_CheckAndLogRequiredLengthWLog(rdpei->base.log, s, 4))
return ERROR_INVALID_DATA;
}
@ -720,7 +786,7 @@ static UINT rdpei_recv_sc_ready_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream*
if (protocolVersion != RDPINPUT_PROTOCOL_V10)
{
WLog_ERR(TAG, "Unknown [MS-RDPEI] protocolVersion: 0x%08"PRIX32"", protocolVersion);
WLog_Print(rdpei->base.log, WLOG_ERROR, "Unknown [MS-RDPEI] protocolVersion: 0x%08"PRIX32"", protocolVersion);
return -1;
}
@ -736,20 +802,22 @@ static UINT rdpei_recv_sc_ready_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream*
static UINT rdpei_recv_suspend_touch_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s)
{
UINT error = CHANNEL_RC_OK;
RdpeiClientContext* rdpei = NULL;
WINPR_UNUSED(s);
if (!callback || !callback->plugin)
return ERROR_INTERNAL_ERROR;
rdpei = (RdpeiClientContext*)callback->plugin->pInterface;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)callback->plugin;
RdpeiClientContext* context = rdpei->context;
if (!rdpei)
return ERROR_INTERNAL_ERROR;
IFCALLRET(rdpei->SuspendTouch, error, rdpei);
IFCALLRET(context->SuspendTouch, error, context);
if (error)
WLog_ERR(TAG, "rdpei->SuspendTouch failed with error %" PRIu32 "!", error);
WLog_Print(rdpei->base.log, WLOG_ERROR,
"rdpei->SuspendTouch failed with error %" PRIu32 "!", error);
return error;
}
@ -761,18 +829,23 @@ static UINT rdpei_recv_suspend_touch_pdu(GENERIC_CHANNEL_CALLBACK* callback, wSt
*/
static UINT rdpei_recv_resume_touch_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s)
{
RdpeiClientContext* rdpei = NULL;
UINT error = CHANNEL_RC_OK;
if (!s || !callback || !callback->plugin)
if (!s || !callback)
return ERROR_INTERNAL_ERROR;
rdpei = (RdpeiClientContext*)callback->plugin->pInterface;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)callback->plugin;
if (!rdpei)
return ERROR_INTERNAL_ERROR;
IFCALLRET(rdpei->ResumeTouch, error, rdpei);
RdpeiClientContext* context = (RdpeiClientContext*)callback->plugin->pInterface;
if (!context)
return ERROR_INTERNAL_ERROR;
IFCALLRET(context->ResumeTouch, error, context);
if (error)
WLog_ERR(TAG, "rdpei->ResumeTouch failed with error %" PRIu32 "!", error);
WLog_Print(rdpei->base.log, WLOG_ERROR, "rdpei->ResumeTouch failed with error %" PRIu32 "!",
error);
return error;
}
@ -788,31 +861,41 @@ static UINT rdpei_recv_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s)
UINT32 pduLength = 0;
UINT error = 0;
if (!s)
if (!callback || !s)
return ERROR_INTERNAL_ERROR;
if (!Stream_CheckAndLogRequiredLength(TAG, s, 6))
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)callback->plugin;
if (!rdpei)
return ERROR_INTERNAL_ERROR;
if (!Stream_CheckAndLogRequiredLengthWLog(rdpei->base.log, s, 6))
return ERROR_INVALID_DATA;
Stream_Read_UINT16(s, eventId); /* eventId (2 bytes) */
Stream_Read_UINT32(s, pduLength); /* pduLength (4 bytes) */
#ifdef WITH_DEBUG_RDPEI
WLog_DBG(TAG, "rdpei_recv_pdu: eventId: %" PRIu16 " (%s) length: %" PRIu32 "", eventId,
rdpei_eventid_string(eventId), pduLength);
WLog_Print(rdpei->base.log, WLOG_DEBUG,
"rdpei_recv_pdu: eventId: %" PRIu16 " (%s) length: %" PRIu32 "", eventId,
rdpei_eventid_string(eventId), pduLength);
#endif
if ((pduLength < 6) || !Stream_CheckAndLogRequiredLengthWLog(rdpei->base.log, s, pduLength - 6))
return ERROR_INVALID_DATA;
switch (eventId)
{
case EVENTID_SC_READY:
if ((error = rdpei_recv_sc_ready_pdu(callback, s)))
{
WLog_ERR(TAG, "rdpei_recv_sc_ready_pdu failed with error %" PRIu32 "!", error);
WLog_Print(rdpei->base.log, WLOG_ERROR,
"rdpei_recv_sc_ready_pdu failed with error %" PRIu32 "!", error);
return error;
}
if ((error = rdpei_send_cs_ready_pdu(callback)))
{
WLog_ERR(TAG, "rdpei_send_cs_ready_pdu failed with error %" PRIu32 "!", error);
WLog_Print(rdpei->base.log, WLOG_ERROR,
"rdpei_send_cs_ready_pdu failed with error %" PRIu32 "!", error);
return error;
}
@ -821,7 +904,8 @@ static UINT rdpei_recv_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s)
case EVENTID_SUSPEND_TOUCH:
if ((error = rdpei_recv_suspend_touch_pdu(callback, s)))
{
WLog_ERR(TAG, "rdpei_recv_suspend_touch_pdu failed with error %" PRIu32 "!", error);
WLog_Print(rdpei->base.log, WLOG_ERROR,
"rdpei_recv_suspend_touch_pdu failed with error %" PRIu32 "!", error);
return error;
}
@ -830,7 +914,8 @@ static UINT rdpei_recv_pdu(GENERIC_CHANNEL_CALLBACK* callback, wStream* s)
case EVENTID_RESUME_TOUCH:
if ((error = rdpei_recv_resume_touch_pdu(callback, s)))
{
WLog_ERR(TAG, "rdpei_recv_resume_touch_pdu failed with error %" PRIu32 "!", error);
WLog_Print(rdpei->base.log, WLOG_ERROR,
"rdpei_recv_resume_touch_pdu failed with error %" PRIu32 "!", error);
return error;
}
@ -928,7 +1013,8 @@ UINT rdpei_send_frame(RdpeiClientContext* context, RDPINPUT_TOUCH_FRAME* frame)
if ((error = rdpei_send_touch_event_pdu(callback, frame)))
{
WLog_ERR(TAG, "rdpei_send_touch_event_pdu failed with error %" PRIu32 "!", error);
WLog_Print(rdpei->base.log, WLOG_ERROR,
"rdpei_send_touch_event_pdu failed with error %" PRIu32 "!", error);
return error;
}
@ -954,7 +1040,7 @@ static UINT rdpei_add_contact(RdpeiClientContext* context, const RDPINPUT_CONTAC
contactPoint = &rdpei->contactPoints[contact->contactId];
contactPoint->data = *contact;
contactPoint->dirty = TRUE;
SetEvent(rdpei->event);
(void)SetEvent(rdpei->event);
LeaveCriticalSection(&rdpei->lock);
return CHANNEL_RC_OK;
@ -965,28 +1051,29 @@ static UINT rdpei_touch_process(RdpeiClientContext* context, INT32 externalId, U
{
INT64 contactIdlocal = -1;
RDPINPUT_CONTACT_POINT* contactPoint = NULL;
RDPEI_PLUGIN* rdpei = NULL;
BOOL begin = 0;
UINT error = CHANNEL_RC_OK;
if (!context || !contactId || !context->handle)
return ERROR_INTERNAL_ERROR;
rdpei = (RDPEI_PLUGIN*)context->handle;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)context->handle;
/* Create a new contact point in an empty slot */
EnterCriticalSection(&rdpei->lock);
begin = contactFlags & RDPINPUT_CONTACT_FLAG_DOWN;
const BOOL begin = (contactFlags & RDPINPUT_CONTACT_FLAG_DOWN) != 0;
contactPoint = rdpei_contact(rdpei, externalId, !begin);
if (contactPoint)
contactIdlocal = contactPoint->contactId;
LeaveCriticalSection(&rdpei->lock);
if (contactIdlocal > UINT32_MAX)
return ERROR_INVALID_PARAMETER;
if (contactIdlocal >= 0)
{
RDPINPUT_CONTACT_DATA contact = { 0 };
contact.x = x;
contact.y = y;
contact.contactId = contactIdlocal;
contact.contactId = (UINT32)contactIdlocal;
contact.contactFlags = contactFlags;
contact.fieldsPresent = fieldFlags;
@ -1002,10 +1089,10 @@ static UINT rdpei_touch_process(RdpeiClientContext* context, INT32 externalId, U
UINT32 p = va_arg(ap, UINT32);
if (p >= 360)
{
WLog_WARN(TAG,
"TouchContact %" PRIu32 ": Invalid orientation value %" PRIu32
"degree, clamping to 359 degree",
contactIdlocal, p);
WLog_Print(rdpei->base.log, WLOG_WARN,
"TouchContact %" PRId64 ": Invalid orientation value %" PRIu32
"degree, clamping to 359 degree",
contactIdlocal, p);
p = 359;
}
contact.orientation = p;
@ -1015,10 +1102,10 @@ static UINT rdpei_touch_process(RdpeiClientContext* context, INT32 externalId, U
UINT32 p = va_arg(ap, UINT32);
if (p > 1024)
{
WLog_WARN(TAG,
"TouchContact %" PRIu32 ": Invalid pressure value %" PRIu32
", clamping to 1024",
contactIdlocal, p);
WLog_Print(rdpei->base.log, WLOG_WARN,
"TouchContact %" PRId64 ": Invalid pressure value %" PRIu32
", clamping to 1024",
contactIdlocal, p);
p = 1024;
}
contact.pressure = p;
@ -1028,7 +1115,7 @@ static UINT rdpei_touch_process(RdpeiClientContext* context, INT32 externalId, U
}
if (contactId)
*contactId = contactIdlocal;
*contactId = (INT32)contactIdlocal;
return error;
}
@ -1168,7 +1255,7 @@ static UINT rdpei_add_pen(RdpeiClientContext* context, INT32 externalId,
{
contactPoint->data = *contact;
contactPoint->dirty = TRUE;
SetEvent(rdpei->event);
(void)SetEvent(rdpei->event);
}
LeaveCriticalSection(&rdpei->lock);
@ -1365,7 +1452,6 @@ static UINT rdpei_pen_raw_event_va(RdpeiClientContext* context, INT32 externalId
static UINT init_plugin_cb(GENERIC_DYNVC_PLUGIN* base, rdpContext* rcontext, rdpSettings* settings)
{
RdpeiClientContext* context = NULL;
RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)base;
WINPR_ASSERT(base);
@ -1378,18 +1464,20 @@ static UINT init_plugin_cb(GENERIC_DYNVC_PLUGIN* base, rdpContext* rcontext, rdp
rdpei->maxPenContacts = MAX_PEN_CONTACTS;
rdpei->rdpcontext = rcontext;
WINPR_ASSERT(rdpei->base.log);
InitializeCriticalSection(&rdpei->lock);
rdpei->event = CreateEventA(NULL, TRUE, FALSE, NULL);
if (!rdpei->event)
{
WLog_ERR(TAG, "calloc failed!");
WLog_Print(rdpei->base.log, WLOG_ERROR, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
context = (RdpeiClientContext*)calloc(1, sizeof(*context));
RdpeiClientContext* context = (RdpeiClientContext*)calloc(1, sizeof(RdpeiClientContext));
if (!context)
{
WLog_ERR(TAG, "calloc failed!");
WLog_Print(rdpei->base.log, WLOG_ERROR, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
@ -1417,12 +1505,24 @@ static UINT init_plugin_cb(GENERIC_DYNVC_PLUGIN* base, rdpContext* rcontext, rdp
rdpei->context = context;
rdpei->base.iface.pInterface = (void*)context;
rdpei->running = TRUE;
rdpei->thread = CreateThread(NULL, 0, rdpei_periodic_update, rdpei, 0, NULL);
if (!rdpei->thread)
rdpei->async =
!freerdp_settings_get_bool(rdpei->rdpcontext->settings, FreeRDP_SynchronousDynamicChannels);
if (rdpei->async)
{
WLog_ERR(TAG, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
rdpei->running = TRUE;
rdpei->thread = CreateThread(NULL, 0, rdpei_periodic_update, rdpei, 0, NULL);
if (!rdpei->thread)
{
WLog_Print(rdpei->base.log, WLOG_ERROR, "calloc failed!");
return CHANNEL_RC_NO_MEMORY;
}
}
else
{
if (!freerdp_client_channel_register(rdpei->rdpcontext->channels, rdpei->event,
rdpei_poll_run, rdpei))
return ERROR_INTERNAL_ERROR;
}
return CHANNEL_RC_OK;
@ -1435,16 +1535,19 @@ static void terminate_plugin_cb(GENERIC_DYNVC_PLUGIN* base)
rdpei->running = FALSE;
if (rdpei->event)
SetEvent(rdpei->event);
(void)SetEvent(rdpei->event);
if (rdpei->thread)
{
WaitForSingleObject(rdpei->thread, INFINITE);
CloseHandle(rdpei->thread);
(void)WaitForSingleObject(rdpei->thread, INFINITE);
(void)CloseHandle(rdpei->thread);
}
if (rdpei->event && !rdpei->async)
(void)freerdp_client_channel_unregister(rdpei->rdpcontext->channels, rdpei->event);
if (rdpei->event)
CloseHandle(rdpei->event);
(void)CloseHandle(rdpei->event);
DeleteCriticalSection(&rdpei->lock);
free(rdpei->context);
@ -1459,9 +1562,9 @@ static const IWTSVirtualChannelCallback geometry_callbacks = { rdpei_on_data_rec
*
* @return 0 on success, otherwise a Win32 error code
*/
FREERDP_ENTRY_POINT(UINT rdpei_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
FREERDP_ENTRY_POINT(UINT VCAPITYPE rdpei_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
{
return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, RDPEI_DVC_CHANNEL_NAME,
return freerdp_generic_DVCPluginEntry(pEntryPoints, RDPEI_TAG, RDPEI_DVC_CHANNEL_NAME,
sizeof(RDPEI_PLUGIN), sizeof(GENERIC_CHANNEL_CALLBACK),
&geometry_callbacks, init_plugin_cb, terminate_plugin_cb);
}

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