summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--.clang-tidy2
-rw-r--r--.github/workflows/abi-checker.yml102
-rw-r--r--.github/workflows/codeql-analysis.yml185
-rw-r--r--.github/workflows/coverity.yml96
-rw-r--r--.github/workflows/mingw.yml31
-rw-r--r--CMakeLists.txt57
-rw-r--r--ChangeLog63
-rw-r--r--README.md9
-rw-r--r--channels/audin/client/alsa/audin_alsa.c2
-rw-r--r--channels/audin/client/oss/CMakeLists.txt7
-rw-r--r--channels/audin/client/oss/audin_oss.c27
-rw-r--r--channels/client/addin.c9
-rw-r--r--channels/client/generic_dynvc.c2
-rw-r--r--channels/cliprdr/client/cliprdr_main.c3
-rw-r--r--channels/cliprdr/cliprdr_common.c2
-rw-r--r--channels/cliprdr/server/cliprdr_main.c4
-rw-r--r--channels/drdynvc/client/drdynvc_main.c34
-rw-r--r--channels/drive/client/drive_main.c2
-rw-r--r--channels/location/CMakeLists.txt4
-rw-r--r--channels/location/ChannelOptions.cmake3
-rw-r--r--channels/location/client/CMakeLists.txt30
-rw-r--r--channels/location/client/location_main.c473
-rw-r--r--channels/parallel/client/parallel_main.c26
-rw-r--r--channels/printer/client/printer_main.c126
-rw-r--r--channels/printer/client/win/printer_win.c5
-rw-r--r--channels/rail/client/rail_orders.c7
-rw-r--r--channels/rail/rail_common.c28
-rw-r--r--channels/rdpdr/client/rdpdr_main.c6
-rw-r--r--channels/rdpdr/server/rdpdr_main.c9
-rw-r--r--channels/rdpecam/CMakeLists.txt4
-rw-r--r--channels/rdpecam/ChannelOptions.cmake1
-rw-r--r--channels/rdpecam/client/CMakeLists.txt0
-rw-r--r--channels/rdpgfx/client/rdpgfx_main.c1
-rw-r--r--channels/rdpsnd/client/alsa/rdpsnd_alsa.c16
-rw-r--r--channels/rdpsnd/client/oss/CMakeLists.txt6
-rw-r--r--channels/rdpsnd/client/oss/rdpsnd_oss.c24
-rw-r--r--channels/rdpsnd/client/pulse/rdpsnd_pulse.c2
-rw-r--r--channels/server/CMakeLists.txt5
-rw-r--r--channels/urbdrc/client/data_transfer.c3
-rw-r--r--channels/urbdrc/client/libusb/libusb_udevice.c2
-rw-r--r--client/CMakeLists.txt5
-rw-r--r--client/FreeRDP-ClientConfig.cmake.in3
-rw-r--r--client/SDL/CMakeLists.txt10
-rw-r--r--client/SDL/dialogs/res/convert_res_to_c.cpp6
-rw-r--r--client/SDL/dialogs/res/sdl_resource_manager.cpp2
-rw-r--r--client/SDL/dialogs/sdl_connection_dialog.cpp13
-rw-r--r--client/SDL/man/CMakeLists.txt6
-rw-r--r--client/SDL/man/sdl-freerdp.1.xml.in3
-rw-r--r--client/SDL/sdl_freerdp.cpp2
-rw-r--r--client/SDL/sdl_kbd.cpp2
-rw-r--r--client/SDL/sdl_monitor.cpp15
-rw-r--r--client/SDL/sdl_window.cpp4
-rw-r--r--client/Sample/CMakeLists.txt21
-rw-r--r--client/Wayland/CMakeLists.txt10
-rw-r--r--client/Wayland/wlf_cliprdr.c8
-rw-r--r--client/Wayland/wlfreerdp.c39
-rw-r--r--client/X11/CMakeLists.txt65
-rw-r--r--client/X11/cli/CMakeLists.txt20
-rw-r--r--client/X11/cli/xfreerdp.c21
-rw-r--r--client/X11/man/CMakeLists.txt7
-rw-r--r--client/X11/man/xfreerdp-shortcuts.1.xml25
-rw-r--r--client/X11/man/xfreerdp.1.xml.in3
-rw-r--r--client/X11/xf_client.c5
-rw-r--r--client/X11/xf_cliprdr.c40
-rw-r--r--client/X11/xf_event.c26
-rw-r--r--client/X11/xf_input.c29
-rw-r--r--client/X11/xf_keyboard.c12
-rw-r--r--client/X11/xf_window.c1
-rw-r--r--client/X11/xfreerdp.h2
-rw-r--r--client/common/CMakeLists.txt28
-rw-r--r--client/common/client.c15
-rw-r--r--client/common/client_cliprdr_file.c50
-rw-r--r--client/common/cmdline.c87
-rw-r--r--client/common/cmdline.h2
-rw-r--r--client/common/file.c17
-rw-r--r--client/common/man/generate_argument_docbook.c1
-rw-r--r--client/common/test/TestClientCmdLine.c4
-rw-r--r--client/freerdp-client.pc.in2
-rw-r--r--cmake/AddFuzzerTest.cmake15
-rw-r--r--cmake/AddTargetWithResourceFile.cmake119
-rw-r--r--cmake/CommonConfigOptions.cmake3
-rw-r--r--cmake/ConfigOptions.cmake2
-rw-r--r--cmake/ConfigureRPATH.cmake23
-rw-r--r--cmake/DetectBSD.cmake18
-rw-r--r--cmake/FindIPP.cmake397
-rw-r--r--cmake/FindOSS.cmake39
-rw-r--r--cmake/InstallFreeRDPMan.cmake33
-rw-r--r--cmake/PlatformDefaults.cmake103
-rw-r--r--cmake/oss-includes.h.in6
-rw-r--r--include/config/config.h.in1
-rw-r--r--include/freerdp/api.h2
-rw-r--r--include/freerdp/channels/location.h1
-rw-r--r--include/freerdp/client/location.h97
-rw-r--r--include/freerdp/primitives.h3
-rw-r--r--include/freerdp/rail.h3
-rw-r--r--include/freerdp/server/shadow.h30
-rw-r--r--include/freerdp/settings.h11
-rw-r--r--include/freerdp/settings_types_private.h6
-rw-r--r--include/freerdp/utils/encoded_types.h9
-rw-r--r--libfreerdp/CMakeLists.txt66
-rw-r--r--libfreerdp/FreeRDPConfig.cmake.in6
-rw-r--r--libfreerdp/codec/clear.c2
-rw-r--r--libfreerdp/codec/interleaved.c2
-rw-r--r--libfreerdp/codec/ncrush.c55
-rw-r--r--libfreerdp/codec/nsc.c4
-rw-r--r--libfreerdp/codec/planar.c54
-rw-r--r--libfreerdp/codec/rfx.c2
-rw-r--r--libfreerdp/codec/rfx_rlgr.c42
-rw-r--r--libfreerdp/codec/test/CMakeLists.txt6
-rw-r--r--libfreerdp/codec/test/TestFuzzCodecs.c480
-rw-r--r--libfreerdp/codec/zgfx.c14
-rw-r--r--libfreerdp/common/settings.c38
-rw-r--r--libfreerdp/common/settings_getters.c14
-rw-r--r--libfreerdp/common/settings_str.h4
-rw-r--r--libfreerdp/common/test/CMakeLists.txt15
-rw-r--r--libfreerdp/core/aad.c4
-rw-r--r--libfreerdp/core/capabilities.c7
-rw-r--r--libfreerdp/core/childsession.c268
-rw-r--r--libfreerdp/core/client.c9
-rw-r--r--libfreerdp/core/connection.c13
-rw-r--r--libfreerdp/core/credssp_auth.c1
-rw-r--r--libfreerdp/core/freerdp.c20
-rw-r--r--libfreerdp/core/gateway/arm.c9
-rw-r--r--libfreerdp/core/gateway/http.c20
-rw-r--r--libfreerdp/core/gateway/rdg.c221
-rw-r--r--libfreerdp/core/gateway/tsg.c120
-rw-r--r--libfreerdp/core/gateway/tsg.h2
-rw-r--r--libfreerdp/core/gateway/wst.c2
-rw-r--r--libfreerdp/core/gcc.c6
-rw-r--r--libfreerdp/core/info.c8
-rw-r--r--libfreerdp/core/input.h2
-rw-r--r--libfreerdp/core/license.c25
-rw-r--r--libfreerdp/core/listener.c14
-rw-r--r--libfreerdp/core/nla.c7
-rw-r--r--libfreerdp/core/peer.c4
-rw-r--r--libfreerdp/core/proxy.c8
-rw-r--r--libfreerdp/core/rdp.c4
-rw-r--r--libfreerdp/core/security.c1
-rw-r--r--libfreerdp/core/smartcardlogon.c11
-rw-r--r--libfreerdp/core/test/CMakeLists.txt17
-rw-r--r--libfreerdp/core/test/settings_property_lists.h2
-rw-r--r--libfreerdp/core/transport.c14
-rw-r--r--libfreerdp/core/transport.h15
-rw-r--r--libfreerdp/core/update.c8
-rw-r--r--libfreerdp/core/utils.c181
-rw-r--r--libfreerdp/core/utils.h14
-rw-r--r--libfreerdp/crypto/cert_common.c12
-rw-r--r--libfreerdp/crypto/certificate.c35
-rw-r--r--libfreerdp/crypto/certificate_data.c42
-rw-r--r--libfreerdp/crypto/privatekey.c6
-rw-r--r--libfreerdp/crypto/tls.c3
-rw-r--r--libfreerdp/emu/scard/smartcard_emulate.c19
-rw-r--r--libfreerdp/emu/scard/smartcard_virtual_gids.c6
-rw-r--r--libfreerdp/freerdp.pc.in4
-rw-r--r--libfreerdp/locale/keyboard_xkbfile.c564
-rw-r--r--libfreerdp/primitives/prim_YUV_neon.c18
-rw-r--r--libfreerdp/primitives/prim_alphaComp.c1
-rw-r--r--libfreerdp/primitives/prim_copy.c21
-rw-r--r--libfreerdp/primitives/test/measure.h59
-rw-r--r--libfreerdp/primitives/test/prim_test.c26
-rw-r--r--libfreerdp/utils/CMakeLists.txt4
-rw-r--r--libfreerdp/utils/encoded_types.c214
-rw-r--r--libfreerdp/utils/http.c6
-rw-r--r--libfreerdp/utils/pcap.c30
-rw-r--r--libfreerdp/utils/stopwatch.c28
-rw-r--r--libfreerdp/utils/test/CMakeLists.txt6
-rw-r--r--libfreerdp/utils/test/TestEncodedTypes.c212
-rw-r--r--rdtk/librdtk/CMakeLists.txt29
-rw-r--r--rdtk/librdtk/rdtk_font.c2
-rw-r--r--rdtk/sample/CMakeLists.txt5
-rw-r--r--scripts/abi-suppr.txt9
-rwxr-xr-xscripts/bundle-mac-os.sh20
-rw-r--r--scripts/mingw-meson.conf15
-rwxr-xr-xscripts/mingw.sh185
-rw-r--r--scripts/mingw64.cmake35
-rw-r--r--server/Sample/CMakeLists.txt24
-rw-r--r--server/Sample/sfreerdp.c10
-rw-r--r--server/Windows/CMakeLists.txt39
-rw-r--r--server/Windows/cli/CMakeLists.txt28
-rw-r--r--server/Windows/wf_rdpsnd.c3
-rw-r--r--server/common/CMakeLists.txt29
-rw-r--r--server/proxy/CMakeLists.txt29
-rw-r--r--server/proxy/cli/CMakeLists.txt35
-rw-r--r--server/proxy/modules/bitmap-filter/CMakeLists.txt6
-rw-r--r--server/proxy/modules/demo/CMakeLists.txt6
-rw-r--r--server/proxy/modules/dyn-channel-dump/CMakeLists.txt6
-rw-r--r--server/proxy/pf_server.c15
-rw-r--r--server/shadow/CMakeLists.txt88
-rw-r--r--server/shadow/X11/x11_shadow.c34
-rw-r--r--server/shadow/X11/x11_shadow.h1
-rw-r--r--server/shadow/freerdp-shadow-cli.1.in8
-rw-r--r--server/shadow/shadow_capture.c214
-rw-r--r--server/shadow/shadow_client.c8
-rw-r--r--server/shadow/shadow_lobby.c25
-rw-r--r--server/shadow/shadow_server.c8
-rw-r--r--server/shadow/shadow_subsystem.c36
-rw-r--r--uwac/libuwac/uwac-input.c4
-rw-r--r--uwac/libuwac/uwac-window.c2
-rw-r--r--winpr/CMakeLists.txt14
-rw-r--r--winpr/include/winpr/comm.h3
-rw-r--r--winpr/include/winpr/crt.h11
-rw-r--r--winpr/include/winpr/environment.h9
-rw-r--r--winpr/include/winpr/file.h13
-rw-r--r--winpr/include/winpr/intrin.h2
-rw-r--r--winpr/include/winpr/io.h2
-rw-r--r--winpr/include/winpr/memory.h6
-rw-r--r--winpr/include/winpr/pipe.h3
-rw-r--r--winpr/include/winpr/pool.h2
-rw-r--r--winpr/include/winpr/synch.h39
-rw-r--r--winpr/include/winpr/sysinfo.h11
-rw-r--r--winpr/include/winpr/thread.h2
-rw-r--r--winpr/include/winpr/winpr.h10
-rw-r--r--winpr/include/winpr/winsock.h4
-rw-r--r--winpr/include/winpr/wtsapi.h10
-rw-r--r--winpr/libwinpr/CMakeLists.txt29
-rw-r--r--winpr/libwinpr/clipboard/synthetic_file.c20
-rw-r--r--winpr/libwinpr/comm/comm.c6
-rw-r--r--winpr/libwinpr/comm/comm_io.c8
-rw-r--r--winpr/libwinpr/comm/comm_serial_sys.c18
-rw-r--r--winpr/libwinpr/crt/alignment.c10
-rw-r--r--winpr/libwinpr/crt/test/TestUnicodeConversion.c8
-rw-r--r--winpr/libwinpr/file/file.c159
-rw-r--r--winpr/libwinpr/file/generic.c2
-rw-r--r--winpr/libwinpr/handle/CMakeLists.txt3
-rw-r--r--winpr/libwinpr/library/library.c9
-rw-r--r--winpr/libwinpr/ncrypt/ncrypt_pkcs11.c7
-rw-r--r--winpr/libwinpr/nt/CMakeLists.txt4
-rw-r--r--winpr/libwinpr/path/CMakeLists.txt4
-rw-r--r--winpr/libwinpr/path/path.c8
-rw-r--r--winpr/libwinpr/path/shell.c6
-rw-r--r--winpr/libwinpr/pool/CMakeLists.txt4
-rw-r--r--winpr/libwinpr/smartcard/smartcard_pcsc.c19
-rw-r--r--winpr/libwinpr/sspi/Kerberos/kerberos.c4
-rw-r--r--winpr/libwinpr/sspi/Kerberos/krb5glue_mit.c7
-rw-r--r--winpr/libwinpr/sspi/NTLM/ntlm.c6
-rw-r--r--winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c7
-rw-r--r--winpr/libwinpr/sspi/NTLM/ntlm_compute.c9
-rw-r--r--winpr/libwinpr/sspi/Negotiate/negotiate.c17
-rw-r--r--winpr/libwinpr/synch/timer.c11
-rw-r--r--winpr/libwinpr/synch/wait.c66
-rw-r--r--winpr/libwinpr/sysinfo/cpufeatures/cpu-features.c1
-rw-r--r--winpr/libwinpr/sysinfo/sysinfo.c150
-rw-r--r--winpr/libwinpr/thread/CMakeLists.txt4
-rw-r--r--winpr/libwinpr/thread/thread.h48
-rw-r--r--winpr/libwinpr/timezone/timezone.c7
-rw-r--r--winpr/libwinpr/utils/cmdline.c7
-rw-r--r--winpr/libwinpr/utils/collections/CountdownEvent.c10
-rw-r--r--winpr/libwinpr/utils/collections/HashTable.c3
-rw-r--r--winpr/libwinpr/utils/collections/PubSub.c3
-rw-r--r--winpr/libwinpr/utils/collections/StreamPool.c2
-rw-r--r--winpr/libwinpr/utils/wlog/PacketMessage.c37
-rw-r--r--winpr/tools/CMakeLists.txt28
-rw-r--r--winpr/tools/hash-cli/CMakeLists.txt30
-rw-r--r--winpr/tools/makecert-cli/CMakeLists.txt32
-rw-r--r--winpr/tools/makecert/CMakeLists.txt8
255 files changed, 5284 insertions, 2743 deletions
diff --git a/.clang-tidy b/.clang-tidy
index 838f711..65bb2f8 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -49,6 +49,8 @@ AnalyzeTemporaryDtors: false
FormatStyle: file
User: nin
CheckOptions:
+ - key: readability-implicit-bool-conversion.AllowIntegerConditions
+ value: 'true'
- key: llvm-else-after-return.WarnOnConditionVariables
value: 'false'
- key: modernize-loop-convert.MinConfidence
diff --git a/.github/workflows/abi-checker.yml b/.github/workflows/abi-checker.yml
new file mode 100644
index 0000000..5506f44
--- /dev/null
+++ b/.github/workflows/abi-checker.yml
@@ -0,0 +1,102 @@
+name: abi-checker
+on:
+ workflow_dispatch:
+ branches: [ master, stable* ]
+ inputs:
+ API_BASE_REF:
+ description: 'Base revision for ABI compatibility check'
+ required: true
+ default: '3.0.0'
+ pull_request_target:
+ branches: [ master, stable* ]
+ schedule:
+ - cron: '30 4 * * SUN'
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ name: "Run ABI checker on ubuntu-latest"
+ steps:
+ - name: "Check out pull request"
+ if: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event_name == 'pull_request_target' }}
+ uses: suzuki-shunsuke/get-pr-action@v0.1.0
+ id: pr
+
+ - name: "Check out source"
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ ref: ${{steps.pr.outputs.merge_commit_sha}}
+
+ - name: "Prepare environment"
+ run: |
+ sudo apt-get update -q -y
+ sudo apt-get install -q -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 \
+ xsltproc \
+ libxcb-cursor-dev \
+ libxcursor-dev \
+ libcairo2-dev \
+ libfaad-dev \
+ libjpeg-dev \
+ libgsm1-dev \
+ ninja-build \
+ libxfixes-dev \
+ libxkbcommon-dev \
+ libwayland-dev \
+ libpam0g-dev \
+ libxdamage-dev \
+ libxcb-damage0-dev \
+ libxtst-dev \
+ libfuse3-dev \
+ libsystemd-dev \
+ libcairo2-dev \
+ libsoxr-dev \
+ libsdl2-dev \
+ docbook-xsl \
+ libkrb5-dev \
+ libcjson-dev \
+ libpkcs11-helper1-dev \
+ libsdl2-ttf-dev \
+ libwebkit2gtk-4.0-dev \
+ libopus-dev \
+ libwebp-dev \
+ libpng-dev \
+ libjpeg-dev \
+ liburiparser-dev \
+ cmake \
+ clang \
+ abigail-tools \
+ pylint \
+ curl
+
+ - 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
+ 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' }}"
+ echo "HEAD=$(git rev-parse HEAD)"
+ echo "remotes=$(git remote -v)"
+
+ - name: "Run ABI check..."
+ env:
+ BASE_REF: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event_name == 'pull_request_target' && 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)
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index 2db775f..0f90de2 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -14,116 +14,129 @@ name: "CodeQL"
on:
workflow_dispatch:
branches: [ master, stable* ]
- pull_request_target:
- branches: [ master, stable* ]
-
-permissions:
- contents: read
+ push:
+ branches: [ "master", "stable*" ]
+ pull_request:
+ branches: [ "master", "stable*" ]
+ schedule:
+ - cron: '41 2 * * 2'
jobs:
analyze:
+ name: Analyze (${{ matrix.language }})
+ # Runner size impacts CodeQL analysis time. To learn more, please see:
+ # - https://gh.io/recommended-hardware-resources-for-running-codeql
+ # - https://gh.io/supported-runners-and-hardware-resources
+ # - https://gh.io/using-larger-runners (GitHub.com only)
+ # Consider using larger runners or machines with greater resources for possible analysis time improvements.
+ runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }}
+ timeout-minutes: ${{ (matrix.language == 'swift' && 120) || 360 }}
permissions:
+ # required for all workflows
security-events: write
+
+ # only required for workflows in private repositories
actions: read
contents: read
- name: Analyze
- runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
- language: [ 'cpp' ]
- # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
- # Learn more:
- # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
-
+ include:
+ - language: c-cpp
+ build-mode: manual
+ # CodeQL supports the following values keywords for 'language': 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'swift'
+ # Use `c-cpp` to analyze code written in C, C++ or both
+ # Use 'java-kotlin' to analyze code written in Java, Kotlin or both
+ # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both
+ # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis,
+ # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning.
+ # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how
+ # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages
steps:
- - uses: suzuki-shunsuke/get-pr-action@v0.1.0
- id: pr
- - uses: actions/checkout@v4
- with:
- ref: ${{steps.pr.outputs.merge_commit_sha}}
+ - name: Checkout repository
+ uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
+ build-mode: ${{ matrix.build-mode }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
- # queries: ./path/to/local/query, your-org/your-repo/queries@main
- # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
- # If this step fails, then you should remove it and run the build manually (see below)
- # - name: Autobuild
- # uses: github/codeql-action/autobuild@v2
+ # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
+ # queries: security-extended,security-and-quality
+ # If the analyze step fails for one of the languages you are analyzing with
+ # "We were unable to automatically build your code", modify the matrix above
+ # to set the build mode to "manual" for that language. Then modify this step
+ # to build your code.
# ℹ️ Command-line programs to run using the OS shell.
- # 📚 https://git.io/JvXDl
-
- # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
- # and modify them (or add more) to build your code if your project
- # uses a compiled language
-
- - run: |
- sudo apt update
- sudo apt install \
- 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 \
- xsltproc \
- libxcb-cursor-dev \
- libxcursor-dev \
- libcairo2-dev \
- libfaac-dev \
- libfaad-dev \
- libjpeg-dev \
- libgsm1-dev \
- ninja-build \
- libxfixes-dev \
- libxkbcommon-dev \
- libwayland-dev \
- libpam0g-dev \
- libxdamage-dev \
- libxcb-damage0-dev \
- ccache \
- libxtst-dev \
- libfuse3-dev \
- libsystemd-dev \
- libcairo2-dev \
- libsoxr-dev \
- libsdl2-dev \
- docbook-xsl \
- libkrb5-dev \
- libcjson-dev \
- libpkcs11-helper1-dev \
- libsdl2-ttf-dev \
- libsdl2-image-dev \
- libwebkit2gtk-4.0-dev \
- clang \
- libopus-dev \
- libwebp-dev \
- libpng-dev \
- libjpeg-dev \
- liburiparser-dev
- mkdir ci-build
- cd ci-build
- export CC=/usr/bin/clang
- export CXX=/usr/bin/clang++
- export CFLAGS="-Weverything"
- export CXXFLAGS="-Weverything"
- cmake -GNinja ../ci/cmake-preloads/config-linux-all.txt ..
- cmake --build .
+ # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
+ - if: matrix.build-mode == 'manual'
+ run: |
+ sudo apt update
+ sudo apt install \
+ 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 \
+ xsltproc \
+ libxcb-cursor-dev \
+ libxcursor-dev \
+ libcairo2-dev \
+ libfaac-dev \
+ libfaad-dev \
+ libjpeg-dev \
+ libgsm1-dev \
+ ninja-build \
+ libxfixes-dev \
+ libxkbcommon-dev \
+ libwayland-dev \
+ libpam0g-dev \
+ libxdamage-dev \
+ libxcb-damage0-dev \
+ ccache \
+ libxtst-dev \
+ libfuse3-dev \
+ libsystemd-dev \
+ libcairo2-dev \
+ libsoxr-dev \
+ libsdl2-dev \
+ docbook-xsl \
+ libkrb5-dev \
+ libcjson-dev \
+ libpkcs11-helper1-dev \
+ libsdl2-ttf-dev \
+ libsdl2-image-dev \
+ libwebkit2gtk-4.0-dev \
+ clang \
+ libopus-dev \
+ libwebp-dev \
+ libpng-dev \
+ libjpeg-dev \
+ liburiparser-dev
+ mkdir ci-build
+ cd ci-build
+ export CC=/usr/bin/clang
+ export CXX=/usr/bin/clang++
+ export CFLAGS="-Weverything"
+ export CXXFLAGS="-Weverything"
+ cmake -GNinja ../ci/cmake-preloads/config-linux-all.txt ..
+ cmake --build .
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
+ with:
+ category: "/language:${{matrix.language}}"
diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml
new file mode 100644
index 0000000..5998a1d
--- /dev/null
+++ b/.github/workflows/coverity.yml
@@ -0,0 +1,96 @@
+
+name: Coverity
+
+on:
+ schedule:
+ - cron: "0 0 * * *"
+ workflow_dispatch:
+
+permissions:
+ contents: read
+
+jobs:
+ scan:
+ runs-on: ubuntu-latest
+ if: ${{ github.repository_owner == 'FreeRDP' }}
+ steps:
+ - uses: actions/checkout@v4
+ - name: Install apt dependencies
+ 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 \
+ xsltproc \
+ libxcb-cursor-dev \
+ libxcursor-dev \
+ libcairo2-dev \
+ libfaac-dev \
+ libfaad-dev \
+ libjpeg-dev \
+ libgsm1-dev \
+ ninja-build \
+ libxfixes-dev \
+ libxkbcommon-dev \
+ libwayland-dev \
+ libpam0g-dev \
+ libxdamage-dev \
+ libxcb-damage0-dev \
+ ccache \
+ libxtst-dev \
+ libfuse3-dev \
+ libsystemd-dev \
+ libcairo2-dev \
+ libsoxr-dev \
+ libsdl2-dev \
+ docbook-xsl \
+ libkrb5-dev \
+ libcjson-dev \
+ libpkcs11-helper1-dev \
+ libsdl2-ttf-dev \
+ libsdl2-image-dev \
+ libwebkit2gtk-4.0-dev \
+ clang \
+ libopus-dev \
+ libwebp-dev \
+ libpng-dev \
+ libjpeg-dev \
+ liburiparser-dev
+ - 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++
+ # 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. \
+ -S.
+ cov-build --dir cov-int cmake --build .
+
+ - name: Submit build result to Coverity Scan
+ run: |
+ tar czvf cov.tar.gz cov-int
+ curl --form token=${{ secrets.COVERITY_SCAN_TOKEN }} \
+ --form email=team+coverity@freerdp.com \
+ --form file=@cov.tar.gz \
+ --form version="Commit $GITHUB_SHA" \
+ --form description="Build submitted via CI" \
+ https://scan.coverity.com/builds?project=FreeRDP
diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml
new file mode 100644
index 0000000..d7920c9
--- /dev/null
+++ b/.github/workflows/mingw.yml
@@ -0,0 +1,31 @@
+name: mingw-builder
+on:
+ workflow_dispatch:
+ branches: [ master, stable* ]
+ schedule:
+ - cron: '30 5 * * SUN'
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ name: "Run mingw build on ubuntu-latest"
+ steps:
+ - name: "Check out source"
+ uses: actions/checkout@v4
+
+ - name: "Prepare environment"
+ run: |
+ sudo apt-get update -q -y
+ sudo apt-get install -q -y \
+ git \
+ nasm \
+ meson \
+ cmake \
+ ninja-build \
+ mingw-w64 \
+ mingw-w64-tools \
+ binutils-mingw-w64
+
+ - name: "Run mingw build..."
+ run: |
+ ./scripts/mingw.sh
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 201a24b..7700e18 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -58,13 +58,6 @@ endif()
# Include our extra modules
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/)
-include(CommonConfigOptions)
-
-if((CMAKE_SYSTEM_NAME MATCHES "WindowsStore") AND (CMAKE_SYSTEM_VERSION MATCHES "10.0"))
- set(UWP 1)
- add_definitions("-D_UWP")
- set(CMAKE_WINDOWS_VERSION "WIN10")
-endif()
# Check for cmake compatibility (enable/disable features)
include(CheckCmakeCompat)
@@ -75,7 +68,6 @@ if(WITH_CLANG_FORMAT)
endif()
include(CompilerFlags)
-include(DetectBSD)
include(CheckIncludeFiles)
include(CheckLibraryExists)
include(CheckSymbolExists)
@@ -99,7 +91,7 @@ if ($ENV{BUILD_NUMBER})
endif()
set(VERSION_REGEX "^(.*)([0-9]+)\\.([0-9]+)\\.([0-9]+)-?(.*)")
-set(RAW_VERSION_STRING "3.3.0")
+set(RAW_VERSION_STRING "3.5.0")
if(EXISTS "${PROJECT_SOURCE_DIR}/.source_tag")
file(READ ${PROJECT_SOURCE_DIR}/.source_tag RAW_VERSION_STRING)
elseif(USE_VERSION_FROM_GIT_TAG)
@@ -215,16 +207,6 @@ if(FREEBSD)
find_library(EPOLLSHIM_LIBS NAMES epoll-shim libepoll-shim HINTS /usr/local/lib)
endif()
-# Enable 64bit file support on linux and FreeBSD.
-if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux" OR FREEBSD)
- add_definitions("-D_FILE_OFFSET_BITS=64")
-endif()
-
-# Use Standard conforming getpwnam_r() on Solaris.
-if("${CMAKE_SYSTEM_NAME}" MATCHES "SunOS")
- add_definitions("-D_POSIX_PTHREAD_SEMANTICS")
-endif()
-
# Compiler-specific flags
if(CMAKE_COMPILER_IS_GNUCC)
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64" OR CMAKE_SYSTEM_PROCESSOR MATCHES "i686")
@@ -385,14 +367,6 @@ if(WIN32)
set(CMAKE_DL_LIBS "")
set(CMAKE_USE_RELATIVE_PATH ON)
- if (${CMAKE_GENERATOR} MATCHES "NMake Makefile*" OR ${CMAKE_GENERATOR} MATCHES "Ninja*" OR ${CMAKE_GENERATOR} MATCHES "Unix Makefiles")
- set(CMAKE_PDB_BINARY_DIR ${PROJECT_BINARY_DIR})
- elseif (${CMAKE_GENERATOR} MATCHES "Visual Studio*")
- set(CMAKE_PDB_BINARY_DIR "${PROJECT_BINARY_DIR}/\${CMAKE_INSTALL_CONFIG_NAME}")
- else()
- message(FATAL_ERROR "Unknown generator ${CMAKE_GENERATOR}")
- endif()
-
string(TIMESTAMP RC_VERSION_YEAR "%Y")
if(NOT DEFINED CMAKE_WINDOWS_VERSION)
@@ -529,10 +503,6 @@ set(VAAPI_FEATURE_TYPE "OPTIONAL")
set(VAAPI_FEATURE_PURPOSE "multimedia")
set(VAAPI_FEATURE_DESCRIPTION "VA-API hardware acceleration for video playback")
-set(IPP_FEATURE_TYPE "OPTIONAL")
-set(IPP_FEATURE_PURPOSE "performance")
-set(IPP_FEATURE_DESCRIPTION "Intel Integrated Performance Primitives library")
-
set(OPENH264_FEATURE_TYPE "OPTIONAL")
set(OPENH264_FEATURE_PURPOSE "codec")
set(OPENH264_FEATURE_DESCRIPTION "use OpenH264 library")
@@ -661,13 +631,6 @@ if (WITH_OPENH264 AND NOT OPENH264_FOUND)
endif()
set(WITH_OPENH264 ${OPENH264_FOUND})
-if(TARGET_ARCH MATCHES "x86|x64")
- if (NOT APPLE)
- # Intel Performance Primitives
- find_feature(IPP ${IPP_FEATURE_TYPE} ${IPP_FEATURE_PURPOSE} ${IPP_FEATURE_DESCRIPTION})
- endif()
-endif()
-
if(OPENSSL_FOUND)
add_definitions("-DWITH_OPENSSL")
message(STATUS "Using OpenSSL Version: ${OPENSSL_VERSION}")
@@ -727,10 +690,6 @@ else()
set(FREERDP_PROXY_PLUGINDIR "${PROXY_PLUGINDIR}")
endif()
-if (BUILD_SHARED_LIBS)
- set(CMAKE_MACOSX_RPATH ON)
-endif()
-
# Android profiling
if(ANDROID)
if(WITH_GPROF)
@@ -755,6 +714,8 @@ if(BUILD_TESTING)
endif()
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)
@@ -798,18 +759,6 @@ endif()
add_subdirectory(libfreerdp)
-if(BSD)
- if(IS_DIRECTORY /usr/local/include)
- include_directories(/usr/local/include)
- link_directories(/usr/local/lib)
- endif()
- if(OPENBSD)
- if(IS_DIRECTORY /usr/X11R6/include)
- include_directories(/usr/X11R6/include)
- endif()
- endif()
-endif()
-
if(WITH_CHANNELS)
add_subdirectory(channels)
endif()
diff --git a/ChangeLog b/ChangeLog
index b8f04f1..ccba111 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,66 @@
+# 2024-04-16 Version 3.5.0
+
+This release focus is on squashing bugs.
+The improved test coverage and ci builds revealed a number of previously
+unnoticed issues we have addressed and we also got a report from
+Evgeny Legerov of Kaspersky Lab identifying a number of out of bound reads
+in decoder components and one very nasty out of bound write.
+
+CVE:
+CVE-2024-32041 [Low[ OutOfBound Read in zgfx_decompress_segment
+CVE-2024-32039 [Moderate] Integer overflow & OutOfBound Write in clear_decompress_residual_data
+CVE-2024-32040 [Low] integer underflow in nsc_rle_decode
+CVE-2024-32458 [Low] OutOfBound Read in planar_skip_plane_rle
+CVE-2024-32459 [Low] OutOfBound Read in ncrush_decompress
+CVE-2024-32460 [Low] OutOfBound Read in interleaved_decompress
+
+Noteworthy changes:
+* location channel support #9981, #9984, #10065
+* bugfixes for report from Evgeny Legerov of Kaspersky Lab #10077
+* fuzzer tests from Evgeny Legerov of Kaspersky Lab #10078
+* bugfixes for coverty scanner #10066, #10068, #10069, #10070, #10075
+* clipboard and generic locking fixes #10076
+* split autoreconnect support from enabling it #10063
+* various nightly and workflow fixes #10064, #10058, #10062
+* always set wm-class to app_id #10051
+* refactored and simplified CMake #10046, #10047
+* fix relative mouse event sending #10010
+* improve and unify check for APIs used (POSIX, win32, mac, ...) #9995
+* fix termination for gateway connections #9985
+* fix drivestoredirect RDP file setting, ignore invalid #9989
+* drop IPP support #10038
+
+For a complete and detailed change log since the last release run:
+git log 3.5.0...3.4.0
+
+# 2024-03-14 Version 3.4.0
+
+This release concentrates on improving test coverage and ci builds.
+Some usability issues and inconvenient API functions were fixed on the way.
+
+New features have been introduced (stub for location channel)
+
+Noteworthy changes:
+* fix a bug in RAIL mode not activating window focus (#9973)
+* improve logging (#9969, #9943)
+* OpenSSL <= 1.1.1 build fixes (#9897)
+* improved help (#9899, #9905)
+* improved MINGW support (#9914, #9915, #9919, #9964, #9965, #9920)
+* fix right control ungrab for xfreerdp (#9960)
+* fix RPATH option settings (#9963)
+* fix SDL client screen updates (#9962, #9954)
+* fix issues with childSession under windows (#9961, #9956, #9922)
+* fix xfreerdp crash with +auth-only (#9947)
+* fix windows printer channel (#9934)
+* add support to enforce gateway policy (#9942)
+* improve big endian support (#9927)
+* ignore empty proxy environment variables (#9929)
+* improve quoting support for command line (#9912)
+
+For a complete and detailed change log since the last release run:
+git log 3.4.0...3.3.0
+
+
# 2024-02-22 Version 3.3.0
This release concentrates on code cleanup and overall quality improvements.
diff --git a/README.md b/README.md
index 5610432..7473ea5 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,15 @@ FreeRDP is a free implementation of the Remote Desktop Protocol (RDP), released
Enjoy the freedom of using your software wherever you want, the way you want it, in a world where
interoperability can finally liberate your computing experience.
+## Code Quality Status
+
+[![abi-checker](https://github.com/FreeRDP/FreeRDP/actions/workflows/abi-checker.yml/badge.svg)](https://github.com/FreeRDP/FreeRDP/actions/workflows/abi-checker.yml)
+[![clang-tidy-review](https://github.com/FreeRDP/FreeRDP/actions/workflows/clang-tidy.yml/badge.svg?event=pull_request_target)](https://github.com/FreeRDP/FreeRDP/actions/workflows/clang-tidy.yml)
+[![CodeQL](https://github.com/FreeRDP/FreeRDP/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/FreeRDP/FreeRDP/actions/workflows/codeql-analysis.yml)
+[![mingw-builder](https://github.com/FreeRDP/FreeRDP/actions/workflows/mingw.yml/badge.svg)](https://github.com/FreeRDP/FreeRDP/actions/workflows/mingw.yml)
+[![[arm,ppc,ricsv] architecture builds](https://github.com/FreeRDP/FreeRDP/actions/workflows/alt-architectures.yml/badge.svg)](https://github.com/FreeRDP/FreeRDP/actions/workflows/alt-architectures.yml)
+[![coverity](https://scan.coverity.com/projects/616/badge.svg)](https://scan.coverity.com/projects/freerdp)
+
## Resources
Project website: https://www.freerdp.com/
diff --git a/channels/audin/client/alsa/audin_alsa.c b/channels/audin/client/alsa/audin_alsa.c
index be3e52a..b1edb82 100644
--- a/channels/audin/client/alsa/audin_alsa.c
+++ b/channels/audin/client/alsa/audin_alsa.c
@@ -55,7 +55,7 @@ typedef struct
rdpContext* rdpcontext;
wLog* log;
- int bytes_per_frame;
+ size_t bytes_per_frame;
} AudinALSADevice;
static snd_pcm_format_t audin_alsa_format(UINT32 wFormatTag, UINT32 bitPerChannel)
diff --git a/channels/audin/client/oss/CMakeLists.txt b/channels/audin/client/oss/CMakeLists.txt
index 6b747e4..5b4dac9 100644
--- a/channels/audin/client/oss/CMakeLists.txt
+++ b/channels/audin/client/oss/CMakeLists.txt
@@ -30,7 +30,12 @@ set(${MODULE_PREFIX}_LIBS
)
include_directories(..)
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${OSS_INCLUDE_DIRS})
-
+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 "")
diff --git a/channels/audin/client/oss/audin_oss.c b/channels/audin/client/oss/audin_oss.c
index 979a800..c42c089 100644
--- a/channels/audin/client/oss/audin_oss.c
+++ b/channels/audin/client/oss/audin_oss.c
@@ -37,11 +37,7 @@
#include <libgen.h>
#include <limits.h>
#include <unistd.h>
-#if defined(__OpenBSD__)
-#include <soundcard.h>
-#else
-#include <sys/soundcard.h>
-#endif
+#include <oss-includes.h>
#include <sys/ioctl.h>
#include <freerdp/freerdp.h>
@@ -67,15 +63,15 @@ typedef struct
rdpContext* rdpcontext;
} AudinOSSDevice;
-#define OSS_LOG_ERR(_text, _error) \
- do \
- { \
- if (_error != 0) \
- { \
- char buffer[256] = { 0 }; \
- WLog_ERR(TAG, "%s: %i - %s\n", _text, _error, \
- winpr_strerror(_error, buffer, sizeof(buffer))); \
- } \
+#define OSS_LOG_ERR(_text, _error) \
+ do \
+ { \
+ if ((_error) != 0) \
+ { \
+ char buffer[256] = { 0 }; \
+ WLog_ERR(TAG, "%s: %i - %s\n", (_text), (_error), \
+ winpr_strerror((_error), buffer, sizeof(buffer))); \
+ } \
} while (0)
static UINT32 audin_oss_get_format(const AUDIO_FORMAT* format)
@@ -233,7 +229,8 @@ static DWORD WINAPI audin_oss_thread_func(LPVOID arg)
if (ioctl(pcm_handle, SNDCTL_DSP_SETFRAGMENT, &tmp) == -1)
OSS_LOG_ERR("SNDCTL_DSP_SETFRAGMENT failed", errno);
- buffer_size = (oss->FramesPerPacket * oss->format.nChannels * (oss->format.wBitsPerSample / 8));
+ buffer_size =
+ (1ull * oss->FramesPerPacket * oss->format.nChannels * (oss->format.wBitsPerSample / 8ull));
buffer = (BYTE*)calloc((buffer_size + sizeof(void*)), sizeof(BYTE));
if (NULL == buffer)
diff --git a/channels/client/addin.c b/channels/client/addin.c
index 6d87f6c..2f3b990 100644
--- a/channels/client/addin.c
+++ b/channels/client/addin.c
@@ -104,19 +104,19 @@ static FREERDP_ADDIN** freerdp_channels_list_client_static_addins(LPCSTR pszName
for (size_t i = 0; CLIENT_STATIC_ADDIN_TABLE[i].name != NULL; i++)
{
FREERDP_ADDIN* pAddin = (FREERDP_ADDIN*)calloc(1, sizeof(FREERDP_ADDIN));
-
+ const STATIC_ADDIN_TABLE* table = &CLIENT_STATIC_ADDIN_TABLE[i];
if (!pAddin)
{
WLog_ERR(TAG, "calloc failed!");
goto error_out;
}
- sprintf_s(pAddin->cName, ARRAYSIZE(pAddin->cName), "%s", CLIENT_STATIC_ADDIN_TABLE[i].name);
+ 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;
ppAddins[nAddins++] = pAddin;
- subsystems = (const STATIC_SUBSYSTEM_ENTRY*)CLIENT_STATIC_ADDIN_TABLE[i].table;
+ subsystems = table->table;
for (size_t j = 0; subsystems[j].name != NULL; j++)
{
@@ -128,8 +128,7 @@ static FREERDP_ADDIN** freerdp_channels_list_client_static_addins(LPCSTR pszName
goto error_out;
}
- sprintf_s(pAddin->cName, ARRAYSIZE(pAddin->cName), "%s",
- CLIENT_STATIC_ADDIN_TABLE[i].name);
+ sprintf_s(pAddin->cName, ARRAYSIZE(pAddin->cName), "%s", table->name);
sprintf_s(pAddin->cSubsystem, ARRAYSIZE(pAddin->cSubsystem), "%s", subsystems[j].name);
pAddin->dwFlags = FREERDP_ADDIN_CLIENT;
pAddin->dwFlags |= FREERDP_ADDIN_STATIC;
diff --git a/channels/client/generic_dynvc.c b/channels/client/generic_dynvc.c
index 263b5ce..6221470 100644
--- a/channels/client/generic_dynvc.c
+++ b/channels/client/generic_dynvc.c
@@ -53,6 +53,8 @@ static UINT generic_on_new_channel_connection(IWTSListenerCallback* pListenerCal
callback->channel = pChannel;
listener_callback->channel_callback = callback;
+ listener_callback->channel = pChannel;
+
*ppCallback = (IWTSVirtualChannelCallback*)callback;
return CHANNEL_RC_OK;
}
diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c
index 60ae27d..68eeb82 100644
--- a/channels/cliprdr/client/cliprdr_main.c
+++ b/channels/cliprdr/client/cliprdr_main.c
@@ -654,7 +654,10 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context,
if (Stream_Write_UTF16_String_From_UTF8(s, tmpDirCharLen - 1, tempDirectory->szTempDir,
ARRAYSIZE(tempDirectory->szTempDir), TRUE) < 0)
+ {
+ Stream_Free(s, TRUE);
return ERROR_INTERNAL_ERROR;
+ }
/* Path must be 260 UTF16 characters with '\0' termination.
* ensure this here */
Stream_Write_UINT16(s, 0);
diff --git a/channels/cliprdr/cliprdr_common.c b/channels/cliprdr/cliprdr_common.c
index d346cb1..f587f30 100644
--- a/channels/cliprdr/cliprdr_common.c
+++ b/channels/cliprdr/cliprdr_common.c
@@ -388,7 +388,7 @@ UINT cliprdr_read_file_contents_response(wStream* s, CLIPRDR_FILE_CONTENTS_RESPO
UINT cliprdr_read_format_list(wStream* s, CLIPRDR_FORMAT_LIST* formatList, BOOL useLongFormatNames)
{
UINT32 index = 0;
- int formatNameLength = 0;
+ size_t formatNameLength = 0;
const char* szFormatName = NULL;
const WCHAR* wszFormatName = NULL;
wStream sub1buffer = { 0 };
diff --git a/channels/cliprdr/server/cliprdr_main.c b/channels/cliprdr/server/cliprdr_main.c
index 9823f17..23a4331 100644
--- a/channels/cliprdr/server/cliprdr_main.c
+++ b/channels/cliprdr/server/cliprdr_main.c
@@ -119,7 +119,6 @@ static UINT cliprdr_server_capabilities(CliprdrServerContext* context,
const CLIPRDR_CAPABILITIES* capabilities)
{
size_t offset = 0;
- wStream* s = NULL;
WINPR_ASSERT(context);
WINPR_ASSERT(capabilities);
@@ -135,7 +134,7 @@ static UINT cliprdr_server_capabilities(CliprdrServerContext* context,
return ERROR_INVALID_PARAMETER;
}
- s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN);
+ wStream* s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN);
if (!s)
{
@@ -173,6 +172,7 @@ static UINT cliprdr_server_capabilities(CliprdrServerContext* context,
if (!Stream_SafeSeek(s, cap->capabilitySetLength))
{
WLog_ERR(TAG, "short stream");
+ Stream_Free(s, TRUE);
return ERROR_NO_DATA;
}
break;
diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c
index 0b85c0f..968d7e2 100644
--- a/channels/drdynvc/client/drdynvc_main.c
+++ b/channels/drdynvc/client/drdynvc_main.c
@@ -396,14 +396,13 @@ static void dvcman_channel_free(DVCMAN_CHANNEL* channel)
static void dvcman_channel_unref(DVCMAN_CHANNEL* channel)
{
- DVCMAN* dvcman = NULL;
-
WINPR_ASSERT(channel);
if (InterlockedDecrement(&channel->refCounter))
return;
- dvcman = channel->dvcman;
- HashTable_Remove(dvcman->channelsById, &channel->channel_id);
+ DVCMAN* dvcman = channel->dvcman;
+ if (dvcman)
+ HashTable_Remove(dvcman->channelsById, &channel->channel_id);
}
static UINT dvcchannel_send_close(DVCMAN_CHANNEL* channel)
@@ -457,7 +456,6 @@ static UINT dvcman_call_on_receive(DVCMAN_CHANNEL* channel, wStream* data)
static UINT dvcman_channel_close(DVCMAN_CHANNEL* channel, BOOL perRequest, BOOL fromHashTableFn)
{
UINT error = CHANNEL_RC_OK;
- drdynvcPlugin* drdynvc = NULL;
DrdynvcClientContext* context = NULL;
WINPR_ASSERT(channel);
@@ -466,20 +464,24 @@ static UINT dvcman_channel_close(DVCMAN_CHANNEL* channel, BOOL perRequest, BOOL
case DVC_CHANNEL_INIT:
break;
case DVC_CHANNEL_RUNNING:
- drdynvc = channel->dvcman->drdynvc;
- context = drdynvc->context;
- if (perRequest)
- WLog_Print(drdynvc->log, WLOG_DEBUG, "sending close confirm for '%s'",
- channel->channel_name);
-
- error = dvcchannel_send_close(channel);
- if (error != CHANNEL_RC_OK)
+ if (channel->dvcman)
{
- const char* msg = "error when sending close confirm for '%s'";
+ drdynvcPlugin* drdynvc = channel->dvcman->drdynvc;
+ WINPR_ASSERT(drdynvc);
+ context = drdynvc->context;
if (perRequest)
- msg = "error when sending closeRequest for '%s'";
+ WLog_Print(drdynvc->log, WLOG_DEBUG, "sending close confirm for '%s'",
+ channel->channel_name);
- WLog_Print(drdynvc->log, WLOG_DEBUG, msg, channel->channel_name);
+ error = dvcchannel_send_close(channel);
+ if (error != CHANNEL_RC_OK)
+ {
+ const char* msg = "error when sending close confirm for '%s'";
+ if (perRequest)
+ msg = "error when sending closeRequest for '%s'";
+
+ WLog_Print(drdynvc->log, WLOG_DEBUG, msg, channel->channel_name);
+ }
}
channel->state = DVC_CHANNEL_CLOSED;
diff --git a/channels/drive/client/drive_main.c b/channels/drive/client/drive_main.c
index 0fdc2e0..04f8d83 100644
--- a/channels/drive/client/drive_main.c
+++ b/channels/drive/client/drive_main.c
@@ -511,7 +511,7 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP*
/* http://msdn.microsoft.com/en-us/library/cc232101.aspx */
const WCHAR* diskType =
InitializeConstWCharFromUtf8("FAT32", LabelBuffer, ARRAYSIZE(LabelBuffer));
- const size_t diskTypeLen = (wcslen(diskType) + 1) * sizeof(WCHAR);
+ const size_t diskTypeLen = (_wcslen(diskType) + 1) * sizeof(WCHAR);
const size_t length = 12ul + diskTypeLen;
Stream_Write_UINT32(output, length); /* Length */
diff --git a/channels/location/CMakeLists.txt b/channels/location/CMakeLists.txt
index 5e77fcb..fbf920c 100644
--- a/channels/location/CMakeLists.txt
+++ b/channels/location/CMakeLists.txt
@@ -17,6 +17,10 @@
define_channel("location")
+if(WITH_CLIENT_CHANNELS)
+ add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
+endif()
+
if(WITH_SERVER_CHANNELS)
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()
diff --git a/channels/location/ChannelOptions.cmake b/channels/location/ChannelOptions.cmake
index 11f5e30..acffc26 100644
--- a/channels/location/ChannelOptions.cmake
+++ b/channels/location/ChannelOptions.cmake
@@ -1,6 +1,6 @@
set(OPTION_DEFAULT ON)
-set(OPTION_CLIENT_DEFAULT OFF)
+set(OPTION_CLIENT_DEFAULT ON)
set(OPTION_SERVER_DEFAULT ON)
define_channel_options(NAME "location" TYPE "dynamic"
@@ -8,5 +8,6 @@ define_channel_options(NAME "location" TYPE "dynamic"
SPECIFICATIONS "[MS-RDPEL]"
DEFAULT ${OPTION_DEFAULT})
+define_channel_client_options(${OPTION_CLIENT_DEFAULT})
define_channel_server_options(${OPTION_SERVER_DEFAULT})
diff --git a/channels/location/client/CMakeLists.txt b/channels/location/client/CMakeLists.txt
new file mode 100644
index 0000000..3c5a05a
--- /dev/null
+++ b/channels/location/client/CMakeLists.txt
@@ -0,0 +1,30 @@
+# FreeRDP: A Remote Desktop Protocol Implementation
+# FreeRDP cmake build script
+#
+# 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.
+# 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("location")
+
+set(${MODULE_PREFIX}_SRCS
+ location_main.c
+)
+
+set(${MODULE_PREFIX}_LIBS
+ winpr
+)
+include_directories(..)
+
+add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DVCPluginEntry")
diff --git a/channels/location/client/location_main.c b/channels/location/client/location_main.c
new file mode 100644
index 0000000..281070f
--- /dev/null
+++ b/channels/location/client/location_main.c
@@ -0,0 +1,473 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Location Virtual Channel Extension
+ *
+ * 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.
+ * 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 <freerdp/config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <float.h>
+#include <math.h>
+
+#include <winpr/crt.h>
+#include <winpr/assert.h>
+#include <winpr/stream.h>
+
+#include <freerdp/client/channels.h>
+#include <freerdp/channels/log.h>
+#include <freerdp/channels/location.h>
+#include <freerdp/client/location.h>
+#include <freerdp/utils/encoded_types.h>
+
+#define TAG CHANNELS_TAG("location.client")
+
+/* implement [MS-RDPEL]
+ * https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpel/4397a0af-c821-4b75-9068-476fb579c327
+ */
+typedef struct
+{
+ GENERIC_DYNVC_PLUGIN baseDynPlugin;
+ LocationClientContext context;
+} LOCATION_PLUGIN;
+
+typedef struct
+{
+ GENERIC_CHANNEL_CALLBACK baseCb;
+ UINT32 serverVersion;
+ UINT32 clientVersion;
+ UINT32 serverFlags;
+ UINT32 clientFlags;
+} LOCATION_CALLBACK;
+
+static BOOL location_read_header(wLog* log, wStream* s, UINT16* ppduType, UINT32* ppduLength)
+{
+ WINPR_ASSERT(log);
+ WINPR_ASSERT(s);
+ WINPR_ASSERT(ppduType);
+ WINPR_ASSERT(ppduLength);
+
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 6))
+ return FALSE;
+ Stream_Read_UINT16(s, *ppduType);
+ Stream_Read_UINT32(s, *ppduLength);
+ if (*ppduLength < 6)
+ {
+ WLog_Print(log, WLOG_ERROR,
+ "RDPLOCATION_HEADER::pduLengh=%" PRIu16 " < sizeof(RDPLOCATION_HEADER)[6]",
+ *ppduLength);
+ return FALSE;
+ }
+ return Stream_CheckAndLogRequiredLengthWLog(log, s, *ppduLength - 6ull);
+}
+
+static BOOL location_write_header(wStream* s, UINT16 pduType, UINT32 pduLength)
+{
+ if (!Stream_EnsureRemainingCapacity(s, 6))
+ return FALSE;
+ Stream_Write_UINT16(s, pduType);
+ Stream_Write_UINT32(s, pduLength + 6);
+ return Stream_EnsureRemainingCapacity(s, pduLength);
+}
+
+static BOOL location_read_server_ready_pdu(LOCATION_CALLBACK* callback, wStream* s, UINT16 pduSize)
+{
+ if (pduSize < 6 + 4)
+ return FALSE; // Short message
+
+ Stream_Read_UINT32(s, callback->serverVersion);
+ if (pduSize >= 6 + 4 + 4)
+ Stream_Read_UINT32(s, callback->serverFlags);
+ return TRUE;
+}
+
+static UINT location_channel_send(IWTSVirtualChannel* channel, wStream* s)
+{
+ const size_t len = Stream_GetPosition(s);
+ Stream_SetPosition(s, 2);
+ Stream_Write_UINT32(s, len);
+
+ WINPR_ASSERT(channel);
+ WINPR_ASSERT(channel->Write);
+ return channel->Write(channel, len, Stream_Buffer(s), NULL);
+}
+
+static UINT location_send_client_ready_pdu(const LOCATION_CALLBACK* callback)
+{
+ wStream sbuffer = { 0 };
+ char buffer[32] = { 0 };
+ wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
+ WINPR_ASSERT(s);
+
+ if (!location_write_header(s, PDUTYPE_CLIENT_READY, 8))
+ return ERROR_OUTOFMEMORY;
+
+ Stream_Write_UINT32(s, callback->clientVersion);
+ Stream_Write_UINT32(s, callback->clientFlags);
+ return location_channel_send(callback->baseCb.channel, s);
+}
+
+static const char* location_version_str(UINT32 version, char* buffer, size_t size)
+{
+ const char* str = NULL;
+ switch (version)
+ {
+ case RDPLOCATION_PROTOCOL_VERSION_100:
+ str = "RDPLOCATION_PROTOCOL_VERSION_100";
+ break;
+ case RDPLOCATION_PROTOCOL_VERSION_200:
+ str = "RDPLOCATION_PROTOCOL_VERSION_200";
+ break;
+ default:
+ str = "RDPLOCATION_PROTOCOL_VERSION_UNKNOWN";
+ break;
+ }
+
+ _snprintf(buffer, size, "%s [0x%08" PRIx32 "]", str, version);
+ return buffer;
+}
+
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+static UINT location_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data)
+{
+ LOCATION_CALLBACK* callback = (LOCATION_CALLBACK*)pChannelCallback;
+
+ WINPR_ASSERT(callback);
+
+ LOCATION_PLUGIN* plugin = (LOCATION_PLUGIN*)callback->baseCb.plugin;
+ WINPR_ASSERT(plugin);
+
+ UINT16 pduType = 0;
+ UINT32 pduLength = 0;
+ if (!location_read_header(plugin->baseDynPlugin.log, data, &pduType, &pduLength))
+ return ERROR_INVALID_DATA;
+
+ switch (pduType)
+ {
+ case PDUTYPE_SERVER_READY:
+ if (!location_read_server_ready_pdu(callback, data, pduLength))
+ return ERROR_INVALID_DATA;
+
+ switch (callback->serverVersion)
+ {
+ case RDPLOCATION_PROTOCOL_VERSION_200:
+ callback->clientVersion = RDPLOCATION_PROTOCOL_VERSION_200;
+ break;
+ case RDPLOCATION_PROTOCOL_VERSION_100:
+ callback->clientVersion = RDPLOCATION_PROTOCOL_VERSION_100;
+ break;
+ default:
+ callback->clientVersion = RDPLOCATION_PROTOCOL_VERSION_100;
+ if (callback->serverVersion > RDPLOCATION_PROTOCOL_VERSION_200)
+ callback->clientVersion = RDPLOCATION_PROTOCOL_VERSION_200;
+ break;
+ }
+
+ char cbuffer[64] = { 0 };
+ char sbuffer[64] = { 0 };
+ WLog_Print(plugin->baseDynPlugin.log, WLOG_DEBUG,
+ "Server version %s, client version %s",
+ location_version_str(callback->serverVersion, sbuffer, sizeof(sbuffer)),
+ location_version_str(callback->clientVersion, cbuffer, sizeof(cbuffer)));
+
+ if (!plugin->context.LocationStart)
+ {
+ WLog_Print(plugin->baseDynPlugin.log, WLOG_WARN,
+ "LocationStart=NULL, no location data will be sent");
+ return CHANNEL_RC_OK;
+ }
+ const UINT res =
+ plugin->context.LocationStart(&plugin->context, callback->clientVersion, 0);
+ if (res != CHANNEL_RC_OK)
+ return res;
+ return location_send_client_ready_pdu(callback);
+ default:
+ WLog_WARN(TAG, "invalid pduType=%s");
+ return ERROR_INVALID_DATA;
+ }
+}
+
+static UINT location_send_base_location3d(IWTSVirtualChannel* channel,
+ const RDPLOCATION_BASE_LOCATION3D_PDU* pdu)
+{
+ wStream sbuffer = { 0 };
+ char buffer[32] = { 0 };
+ wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
+ WINPR_ASSERT(s);
+ WINPR_ASSERT(channel);
+ WINPR_ASSERT(pdu);
+
+ if (pdu->source)
+ WLog_DBG(TAG,
+ "latitude=%lf, logitude=%lf, altitude=%" PRId32
+ ", speed=%lf, heading=%lf, haccuracy=%lf, source=%" PRIu8,
+ pdu->latitude, pdu->longitude, pdu->altitude, pdu->speed, pdu->heading,
+ pdu->horizontalAccuracy, *pdu->source);
+ else
+ WLog_DBG(TAG, "latitude=%lf, logitude=%lf, altitude=%" PRId32, pdu->latitude,
+ pdu->longitude, pdu->altitude);
+
+ if (!location_write_header(s, PDUTYPE_BASE_LOCATION3D, pdu->source ? 25 : 12))
+ return ERROR_OUTOFMEMORY;
+
+ if (!freerdp_write_four_byte_float(s, pdu->latitude) ||
+ !freerdp_write_four_byte_float(s, pdu->longitude) ||
+ !freerdp_write_four_byte_signed_integer(s, pdu->altitude))
+ return ERROR_INTERNAL_ERROR;
+
+ if (pdu->source)
+ {
+ if (!freerdp_write_four_byte_float(s, *pdu->speed) ||
+ !freerdp_write_four_byte_float(s, *pdu->heading) ||
+ !freerdp_write_four_byte_float(s, *pdu->horizontalAccuracy))
+ return ERROR_INTERNAL_ERROR;
+
+ Stream_Write_UINT8(s, *pdu->source);
+ }
+
+ return location_channel_send(channel, s);
+}
+
+static UINT location_send_location2d_delta(IWTSVirtualChannel* channel,
+ const RDPLOCATION_LOCATION2D_DELTA_PDU* pdu)
+{
+ wStream sbuffer = { 0 };
+ char buffer[32] = { 0 };
+ wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
+ WINPR_ASSERT(s);
+
+ WINPR_ASSERT(channel);
+ WINPR_ASSERT(pdu);
+
+ const BOOL ext = pdu->speedDelta && pdu->headingDelta;
+
+ if (ext)
+ WLog_DBG(TAG, "latitude=%lf, logitude=%lf, speed=%lf, heading=%lf", pdu->latitudeDelta,
+ pdu->longitudeDelta, pdu->speedDelta, pdu->headingDelta);
+ else
+ WLog_DBG(TAG, "latitude=%lf, logitude=%lf", pdu->latitudeDelta, pdu->longitudeDelta);
+
+ if (!location_write_header(s, PDUTYPE_LOCATION2D_DELTA, ext ? 16 : 8))
+ return ERROR_OUTOFMEMORY;
+
+ if (!freerdp_write_four_byte_float(s, pdu->latitudeDelta) ||
+ !freerdp_write_four_byte_float(s, pdu->longitudeDelta))
+ return ERROR_INTERNAL_ERROR;
+
+ if (ext)
+ {
+ if (!freerdp_write_four_byte_float(s, *pdu->speedDelta) ||
+ !freerdp_write_four_byte_float(s, *pdu->headingDelta))
+ return ERROR_INTERNAL_ERROR;
+ }
+
+ return location_channel_send(channel, s);
+}
+
+static UINT location_send_location3d_delta(IWTSVirtualChannel* channel,
+ const RDPLOCATION_LOCATION3D_DELTA_PDU* pdu)
+{
+ wStream sbuffer = { 0 };
+ char buffer[32] = { 0 };
+ wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
+ WINPR_ASSERT(s);
+
+ WINPR_ASSERT(channel);
+ WINPR_ASSERT(pdu);
+
+ const BOOL ext = pdu->speedDelta && pdu->headingDelta;
+
+ if (ext)
+ WLog_DBG(TAG, "latitude=%lf, logitude=%lf, altitude=%" PRId32 ", speed=%lf, heading=%lf",
+ pdu->latitudeDelta, pdu->longitudeDelta, pdu->altitudeDelta, pdu->speedDelta,
+ pdu->headingDelta);
+ else
+ WLog_DBG(TAG, "latitude=%lf, logitude=%lf, altitude=%" PRId32, pdu->latitudeDelta,
+ pdu->longitudeDelta, pdu->altitudeDelta);
+
+ if (!location_write_header(s, PDUTYPE_LOCATION3D_DELTA, ext ? 20 : 12))
+ return ERROR_OUTOFMEMORY;
+
+ if (!freerdp_write_four_byte_float(s, pdu->latitudeDelta) ||
+ !freerdp_write_four_byte_float(s, pdu->longitudeDelta) ||
+ !freerdp_write_four_byte_signed_integer(s, pdu->altitudeDelta))
+ return ERROR_INTERNAL_ERROR;
+
+ if (ext)
+ {
+ if (!freerdp_write_four_byte_float(s, *pdu->speedDelta) ||
+ !freerdp_write_four_byte_float(s, *pdu->headingDelta))
+ return ERROR_INTERNAL_ERROR;
+ }
+
+ return location_channel_send(channel, s);
+}
+
+static UINT location_send(LocationClientContext* context, LOCATION_PDUTYPE type, size_t count, ...)
+{
+ WINPR_ASSERT(context);
+
+ LOCATION_PLUGIN* loc = context->handle;
+ WINPR_ASSERT(loc);
+
+ GENERIC_LISTENER_CALLBACK* cb = loc->baseDynPlugin.listener_callback;
+ WINPR_ASSERT(cb);
+
+ IWTSVirtualChannel* channel = cb->channel;
+ WINPR_ASSERT(channel);
+
+ LOCATION_CALLBACK* callback = (LOCATION_CALLBACK*)loc->baseDynPlugin.channel_callbacks;
+ WINPR_ASSERT(callback);
+
+ UINT32 res = ERROR_INTERNAL_ERROR;
+ va_list ap;
+ va_start(ap, count);
+ switch (type)
+ {
+ case PDUTYPE_BASE_LOCATION3D:
+ if ((count != 3) && (count != 7))
+ res = ERROR_INVALID_PARAMETER;
+ else
+ {
+ RDPLOCATION_BASE_LOCATION3D_PDU pdu = { 0 };
+ LOCATIONSOURCE source = LOCATIONSOURCE_IP;
+ double speed = FP_NAN;
+ double heading = FP_NAN;
+ double horizontalAccuracy = FP_NAN;
+ pdu.latitude = va_arg(ap, double);
+ pdu.longitude = va_arg(ap, double);
+ pdu.altitude = va_arg(ap, INT32);
+ if ((count > 3) && (callback->clientVersion >= RDPLOCATION_PROTOCOL_VERSION_200))
+ {
+ speed = va_arg(ap, double);
+ heading = va_arg(ap, double);
+ horizontalAccuracy = va_arg(ap, double);
+ source = va_arg(ap, int);
+ pdu.speed = &speed;
+ pdu.heading = &heading;
+ pdu.horizontalAccuracy = &horizontalAccuracy;
+ pdu.source = &source;
+ }
+ res = location_send_base_location3d(channel, &pdu);
+ }
+ break;
+ case PDUTYPE_LOCATION2D_DELTA:
+ if ((count != 2) && (count != 4))
+ res = ERROR_INVALID_PARAMETER;
+ else
+ {
+ RDPLOCATION_LOCATION2D_DELTA_PDU pdu = { 0 };
+
+ pdu.latitudeDelta = va_arg(ap, double);
+ pdu.longitudeDelta = va_arg(ap, double);
+
+ double speedDelta = FP_NAN;
+ double headingDelta = FP_NAN;
+ if ((count > 2) && (callback->clientVersion >= RDPLOCATION_PROTOCOL_VERSION_200))
+ {
+ speedDelta = va_arg(ap, double);
+ headingDelta = va_arg(ap, double);
+ pdu.speedDelta = &speedDelta;
+ pdu.headingDelta = &headingDelta;
+ }
+ res = location_send_location2d_delta(channel, &pdu);
+ }
+ break;
+ case PDUTYPE_LOCATION3D_DELTA:
+ if ((count != 3) && (count != 5))
+ res = ERROR_INVALID_PARAMETER;
+ else
+ {
+ RDPLOCATION_LOCATION3D_DELTA_PDU pdu = { 0 };
+ double speedDelta = FP_NAN;
+ double headingDelta = FP_NAN;
+
+ pdu.latitudeDelta = va_arg(ap, double);
+ pdu.longitudeDelta = va_arg(ap, double);
+ pdu.altitudeDelta = va_arg(ap, INT32);
+ if ((count > 3) && (callback->clientVersion >= RDPLOCATION_PROTOCOL_VERSION_200))
+ {
+ speedDelta = va_arg(ap, double);
+ headingDelta = va_arg(ap, double);
+ pdu.speedDelta = &speedDelta;
+ pdu.headingDelta = &headingDelta;
+ }
+ res = location_send_location3d_delta(channel, &pdu);
+ }
+ break;
+ default:
+ res = ERROR_INVALID_PARAMETER;
+ break;
+ }
+ va_end(ap);
+ return res;
+}
+
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+static UINT location_on_close(IWTSVirtualChannelCallback* pChannelCallback)
+{
+ UINT res = CHANNEL_RC_OK;
+ GENERIC_CHANNEL_CALLBACK* callback = (GENERIC_CHANNEL_CALLBACK*)pChannelCallback;
+
+ if (callback)
+ {
+ LOCATION_PLUGIN* plugin = (LOCATION_PLUGIN*)callback->plugin;
+ WINPR_ASSERT(plugin);
+
+ res = IFCALLRESULT(CHANNEL_RC_OK, plugin->context.LocationStop, &plugin->context);
+ }
+ free(callback);
+
+ return res;
+}
+
+static UINT location_init(GENERIC_DYNVC_PLUGIN* plugin, rdpContext* context, rdpSettings* settings)
+{
+ LOCATION_PLUGIN* loc = (LOCATION_PLUGIN*)plugin;
+
+ WINPR_ASSERT(loc);
+
+ loc->context.LocationSend = location_send;
+ loc->context.handle = loc;
+ plugin->iface.pInterface = &loc->context;
+ return CHANNEL_RC_OK;
+}
+
+static const IWTSVirtualChannelCallback location_callbacks = { location_on_data_received,
+ NULL, /* Open */
+ location_on_close, NULL };
+
+/**
+ * Function description
+ *
+ * @return 0 on success, otherwise a Win32 error code
+ */
+FREERDP_ENTRY_POINT(UINT location_DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints))
+{
+ return freerdp_generic_DVCPluginEntry(pEntryPoints, TAG, LOCATION_DVC_CHANNEL_NAME,
+ sizeof(LOCATION_PLUGIN), sizeof(LOCATION_CALLBACK),
+ &location_callbacks, location_init, NULL);
+}
diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c
index f0801e1..8f4d3c7 100644
--- a/channels/parallel/client/parallel_main.c
+++ b/channels/parallel/client/parallel_main.c
@@ -78,6 +78,10 @@ static UINT parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp)
{
char* path = NULL;
UINT32 PathLength = 0;
+
+ WINPR_ASSERT(parallel);
+ WINPR_ASSERT(irp);
+
if (!Stream_SafeSeek(irp->input, 28))
return ERROR_INVALID_DATA;
/* DesiredAccess(4) AllocationSize(8), FileAttributes(4) */
@@ -123,6 +127,9 @@ static UINT parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp)
*/
static UINT parallel_process_irp_close(PARALLEL_DEVICE* parallel, IRP* irp)
{
+ WINPR_ASSERT(parallel);
+ WINPR_ASSERT(irp);
+
if (close(parallel->file) < 0)
{
}
@@ -145,6 +152,10 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp)
UINT64 Offset = 0;
ssize_t status = 0;
BYTE* buffer = NULL;
+
+ WINPR_ASSERT(parallel);
+ WINPR_ASSERT(irp);
+
if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 12))
return ERROR_INVALID_DATA;
Stream_Read_UINT32(irp->input, Length);
@@ -201,6 +212,9 @@ static UINT parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp)
UINT64 Offset = 0;
ssize_t status = 0;
+ WINPR_ASSERT(parallel);
+ WINPR_ASSERT(irp);
+
if (!Stream_CheckAndLogRequiredLength(TAG, irp->input, 12))
return ERROR_INVALID_DATA;
@@ -240,6 +254,9 @@ static UINT parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp)
*/
static UINT parallel_process_irp_device_control(PARALLEL_DEVICE* parallel, IRP* irp)
{
+ WINPR_ASSERT(parallel);
+ WINPR_ASSERT(irp);
+
Stream_Write_UINT32(irp->output, 0); /* OutputBufferLength */
return irp->Complete(irp);
}
@@ -253,6 +270,9 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
{
UINT error = 0;
+ WINPR_ASSERT(parallel);
+ WINPR_ASSERT(irp);
+
switch (irp->MajorFunction)
{
case IRP_MJ_CREATE:
@@ -311,11 +331,10 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp)
static DWORD WINAPI parallel_thread_func(LPVOID arg)
{
- IRP* irp = NULL;
- wMessage message = { 0 };
PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*)arg;
UINT error = CHANNEL_RC_OK;
+ WINPR_ASSERT(parallel);
while (1)
{
if (!MessageQueue_Wait(parallel->queue))
@@ -325,6 +344,7 @@ static DWORD WINAPI parallel_thread_func(LPVOID arg)
break;
}
+ wMessage message = { 0 };
if (!MessageQueue_Peek(parallel->queue, &message, TRUE))
{
WLog_ERR(TAG, "MessageQueue_Peek failed!");
@@ -335,7 +355,7 @@ static DWORD WINAPI parallel_thread_func(LPVOID arg)
if (message.id == WMQ_QUIT)
break;
- irp = (IRP*)message.wParam;
+ IRP* irp = (IRP*)message.wParam;
if ((error = parallel_process_irp(parallel, irp)))
{
diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c
index 2aeb3f4..8d11f9b 100644
--- a/channels/printer/client/printer_main.c
+++ b/channels/printer/client/printer_main.c
@@ -62,6 +62,7 @@ typedef struct
HANDLE thread;
rdpContext* rdpcontext;
char port[64];
+ BOOL async;
} PRINTER_DEVICE;
typedef enum
@@ -684,8 +685,21 @@ static UINT printer_irp_request(DEVICE* device, IRP* irp)
WINPR_ASSERT(printer_dev);
WINPR_ASSERT(irp);
- InterlockedPushEntrySList(printer_dev->pIrpList, &(irp->ItemEntry));
- SetEvent(printer_dev->event);
+ if (printer_dev->async)
+ {
+ InterlockedPushEntrySList(printer_dev->pIrpList, &(irp->ItemEntry));
+ SetEvent(printer_dev->event);
+ }
+ else
+ {
+ UINT error = printer_process_irp(printer_dev, irp);
+ if (error)
+ {
+ WLog_ERR(TAG, "printer_process_irp failed with error %" PRIu32 "!", error);
+ return error;
+ }
+ }
+
return CHANNEL_RC_OK;
}
@@ -890,31 +904,34 @@ static UINT printer_free(DEVICE* device)
WINPR_ASSERT(printer_dev);
- SetEvent(printer_dev->stopEvent);
-
- if (WaitForSingleObject(printer_dev->thread, INFINITE) == WAIT_FAILED)
+ if (printer_dev->async)
{
- error = GetLastError();
- WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error);
+ SetEvent(printer_dev->stopEvent);
- /* The analyzer is confused by this premature return value.
- * Since this case can not be handled gracefully silence the
- * analyzer here. */
+ if (WaitForSingleObject(printer_dev->thread, INFINITE) == WAIT_FAILED)
+ {
+ error = GetLastError();
+ WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error);
+
+ /* The analyzer is confused by this premature return value.
+ * Since this case can not be handled gracefully silence the
+ * analyzer here. */
#ifndef __clang_analyzer__
- return error;
+ return error;
#endif
- }
+ }
- while ((irp = (IRP*)InterlockedPopEntrySList(printer_dev->pIrpList)) != NULL)
- {
- WINPR_ASSERT(irp->Discard);
- irp->Discard(irp);
- }
+ while ((irp = (IRP*)InterlockedPopEntrySList(printer_dev->pIrpList)) != NULL)
+ {
+ WINPR_ASSERT(irp->Discard);
+ irp->Discard(irp);
+ }
- CloseHandle(printer_dev->thread);
- CloseHandle(printer_dev->stopEvent);
- CloseHandle(printer_dev->event);
- winpr_aligned_free(printer_dev->pIrpList);
+ CloseHandle(printer_dev->thread);
+ CloseHandle(printer_dev->stopEvent);
+ CloseHandle(printer_dev->event);
+ winpr_aligned_free(printer_dev->pIrpList);
+ }
if (printer_dev->printer)
{
@@ -961,47 +978,62 @@ static UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrint
printer_dev->device.Free = printer_free;
printer_dev->rdpcontext = pEntryPoints->rdpcontext;
printer_dev->printer = printer;
- printer_dev->pIrpList = (WINPR_PSLIST_HEADER)winpr_aligned_malloc(sizeof(WINPR_SLIST_HEADER),
- MEMORY_ALLOCATION_ALIGNMENT);
- if (!printer_dev->pIrpList)
- {
- WLog_ERR(TAG, "_aligned_malloc failed!");
- error = CHANNEL_RC_NO_MEMORY;
- goto error_out;
- }
+ if (!freerdp_settings_get_bool(pEntryPoints->rdpcontext->settings,
+ FreeRDP_SynchronousStaticChannels))
+ printer_dev->async = TRUE;
if (!printer_load_from_config(pEntryPoints->rdpcontext->settings, printer, printer_dev))
goto error_out;
- InitializeSListHead(printer_dev->pIrpList);
-
- if (!(printer_dev->event = CreateEvent(NULL, TRUE, FALSE, NULL)))
+ if (printer_dev->async)
{
- WLog_ERR(TAG, "CreateEvent failed!");
- error = ERROR_INTERNAL_ERROR;
- goto error_out;
- }
+ printer_dev->pIrpList = (WINPR_PSLIST_HEADER)winpr_aligned_malloc(
+ sizeof(WINPR_SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT);
- if (!(printer_dev->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
- {
- WLog_ERR(TAG, "CreateEvent failed!");
- error = ERROR_INTERNAL_ERROR;
- goto error_out;
+ if (!printer_dev->pIrpList)
+ {
+ WLog_ERR(TAG, "_aligned_malloc failed!");
+ error = CHANNEL_RC_NO_MEMORY;
+ goto error_out;
+ }
+
+ InitializeSListHead(printer_dev->pIrpList);
+
+ printer_dev->event = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (!printer_dev->event)
+ {
+ WLog_ERR(TAG, "CreateEvent failed!");
+ error = ERROR_INTERNAL_ERROR;
+ goto error_out;
+ }
+
+ printer_dev->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if (!printer_dev->stopEvent)
+ {
+ WLog_ERR(TAG, "CreateEvent failed!");
+ error = ERROR_INTERNAL_ERROR;
+ goto error_out;
+ }
}
- if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, &printer_dev->device)))
+ error = pEntryPoints->RegisterDevice(pEntryPoints->devman, &printer_dev->device);
+ if (error)
{
WLog_ERR(TAG, "RegisterDevice failed with error %" PRIu32 "!", error);
goto error_out;
}
- if (!(printer_dev->thread =
- CreateThread(NULL, 0, printer_thread_func, (void*)printer_dev, 0, NULL)))
+ if (printer_dev->async)
{
- WLog_ERR(TAG, "CreateThread failed!");
- error = ERROR_INTERNAL_ERROR;
- goto error_out;
+ printer_dev->thread =
+ CreateThread(NULL, 0, printer_thread_func, (void*)printer_dev, 0, NULL);
+ if (!printer_dev->thread)
+ {
+ WLog_ERR(TAG, "CreateThread failed!");
+ error = ERROR_INTERNAL_ERROR;
+ goto error_out;
+ }
}
WINPR_ASSERT(printer->AddRef);
diff --git a/channels/printer/client/win/printer_win.c b/channels/printer/client/win/printer_win.c
index 9bd7589..7c62b40 100644
--- a/channels/printer/client/win/printer_win.c
+++ b/channels/printer/client/win/printer_win.c
@@ -136,7 +136,7 @@ static void printer_win_close_printjob(rdpPrintJob* printjob)
{
}
- if (!ClosePrinter(win_printer->hPrinter))
+ if (!EndDocPrinter(win_printer->hPrinter))
{
}
@@ -208,6 +208,9 @@ static void printer_win_free_printer(rdpPrinter* printer)
if (win_printer->printjob)
win_printer->printjob->printjob.Close((rdpPrintJob*)win_printer->printjob);
+ if (win_printer->hPrinter)
+ ClosePrinter(win_printer->hPrinter);
+
if (printer->backend)
printer->backend->ReleaseRef(printer->backend);
diff --git a/channels/rail/client/rail_orders.c b/channels/rail/client/rail_orders.c
index 7ac432e..b186eb3 100644
--- a/channels/rail/client/rail_orders.c
+++ b/channels/rail/client/rail_orders.c
@@ -469,6 +469,13 @@ static UINT rail_recv_handshake_ex_order(railPlugin* rail, wStream* s)
rail->channelBuildNumber = serverHandshake.buildNumber;
rail->channelFlags = serverHandshake.railHandshakeFlags;
+ {
+ char buffer[192] = { 0 };
+ WLog_DBG(TAG, "HandshakeFlags=%s [buildNumber=0x%08" PRIx32 "]",
+ rail_handshake_ex_flags_to_string(rail->channelFlags, buffer, sizeof(buffer)),
+ rail->channelBuildNumber);
+ }
+
if (rail->sendHandshake)
{
RAIL_HANDSHAKE_ORDER clientHandshake = { 0 };
diff --git a/channels/rail/rail_common.c b/channels/rail/rail_common.c
index fb6bc80..6deb968 100644
--- a/channels/rail/rail_common.c
+++ b/channels/rail/rail_common.c
@@ -589,3 +589,31 @@ BOOL rail_is_extended_spi_supported(UINT32 channelFlags)
{
return (channelFlags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_SUPPORTED) ? TRUE : FALSE;
}
+
+const char* rail_handshake_ex_flags_to_string(UINT32 flags, char* buffer, size_t len)
+{
+ if (len < 1)
+ return NULL;
+
+ _snprintf(buffer, len, "{");
+ char* fbuffer = &buffer[1];
+ len--;
+
+ if (flags & TS_RAIL_ORDER_HANDSHAKEEX_FLAGS_HIDEF)
+ winpr_str_append("HIDEF", fbuffer, len, "|");
+ if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_SUPPORTED)
+ winpr_str_append("EXTENDED_SPI_SUPPORTED", fbuffer, len, "|");
+ if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_SNAP_ARRANGE_SUPPORTED)
+ winpr_str_append("SNAP_ARRANGE_SUPPORTED", fbuffer, len, "|");
+ if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_TEXT_SCALE_SUPPORTED)
+ winpr_str_append("TEXT_SCALE_SUPPORTED", fbuffer, len, "|");
+ if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_CARET_BLINK_SUPPORTED)
+ winpr_str_append("CARET_BLINK_SUPPORTED", fbuffer, len, "|");
+ if (flags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_2_SUPPORTED)
+ winpr_str_append("EXTENDED_SPI_2_SUPPORTED", fbuffer, len, "|");
+
+ char number[16] = { 0 };
+ _snprintf(number, sizeof(number), "[0x%08" PRIx32 "]", flags);
+ winpr_str_append(number, buffer, len, "}");
+ return buffer;
+}
diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c
index 53f5011..2ffa951 100644
--- a/channels/rdpdr/client/rdpdr_main.c
+++ b/channels/rdpdr/client/rdpdr_main.c
@@ -1154,10 +1154,13 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr)
{
const char DynamicDrives[] = "DynamicDrives";
const RDPDR_DRIVE* drive = (const RDPDR_DRIVE*)device;
+ if (!drive->Path)
+ continue;
+
BOOL hotplugAll = strncmp(drive->Path, "*", 2) == 0;
BOOL hotplugLater = strncmp(drive->Path, DynamicDrives, sizeof(DynamicDrives)) == 0;
- if (drive->Path && (hotplugAll || hotplugLater))
+ if (hotplugAll || hotplugLater)
{
if (!rdpdr->async)
{
@@ -1274,7 +1277,6 @@ static UINT rdpdr_send_client_name_request(rdpdrPlugin* rdpdr)
WINPR_ASSERT(rdpdr->computerName);
computerNameW = ConvertUtf8ToWCharAlloc(rdpdr->computerName, &computerNameLenW);
computerNameLenW *= sizeof(WCHAR);
- WINPR_ASSERT(computerNameLenW >= 0);
if (computerNameLenW > 0)
computerNameLenW += sizeof(WCHAR); // also write '\0'
diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c
index bad6e23..f5353e3 100644
--- a/channels/rdpdr/server/rdpdr_main.c
+++ b/channels/rdpdr/server/rdpdr_main.c
@@ -2278,7 +2278,10 @@ static UINT rdpdr_server_send_device_create_request(RdpdrServerContext* context,
/* Convert the path to Unicode. */
if (Stream_Write_UTF16_String_From_UTF8(s, pathLength / sizeof(WCHAR), path,
pathLength / sizeof(WCHAR), TRUE) < 0)
+ {
+ Stream_Free(s, TRUE);
return ERROR_INTERNAL_ERROR;
+ }
return rdpdr_seal_send_free_request(context, s);
}
@@ -2418,7 +2421,10 @@ static UINT rdpdr_server_send_device_query_directory_request(RdpdrServerContext*
{
if (Stream_Write_UTF16_String_From_UTF8(s, pathLength / sizeof(WCHAR), path,
pathLength / sizeof(WCHAR), TRUE) < 0)
+ {
+ Stream_Free(s, TRUE);
return ERROR_INTERNAL_ERROR;
+ }
}
return rdpdr_seal_send_free_request(context, s);
@@ -2468,7 +2474,10 @@ static UINT rdpdr_server_send_device_file_rename_request(RdpdrServerContext* con
{
if (Stream_Write_UTF16_String_From_UTF8(s, pathLength / sizeof(WCHAR), path,
pathLength / sizeof(WCHAR), TRUE) < 0)
+ {
+ Stream_Free(s, TRUE);
return ERROR_INTERNAL_ERROR;
+ }
}
return rdpdr_seal_send_free_request(context, s);
diff --git a/channels/rdpecam/CMakeLists.txt b/channels/rdpecam/CMakeLists.txt
index 63ed410..220d586 100644
--- a/channels/rdpecam/CMakeLists.txt
+++ b/channels/rdpecam/CMakeLists.txt
@@ -20,3 +20,7 @@ define_channel("rdpecam")
if(WITH_SERVER_CHANNELS)
add_channel_server(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()
+
+if(WITH_CLIENT_CHANNELS)
+ add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
+endif()
diff --git a/channels/rdpecam/ChannelOptions.cmake b/channels/rdpecam/ChannelOptions.cmake
index 7528d11..b094e03 100644
--- a/channels/rdpecam/ChannelOptions.cmake
+++ b/channels/rdpecam/ChannelOptions.cmake
@@ -9,4 +9,5 @@ define_channel_options(NAME "rdpecam" TYPE "dynamic"
DEFAULT ${OPTION_DEFAULT})
define_channel_server_options(${OPTION_SERVER_DEFAULT})
+define_channel_client_options(${OPTION_CLIENT_DEFAULT})
diff --git a/channels/rdpecam/client/CMakeLists.txt b/channels/rdpecam/client/CMakeLists.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/channels/rdpecam/client/CMakeLists.txt
diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c
index dd59c8b..aeaa2de 100644
--- a/channels/rdpgfx/client/rdpgfx_main.c
+++ b/channels/rdpgfx/client/rdpgfx_main.c
@@ -2093,6 +2093,7 @@ static UINT rdpgfx_on_data_received(IWTSVirtualChannelCallback* pChannelCallback
if (status < 0)
{
WLog_Print(gfx->log, WLOG_ERROR, "zgfx_decompress failure! status: %d", status);
+ free(pDstData);
return ERROR_INTERNAL_ERROR;
}
diff --git a/channels/rdpsnd/client/alsa/rdpsnd_alsa.c b/channels/rdpsnd/client/alsa/rdpsnd_alsa.c
index 97f0ba0..9751bbe 100644
--- a/channels/rdpsnd/client/alsa/rdpsnd_alsa.c
+++ b/channels/rdpsnd/client/alsa/rdpsnd_alsa.c
@@ -57,14 +57,14 @@ typedef struct
snd_pcm_uframes_t period_size;
} rdpsndAlsaPlugin;
-#define SND_PCM_CHECK(_func, _status) \
- do \
- { \
- if (_status < 0) \
- { \
- WLog_ERR(TAG, "%s: %d\n", _func, _status); \
- return -1; \
- } \
+#define SND_PCM_CHECK(_func, _status) \
+ do \
+ { \
+ if ((_status) < 0) \
+ { \
+ WLog_ERR(TAG, "%s: %d\n", (_func), (_status)); \
+ return -1; \
+ } \
} while (0)
static int rdpsnd_alsa_set_hw_params(rdpsndAlsaPlugin* alsa)
diff --git a/channels/rdpsnd/client/oss/CMakeLists.txt b/channels/rdpsnd/client/oss/CMakeLists.txt
index 83bd59f..c495752 100644
--- a/channels/rdpsnd/client/oss/CMakeLists.txt
+++ b/channels/rdpsnd/client/oss/CMakeLists.txt
@@ -30,6 +30,12 @@ set(${MODULE_PREFIX}_LIBS
)
include_directories(..)
+include_directories(${CMAKE_CURRENT_BINARY_DIR})
include_directories(${OSS_INCLUDE_DIRS})
+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 "")
diff --git a/channels/rdpsnd/client/oss/rdpsnd_oss.c b/channels/rdpsnd/client/oss/rdpsnd_oss.c
index 54869ab..84105fd 100644
--- a/channels/rdpsnd/client/oss/rdpsnd_oss.c
+++ b/channels/rdpsnd/client/oss/rdpsnd_oss.c
@@ -37,11 +37,7 @@
#include <libgen.h>
#include <limits.h>
#include <unistd.h>
-#if defined(__OpenBSD__)
-#include <soundcard.h>
-#else
-#include <sys/soundcard.h>
-#endif
+#include <oss-includes.h>
#include <sys/ioctl.h>
#include <freerdp/types.h>
@@ -64,15 +60,15 @@ typedef struct
AUDIO_FORMAT format;
} rdpsndOssPlugin;
-#define OSS_LOG_ERR(_text, _error) \
- do \
- { \
- if (_error != 0) \
- { \
- char ebuffer[256] = { 0 }; \
- WLog_ERR(TAG, "%s: %i - %s", _text, _error, \
- winpr_strerror(_error, ebuffer, sizeof(ebuffer))); \
- } \
+#define OSS_LOG_ERR(_text, _error) \
+ do \
+ { \
+ if ((_error) != 0) \
+ { \
+ char ebuffer[256] = { 0 }; \
+ WLog_ERR(TAG, "%s: %i - %s", (_text), (_error), \
+ winpr_strerror((_error), ebuffer, sizeof(ebuffer))); \
+ } \
} while (0)
static int rdpsnd_oss_get_format(const AUDIO_FORMAT* format)
diff --git a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c
index 59b2076..2b09680 100644
--- a/channels/rdpsnd/client/pulse/rdpsnd_pulse.c
+++ b/channels/rdpsnd/client/pulse/rdpsnd_pulse.c
@@ -752,7 +752,7 @@ FREERDP_ENTRY_POINT(UINT pulse_freerdp_rdpsnd_client_subsystem_entry(
if (pa_threaded_mainloop_start(pulse->mainloop) < 0)
{
pa_threaded_mainloop_unlock(pulse->mainloop);
- return FALSE;
+ goto error;
}
pa_threaded_mainloop_unlock(pulse->mainloop);
diff --git a/channels/server/CMakeLists.txt b/channels/server/CMakeLists.txt
index 1f49c3b..8ffb184 100644
--- a/channels/server/CMakeLists.txt
+++ b/channels/server/CMakeLists.txt
@@ -30,11 +30,6 @@ endforeach()
add_library(${MODULE_NAME} STATIC ${${MODULE_PREFIX}_SRCS})
-if (WITH_LIBRARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION})
-endif()
-
-
set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr freerdp)
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} PARENT_SCOPE)
diff --git a/channels/urbdrc/client/data_transfer.c b/channels/urbdrc/client/data_transfer.c
index 7a7e5a2..56f3267 100644
--- a/channels/urbdrc/client/data_transfer.c
+++ b/channels/urbdrc/client/data_transfer.c
@@ -705,7 +705,10 @@ static UINT urb_control_transfer(IUDEVICE* pdev, GENERIC_CHANNEL_CALLBACK* callb
if (transferDir == USBD_TRANSFER_DIRECTION_OUT)
{
if (!Stream_CheckAndLogRequiredLength(TAG, s, OutputBufferSize))
+ {
+ Stream_Free(out, TRUE);
return ERROR_INVALID_DATA;
+ }
Stream_Copy(s, out, OutputBufferSize);
}
diff --git a/channels/urbdrc/client/libusb/libusb_udevice.c b/channels/urbdrc/client/libusb/libusb_udevice.c
index c226eb8..331adec 100644
--- a/channels/urbdrc/client/libusb/libusb_udevice.c
+++ b/channels/urbdrc/client/libusb/libusb_udevice.c
@@ -877,7 +877,7 @@ static UINT32 libusb_udev_control_query_device_text(IUDEVICE* idev, UINT32 TextT
* not honor strings with multi '\0' characters well.
*/
const size_t rchar = _wcsnlen((WCHAR*)&data[2], sizeof(data) / 2);
- len = MIN((BYTE)ret, slen);
+ len = MIN((BYTE)ret - 2, slen);
len = MIN(len, inSize);
len = MIN(len, rchar * 2 + sizeof(WCHAR));
memcpy(Buffer, &data[2], len);
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index fcb0d40..1a8f347 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -92,6 +92,11 @@ if(WITH_CLIENT)
endforeach()
endif()
+if (WITH_FUSE)
+ list(APPEND FREERDP_CLIENT_PC_PRIVATE_LIBS "-lfuse3")
+endif()
+
+list(JOIN FREERDP_CLIENT_PC_PRIVATE_LIBS " " FREERDP_CLIENT_PC_PRIVATE_LIBS)
include(pkg-config-install-prefix)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/freerdp-client.pc.in ${CMAKE_CURRENT_BINARY_DIR}/freerdp-client${FREERDP_VERSION_MAJOR}.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/freerdp-client${FREERDP_VERSION_MAJOR}.pc DESTINATION ${PKG_CONFIG_PC_INSTALL_DIR})
diff --git a/client/FreeRDP-ClientConfig.cmake.in b/client/FreeRDP-ClientConfig.cmake.in
index 35b74c1..409dbed 100644
--- a/client/FreeRDP-ClientConfig.cmake.in
+++ b/client/FreeRDP-ClientConfig.cmake.in
@@ -1,6 +1,9 @@
include(CMakeFindDependencyMacro)
find_dependency(WinPR @FREERDP_VERSION@)
find_dependency(FreeRDP @FREERDP_VERSION@)
+if("@WITH_SMARTCARD_EMULATE@")
+ find_dependency(ZLIB)
+endif()
@PACKAGE_INIT@
diff --git a/client/SDL/CMakeLists.txt b/client/SDL/CMakeLists.txt
index 6d2b778..0b3aa1b 100644
--- a/client/SDL/CMakeLists.txt
+++ b/client/SDL/CMakeLists.txt
@@ -46,7 +46,7 @@ option(WITH_WIN_CONSOLE "Build ${PROJECT_NAME} with console support" ON)
option(WITH_SDL_LINK_SHARED "link SDL dynamic or static" ON)
if(WITH_WIN_CONSOLE)
- set(WIN32_GUI_FLAG "")
+ set(WIN32_GUI_FLAG "TRUE")
else()
set(WIN32_GUI_FLAG "WIN32")
endif()
@@ -113,14 +113,8 @@ else()
list(APPEND LIBS ${SDL2_LIBRARIES})
endif()
-add_executable(${PROJECT_NAME}
- ${WIN32_GUI_FLAG}
- ${SRCS}
- )
+AddTargetWithResourceFile(${PROJECT_NAME} "${WIN32_GUI_FLAG}" "${PROJECT_VERSION}" SRCS)
-if (WITH_BINARY_VERSIONING)
- set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}${PROJECT_VERSION_MAJOR}")
-endif()
target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBS})
set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER "Client/SDL")
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)
diff --git a/client/SDL/dialogs/res/convert_res_to_c.cpp b/client/SDL/dialogs/res/convert_res_to_c.cpp
index 07309d5..8ef828a 100644
--- a/client/SDL/dialogs/res/convert_res_to_c.cpp
+++ b/client/SDL/dialogs/res/convert_res_to_c.cpp
@@ -79,6 +79,10 @@ static int readwrite(std::ofstream& out, std::ifstream& ifs)
{
size_t pos = 0;
char c = 0;
+
+ std::ios backup(nullptr);
+ backup.copyfmt(out);
+
while (ifs.read(&c, 1) && ifs.good())
{
unsigned val = c & 0xff;
@@ -89,6 +93,8 @@ static int readwrite(std::ofstream& out, std::ifstream& ifs)
out << std::endl;
}
+ out.copyfmt(backup);
+
return 0;
}
diff --git a/client/SDL/dialogs/res/sdl_resource_manager.cpp b/client/SDL/dialogs/res/sdl_resource_manager.cpp
index 90ccf31..0f0682a 100644
--- a/client/SDL/dialogs/res/sdl_resource_manager.cpp
+++ b/client/SDL/dialogs/res/sdl_resource_manager.cpp
@@ -49,7 +49,7 @@ SDL_RWops* SDLResourceManager::get(const std::string& type, const std::string& i
<< fs::absolute(path) << std::endl;
std::cerr << "file not found, application will fail" << std::endl;
}
- return SDL_RWFromFile(path.native().c_str(), "rb");
+ return SDL_RWFromFile(path.u8string().c_str(), "rb");
#endif
}
diff --git a/client/SDL/dialogs/sdl_connection_dialog.cpp b/client/SDL/dialogs/sdl_connection_dialog.cpp
index cbb6349..56c3853 100644
--- a/client/SDL/dialogs/sdl_connection_dialog.cpp
+++ b/client/SDL/dialogs/sdl_connection_dialog.cpp
@@ -164,6 +164,7 @@ bool SDLConnectionDialog::clearWindow(SDL_Renderer* renderer)
bool SDLConnectionDialog::update(SDL_Renderer* renderer)
{
+ std::lock_guard lock(_mux);
if (!renderer)
return false;
@@ -217,7 +218,7 @@ bool SDLConnectionDialog::handle(const SDL_Event& event)
case SDL_KEYUP:
if (visible())
{
- auto ev = reinterpret_cast<const SDL_KeyboardEvent&>(event);
+ auto& ev = reinterpret_cast<const SDL_KeyboardEvent&>(event);
update(_renderer);
switch (event.key.keysym.sym)
{
@@ -244,7 +245,7 @@ bool SDLConnectionDialog::handle(const SDL_Event& event)
case SDL_MOUSEMOTION:
if (visible())
{
- auto ev = reinterpret_cast<const SDL_MouseMotionEvent&>(event);
+ auto& ev = reinterpret_cast<const SDL_MouseMotionEvent&>(event);
_buttons.set_mouseover(event.button.x, event.button.y);
update(_renderer);
@@ -255,7 +256,7 @@ bool SDLConnectionDialog::handle(const SDL_Event& event)
case SDL_MOUSEBUTTONUP:
if (visible())
{
- auto ev = reinterpret_cast<const SDL_MouseButtonEvent&>(event);
+ auto& ev = reinterpret_cast<const SDL_MouseButtonEvent&>(event);
update(_renderer);
auto button = _buttons.get_selected(event.button);
@@ -274,7 +275,7 @@ bool SDLConnectionDialog::handle(const SDL_Event& event)
case SDL_MOUSEWHEEL:
if (visible())
{
- auto ev = reinterpret_cast<const SDL_MouseWheelEvent&>(event);
+ auto& ev = reinterpret_cast<const SDL_MouseWheelEvent&>(event);
update(_renderer);
return windowID == ev.windowID;
}
@@ -283,7 +284,7 @@ bool SDLConnectionDialog::handle(const SDL_Event& event)
case SDL_FINGERDOWN:
if (visible())
{
- auto ev = reinterpret_cast<const SDL_TouchFingerEvent&>(event);
+ auto& ev = reinterpret_cast<const SDL_TouchFingerEvent&>(event);
update(_renderer);
#if SDL_VERSION_ATLEAST(2, 0, 18)
return windowID == ev.windowID;
@@ -294,7 +295,7 @@ bool SDLConnectionDialog::handle(const SDL_Event& event)
return false;
case SDL_WINDOWEVENT:
{
- auto ev = reinterpret_cast<const SDL_WindowEvent&>(event);
+ auto& ev = reinterpret_cast<const SDL_WindowEvent&>(event);
switch (ev.event)
{
case SDL_WINDOWEVENT_CLOSE:
diff --git a/client/SDL/man/CMakeLists.txt b/client/SDL/man/CMakeLists.txt
index 1fb2adc..e2dfd7a 100644
--- a/client/SDL/man/CMakeLists.txt
+++ b/client/SDL/man/CMakeLists.txt
@@ -5,8 +5,4 @@ set(DEPS
sdl-freerdp-envvar.1.xml
)
-set(MANPAGE_NAME ${PROJECT_NAME})
-if (WITH_BINARY_VERSIONING)
- set(MANPAGE_NAME ${PROJECT_NAME}${PROJECT_VERSION_MAJOR})
-endif()
-generate_and_install_freerdp_man_from_xml(${PROJECT_NAME}.1 ${MANPAGE_NAME}.1 "${DEPS}")
+generate_and_install_freerdp_man_from_xml(${PROJECT_NAME} "1" "${FREERDP_API_VERSION}" "${DEPS}")
diff --git a/client/SDL/man/sdl-freerdp.1.xml.in b/client/SDL/man/sdl-freerdp.1.xml.in
index c4b9918..ba5b6cb 100644
--- a/client/SDL/man/sdl-freerdp.1.xml.in
+++ b/client/SDL/man/sdl-freerdp.1.xml.in
@@ -3,7 +3,6 @@
PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY syntax SYSTEM "freerdp-argument.1.xml">
- <!ENTITY channels SYSTEM "sdl-freerdp-channels.1.xml">
<!ENTITY config SYSTEM "sdl-freerdp-config.1.xml">
<!ENTITY envvar SYSTEM "sdl-freerdp-envvar.1.xml">
<!ENTITY examples SYSTEM "sdl-freerdp-examples.1.xml">
@@ -50,8 +49,6 @@ PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
&syntax;
- &channels;
-
&config;
&envvar;
diff --git a/client/SDL/sdl_freerdp.cpp b/client/SDL/sdl_freerdp.cpp
index 890bf77..b157d3d 100644
--- a/client/SDL/sdl_freerdp.cpp
+++ b/client/SDL/sdl_freerdp.cpp
@@ -1301,7 +1301,7 @@ terminate:
default:
{
std::lock_guard<CriticalSection> lock(sdl->critical);
- if (sdl->connection_dialog)
+ if (sdl->connection_dialog && error_msg)
sdl->connection_dialog->showError(error_msg);
}
break;
diff --git a/client/SDL/sdl_kbd.cpp b/client/SDL/sdl_kbd.cpp
index 4d62389..984614e 100644
--- a/client/SDL/sdl_kbd.cpp
+++ b/client/SDL/sdl_kbd.cpp
@@ -380,7 +380,7 @@ BOOL sdlInput::keyboard_set_ime_status(rdpContext* context, UINT16 imeId, UINT32
uint32_t sdlInput::prefToMask()
{
- const std::map<std::string, SDL_Keymod> mapping = {
+ const std::map<std::string, uint32_t> mapping = {
{ "KMOD_LSHIFT", KMOD_LSHIFT },
{ "KMOD_RSHIFT", KMOD_RSHIFT },
{ "KMOD_LCTRL", KMOD_LCTRL },
diff --git a/client/SDL/sdl_monitor.cpp b/client/SDL/sdl_monitor.cpp
index e637b48..c857028 100644
--- a/client/SDL/sdl_monitor.cpp
+++ b/client/SDL/sdl_monitor.cpp
@@ -189,7 +189,7 @@ static BOOL sdl_apply_display_properties(SdlContext* sdl)
for (UINT32 x = 0; x < numIds; x++)
{
- auto id = static_cast<const UINT32*>(
+ auto id = static_cast<const int*>(
freerdp_settings_get_pointer_array(settings, FreeRDP_MonitorIds, x));
WINPR_ASSERT(id);
@@ -198,8 +198,17 @@ static BOOL sdl_apply_display_properties(SdlContext* sdl)
float vdpi = 1.0f;
SDL_Rect rect = {};
- SDL_GetDisplayBounds(*id, &rect);
- SDL_GetDisplayDPI(*id, &ddpi, &hdpi, &vdpi);
+ if (SDL_GetDisplayBounds(*id, &rect) < 0)
+ return FALSE;
+
+ if (SDL_GetDisplayDPI(*id, &ddpi, &hdpi, &vdpi) < 0)
+ return FALSE;
+
+ WINPR_ASSERT(rect.w > 0);
+ WINPR_ASSERT(rect.h > 0);
+ WINPR_ASSERT(ddpi > 0);
+ WINPR_ASSERT(hdpi > 0);
+ WINPR_ASSERT(vdpi > 0);
bool highDpi = hdpi > 100;
diff --git a/client/SDL/sdl_window.cpp b/client/SDL/sdl_window.cpp
index c5437bc..1706d33 100644
--- a/client/SDL/sdl_window.cpp
+++ b/client/SDL/sdl_window.cpp
@@ -186,9 +186,9 @@ bool SdlWindow::blit(SDL_Surface* surface, const SDL_Rect& srcRect, SDL_Rect& ds
if (!screen || !surface)
return false;
if (!SDL_SetClipRect(surface, &srcRect))
- return false;
+ return true;
if (!SDL_SetClipRect(screen, &dstRect))
- return false;
+ return true;
auto rc = SDL_BlitScaled(surface, &srcRect, screen, &dstRect);
if (rc != 0)
{
diff --git a/client/Sample/CMakeLists.txt b/client/Sample/CMakeLists.txt
index db4e947..dfef11b 100644
--- a/client/Sample/CMakeLists.txt
+++ b/client/Sample/CMakeLists.txt
@@ -45,23 +45,7 @@ set(SRCS
tf_freerdp.h
tf_freerdp.c)
-# On windows create dll version information.
-# Vendor, product and year are already set in top level CMakeLists.txt
-if (WIN32)
- set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
- set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR})
- set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION})
- set (RC_VERSION_FILE "${PROJECT_NAME}${CMAKE_EXECUTABLE_SUFFIX}" )
-
- configure_file(
- ${PROJECT_SOURCE_DIR}/../../cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
-list (APPEND SRCS ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-endif()
-
-add_executable(${PROJECT_NAME} ${SRCS})
+AddTargetWithResourceFile(${PROJECT_NAME} TRUE "${PROJECT_VERSION}" SRCS)
set(LIBS
freerdp-client
@@ -70,8 +54,5 @@ set(LIBS
)
target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBS})
-if (WITH_BINARY_VERSIONING)
- set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}${PROJECT_VERSION_MAJOR}")
-endif()
set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER "Client/Sample")
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)
diff --git a/client/Wayland/CMakeLists.txt b/client/Wayland/CMakeLists.txt
index 7076ff1..41226ba 100644
--- a/client/Wayland/CMakeLists.txt
+++ b/client/Wayland/CMakeLists.txt
@@ -46,17 +46,11 @@ endif()
list (APPEND ${MODULE_PREFIX}_LIBS freerdp-client freerdp uwac)
-add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
+AddTargetWithResourceFile(${MODULE_NAME} TRUE ${FREERDP_VERSION} ${MODULE_PREFIX}_SRCS)
-set(MANPAGE_NAME ${MODULE_NAME})
-if (WITH_BINARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "${MODULE_NAME}${FREERDP_API_VERSION}")
- set(MANPAGE_NAME ${MODULE_NAME}${FREERDP_API_VERSION})
-endif()
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Wayland")
-configure_file(wlfreerdp.1.in ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE_NAME}.1)
-install_freerdp_man(${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE_NAME}.1 1)
+generate_and_install_freerdp_man_from_template(${MODULE_NAME} "1" "${FREERDP_API_VERSION}")
diff --git a/client/Wayland/wlf_cliprdr.c b/client/Wayland/wlf_cliprdr.c
index dc189d5..f0c3318 100644
--- a/client/Wayland/wlf_cliprdr.c
+++ b/client/Wayland/wlf_cliprdr.c
@@ -849,6 +849,7 @@ wlf_cliprdr_server_format_data_response(CliprdrClientContext* context,
ClipboardLock(clipboard->system);
EnterCriticalSection(&clipboard->lock);
+ BYTE* cdata = NULL;
UINT32 srcFormatId = 0;
UINT32 dstFormatId = 0;
switch (request->responseFormat)
@@ -895,14 +896,14 @@ wlf_cliprdr_server_format_data_response(CliprdrClientContext* context,
const BOOL sres = ClipboardSetData(clipboard->system, srcFormatId, data, size);
if (sres)
- data = ClipboardGetData(clipboard->system, dstFormatId, &len);
+ cdata = ClipboardGetData(clipboard->system, dstFormatId, &len);
- if (!sres || !data)
+ if (!sres || !cdata)
goto unlock;
if (request->responseFile)
{
- const size_t res = fwrite(data, 1, len, request->responseFile);
+ const size_t res = fwrite(cdata, 1, len, request->responseFile);
if (res == len)
rc = CHANNEL_RC_OK;
}
@@ -910,6 +911,7 @@ wlf_cliprdr_server_format_data_response(CliprdrClientContext* context,
rc = CHANNEL_RC_OK;
unlock:
+ free(cdata);
ClipboardUnlock(clipboard->system);
LeaveCriticalSection(&clipboard->lock);
fail:
diff --git a/client/Wayland/wlfreerdp.c b/client/Wayland/wlfreerdp.c
index 037c999..3007d41 100644
--- a/client/Wayland/wlfreerdp.c
+++ b/client/Wayland/wlfreerdp.c
@@ -224,29 +224,29 @@ static BOOL wl_pre_connect(freerdp* instance)
static BOOL wl_post_connect(freerdp* instance)
{
- rdpGdi* gdi = NULL;
- UwacWindow* window = NULL;
- wlfContext* context = NULL;
- rdpSettings* settings = NULL;
- char* title = "FreeRDP";
- char* app_id = "wlfreerdp";
- UINT32 w = 0;
- UINT32 h = 0;
-
if (!instance || !instance->context)
return FALSE;
- context = (wlfContext*)instance->context;
- settings = instance->context->settings;
+ wlfContext* context = (wlfContext*)instance->context;
+ WINPR_ASSERT(context);
+ rdpSettings* settings = instance->context->settings;
+ WINPR_ASSERT(settings);
+
+ const char* title = "FreeRDP";
const char* wtitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
if (wtitle)
title = wtitle;
+ const char* app_id = "wlfreerdp";
+ const char* wmclass = freerdp_settings_get_string(settings, FreeRDP_WmClass);
+ if (wmclass)
+ app_id = wmclass;
+
if (!gdi_init(instance, PIXEL_FORMAT_BGRA32))
return FALSE;
- gdi = instance->context->gdi;
+ rdpGdi* gdi = instance->context->gdi;
if (!gdi || (gdi->width < 0) || (gdi->height < 0))
return FALSE;
@@ -254,8 +254,8 @@ static BOOL wl_post_connect(freerdp* instance)
if (!wlf_register_pointer(instance->context->graphics))
return FALSE;
- w = (UINT32)gdi->width;
- h = (UINT32)gdi->height;
+ UINT32 w = (UINT32)gdi->width;
+ UINT32 h = (UINT32)gdi->height;
if (freerdp_settings_get_bool(settings, FreeRDP_SmartSizing) && !context->fullscreen)
{
@@ -268,15 +268,16 @@ static BOOL wl_post_connect(freerdp* instance)
h = sh;
}
- context->window = window = UwacCreateWindowShm(context->display, w, h, WL_SHM_FORMAT_XRGB8888);
+ context->window = UwacCreateWindowShm(context->display, w, h, WL_SHM_FORMAT_XRGB8888);
- if (!window)
+ if (!context->window)
return FALSE;
UwacWindowSetFullscreenState(
- window, NULL, freerdp_settings_get_bool(instance->context->settings, FreeRDP_Fullscreen));
- UwacWindowSetTitle(window, title);
- UwacWindowSetAppId(window, app_id);
+ context->window, NULL,
+ freerdp_settings_get_bool(instance->context->settings, FreeRDP_Fullscreen));
+ UwacWindowSetTitle(context->window, title);
+ UwacWindowSetAppId(context->window, app_id);
UwacWindowSetOpaqueRegion(context->window, 0, 0, w, h);
instance->context->update->EndPaint = wl_end_paint;
instance->context->update->DesktopResize = wl_resize_display;
diff --git a/client/X11/CMakeLists.txt b/client/X11/CMakeLists.txt
index 099d00d..bf7c842 100644
--- a/client/X11/CMakeLists.txt
+++ b/client/X11/CMakeLists.txt
@@ -21,7 +21,7 @@ if (NOT FREERDP_DEFAULT_PROJECT_VERSION)
set(FREERDP_DEFAULT_PROJECT_VERSION "1.0.0.0")
endif()
-project(xfreerdp
+project(xfreerdp-client
LANGUAGES C
VERSION ${FREERDP_DEFAULT_PROJECT_VERSION}
)
@@ -84,29 +84,14 @@ if (CHANNEL_TSMF_CLIENT)
)
endif()
-if(WITH_CLIENT_INTERFACE)
- if(CLIENT_INTERFACE_SHARED)
- add_library(${PROJECT_NAME} SHARED ${SRCS})
- if (WITH_LIBRARY_VERSIONING)
- set_target_properties(${PROJECT_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION})
- endif()
- else()
- add_library(${PROJECT_NAME} ${SRCS})
- endif()
- target_include_directories(${PROJECT_NAME} INTERFACE $<INSTALL_INTERFACE:include>)
-
+if(CLIENT_INTERFACE_SHARED)
+ AddTargetWithResourceFile(${PROJECT_NAME} "SHARED" "${PROJECT_VERSION}" SRCS)
else()
- list(APPEND SRCS
- cli/xfreerdp.c xfreerdp.h
- )
- add_executable(${PROJECT_NAME} ${SRCS})
- if (WITH_BINARY_VERSIONING)
- set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}${PROJECT_VERSION_MAJOR}")
- endif()
- include_directories(..)
+ AddTargetWithResourceFile(${PROJECT_NAME} "STATIC" "${PROJECT_VERSION}" SRCS)
endif()
+target_include_directories(${PROJECT_NAME} INTERFACE $<INSTALL_INTERFACE:include>)
-set(LIBS
+set(PRIV_LIBS
${X11_LIBRARIES}
)
@@ -116,7 +101,7 @@ find_package(X11 REQUIRED)
if(X11_XShm_FOUND)
add_definitions(-DWITH_XSHM)
include_directories(${X11_XShm_INCLUDE_PATH})
- list(APPEND LIBS
+ list(APPEND PRIV_LIBS
${X11_Xext_LIB}
)
endif()
@@ -128,7 +113,7 @@ if (WITH_XINERAMA)
if(X11_Xinerama_FOUND)
add_definitions(-DWITH_XINERAMA)
include_directories(${X11_Xinerama_INCLUDE_PATH})
- list(APPEND LIBS
+ list(APPEND PRIV_LIBS
${X11_Xinerama_LIB}
)
endif()
@@ -139,7 +124,7 @@ if (WITH_XEXT)
find_package(X11 REQUIRED)
if(X11_Xext_FOUND)
add_definitions(-DWITH_XEXT)
- list(APPEND LIBS
+ list(APPEND PRIV_LIBS
${X11_Xext_LIB}
)
endif()
@@ -151,7 +136,7 @@ if (WITH_XCURSOR)
if(X11_Xcursor_FOUND)
add_definitions(-DWITH_XCURSOR)
include_directories(${X11_Xcursor_INCLUDE_PATH})
- list(APPEND LIBS
+ list(APPEND PRIV_LIBS
${X11_Xcursor_LIB}
)
endif()
@@ -163,7 +148,7 @@ if (WITH_XV)
if(X11_Xv_FOUND)
add_definitions(-DWITH_XV)
include_directories(${X11_Xv_INCLUDE_PATH})
- list(APPEND LIBS
+ list(APPEND PRIV_LIBS
${X11_Xv_LIB}
)
endif()
@@ -175,7 +160,7 @@ if (WITH_XI)
if(X11_Xi_FOUND)
add_definitions(-DWITH_XI)
include_directories(${X11_Xi_INCLUDE_PATH})
- list(APPEND LIBS
+ list(APPEND PRIV_LIBS
${X11_Xi_LIB}
)
endif()
@@ -187,7 +172,7 @@ if(WITH_XRENDER)
if(X11_Xrender_FOUND)
add_definitions(-DWITH_XRENDER)
include_directories(${X11_Xrender_INCLUDE_PATH})
- list(APPEND LIBS
+ list(APPEND PRIV_LIBS
${X11_Xrender_LIB}
)
endif()
@@ -199,7 +184,7 @@ if (WITH_XRANDR)
if(X11_Xrandr_FOUND)
add_definitions(-DWITH_XRANDR)
include_directories(${X11_Xrandr_INCLUDE_PATH})
- list(APPEND LIBS
+ list(APPEND PRIV_LIBS
${X11_Xrandr_LIB}
)
endif()
@@ -211,7 +196,7 @@ if (WITH_XFIXES)
if(X11_Xfixes_FOUND)
add_definitions(-DWITH_XFIXES)
include_directories(${X11_Xfixes_INCLUDE_PATH})
- list(APPEND LIBS
+ list(APPEND PRIV_LIBS
${X11_Xfixes_LIB}
)
endif()
@@ -219,27 +204,23 @@ endif()
include_directories(${PROJECT_SOURCE_DIR}/resources)
-list(APPEND LIBS
+list(APPEND PUB_LIBS
freerdp-client
- freerdp
+)
+
+list(APPEND PRIV_LIBS
m
)
if (NOT APPLE)
- list(APPEND LIBS rt)
+ list(APPEND PRIV_LIBS rt)
endif()
-target_link_libraries(${PROJECT_NAME} PRIVATE ${LIBS})
+target_link_libraries(${PROJECT_NAME} PUBLIC ${PUB_LIBS})
+target_link_libraries(${PROJECT_NAME} PRIVATE ${PRIV_LIBS})
-if(WITH_IPP)
- target_link_libraries(${PROJECT_NAME} PRIVATE ${IPP_LIBRARY_LIST})
-endif()
-
-option(WITH_CLIENT_INTERFACE "Build clients as a library with an interface" OFF)
if(WITH_CLIENT_INTERFACE)
install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT libraries)
- add_subdirectory(cli)
-else()
- install(TARGETS ${PROJECT_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)
endif()
+add_subdirectory(cli)
set_property(TARGET ${PROJECT_NAME} PROPERTY FOLDER "Client/X11")
diff --git a/client/X11/cli/CMakeLists.txt b/client/X11/cli/CMakeLists.txt
index 580337b..0761b2f 100644
--- a/client/X11/cli/CMakeLists.txt
+++ b/client/X11/cli/CMakeLists.txt
@@ -15,32 +15,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-set(MODULE_NAME "xfreerdp-cli")
+set(MODULE_NAME "xfreerdp")
set(MODULE_PREFIX "FREERDP_CLIENT_X11")
set(SRCS
- xfreerdp.c
+ xfreerdp.c
)
-add_executable(${MODULE_NAME} ${SRCS})
-
-if (WITH_BINARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "xfreerdp${PROJECT_VERSION_MAJOR}")
-else()
- set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "xfreerdp")
-endif()
+AddTargetWithResourceFile(${MODULE_NAME} TRUE "${PROJECT_VERSION}" SRCS)
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "..")
list(APPEND LIBS
- xfreerdp-client freerdp-client
+ xfreerdp-client
)
-if(OPENBSD)
- list(APPEND LIBS
- ossaudio
- )
-endif()
-
target_link_libraries(${MODULE_NAME} PRIVATE ${LIBS})
install(TARGETS ${MODULE_NAME} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT client)
diff --git a/client/X11/cli/xfreerdp.c b/client/X11/cli/xfreerdp.c
index 33b2a96..4bdaf4c 100644
--- a/client/X11/cli/xfreerdp.c
+++ b/client/X11/cli/xfreerdp.c
@@ -31,6 +31,25 @@
#include "../xf_client.h"
#include "../xfreerdp.h"
+static void xfreerdp_print_help(void)
+{
+ printf("Keyboard Shortcuts:\n");
+ printf("\t<Right CTRL>\n");
+ printf("\t\treleases keyboard and mouse grab\n");
+ printf("\t<CTRL>+<ALT>+<Return>\n");
+ printf("\t\ttoggles fullscreen state of the application\n");
+ printf("\t<CTRL>+<ALT>+c\n");
+ printf("\t\ttoggles remote control in a remote assistance session\n");
+ printf("\tAction Script\n");
+ printf("\t\tExecutes a predefined script on key press.\n");
+ printf("\t\tShould the script not exist it is ignored.\n");
+ printf("\t\tScripts can be provided at the default localtion ~/.config/freerdp/action.sh or as "
+ "command line argument /action:script:<path>\n");
+ printf("\t\tThe script will receive the current key combination as argument.\n");
+ printf("\t\tThe output of the script is parsed for 'key-local' which tells that the script "
+ "used the key combination, otherwise the combination is forwarded to the remote.\n");
+}
+
int main(int argc, char* argv[])
{
int rc = 1;
@@ -59,6 +78,8 @@ int main(int argc, char* argv[])
{
rc = freerdp_client_settings_command_line_status_print(settings, status, argc, argv);
+ xfreerdp_print_help();
+
if (freerdp_settings_get_bool(settings, FreeRDP_ListMonitors))
xf_list_monitors(xfc);
diff --git a/client/X11/man/CMakeLists.txt b/client/X11/man/CMakeLists.txt
index 386f13d..ed50e63 100644
--- a/client/X11/man/CMakeLists.txt
+++ b/client/X11/man/CMakeLists.txt
@@ -1,11 +1,8 @@
set(DEPS
xfreerdp-channels.1.xml
xfreerdp-examples.1.xml
+ xfreerdp-shortcuts.1.xml
xfreerdp-envvar.1.xml
)
-set(MANPAGE_NAME ${PROJECT_NAME})
-if (WITH_BINARY_VERSIONING)
- set(MANPAGE_NAME ${PROJECT_NAME}${PROJECT_VERSION_MAJOR})
-endif()
-generate_and_install_freerdp_man_from_xml(${PROJECT_NAME}.1 ${MANPAGE_NAME}.1 ${DEPS})
+generate_and_install_freerdp_man_from_xml("xfreerdp" "1" "${FREERDP_API_VERSION}" ${DEPS})
diff --git a/client/X11/man/xfreerdp-shortcuts.1.xml b/client/X11/man/xfreerdp-shortcuts.1.xml
new file mode 100644
index 0000000..a6b96ea
--- /dev/null
+++ b/client/X11/man/xfreerdp-shortcuts.1.xml
@@ -0,0 +1,25 @@
+<refsect1>
+ <title>Keyboard Shortcuts</title>
+ <variablelist>
+ <varlistentry>
+ <term>&lt;Right CTRL&gt;</term>
+ <listitem><para>releases keyboard and mouse grab</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>&lt;CTRL&gt;+&lt;ALT&gt;+&lt;Return&gt;</term>
+ <listitem><para>toggles fullscreen state of the application</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>&lt;CTRL&gt;+&lt;ALT&gt;+c</term>
+ <listitem><para>toggles remote control in a remote assistance session</para></listitem>
+ </varlistentry>
+ <varlistentry>
+ <term>Action Script</term>
+ <listitem><para>executes a predefined script on key press.</para></listitem>
+ <listitem><para>Should the script not exist it is ignored.</para></listitem>
+ <listitem><para>Scripts can be provided at the default localtion ~/.config/freerdp/action.sh or as command line argument /action:script:&lt;path&gt;.</para></listitem>
+ <listitem><para>The script will receive the current key combination as argument.</para></listitem>
+ <listitem><para>The output of the script is parsed for key-local which tells that the script used the key combination, otherwise the combination is forwarded to the remote.</para></listitem>
+ </varlistentry>
+ </variablelist>
+</refsect1>
diff --git a/client/X11/man/xfreerdp.1.xml.in b/client/X11/man/xfreerdp.1.xml.in
index 271e39d..7e7c782 100644
--- a/client/X11/man/xfreerdp.1.xml.in
+++ b/client/X11/man/xfreerdp.1.xml.in
@@ -3,6 +3,7 @@
PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd" [
<!ENTITY syntax SYSTEM "freerdp-argument.1.xml">
+ <!ENTITY shortcuts SYSTEM "xfreerdp-shortcuts.1.xml">
<!ENTITY channels SYSTEM "xfreerdp-channels.1.xml">
<!ENTITY envvar SYSTEM "xfreerdp-envvar.1.xml">
<!ENTITY examples SYSTEM "xfreerdp-examples.1.xml">
@@ -49,6 +50,8 @@ PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
&syntax;
+ &shortcuts;
+
&channels;
&envvar;
diff --git a/client/X11/xf_client.c b/client/X11/xf_client.c
index 0f51745..7324bdc 100644
--- a/client/X11/xf_client.c
+++ b/client/X11/xf_client.c
@@ -1156,11 +1156,10 @@ static BOOL xf_pre_connect(freerdp* instance)
{
if (!xf_keyboard_init(xfc))
return FALSE;
+ if (!xf_detect_monitors(xfc, &maxWidth, &maxHeight))
+ return FALSE;
}
- if (!xf_detect_monitors(xfc, &maxWidth, &maxHeight))
- return FALSE;
-
if (maxWidth && maxHeight && !freerdp_settings_get_bool(settings, FreeRDP_SmartSizing))
{
if (!freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth, maxWidth))
diff --git a/client/X11/xf_cliprdr.c b/client/X11/xf_cliprdr.c
index a68dae9..de92b41 100644
--- a/client/X11/xf_cliprdr.c
+++ b/client/X11/xf_cliprdr.c
@@ -181,7 +181,7 @@ static xfCachedData* xf_cached_data_new(BYTE* data, UINT32 data_length)
return cached_data;
}
-static xfCachedData* xf_cached_data_new_copy(BYTE* data, UINT32 data_length)
+static xfCachedData* xf_cached_data_new_copy(const BYTE* data, size_t data_length)
{
BYTE* copy = NULL;
if (data_length > 0)
@@ -214,26 +214,28 @@ static void xf_clipboard_free_server_formats(xfClipboard* clipboard)
}
}
-static void xf_cliprdr_check_owner(xfClipboard* clipboard)
+static BOOL xf_cliprdr_update_owner(xfClipboard* clipboard)
{
- Window owner = 0;
- xfContext* xfc = NULL;
-
WINPR_ASSERT(clipboard);
- xfc = clipboard->xfc;
+ xfContext* xfc = clipboard->xfc;
WINPR_ASSERT(xfc);
- if (clipboard->sync)
- {
- owner = XGetSelectionOwner(xfc->display, clipboard->clipboard_atom);
+ if (!clipboard->sync)
+ return FALSE;
- if (clipboard->owner != owner)
- {
- clipboard->owner = owner;
- xf_cliprdr_send_client_format_list(clipboard, FALSE);
- }
- }
+ Window owner = XGetSelectionOwner(xfc->display, clipboard->clipboard_atom);
+ if (clipboard->owner == owner)
+ return FALSE;
+
+ clipboard->owner = owner;
+ return TRUE;
+}
+
+static void xf_cliprdr_check_owner(xfClipboard* clipboard)
+{
+ if (xf_cliprdr_update_owner(clipboard))
+ xf_cliprdr_send_client_format_list(clipboard, FALSE);
}
static BOOL xf_cliprdr_is_self_owned(xfClipboard* clipboard)
@@ -580,9 +582,11 @@ static CLIPRDR_FORMAT* xf_cliprdr_get_raw_server_formats(xfClipboard* clipboard,
WINPR_ASSERT(xfc);
*numFormats = 0;
- LogTagAndXGetWindowProperty(
- TAG, xfc->display, clipboard->owner, clipboard->raw_format_list_atom, 0, 4096, False,
- clipboard->raw_format_list_atom, &type, &format, &length, &remaining, &data);
+
+ Window owner = XGetSelectionOwner(xfc->display, clipboard->clipboard_atom);
+ LogTagAndXGetWindowProperty(TAG, xfc->display, owner, clipboard->raw_format_list_atom, 0, 4096,
+ False, clipboard->raw_format_list_atom, &type, &format, &length,
+ &remaining, &data);
if (data && length > 0 && format == 8 && type == clipboard->raw_format_list_atom)
{
diff --git a/client/X11/xf_event.c b/client/X11/xf_event.c
index 6bc4c4d..a00a950 100644
--- a/client/X11/xf_event.c
+++ b/client/X11/xf_event.c
@@ -41,10 +41,13 @@
#define TAG CLIENT_TAG("x11")
#define CLAMP_COORDINATES(x, y) \
- if (x < 0) \
- x = 0; \
- if (y < 0) \
- y = 0
+ do \
+ { \
+ if ((x) < 0) \
+ (x) = 0; \
+ if ((y) < 0) \
+ (y) = 0; \
+ } while (0)
const char* x11_event_string(int event)
{
@@ -201,7 +204,7 @@ BOOL xf_event_action_script_init(xfContext* xfc)
char* context = NULL;
strtok_s(buffer, "\n", &context);
- if (!buffer || !ArrayList_Append(xfc->xevents, buffer))
+ if (!ArrayList_Append(xfc->xevents, buffer))
{
pclose(actionScript);
ArrayList_Free(xfc->xevents);
@@ -447,7 +450,8 @@ static BOOL xf_event_MotionNotify(xfContext* xfc, const XMotionEvent* event, BOO
{
WINPR_ASSERT(xfc);
- if (xfc->xi_event)
+ if (xfc->xi_event ||
+ (xfc->common.mouse_grabbed && freerdp_client_use_relative_mouse_events(&xfc->common)))
return TRUE;
if (xfc->window)
@@ -556,7 +560,8 @@ static BOOL xf_event_ButtonPress(xfContext* xfc, const XButtonEvent* event, BOOL
{
xf_grab_mouse(xfc);
- if (xfc->xi_event)
+ if (xfc->xi_event ||
+ (xfc->common.mouse_grabbed && freerdp_client_use_relative_mouse_events(&xfc->common)))
return TRUE;
return xf_generic_ButtonEvent(xfc, event->x, event->y, event->button, event->window, app, TRUE);
}
@@ -565,7 +570,8 @@ static BOOL xf_event_ButtonRelease(xfContext* xfc, const XButtonEvent* event, BO
{
xf_grab_mouse(xfc);
- if (xfc->xi_event)
+ if (xfc->xi_event ||
+ (xfc->common.mouse_grabbed && freerdp_client_use_relative_mouse_events(&xfc->common)))
return TRUE;
return xf_generic_ButtonEvent(xfc, event->x, event->y, event->button, event->window, app,
FALSE);
@@ -645,6 +651,8 @@ static BOOL xf_event_FocusIn(xfContext* xfc, const XFocusInEvent* event, BOOL ap
* if the WM decided to use an alternate event order */
if (!app)
xf_keyboard_release_all_keypress(xfc);
+ else
+ xf_rail_send_activate(xfc, event->window, TRUE);
xf_pointer_update_scale(xfc);
@@ -673,6 +681,8 @@ static BOOL xf_event_FocusOut(xfContext* xfc, const XFocusOutEvent* event, BOOL
XUngrabKeyboard(xfc->display, CurrentTime);
xf_keyboard_release_all_keypress(xfc);
+ if (app)
+ xf_rail_send_activate(xfc, event->window, FALSE);
return TRUE;
}
diff --git a/client/X11/xf_input.c b/client/X11/xf_input.c
index f1cdc83..dfbe051 100644
--- a/client/X11/xf_input.c
+++ b/client/X11/xf_input.c
@@ -200,7 +200,7 @@ static BOOL register_raw_events(xfContext* xfc, Window window)
settings = xfc->common.context.settings;
WINPR_ASSERT(settings);
- if (freerdp_client_use_relative_mouse_events(&xfc->common))
+ if (freerdp_settings_get_bool(settings, FreeRDP_MouseUseRelativeMove))
{
XISetMask(mask_bytes, XI_RawMotion);
XISetMask(mask_bytes, XI_RawButtonPress);
@@ -780,21 +780,26 @@ int xf_input_event(xfContext* xfc, const XEvent* xevent, XIDeviceEvent* event, i
switch (evtype)
{
case XI_ButtonPress:
- xfc->xi_event = TRUE;
- xf_generic_ButtonEvent(xfc, (int)event->event_x, (int)event->event_y, event->detail,
- event->event, xfc->remote_app, TRUE);
- break;
-
case XI_ButtonRelease:
- xfc->xi_event = TRUE;
- xf_generic_ButtonEvent(xfc, (int)event->event_x, (int)event->event_y, event->detail,
- event->event, xfc->remote_app, FALSE);
+ xfc->xi_event = !xfc->common.mouse_grabbed ||
+ !freerdp_client_use_relative_mouse_events(&xfc->common);
+
+ if (xfc->xi_event)
+ {
+ xf_generic_ButtonEvent(xfc, (int)event->event_x, (int)event->event_y, event->detail,
+ event->event, xfc->remote_app, evtype == XI_ButtonPress);
+ }
break;
case XI_Motion:
- xfc->xi_event = TRUE;
- xf_generic_MotionNotify(xfc, (int)event->event_x, (int)event->event_y, event->detail,
- event->event, xfc->remote_app);
+ xfc->xi_event = !xfc->common.mouse_grabbed ||
+ !freerdp_client_use_relative_mouse_events(&xfc->common);
+
+ if (xfc->xi_event)
+ {
+ xf_generic_MotionNotify(xfc, (int)event->event_x, (int)event->event_y,
+ event->detail, event->event, xfc->remote_app);
+ }
break;
case XI_RawButtonPress:
case XI_RawButtonRelease:
diff --git a/client/X11/xf_keyboard.c b/client/X11/xf_keyboard.c
index 9b575c2..cfbd6ca 100644
--- a/client/X11/xf_keyboard.c
+++ b/client/X11/xf_keyboard.c
@@ -120,7 +120,7 @@ static BOOL xf_keyboard_action_script_init(xfContext* xfc)
char* context = NULL;
strtok_s(buffer, "\n", &context);
- if (!buffer || !ArrayList_Append(xfc->keyCombinations, buffer))
+ if (!ArrayList_Append(xfc->keyCombinations, buffer))
{
ArrayList_Free(xfc->keyCombinations);
xfc->actionScriptExists = FALSE;
@@ -180,7 +180,7 @@ void xf_keyboard_key_press(xfContext* xfc, const XKeyEvent* event, KeySym keysym
WINPR_ASSERT(xfc);
WINPR_ASSERT(event);
- WINPR_ASSERT(event->keycode <= ARRAYSIZE(xfc->KeyboardState));
+ WINPR_ASSERT(event->keycode < ARRAYSIZE(xfc->KeyboardState));
last = xfc->KeyboardState[event->keycode];
xfc->KeyboardState[event->keycode] = TRUE;
@@ -195,7 +195,7 @@ void xf_keyboard_key_release(xfContext* xfc, const XKeyEvent* event, KeySym keys
{
WINPR_ASSERT(xfc);
WINPR_ASSERT(event);
- WINPR_ASSERT(event->keycode <= ARRAYSIZE(xfc->KeyboardState));
+ WINPR_ASSERT(event->keycode < ARRAYSIZE(xfc->KeyboardState));
BOOL last = xfc->KeyboardState[event->keycode];
xfc->KeyboardState[event->keycode] = FALSE;
@@ -555,11 +555,11 @@ BOOL xf_keyboard_handle_special_keys(xfContext* xfc, KeySym keysym)
// do not return anything such that the key could be used by client if ungrab is not the goal
if (keysym == XK_Control_R)
{
- if (mod.RightCtrl && xfc->firstPressRightCtrl)
+ if (mod.RightCtrl && !xfc->wasRightCtrlAlreadyPressed)
{
// Right Ctrl is pressed, getting ready to ungrab
xfc->ungrabKeyboardWithRightCtrl = TRUE;
- xfc->firstPressRightCtrl = FALSE;
+ xfc->wasRightCtrlAlreadyPressed = TRUE;
}
}
else
@@ -689,7 +689,7 @@ void xf_keyboard_handle_special_keys_release(xfContext* xfc, KeySym keysym)
if (keysym != XK_Control_R)
return;
- xfc->firstPressRightCtrl = TRUE;
+ xfc->wasRightCtrlAlreadyPressed = FALSE;
if (!xfc->ungrabKeyboardWithRightCtrl)
return;
diff --git a/client/X11/xf_window.c b/client/X11/xf_window.c
index a5e68c7..1d7330d 100644
--- a/client/X11/xf_window.c
+++ b/client/X11/xf_window.c
@@ -562,6 +562,7 @@ xfWindow* xf_CreateDesktopWindow(xfContext* xfc, char* name, int width, int heig
else
res_class = _strdup("xfreerdp");
+ classHints->res_class = res_class;
XSetClassHint(xfc->display, window->handle, classHints);
XFree(classHints);
free(res_class);
diff --git a/client/X11/xfreerdp.h b/client/X11/xfreerdp.h
index 314c63d..42a2224 100644
--- a/client/X11/xfreerdp.h
+++ b/client/X11/xfreerdp.h
@@ -277,7 +277,7 @@ struct xf_context
button_map button_map[NUM_BUTTONS_MAPPED];
BYTE savedMaximizedState;
UINT32 locked;
- BOOL firstPressRightCtrl;
+ BOOL wasRightCtrlAlreadyPressed;
BOOL ungrabKeyboardWithRightCtrl;
#if defined(WITH_XI)
diff --git a/client/common/CMakeLists.txt b/client/common/CMakeLists.txt
index 6040bf3..1773533 100644
--- a/client/common/CMakeLists.txt
+++ b/client/common/CMakeLists.txt
@@ -58,30 +58,9 @@ if(WITH_FUSE)
add_definitions(-D_FILE_OFFSET_BITS=64)
endif()
-# On windows create dll version information.
-# Vendor, product and year are already set in top level CMakeLists.txt
-if (WIN32 AND BUILD_SHARED_LIBS)
- set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
- set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR})
- set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION})
- set (RC_VERSION_FILE "${CMAKE_SHARED_LIBRARY_PREFIX}${MODULE_NAME}${FREERDP_API_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}" )
-
- configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
-list (APPEND SRCS ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-endif()
-
include_directories(${OPENSSL_INCLUDE_DIR})
-add_library(${MODULE_NAME} ${SRCS})
-
-set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME ${MODULE_NAME}${FREERDP_API_VERSION})
-if (WITH_LIBRARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION})
-endif()
+AddTargetWithResourceFile(${MODULE_NAME} FALSE "${FREERDP_VERSION}" SRCS)
list(APPEND LIBS freerdp winpr)
@@ -94,11 +73,6 @@ install(TARGETS ${MODULE_NAME} COMPONENT libraries EXPORT FreeRDP-ClientTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-if (WITH_DEBUG_SYMBOLS AND MSVC AND BUILD_SHARED_LIBS)
- get_target_property(OUTPUT_FILENAME ${MODULE_NAME} OUTPUT_NAME)
- install(FILES ${CMAKE_PDB_BINARY_DIR}/${OUTPUT_FILENAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT symbols)
-endif()
-
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Common")
if(BUILD_TESTING)
diff --git a/client/common/client.c b/client/common/client.c
index 9d6ec03..83a5746 100644
--- a/client/common/client.c
+++ b/client/common/client.c
@@ -1574,8 +1574,9 @@ BOOL freerdp_client_send_button_event(rdpClientContext* cctx, BOOL relative, UIN
WINPR_ASSERT(cctx);
- const BOOL relativeInput = freerdp_client_use_relative_mouse_events(cctx);
- if (relative && relativeInput)
+ const BOOL haveRelative =
+ freerdp_settings_get_bool(cctx->context.settings, FreeRDP_HasRelativeMouseEvent);
+ if (relative && haveRelative)
{
return freerdp_input_send_rel_mouse_event(cctx->context.input, mflags, x, y);
}
@@ -1585,7 +1586,7 @@ BOOL freerdp_client_send_button_event(rdpClientContext* cctx, BOOL relative, UIN
{
UINT64 flags = 0;
- if (cctx->mouse_grabbed && relativeInput)
+ if (cctx->mouse_grabbed && freerdp_client_use_relative_mouse_events(cctx))
flags |= AINPUT_FLAGS_HAVE_REL;
if (relative)
@@ -1630,7 +1631,9 @@ BOOL freerdp_client_send_extended_button_event(rdpClientContext* cctx, BOOL rela
BOOL handled = FALSE;
WINPR_ASSERT(cctx);
- if (relative && freerdp_client_use_relative_mouse_events(cctx))
+ const BOOL haveRelative =
+ freerdp_settings_get_bool(cctx->context.settings, FreeRDP_HasRelativeMouseEvent);
+ if (relative && haveRelative)
{
return freerdp_input_send_rel_mouse_event(cctx->context.input, mflags, x, y);
}
@@ -2147,8 +2150,8 @@ BOOL freerdp_client_use_relative_mouse_events(rdpClientContext* ccontext)
const rdpSettings* settings = ccontext->context.settings;
const BOOL useRelative = freerdp_settings_get_bool(settings, FreeRDP_MouseUseRelativeMove);
const BOOL haveRelative = freerdp_settings_get_bool(settings, FreeRDP_HasRelativeMouseEvent);
- BOOL ainput = false;
-#if defined(CHANNEL_AINPUT_SERVER)
+ BOOL ainput = FALSE;
+#if defined(CHANNEL_AINPUT_CLIENT)
ainput = ccontext->ainput != NULL;
#endif
diff --git a/client/common/client_cliprdr_file.c b/client/common/client_cliprdr_file.c
index 9b3ee22..df9226f 100644
--- a/client/common/client_cliprdr_file.c
+++ b/client/common/client_cliprdr_file.c
@@ -353,7 +353,6 @@ static BOOL maybe_clear_fuse_request(const void* key, void* value, void* arg)
fuse_reply_err(fuse_request->fuse_req, EIO);
HashTable_Remove(file_context->request_table, key);
- free(fuse_request);
return TRUE;
}
@@ -505,16 +504,15 @@ static void clear_no_cdi_entry(CliprdrFileContext* file_context)
{
WINPR_ASSERT(file_context);
- if (!file_context->clip_data_entry_without_id)
- return;
-
WINPR_ASSERT(file_context->inode_table);
-
HashTable_Lock(file_context->inode_table);
- clear_entry_selection(file_context->clip_data_entry_without_id);
+ if (file_context->clip_data_entry_without_id)
+ {
+ clear_entry_selection(file_context->clip_data_entry_without_id);
- clip_data_entry_free(file_context->clip_data_entry_without_id);
- file_context->clip_data_entry_without_id = NULL;
+ clip_data_entry_free(file_context->clip_data_entry_without_id);
+ file_context->clip_data_entry_without_id = NULL;
+ }
HashTable_Unlock(file_context->inode_table);
}
@@ -555,6 +553,7 @@ static UINT prepare_clip_data_entry_with_id(CliprdrFileContext* file_context)
{
WLog_Print(file_context->log, WLOG_ERROR, "Failed to insert clipDataEntry");
clip_data_entry_free(clip_data_entry);
+ HashTable_Unlock(file_context->inode_table);
return ERROR_INTERNAL_ERROR;
}
HashTable_Unlock(file_context->inode_table);
@@ -748,7 +747,6 @@ static BOOL request_file_size_async(CliprdrFileContext* file_context, CliprdrFus
"Failed to send FileContentsRequest for file \"%s\"",
fuse_file->filename_with_root);
HashTable_Remove(file_context->request_table, (void*)(UINT_PTR)fuse_request->stream_id);
- free(fuse_request);
return FALSE;
}
DEBUG_CLIPRDR(file_context->log, "Requested file size for file \"%s\" with stream id %u",
@@ -1191,18 +1189,17 @@ static UINT cliprdr_file_context_server_file_contents_response(
HashTable_Unlock(file_context->inode_table);
return CHANNEL_RC_OK;
}
- HashTable_Remove(file_context->request_table,
- (void*)(UINT_PTR)file_contents_response->streamId);
if (!(file_contents_response->common.msgFlags & CB_RESPONSE_OK))
{
WLog_Print(file_context->log, WLOG_WARN,
"FileContentsRequests for file \"%s\" was unsuccessful",
fuse_request->fuse_file->filename);
- HashTable_Unlock(file_context->inode_table);
fuse_reply_err(fuse_request->fuse_req, EIO);
- free(fuse_request);
+ HashTable_Remove(file_context->request_table,
+ (void*)(UINT_PTR)file_contents_response->streamId);
+ HashTable_Unlock(file_context->inode_table);
return CHANNEL_RC_OK;
}
@@ -1213,10 +1210,10 @@ static UINT cliprdr_file_context_server_file_contents_response(
WLog_Print(file_context->log, WLOG_WARN,
"Received invalid file size for file \"%s\" from the client",
fuse_request->fuse_file->filename);
- HashTable_Unlock(file_context->inode_table);
-
fuse_reply_err(fuse_request->fuse_req, EIO);
- free(fuse_request);
+ HashTable_Remove(file_context->request_table,
+ (void*)(UINT_PTR)file_contents_response->streamId);
+ HashTable_Unlock(file_context->inode_table);
return CHANNEL_RC_OK;
}
@@ -1258,7 +1255,8 @@ static UINT cliprdr_file_context_server_file_contents_response(
break;
}
- free(fuse_request);
+ HashTable_Remove(file_context->request_table,
+ (void*)(UINT_PTR)file_contents_response->streamId);
return CHANNEL_RC_OK;
}
@@ -1806,7 +1804,7 @@ static CliprdrFuseFile* get_parent_directory(CliprdrFileContext* file_context, c
static BOOL set_selection_for_clip_data_entry(CliprdrFileContext* file_context,
CliprdrFuseClipDataEntry* clip_data_entry,
- FILEDESCRIPTORW* files, UINT32 n_files)
+ const FILEDESCRIPTORW* files, UINT32 n_files)
{
CliprdrFuseFile* clip_data_dir = NULL;
@@ -1826,7 +1824,7 @@ static BOOL set_selection_for_clip_data_entry(CliprdrFileContext* file_context,
// NOLINTBEGIN(clang-analyzer-unix.Malloc) HashTable_Insert owns fuse_file
for (UINT32 i = 0; i < n_files; ++i)
{
- FILEDESCRIPTORW* file = &files[i];
+ const FILEDESCRIPTORW* file = &files[i];
CliprdrFuseFile* fuse_file = NULL;
char* filename = NULL;
size_t path_length = 0;
@@ -2016,6 +2014,7 @@ BOOL cliprdr_file_context_update_server_data(CliprdrFileContext* file_context, w
}
HashTable_Unlock(file_context->inode_table);
+ free(files);
return TRUE;
#else
return FALSE;
@@ -2417,9 +2416,16 @@ CliprdrFileContext* cliprdr_file_context_new(void* context)
if (!file->inode_table || !file->clip_data_table || !file->request_table)
goto fail;
- wObject* ctobj = HashTable_ValueObject(file->clip_data_table);
- WINPR_ASSERT(ctobj);
- ctobj->fnObjectFree = clip_data_entry_free;
+ {
+ wObject* ctobj = HashTable_ValueObject(file->request_table);
+ WINPR_ASSERT(ctobj);
+ ctobj->fnObjectFree = free;
+ }
+ {
+ wObject* ctobj = HashTable_ValueObject(file->clip_data_table);
+ WINPR_ASSERT(ctobj);
+ ctobj->fnObjectFree = clip_data_entry_free;
+ }
file->root_dir = fuse_file_new_root(file);
if (!file->root_dir)
diff --git a/client/common/cmdline.c b/client/common/cmdline.c
index 2ce693b..01d5b37 100644
--- a/client/common/cmdline.c
+++ b/client/common/cmdline.c
@@ -214,18 +214,20 @@ static BOOL freerdp_client_add_drive(rdpSettings* settings, const char* path, co
if (!path)
goto fail;
- else
+
{
BOOL isSpecial = FALSE;
BOOL isPath = freerdp_path_valid(path, &isSpecial);
if (!isPath && !isSpecial)
+ {
+ WLog_WARN(TAG, "Invalid drive to redirect: '%s' does not exist, skipping.", path);
+ freerdp_device_free(device);
+ }
+ else if (!freerdp_device_collection_add(settings, device))
goto fail;
}
- if (!freerdp_device_collection_add(settings, device))
- goto fail;
-
return TRUE;
fail:
@@ -370,7 +372,7 @@ static char* print_token(char* text, size_t start_offset, size_t* current, size_
const size_t tlen = strnlen(text, limit);
size_t len = tlen;
const SSIZE_T force_at = forced_newline_at(text, len, limit - *current, force_newline);
- BOOL isForce = (force_at > 0);
+ BOOL isForce = (force_at >= 0);
if (isForce)
len = MIN(len, (size_t)force_at);
@@ -394,7 +396,7 @@ static char* print_token(char* text, size_t start_offset, size_t* current, size_
printf("\n");
*current = 0;
- const size_t offset = len + (isForce ? 1 : 0);
+ const size_t offset = len + ((isForce && (force_at == 0)) ? 1 : 0);
return &text[offset];
}
@@ -411,8 +413,10 @@ static size_t print_optionals(const char* text, size_t start_offset, size_t curr
char* str = _strdup(text);
char* cur = str;
- while ((cur = print_token(cur, start_offset + 1, &current, limit, "[], ", "\r\n")) != NULL)
- ;
+ do
+ {
+ cur = print_token(cur, start_offset + 1, &current, limit, "[], ", "\r\n");
+ } while (cur != NULL);
free(str);
return current;
@@ -424,8 +428,10 @@ static size_t print_description(const char* text, size_t start_offset, size_t cu
char* str = _strdup(text);
char* cur = str;
- while ((cur = print_token(cur, start_offset, &current, limit, " ", "\r\n")) != NULL)
- ;
+ do
+ {
+ cur = print_token(cur, start_offset, &current, limit, " ", "\r\n");
+ } while (cur != NULL);
free(str);
current += (size_t)printf("\n");
@@ -895,7 +901,10 @@ static BOOL read_pem_file(rdpSettings* settings, FreeRDP_Settings_Keys_String id
size_t length = 0;
char* pem = crypto_read_pem(file, &length);
if (!pem || (length == 0))
+ {
+ free(pem);
return FALSE;
+ }
BOOL rc = freerdp_settings_set_string_len(settings, id, pem, length);
free(pem);
@@ -1167,6 +1176,14 @@ static int freerdp_client_command_line_post_filter(void* context, COMMAND_LINE_A
static BOOL freerdp_parse_username_ptr(const char* username, const char** user, size_t* userlen,
const char** domain, size_t* domainlen)
{
+ WINPR_ASSERT(user);
+ WINPR_ASSERT(userlen);
+ WINPR_ASSERT(domain);
+ WINPR_ASSERT(domainlen);
+
+ if (!username)
+ return FALSE;
+
const char* p = strchr(username, '\\');
*user = NULL;
@@ -1184,7 +1201,7 @@ static BOOL freerdp_parse_username_ptr(const char* username, const char** user,
*domain = username;
*domainlen = length;
}
- else if (username)
+ else
{
/* Do not break up the name for '@'; both credSSP and the
* ClientInfo PDU expect 'user@corp.net' to be transmitted
@@ -1193,8 +1210,6 @@ static BOOL freerdp_parse_username_ptr(const char* username, const char** user,
*user = username;
*userlen = strlen(username);
}
- else
- return FALSE;
return TRUE;
}
@@ -1382,24 +1397,27 @@ BOOL freerdp_set_connection_type(rdpSettings* settings, UINT32 type)
static UINT32 freerdp_get_keyboard_layout_for_type(const char* name, DWORD type)
{
+ UINT32 res = 0;
size_t count = 0;
RDP_KEYBOARD_LAYOUT* layouts =
freerdp_keyboard_get_layouts(RDP_KEYBOARD_LAYOUT_TYPE_STANDARD, &count);
if (!layouts || (count == 0))
- return FALSE;
+ goto fail;
for (size_t x = 0; x < count; x++)
{
const RDP_KEYBOARD_LAYOUT* layout = &layouts[x];
if (option_equals(layout->name, name))
{
- return layout->code;
+ res = layout->code;
+ break;
}
}
+fail:
freerdp_keyboard_layouts_free(layouts, count);
- return 0;
+ return res;
}
static UINT32 freerdp_map_keyboard_layout_name_to_id(const char* name)
@@ -2308,7 +2326,8 @@ static int parse_codec_cache_options(rdpSettings* settings, const COMMAND_LINE_A
}
else if (option_equals(arg->Value, "nsc"))
{
- freerdp_settings_set_bool(settings, FreeRDP_NSCodec, TRUE);
+ if (!freerdp_settings_set_bool(settings, FreeRDP_NSCodec, TRUE))
+ return COMMAND_LINE_ERROR;
}
#if defined(WITH_JPEG)
@@ -2325,6 +2344,7 @@ static int parse_codec_cache_options(rdpSettings* settings, const COMMAND_LINE_A
}
#endif
+ return 0;
}
#endif
@@ -3576,18 +3596,18 @@ static int parse_app_options(rdpSettings* settings, const COMMAND_LINE_ARGUMENT_
struct app_map
{
const char* name;
- FreeRDP_Settings_Keys_String id;
+ SSIZE_T id;
int (*fkt)(rdpSettings* settings, const char* value);
};
- const struct app_map amap[] = {
- { "program:", FreeRDP_RemoteApplicationProgram, parse_app_option_program },
- { "workdir:", FreeRDP_RemoteApplicationWorkingDir, NULL },
- { "name:", FreeRDP_RemoteApplicationName, NULL },
- { "icon:", FreeRDP_RemoteApplicationIcon, NULL },
- { "cmd:", FreeRDP_RemoteApplicationCmdLine, NULL },
- { "file:", FreeRDP_RemoteApplicationFile, NULL },
- { "guid:", FreeRDP_RemoteApplicationGuid, NULL },
- };
+ const struct app_map amap[] = { { "program:", FreeRDP_RemoteApplicationProgram,
+ parse_app_option_program },
+ { "workdir:", FreeRDP_RemoteApplicationWorkingDir, NULL },
+ { "name:", FreeRDP_RemoteApplicationName, NULL },
+ { "icon:", FreeRDP_RemoteApplicationIcon, NULL },
+ { "cmd:", FreeRDP_RemoteApplicationCmdLine, NULL },
+ { "file:", FreeRDP_RemoteApplicationFile, NULL },
+ { "guid:", FreeRDP_RemoteApplicationGuid, NULL },
+ { "hidef:", FreeRDP_HiDefRemoteApp, NULL } };
for (size_t x = 0; x < count; x++)
{
BOOL handled = FALSE;
@@ -3601,8 +3621,12 @@ static int parse_app_options(rdpSettings* settings, const COMMAND_LINE_ARGUMENT_
const char* xval = &val[strlen(cur->name)];
if (cur->fkt)
rc = cur->fkt(settings, xval);
- else if (!freerdp_settings_set_string(settings, cur->id, xval))
- rc = COMMAND_LINE_ERROR_MEMORY;
+ else
+ {
+ const char* name = freerdp_settings_get_name_for_key(cur->id);
+ if (!freerdp_settings_set_value_for_name(settings, name, xval))
+ rc = COMMAND_LINE_ERROR_MEMORY;
+ }
handled = TRUE;
break;
@@ -4749,11 +4773,14 @@ static int freerdp_client_settings_parse_command_line_arguments_int(
"vs-debug") ||
!freerdp_settings_set_string(settings, FreeRDP_ServerHostname, "localhost") ||
!freerdp_settings_set_string(settings, FreeRDP_AuthenticationPackageList, "ntlm") ||
+ !freerdp_settings_set_string(settings, FreeRDP_ClientAddress, "0.0.0.0") ||
!freerdp_settings_set_bool(settings, FreeRDP_NegotiateSecurityLayer, FALSE) ||
!freerdp_settings_set_bool(settings, FreeRDP_VmConnectMode, TRUE) ||
!freerdp_settings_set_bool(settings, FreeRDP_ConnectChildSession, TRUE) ||
!freerdp_settings_set_bool(settings, FreeRDP_NlaSecurity, TRUE) ||
- !freerdp_settings_set_uint32(settings, FreeRDP_AuthenticationLevel, 0))
+ !freerdp_settings_set_uint32(settings, FreeRDP_AuthenticationLevel, 0) ||
+ !freerdp_settings_set_bool(settings, FreeRDP_NetworkAutoDetect, TRUE) ||
+ !freerdp_settings_set_uint32(settings, FreeRDP_ConnectionType, CONNECTION_TYPE_LAN))
return COMMAND_LINE_ERROR_MEMORY;
}
#endif
diff --git a/client/common/cmdline.h b/client/common/cmdline.h
index 8186cc6..3afddb1 100644
--- a/client/common/cmdline.h
+++ b/client/common/cmdline.h
@@ -34,7 +34,7 @@ static const COMMAND_LINE_ARGUMENT_A global_cmd_args[] = {
"desktop composition" },
{ "app", COMMAND_LINE_VALUE_REQUIRED,
"program:[<path>|<||alias>],cmd:<command>,file:<filename>,guid:<guid>,icon:<filename>,name:<"
- "name>,workdir:<directory>",
+ "name>,workdir:<directory>,hidef:[on|off]",
NULL, NULL, -1, NULL, "Remote application program" },
#if defined(WITH_FREERDP_DEPRECATED_COMMANDLINE)
{ "app-cmd", COMMAND_LINE_VALUE_REQUIRED, "<parameters>", NULL, NULL, -1, NULL,
diff --git a/client/common/file.c b/client/common/file.c
index 760c62e..a72ab41 100644
--- a/client/common/file.c
+++ b/client/common/file.c
@@ -1309,7 +1309,7 @@ BOOL freerdp_client_populate_rdp_file_from_settings(rdpFile* file, const rdpSett
file->RedirectComPorts = (freerdp_settings_get_bool(settings, FreeRDP_RedirectSerialPorts) ||
freerdp_settings_get_bool(settings, FreeRDP_RedirectParallelPorts));
file->RedirectLocation =
- freerdp_dynamic_channel_collection_find(settings, LOCATION_DVC_CHANNEL_NAME) ? TRUE : FALSE;
+ freerdp_dynamic_channel_collection_find(settings, LOCATION_CHANNEL_NAME) ? TRUE : FALSE;
if (!FILE_POPULATE_STRING(&file->DrivesToRedirect, settings, FreeRDP_DrivesToRedirect) ||
!FILE_POPULATE_STRING(&file->PreconnectionBlob, settings, FreeRDP_PreconnectionBlob) ||
!FILE_POPULATE_STRING(&file->KdcProxyName, settings, FreeRDP_KerberosKdcUrl))
@@ -2296,13 +2296,18 @@ BOOL freerdp_client_populate_settings_from_rdp_file(const rdpFile* file, rdpSett
return FALSE;
}
- if (~file->RedirectLocation)
+ if (~file->RedirectLocation && file->RedirectLocation != 0)
{
size_t count = 0;
- char** str =
- CommandLineParseCommaSeparatedValuesEx(LOCATION_DVC_CHANNEL_NAME, NULL, &count);
- const BOOL rc = freerdp_client_add_dynamic_channel(settings, count, str);
- free(str);
+ union
+ {
+ void* pv;
+ char** str;
+ const char** cstr;
+ } cnv;
+ cnv.str = CommandLineParseCommaSeparatedValuesEx(LOCATION_CHANNEL_NAME, NULL, &count);
+ const BOOL rc = freerdp_client_add_dynamic_channel(settings, count, cnv.cstr);
+ free(cnv.pv);
if (!rc)
return FALSE;
}
diff --git a/client/common/man/generate_argument_docbook.c b/client/common/man/generate_argument_docbook.c
index 156d809..a591dd0 100644
--- a/client/common/man/generate_argument_docbook.c
+++ b/client/common/man/generate_argument_docbook.c
@@ -15,6 +15,7 @@ static char* resize(char** buffer, size_t* size, size_t increment)
fprintf(stderr, "Could not reallocate string buffer from %" PRIuz " to %" PRIuz " bytes.\n",
*size, nsize);
free(*buffer);
+ return NULL;
}
memset(&tmp[*size], '\0', increment);
*size = nsize;
diff --git a/client/common/test/TestClientCmdLine.c b/client/common/test/TestClientCmdLine.c
index 2ce0c47..ba0cfe6 100644
--- a/client/common/test/TestClientCmdLine.c
+++ b/client/common/test/TestClientCmdLine.c
@@ -191,11 +191,11 @@ static const test tests[] = {
check_settings_smartcard_no_redirection,
{ "testfreerdp", "/list:monitor", 0 },
{ { 0 } } },
- { COMMAND_LINE_ERROR,
+ { 0,
check_settings_smartcard_no_redirection,
{ "testfreerdp", "/sound", "/drive:media:" DRIVE_REDIRECT_PATH, "/v:test.freerdp.com", 0 },
{ { 0 } } },
- { COMMAND_LINE_ERROR,
+ { 0,
check_settings_smartcard_no_redirection,
{ "testfreerdp", "/sound", "/drive:media,/foo/bar/blabla", "/v:test.freerdp.com", 0 },
{ { 0 } } },
diff --git a/client/freerdp-client.pc.in b/client/freerdp-client.pc.in
index eca4ab8..e446657 100644
--- a/client/freerdp-client.pc.in
+++ b/client/freerdp-client.pc.in
@@ -11,5 +11,5 @@ Version: @FREERDP_VERSION@
Requires:
Requires.private: @WINPR_PKG_CONFIG_FILENAME@ freerdp@FREERDP_VERSION_MAJOR@
Libs: -L${libdir} ${libs}
-Libs.private: -ldl -lpthread
+Libs.private: -ldl -lpthread @FREERDP_CLIENT_PC_PRIVATE_LIBS@
Cflags: -I${includedir}
diff --git a/cmake/AddFuzzerTest.cmake b/cmake/AddFuzzerTest.cmake
new file mode 100644
index 0000000..e16aa1b
--- /dev/null
+++ b/cmake/AddFuzzerTest.cmake
@@ -0,0 +1,15 @@
+macro(add_fuzzer_test FILES LINK_LIBS)
+ if (BUILD_FUZZERS)
+ string(REPLACE " " ";" LOCAL_LINK_LIBS ${LINK_LIBS})
+ list(APPEND LOCAL_LINK_LIBS fuzzer_config)
+ foreach(test ${FILES})
+ get_filename_component(TestName ${test} NAME_WE)
+ add_executable(${TestName} ${test})
+ # Use PUBLIC to force 'fuzzer_config' for all dependent targets.
+ target_link_libraries(${TestName} PUBLIC ${LOCAL_LINK_LIBS})
+ add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
+ set_target_properties(${TestName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
+ add_dependencies(fuzzers ${TestName})
+ endforeach()
+ endif (BUILD_FUZZERS)
+endmacro()
diff --git a/cmake/AddTargetWithResourceFile.cmake b/cmake/AddTargetWithResourceFile.cmake
new file mode 100644
index 0000000..355902e
--- /dev/null
+++ b/cmake/AddTargetWithResourceFile.cmake
@@ -0,0 +1,119 @@
+set(add_resource_macro_internal_dir ${CMAKE_CURRENT_LIST_DIR} CACHE INTERNAL "")
+
+macro(AddTargetWithResourceFile nameAndTarget is_exe version sources)
+ list(LENGTH ${nameAndTarget} target_length)
+ if (target_length GREATER 1)
+ list(GET ${nameAndTarget} 1 name)
+ list(GET ${nameAndTarget} 0 target)
+ else()
+ set(name ${nameAndTarget})
+ set(target ${nameAndTarget})
+ endif()
+
+ set(VERSIONING OFF)
+ set(IS_EXE OFF)
+ if ("${is_exe}" MATCHES "TRUE")
+ set(IS_EXE ON)
+ elseif ("${is_exe}" MATCHES "WIN32")
+ set(IS_EXE ON)
+ set(exe_options "WIN32")
+ elseif ("${is_exe}" MATCHES "SHARED")
+ set(lib_options "SHARED")
+ elseif ("${is_exe}" MATCHES "STATIC")
+ set(lib_options "STATIC")
+ endif()
+
+ if (IS_EXE AND WITH_BINARY_VERSIONING)
+ set(VERSIONING ON)
+ elseif (NOT IS_EXE AND WITH_LIBRARY_VERSIONING)
+ set(VERSIONING ON)
+ endif()
+ if (${ARGC} GREATER 4)
+ set(VERSIONING ${ARGV5})
+ endif()
+
+ string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+).*"
+ RC_PROGRAM_VERSION_MATCH ${version})
+ set (RC_VERSION_MAJOR ${CMAKE_MATCH_1})
+ set (RC_VERSION_MINOR ${CMAKE_MATCH_2})
+ set (RC_VERSION_BUILD ${CMAKE_MATCH_3})
+
+ if (WIN32)
+ if (IS_EXE)
+ if (VERSIONING)
+ set (RC_VERSION_FILE "${name}${RC_VERSION_MAJOR}${CMAKE_EXECUTABLE_SUFFIX}" )
+ else()
+ set (RC_VERSION_FILE "${name}${CMAKE_EXECUTABLE_SUFFIX}" )
+ endif()
+ else()
+ if (VERSIONING)
+ set (RC_VERSION_FILE "${CMAKE_SHARED_LIBRARY_PREFIX}${name}${RC_VERSION_MAJOR}${CMAKE_SHARED_LIBRARY_SUFFIX}" )
+ else()
+ set (RC_VERSION_FILE "${CMAKE_SHARED_LIBRARY_PREFIX}${name}${CMAKE_SHARED_LIBRARY_SUFFIX}" )
+ endif()
+ endif()
+
+ configure_file(
+ ${add_resource_macro_internal_dir}/WindowsDLLVersion.rc.in
+ ${CMAKE_CURRENT_BINARY_DIR}/version.rc
+ @ONLY
+ )
+
+ list(APPEND ${sources} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
+ endif()
+
+ set(OUTPUT_FILENAME "${name}")
+ if (VERSIONING)
+ string(APPEND OUTPUT_FILENAME "${RC_VERSION_MAJOR}")
+ endif()
+
+ if (IS_EXE)
+ message("add_executable(${target}) [${exe_options}]")
+ add_executable(
+ ${target}
+ ${exe_options}
+ ${${sources}}
+ )
+
+ set_target_properties(
+ ${target}
+ PROPERTIES
+ OUTPUT_NAME ${OUTPUT_FILENAME}
+ )
+ string(APPEND OUTPUT_FILENAME "${CMAKE_EXECUTABLE_SUFFIX}")
+ else()
+ message("add_library(${target}) [${lib_options}]")
+ add_library(${target}
+ ${lib_options}
+ ${${sources}})
+
+ if (VERSIONING)
+ set_target_properties(
+ ${target}
+ PROPERTIES
+ VERSION ${version}
+ SOVERSION ${RC_VERSION_MAJOR}
+ )
+ else()
+ set_target_properties(${target} PROPERTIES PREFIX "")
+ endif()
+
+ set_target_properties(
+ ${target}
+ PROPERTIES
+ OUTPUT_NAME ${OUTPUT_FILENAME}
+ )
+ set (OUTPUT_FILENAME "${CMAKE_SHARED_LIBRARY_PREFIX}${OUTPUT_FILENAME}${CMAKE_SHARED_LIBRARY_SUFFIX}" )
+ endif()
+
+
+ if (WITH_DEBUG_SYMBOLS AND MSVC AND (is_exe OR BUILD_SHARED_LIBS))
+ message("add PDB for ${OUTPUT_FILENAME}")
+ set_target_properties(
+ ${target}
+ PROPERTIES
+ PDB_NAME ${OUTPUT_FILENAME}
+ )
+ install(FILES $<TARGET_PDB_FILE:${target}> DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT symbols)
+ endif()
+endmacro()
diff --git a/cmake/CommonConfigOptions.cmake b/cmake/CommonConfigOptions.cmake
index 8d7f485..66924e8 100644
--- a/cmake/CommonConfigOptions.cmake
+++ b/cmake/CommonConfigOptions.cmake
@@ -28,9 +28,10 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "project default")
endif()
+include(PlatformDefaults)
include(PreventInSourceBuilds)
include(GNUInstallDirsWrapper)
include(MSVCRuntime)
include(ConfigureRPATH)
include(ClangTidy)
-
+include(AddTargetWithResourceFile)
diff --git a/cmake/ConfigOptions.cmake b/cmake/ConfigOptions.cmake
index ce451c6..7f3ffb8 100644
--- a/cmake/ConfigOptions.cmake
+++ b/cmake/ConfigOptions.cmake
@@ -24,7 +24,6 @@ option(WITH_GPROF "Compile with GProf profiler." OFF)
option(WITH_SSE2 "Enable SSE2 optimization." OFF)
option(WITH_NEON "Enable NEON optimization." OFF)
-option(WITH_IPP "Use Intel Performance Primitives." OFF)
option(WITH_JPEG "Use JPEG decoding." OFF)
@@ -80,6 +79,7 @@ endif()
option(WITH_THIRD_PARTY "Build third-party components" OFF)
option(WITH_CLIENT_INTERFACE "Build clients as a library with an interface" OFF)
+CMAKE_DEPENDENT_OPTION(CLIENT_INTERFACE_SHARED "Build clients as a shared library with an interface" OFF "WITH_CLIENT_INTERFACE" OFF)
option(WITH_SERVER_INTERFACE "Build servers as a library with an interface" ON)
option(WITH_DEBUG_ALL "Print all debug messages." OFF)
diff --git a/cmake/ConfigureRPATH.cmake b/cmake/ConfigureRPATH.cmake
index 9af2af8..284511f 100644
--- a/cmake/ConfigureRPATH.cmake
+++ b/cmake/ConfigureRPATH.cmake
@@ -1,18 +1,25 @@
# RPATH configuration
-set(CMAKE_SKIP_BUILD_RPATH FALSE)
-set(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
-set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
+option(CMAKE_SKIP_BUILD_RPATH "skip build RPATH" OFF)
+option(CMAKE_BUILD_WITH_INSTALL_RPATH "build with install RPATH" OFF)
+option(CMAKE_INSTALL_RPATH_USE_LINK_PATH "build with link RPATH" OFF)
+
if (APPLE)
+ if (BUILD_SHARED_LIBS)
+ option(CMAKE_MACOSX_RPATH "MacOSX RPATH" ON)
+ endif()
+
file(RELATIVE_PATH FRAMEWORK_PATH ${CMAKE_INSTALL_FULL_BINDIR} ${CMAKE_INSTALL_FULL_LIBDIR})
- set(CMAKE_INSTALL_RPATH "@loader_path/${FRAMEWORK_PATH}")
-else (APPLE)
+ set(CFG_INSTALL_RPATH "@loader_path/${FRAMEWORK_PATH}")
+elseif(NOT WIN32)
if (NOT FREEBSD)
- set(CMAKE_INSTALL_RPATH "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:\$ORIGIN/..")
option(WITH_ADD_PLUGIN_TO_RPATH "Add extension and plugin path to RPATH" OFF)
if (WITH_ADD_PLUGIN_TO_RPATH)
- set(CMAKE_INSTALL_RPATH "\$ORIGIN/../${FREERDP_EXTENSION_REL_PATH}:\$ORIGIN/../${FREERDP_PLUGIN_PATH}:${CMAKE_INSTALL_RPATH}")
+ set(CFG_INSTALL_RPATH "\$ORIGIN/../${FREERDP_EXTENSION_REL_PATH}:\$ORIGIN/../${FREERDP_PLUGIN_PATH}:\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:\$ORIGIN/..")
+ else()
+ set(CFG_INSTALL_RPATH "\$ORIGIN/../${CMAKE_INSTALL_LIBDIR}:\$ORIGIN/..")
endif()
endif()
endif(APPLE)
-
+set(CMAKE_INSTALL_RPATH ${CFG_INSTALL_RPATH} CACHE INTERNAL "ConfigureRPATH")
+message("Configured RPATH=${CMAKE_INSTALL_RPATH}")
diff --git a/cmake/DetectBSD.cmake b/cmake/DetectBSD.cmake
deleted file mode 100644
index 5c5b3b0..0000000
--- a/cmake/DetectBSD.cmake
+++ /dev/null
@@ -1,18 +0,0 @@
-# BSD
-if(${CMAKE_SYSTEM_NAME} MATCHES "BSD")
- set(BSD TRUE CACHE INTERNAL "BSD detection")
- if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
- set(FREEBSD TRUE CACHE INTERNAL "BSD detection")
- endif()
- if(${CMAKE_SYSTEM_NAME} MATCHES "kFreeBSD")
- set(KFREEBSD TRUE CACHE INTERNAL "BSD detection")
- endif()
- if(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
- set(OPENBSD TRUE CACHE INTERNAL "BSD detection")
- endif()
-endif()
-
-if(${CMAKE_SYSTEM_NAME} MATCHES "DragonFly")
- set(BSD TRUE CACHE INTERNAL "BSD detection")
- set(FREEBSD TRUE CACHE INTERNAL "BSD detection")
-endif()
diff --git a/cmake/FindIPP.cmake b/cmake/FindIPP.cmake
deleted file mode 100644
index 1e06762..0000000
--- a/cmake/FindIPP.cmake
+++ /dev/null
@@ -1,397 +0,0 @@
-# This cmake script is taken from the OpenCV project (BSD license)
-
-#
-# The script to detect Intel(R) Integrated Performance Primitives (IPP)
-# installation/package
-#
-# This will try to find Intel IPP libraries, and include path by automatic
-# search through typical install locations and if failed it will
-# examine IPPROOT environment variable.
-# Note, IPPROOT is not set by IPP installer, it should be set manually.
-#
-# On return this will define:
-#
-# IPP_FOUND - True if Intel IPP found
-# IPP_ROOT_DIR - root of IPP installation
-# IPP_INCLUDE_DIRS - IPP include folder
-# IPP_LIBRARY_DIRS - IPP libraries folder
-# IPP_LIBRARIES - IPP libraries names that are used by OpenCV
-# IPP_LATEST_VERSION_STR - string with the newest detected IPP version
-# IPP_LATEST_VERSION_MAJOR - numbers of IPP version (MAJOR.MINOR.BUILD)
-# IPP_LATEST_VERSION_MINOR
-# IPP_LATEST_VERSION_BUILD
-#
-# Created: 30 Dec 2010 by Vladimir Dudnik (vladimir.dudnik@intel.com)
-#
-
-set(IPP_FOUND)
-set(IPP_VERSION_STR "5.3.0.0") # will not detect earlier versions
-set(IPP_VERSION_MAJOR 0)
-set(IPP_VERSION_MINOR 0)
-set(IPP_VERSION_BUILD 0)
-set(IPP_ROOT_DIR)
-set(IPP_INCLUDE_DIRS)
-set(IPP_LIBRARY_DIRS)
-set(IPP_LIBRARIES)
-set(IPP_LIB_PREFIX ${CMAKE_STATIC_LIBRARY_PREFIX})
-set(IPP_LIB_SUFFIX ${CMAKE_STATIC_LIBRARY_SUFFIX})
-set(IPP_PREFIX "ipp")
-set(IPP_SUFFIX "_l")
-set(IPPCORE "core") # core functionality
-set(IPPS "s") # signal processing
-set(IPPI "i") # image processing
-set(IPPCC "cc") # color conversion
-set(IPPCV "cv") # computer vision
-set(IPPVM "vm") # vector math
-
-
-set(IPP_X64 0)
-if (CMAKE_SIZEOF_VOID_P EQUAL 8)
- set(IPP_X64 1)
-endif()
-if (CMAKE_CL_64)
- set(IPP_X64 1)
-endif()
-
-# ------------------------------------------------------------------------
-# This function detect IPP version by analyzing ippversion.h file
-# Note, ippversion.h file was inroduced since IPP 5.3
-# ------------------------------------------------------------------------
-function(get_ipp_version _ROOT_DIR)
- set(_VERSION_STR)
- set(_MAJOR)
- set(_MINOR)
- set(_BUILD)
-
- # read IPP version info from file
- file(STRINGS ${_ROOT_DIR}/include/ippversion.h STR1 REGEX "IPP_VERSION_MAJOR")
- file(STRINGS ${_ROOT_DIR}/include/ippversion.h STR2 REGEX "IPP_VERSION_MINOR")
- file(STRINGS ${_ROOT_DIR}/include/ippversion.h STR3 REGEX "IPP_VERSION_BUILD")
-
- if(NOT STR3)
- file(STRINGS ${_ROOT_DIR}/include/ippversion.h STR3 REGEX "IPP_VERSION_UPDATE")
- endif()
-
- file(STRINGS ${_ROOT_DIR}/include/ippversion.h STR4 REGEX "IPP_VERSION_STR")
-
- # extract info and assign to variables
- string(REGEX MATCHALL "[0-9]+" _MAJOR ${STR1})
- string(REGEX MATCHALL "[0-9]+" _MINOR ${STR2})
- string(REGEX MATCHALL "[0-9]+" _BUILD ${STR3})
- string(REGEX MATCHALL "[0-9]+[.]+[0-9]+[^\"]+|[0-9]+[.]+[0-9]+" _VERSION_STR ${STR4})
-
- # export info to parent scope
- set(IPP_VERSION_STR ${_VERSION_STR} PARENT_SCOPE)
- set(IPP_VERSION_MAJOR ${_MAJOR} PARENT_SCOPE)
- set(IPP_VERSION_MINOR ${_MINOR} PARENT_SCOPE)
- set(IPP_VERSION_BUILD ${_BUILD} PARENT_SCOPE)
-
- message(STATUS "found IPP: ${_MAJOR}.${_MINOR}.${_BUILD} [${_VERSION_STR}]")
- message(STATUS "at: ${_ROOT_DIR}")
-
- return()
-
-endfunction()
-
-
-# ------------------------------------------------------------------------
-# This is auxiliary function called from set_ipp_variables()
-# to set IPP_LIBRARIES variable in IPP 6.x style (IPP 5.3 should also work)
-# ------------------------------------------------------------------------
-function(set_ipp_old_libraries)
- set(IPP_PREFIX "ipp")
- set(IPP_SUFFIX) # old style static core libs suffix
- set(IPP_ARCH) # architecture suffix
- set(IPP_DISP "emerged") # old style dipatcher and cpu-specific
- set(IPP_MRGD "merged") # static libraries
- set(IPPCORE "core") # core functionality
- set(IPPSP "s") # signal processing
- set(IPPIP "i") # image processing
- set(IPPCC "cc") # color conversion
- set(IPPCV "cv") # computer vision
- set(IPPVM "vm") # vector math
-
- if (IPP_X64)
- set(IPP_ARCH "em64t")
- endif()
-
- if(WIN32)
- set(IPP_SUFFIX "l")
- endif()
-
- set(IPP_LIBRARIES
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPVM}${IPP_MRGD}${IPP_ARCH}${IPP_LIB_SUFFIX}
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPVM}${IPP_DISP}${IPP_ARCH}${IPP_LIB_SUFFIX}
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPCC}${IPP_MRGD}${IPP_ARCH}${IPP_LIB_SUFFIX}
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPCC}${IPP_DISP}${IPP_ARCH}${IPP_LIB_SUFFIX}
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPCV}${IPP_MRGD}${IPP_ARCH}${IPP_LIB_SUFFIX}
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPCV}${IPP_DISP}${IPP_ARCH}${IPP_LIB_SUFFIX}
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPIP}${IPP_MRGD}${IPP_ARCH}${IPP_LIB_SUFFIX}
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPIP}${IPP_DISP}${IPP_ARCH}${IPP_LIB_SUFFIX}
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPSP}${IPP_MRGD}${IPP_ARCH}${IPP_LIB_SUFFIX}
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPSP}${IPP_DISP}${IPP_ARCH}${IPP_LIB_SUFFIX}
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPCORE}${IPP_ARCH}${IPP_SUFFIX}${IPP_LIB_SUFFIX}
- PARENT_SCOPE)
-
- return()
-
-endfunction()
-
-
-# ------------------------------------------------------------------------
-# This is auxiliary function called from set_ipp_variables()
-# to set IPP_LIBRARIES variable in IPP 7.x style
-# ------------------------------------------------------------------------
-function(set_ipp_new_libraries)
- set(IPP_PREFIX "ipp")
- set(IPP_SUFFIX "_l") # static not threaded libs suffix
- set(IPP_THRD "_t") # static threaded libs suffix
- set(IPPCORE "core") # core functionality
- set(IPPSP "s") # signal processing
- set(IPPIP "i") # image processing
- set(IPPCC "cc") # color conversion
- set(IPPCV "cv") # computer vision
- set(IPPVM "vm") # vector math
-
- set(IPP_LIBRARIES
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPVM}${IPP_SUFFIX}${IPP_LIB_SUFFIX}
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPCC}${IPP_SUFFIX}${IPP_LIB_SUFFIX}
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPCV}${IPP_SUFFIX}${IPP_LIB_SUFFIX}
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPI}${IPP_SUFFIX}${IPP_LIB_SUFFIX}
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPS}${IPP_SUFFIX}${IPP_LIB_SUFFIX}
- ${IPP_LIB_PREFIX}${IPP_PREFIX}${IPPCORE}${IPP_SUFFIX}${IPP_LIB_SUFFIX}
- PARENT_SCOPE)
-
- return()
-
-endfunction()
-
-
-# ------------------------------------------------------------------------
-# This function will set
-# IPP_INCLUDE_DIRS, IPP_LIBRARY_DIRS and IPP_LIBRARIES variables depending
-# on IPP version parameter.
-# Since IPP 7.0 version library names and install folder structure
-# was changed
-# ------------------------------------------------------------------------
-function(set_ipp_variables _LATEST_VERSION)
- if(${_LATEST_VERSION} VERSION_LESS "7.0")
-# message(STATUS "old")
-
- # set INCLUDE and LIB folders
- set(IPP_INCLUDE_DIRS ${IPP_ROOT_DIR}/include PARENT_SCOPE)
- set(IPP_LIBRARY_DIRS ${IPP_ROOT_DIR}/lib PARENT_SCOPE)
-
- if (IPP_X64)
- if(NOT EXISTS ${IPP_ROOT_DIR}/../em64t)
- message(SEND_ERROR "IPP EM64T libraries not found")
- endif()
- else()
- if(NOT EXISTS ${IPP_ROOT_DIR}/../ia32)
- message(SEND_ERROR "IPP IA32 libraries not found")
- endif()
- endif()
-
- # set IPP_LIBRARIES variable (6.x lib names)
- set_ipp_old_libraries()
- set(IPP_LIBRARIES ${IPP_LIBRARIES} PARENT_SCOPE)
- message(STATUS "IPP libs: ${IPP_LIBRARIES}")
-
- else()
-# message(STATUS "new")
-
- # set INCLUDE and LIB folders
- set(IPP_INCLUDE_DIRS ${IPP_ROOT_DIR}/include PARENT_SCOPE)
-
- if(APPLE)
- set(IPP_LIBRARY_DIRS ${IPP_ROOT_DIR}/lib PARENT_SCOPE)
- else()
- if(IPP_X64)
- if(NOT EXISTS ${IPP_ROOT_DIR}/lib/intel64)
- message(SEND_ERROR "IPP EM64T libraries not found")
- endif()
- set(IPP_LIBRARY_DIRS ${IPP_ROOT_DIR}/lib/intel64 PARENT_SCOPE)
- else()
- if(NOT EXISTS ${IPP_ROOT_DIR}/lib/ia32)
- message(SEND_ERROR "IPP IA32 libraries not found")
- endif()
- set(IPP_LIBRARY_DIRS ${IPP_ROOT_DIR}/lib/ia32 PARENT_SCOPE)
- endif()
- endif()
-
- # set IPP_LIBRARIES variable (7.x lib names)
- set_ipp_new_libraries()
- set(IPP_LIBRARIES ${IPP_LIBRARIES} PARENT_SCOPE)
- message(STATUS "IPP libs: ${IPP_LIBRARIES}")
-
- endif()
-
- return()
-
-endfunction()
-
-
-# ------------------------------------------------------------------------
-# This section will look for IPP through IPPROOT env variable
-# Note, IPPROOT is not set by IPP installer, you may need to set it manually
-# ------------------------------------------------------------------------
-find_path(
- IPP_H_PATH
- NAMES ippversion.h
- PATHS $ENV{IPPROOT}
- PATH_SUFFIXES include
- DOC "The path to Intel(R) IPP header files"
- NO_DEFAULT_PATH
- NO_CMAKE_PATH)
-
-if(IPP_H_PATH)
- set(IPP_FOUND 1)
-
- # traverse up to IPPROOT level
- get_filename_component(IPP_ROOT_DIR ${IPP_H_PATH} PATH)
-
- # extract IPP version info
- get_ipp_version(${IPP_ROOT_DIR})
-
- # keep info in the same vars for auto search and search by IPPROOT
- set(IPP_LATEST_VERSION_STR ${IPP_VERSION_STR})
- set(IPP_LATEST_VERSION_MAJOR ${IPP_VERSION_MAJOR})
- set(IPP_LATEST_VERSION_MINOR ${IPP_VERSION_MINOR})
- set(IPP_LATEST_VERSION_BUILD ${IPP_VERSION_BUILD})
-
- # set IPP INCLUDE, LIB dirs and library names
- set_ipp_variables(${IPP_LATEST_VERSION_STR})
-endif()
-
-
-if(NOT IPP_FOUND)
- # reset var from previous search
- set(IPP_H_PATH)
-
-
- # ------------------------------------------------------------------------
- # This section will look for IPP through system program folders
- # Note, if several IPP installations found the newest version will be
- # selected
- # ------------------------------------------------------------------------
- foreach(curdir ${CMAKE_SYSTEM_PREFIX_PATH} /opt)
- set(curdir ${curdir}/intel)
- file(TO_CMAKE_PATH ${curdir} CURDIR)
-
- if(EXISTS ${curdir})
- file(GLOB_RECURSE IPP_H_DIR ${curdir}/ippversion.h)
-
- if(IPP_H_DIR)
- set(IPP_FOUND 1)
- endif()
-
- # init IPP_LATEST_VERSION version with oldest detectable version (5.3.0.0)
- # IPP prior 5.3 did not have ippversion.h file
- set(IPP_LATEST_VERSION_STR ${IPP_VERSION_STR})
-
- # look through all dirs where ippversion.h was found
- foreach(item ${IPP_H_DIR})
-
- # traverse up to IPPROOT level
- get_filename_component(_FILE_PATH ${item} PATH)
- get_filename_component(_ROOT_DIR ${_FILE_PATH} PATH)
-
- # extract IPP version info
- get_ipp_version(${_ROOT_DIR})
-
- # remember the latest version (if many found)
- if(${IPP_LATEST_VERSION_STR} VERSION_LESS ${IPP_VERSION_STR})
- set(IPP_LATEST_VERSION_STR ${IPP_VERSION_STR})
- set(IPP_LATEST_VERSION_MAJOR ${IPP_VERSION_MAJOR})
- set(IPP_LATEST_VERSION_MINOR ${IPP_VERSION_MINOR})
- set(IPP_LATEST_VERSION_BUILD ${IPP_VERSION_BUILD})
- set(IPP_ROOT_DIR ${_ROOT_DIR})
- endif()
- endforeach()
- endif()
- endforeach()
-endif()
-
-if(IPP_FOUND)
- # set IPP INCLUDE, LIB dirs and library names
- set_ipp_variables(${IPP_LATEST_VERSION_STR})
-
- # set CACHE variable IPP_H_PATH,
- # path to IPP header files for the latest version
- find_path(
- IPP_H_PATH
- NAMES ippversion.h
- PATHS ${IPP_ROOT_DIR}
- PATH_SUFFIXES include
- DOC "The path to Intel(R) IPP header files"
- NO_DEFAULT_PATH
- NO_CMAKE_PATH)
-endif()
-
-if(WIN32 AND MINGW AND NOT IPP_LATEST_VERSION_MAJOR LESS 7)
- # Since IPP built with Microsoft compiler and /GS option
- # ======================================================
- # From Windows SDK 7.1
- # (usually in "C:\Program Files\Microsoft Visual Studio 10.0\VC\lib"),
- # to avoid undefined reference to __security_cookie and _chkstk:
- set(MSV_RUNTMCHK "RunTmChk")
- set(IPP_LIBRARIES ${IPP_LIBRARIES} ${MSV_RUNTMCHK}${IPP_LIB_SUFFIX})
-
- # To avoid undefined reference to _alldiv and _chkstk
- # ===================================================
- # NB: it may require a recompilation of w32api (after having modified
- # the file ntdll.def) to export the required functions
- # See http://code.opencv.org/issues/1906 for additional details
- set(MSV_NTDLL "ntdll")
- set(IPP_LIBRARIES ${IPP_LIBRARIES} ${MSV_NTDLL}${IPP_LIB_SUFFIX})
-endif()
-
-# ------------------------------------------------------------------------
-# This section will look for the IPP "compiler" dependent library
-# libiomp5.
-# ------------------------------------------------------------------------
-foreach(curdir ${CMAKE_SYSTEM_PREFIX_PATH} /opt)
- set(curdir ${curdir}/intel)
-
- if(EXISTS ${curdir})
- file(GLOB_RECURSE liblist FOLLOW_SYMLINKS ${curdir}/libiomp5.*)
- foreach(lib ${liblist})
- get_filename_component(libdir ${lib} REALPATH)
- get_filename_component(libdir ${libdir} PATH)
-
- if(${IPP_VERSION_MAJOR} VERSION_LESS "7")
- set(IPP_COMPILER_LIBRARY_DIRS ${libdir})
- set(IPP_COMPILER_LIBRARIES iomp5)
- else()
- if(APPLE)
- set(IPP_COMPILER_LIBRARY_DIRS ${libdir})
- set(IPP_COMPILER_LIBRARIES iomp5)
- else()
- if(IPP_X64)
- if(("${libdir}" MATCHES "intel64"))
- set(IPP_COMPILER_LIBRARY_DIRS ${libdir})
- set(IPP_COMPILER_LIBRARIES iomp5)
- endif()
- else()
- set(IPP_COMPILER_LIBRARY_DIRS ${libdir})
- set(IPP_COMPILER_LIBRARIES iomp5)
- endif()
- endif()
- endif()
- endforeach(lib)
- endif()
-endforeach(curdir)
-
-# ------------------------------------------------------------------------
-# Build fullpath library list.
-# ------------------------------------------------------------------------
-find_library(LIB_IPPI ippi PATHS ${IPP_LIBRARY_DIRS})
-set(IPP_LIBRARY_LIST ${IPP_LIBRARY_LIST} ${LIB_IPPI})
-find_library(LIB_IPPS ipps PATHS ${IPP_LIBRARY_DIRS})
-set(IPP_LIBRARY_LIST ${IPP_LIBRARY_LIST} ${LIB_IPPS})
-find_library(LIB_IPPCORE ippcore PATHS ${IPP_LIBRARY_DIRS})
-set(IPP_LIBRARY_LIST ${IPP_LIBRARY_LIST} ${LIB_IPPCORE})
-find_library(LIB_IOMP5 iomp5 PATHS ${IPP_COMPILER_LIBRARY_DIRS})
-set(IPP_LIBRARY_LIST ${IPP_LIBRARY_LIST} ${LIB_IOMP5})
-
-
diff --git a/cmake/FindOSS.cmake b/cmake/FindOSS.cmake
index 811e052..a750db6 100644
--- a/cmake/FindOSS.cmake
+++ b/cmake/FindOSS.cmake
@@ -4,29 +4,27 @@
IF(UNIX)
IF(CMAKE_SYSTEM_NAME MATCHES "Linux")
- SET(OSS_HDR_NAME "linux/soundcard.h")
- ELSE(CMAKE_SYSTEM_NAME MATCHES "Linux")
- IF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
- SET(OSS_HDR_NAME "sys/soundcard.h")
- ELSE(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
- IF(CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
- SET(OSS_HDR_NAME "soundcard.h")
- ELSE(CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
- SET(OSS_HDR_NAME "machine/soundcard.h")
- ENDIF(CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
- ENDIF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
- ENDIF(CMAKE_SYSTEM_NAME MATCHES "Linux")
+ set(PLATFORM_PREFIX "linux/")
+ ELSEIF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD")
+ set(PLATFORM_PREFIX "sys/")
+ ELSEIF(CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
+ set(PLATFORM_PREFIX "machine/")
+ ENDIF()
ENDIF(UNIX)
-FIND_PATH(OSS_INCLUDE_DIR "${OSS_HDR_NAME}"
- "/usr/include" "/usr/local/include"
+set(OSS_HDR_NAME "${PLATFORM_PREFIX}soundcard.h" CACHE STRING "oss header include file name")
+FIND_PATH(OSS_INCLUDE_DIRS ${OSS_HDR_NAME}
+ PATHS
+ "/usr/local/include"
+ PATH_SUFFIXES
+ ${PLATFORM_SUFFIX}
)
-IF(OSS_INCLUDE_DIR)
- SET(OSS_FOUND TRUE)
-ELSE(OSS_INCLUDE_DIR)
- SET(OSS_FOUND)
-ENDIF(OSS_INCLUDE_DIR)
+IF(OSS_INCLUDE_DIRS)
+ SET(OSS_FOUND ON CACHE BOOL "oss detection status")
+ELSE(OSS_INCLUDE_DIRS)
+ SET(OSS_FOUND OFF CACHE BOOL "oss detection status")
+ENDIF(OSS_INCLUDE_DIRS)
IF(OSS_FOUND)
MESSAGE(STATUS "Found OSS Audio")
@@ -40,5 +38,6 @@ ENDIF(OSS_FOUND)
MARK_AS_ADVANCED (
OSS_FOUND
- OSS_INCLUDE_DIR
+ OSS_HDR_NAME
+ OSS_INCLUDE_DIRS
)
diff --git a/cmake/InstallFreeRDPMan.cmake b/cmake/InstallFreeRDPMan.cmake
index ba0d8a8..c333f64 100644
--- a/cmake/InstallFreeRDPMan.cmake
+++ b/cmake/InstallFreeRDPMan.cmake
@@ -7,11 +7,27 @@ function(install_freerdp_man manpage section)
endif()
endfunction()
-function(generate_and_install_freerdp_man_from_xml template manpage dependencies)
+function(generate_and_install_freerdp_man_from_template name_base section api)
if(WITH_MANPAGES)
- find_program(XSLTPROC_EXECUTABLE NAMES xsltproc REQUIRED)
- if (NOT DOCBOOKXSL_FOUND)
- message(FATAL_ERROR "docbook xsl not found but required for manpage generation")
+ if (WITH_BINARY_VERSIONING)
+ set(manpage "${CMAKE_CURRENT_BINARY_DIR}/${name_base}${api}.${section}")
+ else()
+ set(manpage "${CMAKE_CURRENT_BINARY_DIR}/${name_base}.${section}")
+ endif()
+ configure_file(${name_base}.${section}.in ${manpage})
+ install_freerdp_man(${manpage} ${section})
+ endif()
+endfunction()
+
+function(generate_and_install_freerdp_man_from_xml name_base section api dependencies)
+ if(WITH_MANPAGES)
+ set(template "${name_base}.${section}")
+ if (WITH_BINARY_VERSIONING)
+ set(MANPAGE_NAME "${name_base}${api}")
+ set(manpage "${name_base}${api}.${section}")
+ else()
+ set(MANPAGE_NAME "${name_base}")
+ set(manpage "${name_base}.${section}")
endif()
# We need the variable ${MAN_TODAY} to contain the current date in ISO
@@ -34,8 +50,13 @@ function(generate_and_install_freerdp_man_from_xml template manpage dependencies
endif()
endforeach()
+ find_program(XSLTPROC_EXECUTABLE NAMES xsltproc REQUIRED)
+ if (NOT DOCBOOKXSL_FOUND)
+ message(FATAL_ERROR "docbook xsl not found but required for manpage generation")
+ endif()
+
add_custom_command(
- OUTPUT ${manpage}
+ OUTPUT "${manpage}"
COMMAND ${CMAKE_BINARY_DIR}/client/common/man/generate_argument_docbook
COMMAND ${XSLTPROC_EXECUTABLE} --path "${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}" ${DOCBOOKXSL_DIR}/manpages/docbook.xsl ${manpage}.xml
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
@@ -50,6 +71,6 @@ function(generate_and_install_freerdp_man_from_xml template manpage dependencies
DEPENDS
${manpage}
)
- install_freerdp_man(${CMAKE_CURRENT_BINARY_DIR}/${manpage} 1)
+ install_freerdp_man(${CMAKE_CURRENT_BINARY_DIR}/${manpage} ${section})
endif()
endfunction()
diff --git a/cmake/PlatformDefaults.cmake b/cmake/PlatformDefaults.cmake
new file mode 100644
index 0000000..30c8a92
--- /dev/null
+++ b/cmake/PlatformDefaults.cmake
@@ -0,0 +1,103 @@
+# This option allows deactivating FreeRDP supplied platform defauts to replace these with
+# user supplied values.
+#
+# Compilation will fail without a replacement defining the symbols, but that can be
+# done by supplying a TOOLCHAIN_FILE defining these.
+option(USE_PLATFORM_DEFAULT "Use this configuration file for platform defaults. Supply -DCMAKE_TOOLCHAIN_FILE=<yourfile>." ON)
+if (USE_PLATFORM_DEFAULT)
+ # default defines or other required preferences per platform
+ if((CMAKE_SYSTEM_NAME MATCHES "WindowsStore") AND (CMAKE_SYSTEM_VERSION MATCHES "10.0"))
+ set(UWP 1 CACHE BOOL "platform default")
+ add_definitions("-D_UWP")
+ set(CMAKE_WINDOWS_VERSION "WIN10" CACHE STRING "platform default")
+ endif()
+
+ if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux")
+ # Linux already does define _POSIX_C_SOURCE by default, nothing to do
+ add_definitions("-D_FILE_OFFSET_BITS=64")
+ set(WINPR_TIMEZONE_FILE "/etc/timezone")
+ endif()
+
+ if("${CMAKE_SYSTEM_NAME}" MATCHES "FreeBSD")
+ set(BSD TRUE CACHE INTERNAL "platform default")
+ set(FREEBSD TRUE CACHE INTERNAL "platform default")
+ # we want POSIX 2008. FreeBSD 14 does only support 2001 fully, but the subset we require from 2008
+ # is implemented, so ignore _POSIX_VERSION from unistd.h
+ add_definitions("-D_POSIX_C_SOURCE=200809L")
+ # TODO: FreeBSD allows mixing POSIX and BSD API calls if we do not set
+ # _POSIX_C_SOURCE but lack a macro to reenable the BSD calls...
+ add_definitions("-D__BSD_VISIBLE")
+
+ # There are some symbols only visible for XOpen standard
+ add_definitions("-D_XOPEN_SOURCE=700")
+ add_definitions("-D_FILE_OFFSET_BITS=64")
+ set(WINPR_TIMEZONE_FILE "/var/db/zoneinfo")
+ endif()
+
+ if("${CMAKE_SYSTEM_NAME}" MATCHES "SunOS")
+ # TODO: Does somebody still use this? please show yourself and
+ # tell us if this still works.
+ add_definitions("-D_POSIX_PTHREAD_SEMANTICS")
+ list(APPEND CMAKE_STANDARD_LIBRARIES rt)
+ set(CMAKE_STANDARD_LIBRARIES ${CMAKE_STANDARD_LIBRARIES} CACHE STRING "platform default")
+ set(WITH_SUN true CACHE BOOL "platform default")
+ endif()
+
+ if("${CMAKE_SYSTEM_NAME}" MATCHES "Darwin")
+ # we want POSIX 2008. MacOS does only support 2001 fully, but the subset we require from 2008
+ # is implemented, so ignore _POSIX_VERSION from unistd.h
+ add_definitions("-D_POSIX_C_SOURCE=200809L")
+
+ # as _POSIX_C_SOURCE sets a fully POSIX confirmant environment reenable
+ # MacOS API visibility by defining the following feature test macro
+ add_definitions("-D_DARWIN_C_SOURCE")
+ endif()
+
+ if(${CMAKE_SYSTEM_NAME} MATCHES "kFreeBSD")
+ set(BSD TRUE CACHE INTERNAL "platform default")
+ set(KFREEBSD TRUE CACHE INTERNAL "platform default")
+ add_definitions(-DKFREEBSD)
+ add_definitions("-D_GNU_SOURCE")
+ endif()
+
+ if(${CMAKE_SYSTEM_NAME} MATCHES "OpenBSD")
+ set(BSD TRUE CACHE INTERNAL "platform default")
+ set(OPENBSD TRUE CACHE INTERNAL "platform default")
+ endif()
+
+ if(${CMAKE_SYSTEM_NAME} MATCHES "DragonFly")
+ set(BSD TRUE CACHE INTERNAL "platform default")
+ set(FREEBSD TRUE CACHE INTERNAL "platform default")
+
+ # we want POSIX 2008. FreeBSD 14 does only support 2001 fully, but the subset we require from 2008
+ # is implemented, so ignore _POSIX_VERSION from unistd.h
+ add_definitions("-D_POSIX_C_SOURCE=200809L")
+ # TODO: FreeBSD allows mixing POSIX and BSD API calls if we do not set
+ # _POSIX_C_SOURCE but lack a macro to reenable the BSD calls...
+ add_definitions("-D__BSD_VISIBLE")
+
+ # There are some symbols only visible for XOpen standard
+ add_definitions("-D_XOPEN_SOURCE=700")
+ add_definitions("-D_FILE_OFFSET_BITS=64")
+ set(WINPR_TIMEZONE_FILE "/var/db/zoneinfo")
+ endif()
+
+ if(BSD)
+ if(IS_DIRECTORY /usr/local/include)
+ include_directories(/usr/local/include)
+ link_directories(/usr/local/lib)
+ endif()
+ if(OPENBSD)
+ if(IS_DIRECTORY /usr/X11R6/include)
+ include_directories(/usr/X11R6/include)
+ endif()
+ endif()
+ endif()
+
+ # define a fallback for systems that do not support a timezone file or we did not yet test.
+ # since most of these are BSD try a sensible default
+ if (NOT WINPR_TIMEZONE_FILE)
+ set(WINPR_TIMEZONE_FILE "/var/db/zoneinfo")
+ endif()
+ add_definitions("-DWINPR_TIMEZONE_FILE=\"${WINPR_TIMEZONE_FILE}\"")
+endif()
diff --git a/cmake/oss-includes.h.in b/cmake/oss-includes.h.in
new file mode 100644
index 0000000..f3fb673
--- /dev/null
+++ b/cmake/oss-includes.h.in
@@ -0,0 +1,6 @@
+#ifndef OSS_INCLUDES_H_
+#define OSS_INCLUDES_H_
+
+#include <@OSS_HDR_NAME@>
+
+#endif /* OSS_INCLUDES_H_ */
diff --git a/include/config/config.h.in b/include/config/config.h.in
index 0c6ec7b..460389b 100644
--- a/include/config/config.h.in
+++ b/include/config/config.h.in
@@ -18,7 +18,6 @@
#cmakedefine WITH_GPROF
#cmakedefine WITH_SSE2
#cmakedefine WITH_NEON
-#cmakedefine WITH_IPP
#cmakedefine WITH_CUPS
#cmakedefine WITH_JPEG
#cmakedefine WITH_WIN8
diff --git a/include/freerdp/api.h b/include/freerdp/api.h
index aa25555..b7655cf 100644
--- a/include/freerdp/api.h
+++ b/include/freerdp/api.h
@@ -103,7 +103,7 @@
((_cb != NULL) ? _cb(__VA_ARGS__) : (_default_return))
#endif
-#if defined(__GNUC__)
+#if defined(__GNUC__) || defined(__clang__)
#define ALIGN64 __attribute__((aligned(8)))
#else
#ifdef _WIN32
diff --git a/include/freerdp/channels/location.h b/include/freerdp/channels/location.h
index 5b91ea4..45682b0 100644
--- a/include/freerdp/channels/location.h
+++ b/include/freerdp/channels/location.h
@@ -24,6 +24,7 @@
#include <freerdp/dvc.h>
#include <freerdp/types.h>
+#define LOCATION_CHANNEL_NAME "location"
#define LOCATION_DVC_CHANNEL_NAME "Microsoft::Windows::RDS::Location"
#ifdef __cplusplus
diff --git a/include/freerdp/client/location.h b/include/freerdp/client/location.h
new file mode 100644
index 0000000..67db655
--- /dev/null
+++ b/include/freerdp/client/location.h
@@ -0,0 +1,97 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Location Virtual Channel Extension
+ *
+ * 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.
+ * 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_LOCATION_CLIENT_LOCATION_H
+#define FREERDP_CHANNEL_LOCATION_CLIENT_LOCATION_H
+
+#include <freerdp/channels/location.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+ typedef struct s_location_client_context LocationClientContext;
+
+ typedef UINT (*pcLocationStart)(LocationClientContext* context, UINT32 version, UINT32 flags);
+ typedef UINT (*pcLocationStop)(LocationClientContext* context);
+ typedef UINT (*pcLocationSend)(LocationClientContext* context, LOCATION_PDUTYPE type,
+ size_t count, ...);
+
+ struct s_location_client_context
+ {
+ void* handle;
+ void* custom;
+
+ /**! \brief initialize location services on client
+ *
+ * \param context The client context to operate on
+ * \param version The location channel version (determines which features are available.
+ * \param flags The location channel flags.
+ *
+ * \return \b CHANNEL_RC_OK for success, an appropriate error otherwise.
+ */
+ pcLocationStart LocationStart;
+
+ /**! \brief stop location services on client
+ *
+ * \param context The client context to operate on
+ *
+ * \return \b CHANNEL_RC_OK for success, an appropriate error otherwise.
+ */
+ pcLocationStop LocationStop;
+
+ /**! \brief Send a location update.
+ *
+ * This function sends location updates to a server.
+ * The following parameter formats are supported:
+ *
+ * \param type one of the following:
+ * PDUTYPE_BASE_LOCATION3D : count = 3 | 7
+ * latitude : double, required
+ * longitude : double, required
+ * altitude : INT32, required
+ * speed : double, optional
+ * heading : double, optional
+ * horizontalAccuracy : double, optional
+ * source : int, optional
+ * PDUTYPE_LOCATION2D_DELTA : count = 2 | 4
+ * latitudeDelta : double, required
+ * longitudeDelta : double, required
+ * speedDelta : double, optional
+ * headingDelta : double, optional
+ * PDUTYPE_LOCATION3D_DELTA : count = 3 | 5
+ * latitudeDelta : double, required
+ * longitudeDelta : double, required
+ * altitudeDelta : INT32, optional
+ * speedDelta : double, optional
+ * headingDelta : double, optional
+ * \param count the number of variable arguments following
+ *
+ * return \b CHANNEL_RC_OK for success, an appropriate error otherwise.
+ */
+ pcLocationSend LocationSend;
+ };
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREERDP_CHANNEL_LOCATION_CLIENT_LOCATION_H */
diff --git a/include/freerdp/primitives.h b/include/freerdp/primitives.h
index 20b74d6..29f103a 100644
--- a/include/freerdp/primitives.h
+++ b/include/freerdp/primitives.h
@@ -70,12 +70,11 @@ enum
PRIM_FLAGS_HAVE_EXTGPU = (1U << 1), /* primitives are using the GPU */
};
-/* Structures compatible with IPP */
typedef struct
{
UINT32 width;
UINT32 height;
-} prim_size_t; /* like IppiSize */
+} prim_size_t;
typedef enum
{
diff --git a/include/freerdp/rail.h b/include/freerdp/rail.h
index 66ad34b..b3cd702 100644
--- a/include/freerdp/rail.h
+++ b/include/freerdp/rail.h
@@ -583,6 +583,9 @@ typedef enum
FREERDP_API BOOL utf8_string_to_rail_string(const char* string,
RAIL_UNICODE_STRING* unicode_string);
+ FREERDP_API const char* rail_handshake_ex_flags_to_string(UINT32 flags, char* buffer,
+ size_t len);
+
#ifdef __cplusplus
}
#endif
diff --git a/include/freerdp/server/shadow.h b/include/freerdp/server/shadow.h
index 9ddb8ae..9544e16 100644
--- a/include/freerdp/server/shadow.h
+++ b/include/freerdp/server/shadow.h
@@ -302,9 +302,15 @@ extern "C"
FREERDP_API void shadow_subsystem_set_entry_builtin(const char* name);
FREERDP_API void shadow_subsystem_set_entry(pfnShadowSubsystemEntry pEntry);
- FREERDP_API int shadow_subsystem_pointer_convert_alpha_pointer_data(
- BYTE* pixels, BOOL premultiplied, UINT32 width, UINT32 height,
- SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* pointerColor);
+ FREERDP_API WINPR_DEPRECATED_VAR(
+ "Use shadow_subsystem_pointer_convert_alpha_pointer_data_to_format instead",
+ int shadow_subsystem_pointer_convert_alpha_pointer_data(
+ const BYTE* WINPR_RESTRICT pixels, BOOL premultiplied, UINT32 width, UINT32 height,
+ SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* WINPR_RESTRICT pointerColor));
+
+ FREERDP_API int shadow_subsystem_pointer_convert_alpha_pointer_data_to_format(
+ const BYTE* WINPR_RESTRICT pixels, UINT32 format, BOOL premultiplied, UINT32 width,
+ UINT32 height, SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* WINPR_RESTRICT pointerColor);
FREERDP_API int shadow_server_parse_command_line(rdpShadowServer* server, int argc, char** argv,
COMMAND_LINE_ARGUMENT_A* cargs);
@@ -325,10 +331,20 @@ extern "C"
WINPR_ATTR_MALLOC(shadow_server_free, 1)
FREERDP_API rdpShadowServer* shadow_server_new(void);
- FREERDP_API int shadow_capture_align_clip_rect(RECTANGLE_16* rect, RECTANGLE_16* clip);
- FREERDP_API int shadow_capture_compare(BYTE* pData1, UINT32 nStep1, UINT32 nWidth,
- UINT32 nHeight, BYTE* pData2, UINT32 nStep2,
- RECTANGLE_16* rect);
+ FREERDP_API int shadow_capture_align_clip_rect(RECTANGLE_16* rect, const RECTANGLE_16* clip);
+
+ FREERDP_API WINPR_DEPRECATED_VAR(
+ "Use shadow_capture_compare_with_format",
+ int shadow_capture_compare(const BYTE* WINPR_RESTRICT pData1, UINT32 nStep1, UINT32 nWidth,
+ UINT32 nHeight, const BYTE* WINPR_RESTRICT pData2, UINT32 nStep2,
+ RECTANGLE_16* WINPR_RESTRICT rect));
+
+ FREERDP_API int shadow_capture_compare_with_format(const BYTE* WINPR_RESTRICT pData1,
+ UINT32 format1, UINT32 nStep1, UINT32 nWidth,
+ UINT32 nHeight,
+ const BYTE* WINPR_RESTRICT pData2,
+ UINT32 format2, UINT32 nStep2,
+ RECTANGLE_16* WINPR_RESTRICT rect);
FREERDP_API void shadow_subsystem_frame_update(rdpShadowSubsystem* subsystem);
diff --git a/include/freerdp/settings.h b/include/freerdp/settings.h
index cd89b32..705ba45 100644
--- a/include/freerdp/settings.h
+++ b/include/freerdp/settings.h
@@ -164,6 +164,17 @@ typedef struct rdp_settings rdpSettings;
const char* option, const char* value);
FREERDP_API BOOL freerdp_device_collection_add(rdpSettings* settings, RDPDR_DEVICE* device);
+
+ /** \brief Removed a device from the settings, returns ownership of the allocated device to
+ * caller.
+ *
+ * \param settings the settings to remove the device from
+ * \param device the device to remove
+ *
+ * \return \b TRUE if the device was removed, \b FALSE if device was not found or is NULL
+ */
+ FREERDP_API BOOL freerdp_device_collection_del(rdpSettings* settings,
+ const RDPDR_DEVICE* device);
FREERDP_API RDPDR_DEVICE* freerdp_device_collection_find(rdpSettings* settings,
const char* name);
FREERDP_API RDPDR_DEVICE* freerdp_device_collection_find_type(rdpSettings* settings,
diff --git a/include/freerdp/settings_types_private.h b/include/freerdp/settings_types_private.h
index 6d23110..4f1c71e 100644
--- a/include/freerdp/settings_types_private.h
+++ b/include/freerdp/settings_types_private.h
@@ -213,7 +213,8 @@ struct rdp_settings
SETTINGS_DEPRECATED(ALIGN64 ARC_CS_PRIVATE_PACKET* ClientAutoReconnectCookie); /* 834 */
SETTINGS_DEPRECATED(ALIGN64 ARC_SC_PRIVATE_PACKET* ServerAutoReconnectCookie); /* 835 */
SETTINGS_DEPRECATED(ALIGN64 BOOL PrintReconnectCookie); /* 836 */
- UINT64 padding0896[896 - 837]; /* 837 */
+ SETTINGS_DEPRECATED(ALIGN64 BOOL AutoReconnectionPacketSupported); /* 837 */
+ UINT64 padding0896[896 - 838]; /* 838 */
/* Client Info (Time Zone) */
SETTINGS_DEPRECATED(ALIGN64 TIME_ZONE_INFORMATION* ClientTimeZone); /* 896 */
@@ -467,7 +468,8 @@ struct rdp_settings
SETTINGS_DEPRECATED(ALIGN64 char* GatewayAvdDiagnosticserviceurl); /* 2009 */
SETTINGS_DEPRECATED(ALIGN64 char* GatewayAvdHubdiscoverygeourl); /* 2010 */
SETTINGS_DEPRECATED(ALIGN64 char* GatewayAvdActivityhint); /* 2011 */
- UINT64 padding2015[2015 - 2012]; /* 2012 */
+ SETTINGS_DEPRECATED(ALIGN64 BOOL GatewayIgnoreRedirectionPolicy); /* 2012 */
+ UINT64 padding2015[2015 - 2013]; /* 2013 */
/* Proxy */
SETTINGS_DEPRECATED(ALIGN64 UINT32 ProxyType); /* 2015 */
diff --git a/include/freerdp/utils/encoded_types.h b/include/freerdp/utils/encoded_types.h
index b3852fe..c1f45e6 100644
--- a/include/freerdp/utils/encoded_types.h
+++ b/include/freerdp/utils/encoded_types.h
@@ -29,9 +29,18 @@ extern "C"
{
#endif
+#define FREERDP_FOUR_BYTE_SIGNED_INT_MAX 0x1FFFFFFFl
+#define FREERDP_FOUR_BYTE_SIGNED_INT_MIN -0x1FFFFFFFl
+
+#define FREERDP_FOUR_BYTE_FLOAT_MAX 0x3FFFFFF
+#define FREERDP_FOUR_BYTE_FLOAT_MIN -0x3FFFFFF
+
FREERDP_API BOOL freerdp_read_four_byte_signed_integer(wStream* s, INT32* value);
+ FREERDP_API BOOL freerdp_write_four_byte_signed_integer(wStream* s, INT32 value);
FREERDP_API BOOL freerdp_read_four_byte_float(wStream* s, double* value);
+ FREERDP_API BOOL freerdp_read_four_byte_float_exp(wStream* s, double* value, BYTE* exp);
+ FREERDP_API BOOL freerdp_write_four_byte_float(wStream* s, double value);
#ifdef __cplusplus
}
diff --git a/libfreerdp/CMakeLists.txt b/libfreerdp/CMakeLists.txt
index 5b47d98..54c9cd1 100644
--- a/libfreerdp/CMakeLists.txt
+++ b/libfreerdp/CMakeLists.txt
@@ -21,15 +21,6 @@ set(MODULE_PREFIX "FREERDP")
# CMake modules includes
include(FindCairo)
-# Create imported targets for Intel IPP libraries
-
-if(IPP_FOUND)
- foreach(ipp_lib ${IPP_LIBRARIES})
- add_library("${ipp_lib}_imported" STATIC IMPORTED)
- set_property(TARGET "${ipp_lib}_imported" PROPERTY IMPORTED_LOCATION "${IPP_LIBRARY_DIRS}/${ipp_lib}")
- endforeach()
-endif()
-
set(LIBFREERDP_DIR ${CMAKE_CURRENT_SOURCE_DIR})
set(LIBFREERDP_SRCS "")
set(LIBFREERDP_LIBS "")
@@ -376,15 +367,6 @@ set(PRIMITIVES_OPT_SRCS
${PRIMITIVES_SSSE3_SRCS}
${PRIMITIVES_OPENCL_SRCS})
-### IPP Variable debugging
-if(WITH_IPP)
- if(CMAKE_COMPILER_IS_GNUCC OR ${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
- foreach(INCLDIR ${IPP_INCLUDE_DIRS})
- set(OPTIMIZATION "${OPTIMIZATION} -I${INCLDIR}")
- endforeach(INCLDIR)
- endif()
-endif()
-
if(WITH_SSE2)
if(CMAKE_COMPILER_IS_GNUCC OR ${CMAKE_C_COMPILER_ID} STREQUAL "Clang")
set_source_files_properties(${PRIMITIVES_SSE2_SRCS}
@@ -413,13 +395,6 @@ set(PRIMITIVES_SRCS ${PRIMITIVES_SRCS} ${PRIMITIVES_OPT_SRCS})
freerdp_module_add(${PRIMITIVES_SRCS})
-if(IPP_FOUND)
- freerdp_include_directory_add(${IPP_INCLUDE_DIRS})
- foreach(ipp_lib ${IPP_LIBRARIES})
- freerdp_library_add("${ipp_lib}_imported")
- endforeach()
-endif()
-
if(BUILD_TESTING AND NOT WIN32 AND NOT APPLE)
add_subdirectory(primitives/test)
endif()
@@ -430,37 +405,13 @@ endif()
list(APPEND LIBFREERDP_PUB_LIBS winpr)
list(REMOVE_DUPLICATES LIBFREERDP_DEFINITIONS)
-list(REMOVE_DUPLICATES LIBFREERDP_LIBS)
-list(REMOVE_DUPLICATES LIBFREERDP_PUB_LIBS)
list(REMOVE_DUPLICATES LIBFREERDP_INCLUDES)
include_directories(${LIBFREERDP_INCLUDES})
-# On windows create dll version information.
-# Vendor, product and year are already set in top level CMakeLists.txt
-if (WIN32)
- set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
- set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR})
- set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION})
- set (RC_VERSION_FILE "${CMAKE_SHARED_LIBRARY_PREFIX}${MODULE_NAME}${FREERDP_API_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}" )
+AddTargetWithResourceFile(${MODULE_NAME} FALSE "${FREERDP_VERSION}" LIBFREERDP_SRCS)
- configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
- set (LIBFREERDP_SRCS ${LIBFREERDP_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-endif()
-
-add_library(${MODULE_NAME} ${LIBFREERDP_SRCS})
add_definitions(${LIBFREERDP_DEFINITIONS})
-set_target_properties(${MODULE_NAME} PROPERTIES LINKER_LANGUAGE C)
-set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME ${MODULE_NAME}${FREERDP_VERSION_MAJOR})
-
-if (WITH_LIBRARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION})
-endif()
-
target_include_directories(${MODULE_NAME} INTERFACE $<INSTALL_INTERFACE:include>)
target_link_libraries(${MODULE_NAME} PRIVATE ${LIBFREERDP_LIBS})
target_link_libraries(${MODULE_NAME} PUBLIC ${LIBFREERDP_PUB_LIBS})
@@ -469,14 +420,19 @@ install(TARGETS ${MODULE_NAME} COMPONENT libraries EXPORT FreeRDPTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-if (WITH_DEBUG_SYMBOLS AND MSVC AND BUILD_SHARED_LIBS)
- get_target_property(OUTPUT_FILENAME ${MODULE_NAME} OUTPUT_NAME)
- install(FILES ${CMAKE_PDB_BINARY_DIR}/${OUTPUT_FILENAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT symbols)
-endif()
-
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/libfreerdp")
include(pkg-config-install-prefix)
+set(FREERDP_REQUIRES_PRIVATE "")
+if(cJSON_FOUND)
+ string(APPEND FREERDP_REQUIRES_PRIVATE " libcjson")
+ list(APPEND FREERDP_PC_PRIVATE_LIBS "-lcjson")
+endif()
+if(WITH_SMARTCARD_EMULATE)
+ string(APPEND FREERDP_REQUIRES_PRIVATE " zlib")
+ list(APPEND FREERDP_PC_PRIVATE_LIBS "-lz")
+endif()
+list(JOIN FREERDP_PC_PRIVATE_LIBS " " FREERDP_PC_PRIVATE_LIBS)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/freerdp.pc.in ${CMAKE_CURRENT_BINARY_DIR}/freerdp${FREERDP_VERSION_MAJOR}.pc @ONLY)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/freerdp${FREERDP_VERSION_MAJOR}.pc DESTINATION ${PKG_CONFIG_PC_INSTALL_DIR})
diff --git a/libfreerdp/FreeRDPConfig.cmake.in b/libfreerdp/FreeRDPConfig.cmake.in
index 21ecd59..0052c3d 100644
--- a/libfreerdp/FreeRDPConfig.cmake.in
+++ b/libfreerdp/FreeRDPConfig.cmake.in
@@ -1,5 +1,11 @@
include(CMakeFindDependencyMacro)
find_dependency(WinPR @FREERDP_VERSION@)
+if("@cJSON_FOUND@" AND NOT "@BUILD_SHARED_LIBS@")
+ find_dependency(cJSON)
+endif()
+if("@WITH_SMARTCARD_EMULATE@" AND NOT "@BUILD_SHARED_LIBS@")
+ find_dependency(ZLIB)
+endif()
@PACKAGE_INIT@
diff --git a/libfreerdp/codec/clear.c b/libfreerdp/codec/clear.c
index 5c009d8..512aeae 100644
--- a/libfreerdp/codec/clear.c
+++ b/libfreerdp/codec/clear.c
@@ -409,7 +409,7 @@ static BOOL clear_decompress_residual_data(CLEAR_CONTEXT* clear, wStream* s,
}
}
- if ((pixelIndex + runLengthFactor) > pixelCount)
+ if ((pixelIndex >= pixelCount) || (runLengthFactor > (pixelCount - pixelIndex)))
{
WLog_ERR(TAG,
"pixelIndex %" PRIu32 " + runLengthFactor %" PRIu32 " > pixelCount %" PRIu32
diff --git a/libfreerdp/codec/interleaved.c b/libfreerdp/codec/interleaved.c
index 75b2e27..df148b6 100644
--- a/libfreerdp/codec/interleaved.c
+++ b/libfreerdp/codec/interleaved.c
@@ -237,7 +237,7 @@ static UINT ExtractRunLengthLiteFgBg(const BYTE* pbOrderHdr, const BYTE* pbEnd,
runLength = *pbOrderHdr & g_MaskLiteRunLength;
if (runLength == 0)
{
- if (!buffer_within_range(pbOrderHdr, 1, pbEnd))
+ if (!buffer_within_range(pbOrderHdr, 2, pbEnd))
{
*advance = 0;
return 0;
diff --git a/libfreerdp/codec/ncrush.c b/libfreerdp/codec/ncrush.c
index 4a7162c..28b98d9 100644
--- a/libfreerdp/codec/ncrush.c
+++ b/libfreerdp/codec/ncrush.c
@@ -2068,6 +2068,12 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSi
return 1;
}
+ if (SrcSize < 4)
+ {
+ WLog_ERR(TAG, "Input size short: SrcSize %" PRIu32 " < 4", SrcSize);
+ return -1;
+ }
+
const BYTE* SrcEnd = &pSrcData[SrcSize];
const BYTE* SrcPtr = pSrcData + 4;
@@ -2119,7 +2125,7 @@ int ncrush_decompress(NCRUSH_CONTEXT* ncrush, const BYTE* pSrcData, UINT32 SrcSi
CopyOffset = ncrush->OffsetCache[OffsetCacheIndex];
const UINT16 Mask = get_word(&HuffTableMask[21]);
const UINT32 MaskedBits = bits & Mask;
- if (MaskedBits > ARRAYSIZE(HuffTableLOM))
+ if (MaskedBits >= ARRAYSIZE(HuffTableLOM))
return -1;
LengthOfMatch = HuffTableLOM[MaskedBits] & 0xFFF;
BitLength = HuffTableLOM[MaskedBits] >> 12;
@@ -2480,50 +2486,39 @@ static int ncrush_find_best_match(NCRUSH_CONTEXT* ncrush, UINT16 HistoryOffset,
static int ncrush_move_encoder_windows(NCRUSH_CONTEXT* ncrush, BYTE* HistoryPtr)
{
- int NewHash = 0;
- int NewMatch = 0;
- UINT32 HistoryOffset = 0;
-
WINPR_ASSERT(ncrush);
WINPR_ASSERT(HistoryPtr);
- if (HistoryPtr < &ncrush->HistoryBuffer[32768])
+ const size_t history_half = ARRAYSIZE(ncrush->HistoryBuffer) / 2;
+ if (HistoryPtr < &ncrush->HistoryBuffer[history_half])
return -1;
- if (HistoryPtr > &ncrush->HistoryBuffer[65536])
+ if (HistoryPtr > &ncrush->HistoryBuffer[ARRAYSIZE(ncrush->HistoryBuffer)])
return -1;
- MoveMemory(ncrush->HistoryBuffer, HistoryPtr - 32768, 32768);
- const intptr_t hsize = HistoryPtr - 32768 - ncrush->HistoryBuffer;
- WINPR_ASSERT(hsize <= UINT32_MAX);
+ MoveMemory(ncrush->HistoryBuffer, HistoryPtr - history_half, history_half * sizeof(BYTE));
+ const intptr_t hsize = HistoryPtr - history_half - ncrush->HistoryBuffer;
+ WINPR_ASSERT(hsize <= UINT16_MAX);
WINPR_ASSERT(hsize >= 0);
- HistoryOffset = (UINT32)hsize;
+ INT32 HistoryOffset = (INT32)hsize;
- for (int i = 0; i < 65536; i += 4)
+ for (size_t i = 0; i < ARRAYSIZE(ncrush->HashTable); i++)
{
- NewHash = ncrush->HashTable[i + 0] - HistoryOffset;
- ncrush->HashTable[i + 0] = (NewHash <= 0) ? 0 : NewHash;
- NewHash = ncrush->HashTable[i + 1] - HistoryOffset;
- ncrush->HashTable[i + 1] = (NewHash <= 0) ? 0 : NewHash;
- NewHash = ncrush->HashTable[i + 2] - HistoryOffset;
- ncrush->HashTable[i + 2] = (NewHash <= 0) ? 0 : NewHash;
- NewHash = ncrush->HashTable[i + 3] - HistoryOffset;
- ncrush->HashTable[i + 3] = (NewHash <= 0) ? 0 : NewHash;
+ INT32 NewHash = ncrush->HashTable[i] - HistoryOffset;
+ ncrush->HashTable[i] = (NewHash <= 0) ? 0 : NewHash;
}
- for (int j = 0; j < 32768; j += 4)
+ const size_t match_half = ARRAYSIZE(ncrush->MatchTable) / 2;
+ for (size_t j = 0; j < match_half; j++)
{
- NewMatch = ncrush->MatchTable[HistoryOffset + j + 0] - HistoryOffset;
- ncrush->MatchTable[j + 0] = (NewMatch <= 0) ? 0 : NewMatch;
- NewMatch = ncrush->MatchTable[HistoryOffset + j + 1] - HistoryOffset;
- ncrush->MatchTable[j + 1] = (NewMatch <= 0) ? 0 : NewMatch;
- NewMatch = ncrush->MatchTable[HistoryOffset + j + 2] - HistoryOffset;
- ncrush->MatchTable[j + 2] = (NewMatch <= 0) ? 0 : NewMatch;
- NewMatch = ncrush->MatchTable[HistoryOffset + j + 3] - HistoryOffset;
- ncrush->MatchTable[j + 3] = (NewMatch <= 0) ? 0 : NewMatch;
+ if (HistoryOffset + j >= ARRAYSIZE(ncrush->MatchTable))
+ continue;
+
+ INT32 NewMatch = ncrush->MatchTable[HistoryOffset + j] - HistoryOffset;
+ ncrush->MatchTable[j] = (NewMatch <= 0) ? 0 : NewMatch;
}
- ZeroMemory(&ncrush->MatchTable[32768], 65536);
+ ZeroMemory(&ncrush->MatchTable[match_half], match_half * sizeof(UINT16));
return 1;
}
diff --git a/libfreerdp/codec/nsc.c b/libfreerdp/codec/nsc.c
index 049b541..74f4e28 100644
--- a/libfreerdp/codec/nsc.c
+++ b/libfreerdp/codec/nsc.c
@@ -160,7 +160,7 @@ static BOOL nsc_rle_decode(const BYTE* in, size_t inSize, BYTE* out, UINT32 outS
len |= ((UINT32)(*in++)) << 24U;
}
- if (outSize < len)
+ if ((outSize < len) || (left < len))
return FALSE;
outSize -= len;
@@ -262,7 +262,7 @@ static BOOL nsc_context_initialize(NSC_CONTEXT* context, wStream* s)
if (!nsc_stream_initialize(context, s))
return FALSE;
- const size_t blength = context->width * context->height * 4ull;
+ const size_t blength = 4ull * context->width * context->height;
if (!context->BitmapData || (blength > context->BitmapDataLength))
{
diff --git a/libfreerdp/codec/planar.c b/libfreerdp/codec/planar.c
index 0ec0862..4b51a02 100644
--- a/libfreerdp/codec/planar.c
+++ b/libfreerdp/codec/planar.c
@@ -788,18 +788,26 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
rawHeights[3] = nSrcHeight;
}
+ const size_t diff = srcp - pSrcData;
+ if (SrcSize < diff)
+ {
+ WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff);
+ return FALSE;
+ }
+
if (!rle) /* RAW */
{
+
UINT32 base = planeSize * 3;
if (cs)
base = planeSize + planeSize / 2;
if (alpha)
{
- if ((SrcSize - (srcp - pSrcData)) < (planeSize + base))
+ if ((SrcSize - diff) < (planeSize + base))
{
- WLog_ERR(TAG, "Alpha plane size mismatch %" PRIu32 " < %" PRIu32,
- SrcSize - (srcp - pSrcData), (planeSize + base));
+ WLog_ERR(TAG, "Alpha plane size mismatch %" PRIuz " < %" PRIu32, SrcSize - diff,
+ (planeSize + base));
return FALSE;
}
@@ -817,10 +825,9 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
}
else
{
- if ((SrcSize - (srcp - pSrcData)) < base)
+ if ((SrcSize - diff) < base)
{
- WLog_ERR(TAG, "plane size mismatch %" PRIu32 " < %" PRIu32,
- SrcSize - (srcp - pSrcData), base);
+ WLog_ERR(TAG, "plane size mismatch %" PRIu32 " < %" PRIu32, SrcSize - diff, base);
return FALSE;
}
@@ -841,8 +848,8 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
if (alpha)
{
planes[3] = srcp;
- rleSizes[3] = planar_skip_plane_rle(planes[3], SrcSize - (planes[3] - pSrcData),
- rawWidths[3], rawHeights[3]); /* AlphaPlane */
+ rleSizes[3] = planar_skip_plane_rle(planes[3], SrcSize - diff, rawWidths[3],
+ rawHeights[3]); /* AlphaPlane */
if (rleSizes[3] < 0)
return FALSE;
@@ -852,22 +859,41 @@ BOOL planar_decompress(BITMAP_PLANAR_CONTEXT* planar, const BYTE* pSrcData, UINT
else
planes[0] = srcp;
- rleSizes[0] = planar_skip_plane_rle(planes[0], SrcSize - (planes[0] - pSrcData),
- rawWidths[0], rawHeights[0]); /* RedPlane */
+ const size_t diff0 = (planes[0] - pSrcData);
+ if (SrcSize < diff0)
+ {
+ WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff0);
+ return FALSE;
+ }
+ rleSizes[0] = planar_skip_plane_rle(planes[0], SrcSize - diff0, rawWidths[0],
+ rawHeights[0]); /* RedPlane */
if (rleSizes[0] < 0)
return FALSE;
planes[1] = planes[0] + rleSizes[0];
- rleSizes[1] = planar_skip_plane_rle(planes[1], SrcSize - (planes[1] - pSrcData),
- rawWidths[1], rawHeights[1]); /* GreenPlane */
+
+ const size_t diff1 = (planes[1] - pSrcData);
+ if (SrcSize < diff1)
+ {
+ WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff1);
+ return FALSE;
+ }
+ rleSizes[1] = planar_skip_plane_rle(planes[1], SrcSize - diff1, rawWidths[1],
+ rawHeights[1]); /* GreenPlane */
if (rleSizes[1] < 1)
return FALSE;
planes[2] = planes[1] + rleSizes[1];
- rleSizes[2] = planar_skip_plane_rle(planes[2], SrcSize - (planes[2] - pSrcData),
- rawWidths[2], rawHeights[2]); /* BluePlane */
+ const size_t diff2 = (planes[2] - pSrcData);
+ if (SrcSize < diff2)
+ {
+ WLog_ERR(TAG, "Size mismatch %" PRIu32 " < %" PRIuz, SrcSize, diff);
+ return FALSE;
+ }
+ rleSizes[2] = planar_skip_plane_rle(planes[2], SrcSize - diff2, rawWidths[2],
+ rawHeights[2]); /* BluePlane */
if (rleSizes[2] < 1)
return FALSE;
diff --git a/libfreerdp/codec/rfx.c b/libfreerdp/codec/rfx.c
index c83cfd5..66ed1e0 100644
--- a/libfreerdp/codec/rfx.c
+++ b/libfreerdp/codec/rfx.c
@@ -1368,7 +1368,7 @@ const RFX_TILE** rfx_message_get_tiles(const RFX_MESSAGE* message, UINT16* numTi
WINPR_ASSERT(message);
if (numTiles)
*numTiles = message->numTiles;
- return message->tiles;
+ return (const RFX_TILE**)message->tiles;
}
UINT16 rfx_message_get_tile_count(const RFX_MESSAGE* message)
diff --git a/libfreerdp/codec/rfx_rlgr.c b/libfreerdp/codec/rfx_rlgr.c
index da1b63f..6ecbfbe 100644
--- a/libfreerdp/codec/rfx_rlgr.c
+++ b/libfreerdp/codec/rfx_rlgr.c
@@ -50,12 +50,12 @@
#define GetMinBits(_val, _nbits) \
do \
{ \
- UINT32 _v = _val; \
- _nbits = 0; \
+ UINT32 _v = (_val); \
+ (_nbits) = 0; \
while (_v) \
{ \
_v >>= 1; \
- _nbits++; \
+ (_nbits)++; \
} \
} while (0)
@@ -66,12 +66,12 @@
#define UpdateParam(_param, _deltaP, _k) \
do \
{ \
- _param += _deltaP; \
- if (_param > KPMAX) \
- _param = KPMAX; \
- if (_param < 0) \
- _param = 0; \
- _k = (_param >> LSGR); \
+ (_param) += (_deltaP); \
+ if ((_param) > KPMAX) \
+ (_param) = KPMAX; \
+ if ((_param) < 0) \
+ (_param) = 0; \
+ (_k) = ((_param) >> LSGR); \
} while (0)
static BOOL g_LZCNT = FALSE;
@@ -568,18 +568,18 @@ int rfx_rlgr_decode(RLGR_MODE mode, const BYTE* WINPR_RESTRICT pSrcData, UINT32
}
/* Returns the next coefficient (a signed int) to encode, from the input stream */
-#define GetNextInput(_n) \
- do \
- { \
- if (data_size > 0) \
- { \
- _n = *data++; \
- data_size--; \
- } \
- else \
- { \
- _n = 0; \
- } \
+#define GetNextInput(_n) \
+ do \
+ { \
+ if (data_size > 0) \
+ { \
+ (_n) = *data++; \
+ data_size--; \
+ } \
+ else \
+ { \
+ (_n) = 0; \
+ } \
} while (0)
/* Emit bitPattern to the output bitstream */
diff --git a/libfreerdp/codec/test/CMakeLists.txt b/libfreerdp/codec/test/CMakeLists.txt
index 4258b50..ebc7b8e 100644
--- a/libfreerdp/codec/test/CMakeLists.txt
+++ b/libfreerdp/codec/test/CMakeLists.txt
@@ -35,3 +35,9 @@ endforeach()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "FreeRDP/Test")
+set(FUZZERS
+ TestFuzzCodecs.c
+)
+
+include (AddFuzzerTest)
+add_fuzzer_test("${FUZZERS}" "freerdp winpr")
diff --git a/libfreerdp/codec/test/TestFuzzCodecs.c b/libfreerdp/codec/test/TestFuzzCodecs.c
new file mode 100644
index 0000000..d83d8d4
--- /dev/null
+++ b/libfreerdp/codec/test/TestFuzzCodecs.c
@@ -0,0 +1,480 @@
+/* https://github.com/ergnoorr/fuzzrdp
+ *
+ * MIT License
+ *
+ * Copyright (c) 2024 ergnoorr
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+#include <freerdp/assistance.h>
+
+#include <winpr/crt.h>
+#include <winpr/print.h>
+#include <winpr/platform.h>
+#include <freerdp/codec/interleaved.h>
+#include <freerdp/codec/planar.h>
+#include <freerdp/codec/bulk.h>
+#include <freerdp/codec/clear.h>
+#include <freerdp/codec/zgfx.h>
+#include <freerdp/log.h>
+#include <winpr/bitstream.h>
+#include <freerdp/codec/rfx.h>
+#include <freerdp/codec/progressive.h>
+
+#include <freerdp/freerdp.h>
+#include <freerdp/gdi/gdi.h>
+
+#include "../progressive.h"
+#include "../mppc.h"
+#include "../xcrush.h"
+#include "../ncrush.h"
+
+static BOOL test_ClearDecompressExample(UINT32 nr, UINT32 width, UINT32 height,
+ const BYTE* pSrcData, const UINT32 SrcSize)
+{
+ BOOL rc = FALSE;
+ int status = 0;
+ BYTE* pDstData = calloc(1ull * width * height, 4);
+ CLEAR_CONTEXT* clear = clear_context_new(FALSE);
+
+ WINPR_UNUSED(nr);
+ if (!clear || !pDstData)
+ goto fail;
+
+ status = clear_decompress(clear, pSrcData, SrcSize, width, height, pDstData,
+ PIXEL_FORMAT_XRGB32, 0, 0, 0, width, height, NULL);
+ // printf("clear_decompress example %" PRIu32 " status: %d\n", nr, status);
+ // fflush(stdout);
+ rc = (status == 0);
+fail:
+ clear_context_free(clear);
+ free(pDstData);
+ return rc;
+}
+
+static int TestFreeRDPCodecClear(const uint8_t* Data, size_t Size)
+{
+ if (Size > UINT32_MAX)
+ return -1;
+ test_ClearDecompressExample(2, 78, 17, Data, (UINT32)Size);
+ test_ClearDecompressExample(3, 64, 24, Data, (UINT32)Size);
+ test_ClearDecompressExample(4, 7, 15, Data, (UINT32)Size);
+ return 0;
+}
+
+static int TestFreeRDPCodecXCrush(const uint8_t* Data, size_t Size)
+{
+ if (Size > UINT32_MAX)
+ return -1;
+
+ const BYTE* OutputBuffer = NULL;
+ UINT32 DstSize = 0;
+ XCRUSH_CONTEXT* xcrush = xcrush_context_new(TRUE);
+ if (!xcrush)
+ return 0;
+ xcrush_decompress(xcrush, Data, (UINT32)Size, &OutputBuffer, &DstSize, 0);
+ xcrush_context_free(xcrush);
+ return 0;
+}
+
+static int test_ZGfxDecompressFoxSingle(const uint8_t* Data, size_t Size)
+{
+ if (Size > UINT32_MAX)
+ return -1;
+ int rc = -1;
+ int status = 0;
+ UINT32 Flags = 0;
+ const BYTE* pSrcData = (const BYTE*)Data;
+ UINT32 SrcSize = (UINT32)Size;
+ UINT32 DstSize = 0;
+ BYTE* pDstData = NULL;
+ ZGFX_CONTEXT* zgfx = zgfx_context_new(TRUE);
+
+ if (!zgfx)
+ return -1;
+
+ status = zgfx_decompress(zgfx, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
+ if (status < 0)
+ goto fail;
+
+ rc = 0;
+fail:
+ free(pDstData);
+ zgfx_context_free(zgfx);
+ return rc;
+}
+
+static int TestFreeRDPCodecZGfx(const uint8_t* Data, size_t Size)
+{
+ test_ZGfxDecompressFoxSingle(Data, Size);
+ return 0;
+}
+
+static BOOL test_NCrushDecompressBells(const uint8_t* Data, size_t Size)
+{
+ if (Size > UINT32_MAX)
+ return FALSE;
+
+ BOOL rc = FALSE;
+ int status = 0;
+ UINT32 Flags = PACKET_COMPRESSED | 2;
+ const BYTE* pSrcData = (const BYTE*)Data;
+ UINT32 SrcSize = (UINT32)Size;
+ UINT32 DstSize = 0;
+ const BYTE* pDstData = NULL;
+ NCRUSH_CONTEXT* ncrush = ncrush_context_new(FALSE);
+
+ if (!ncrush)
+ return rc;
+
+ status = ncrush_decompress(ncrush, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
+ if (status < 0)
+ goto fail;
+
+ rc = TRUE;
+fail:
+ ncrush_context_free(ncrush);
+ return rc;
+}
+
+static int TestFreeRDPCodecNCrush(const uint8_t* Data, size_t Size)
+{
+ test_NCrushDecompressBells(Data, Size);
+ return 0;
+}
+
+static const size_t IMG_WIDTH = 64;
+static const size_t IMG_HEIGHT = 64;
+static const size_t FORMAT_SIZE = 4;
+static const UINT32 FORMAT = PIXEL_FORMAT_XRGB32;
+
+static int TestFreeRDPCodecRemoteFX(const uint8_t* Data, size_t Size)
+{
+ int rc = -1;
+ REGION16 region = { 0 };
+ RFX_CONTEXT* context = rfx_context_new(FALSE);
+ BYTE* dest = calloc(IMG_WIDTH * IMG_HEIGHT, FORMAT_SIZE);
+ size_t stride = FORMAT_SIZE * IMG_WIDTH;
+ if (!context)
+ goto fail;
+ if (Size > UINT32_MAX)
+ goto fail;
+ if (stride > UINT32_MAX)
+ goto fail;
+ if (!dest)
+ goto fail;
+
+ region16_init(&region);
+ if (!rfx_process_message(context, Data, (UINT32)Size, 0, 0, dest, FORMAT, (UINT32)stride,
+ IMG_HEIGHT, &region))
+ goto fail;
+
+ region16_clear(&region);
+ if (!rfx_process_message(context, Data, (UINT32)Size, 0, 0, dest, FORMAT, (UINT32)stride,
+ IMG_HEIGHT, &region))
+ goto fail;
+ region16_print(&region);
+
+ rc = 0;
+fail:
+ region16_uninit(&region);
+ rfx_context_free(context);
+ free(dest);
+ return rc;
+}
+
+static int test_MppcDecompressBellsRdp5(const uint8_t* Data, size_t Size)
+{
+ int rc = -1;
+ int status = 0;
+ UINT32 Flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 1;
+ const BYTE* pSrcData = Data;
+ UINT32 SrcSize = (UINT32)Size;
+ UINT32 DstSize = 0;
+ const BYTE* pDstData = NULL;
+ MPPC_CONTEXT* mppc = mppc_context_new(1, FALSE);
+
+ if (!mppc)
+ return -1;
+
+ status = mppc_decompress(mppc, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
+
+ if (status < 0)
+ goto fail;
+
+ rc = 0;
+
+fail:
+ mppc_context_free(mppc);
+ return rc;
+}
+
+static int test_MppcDecompressBellsRdp4(const uint8_t* Data, size_t Size)
+{
+ if (Size > UINT32_MAX)
+ return -1;
+ int rc = -1;
+ int status = 0;
+ UINT32 Flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 0;
+ const BYTE* pSrcData = (const BYTE*)Data;
+ UINT32 SrcSize = (UINT32)Size;
+ UINT32 DstSize = 0;
+ const BYTE* pDstData = NULL;
+ MPPC_CONTEXT* mppc = mppc_context_new(0, FALSE);
+
+ if (!mppc)
+ return -1;
+
+ status = mppc_decompress(mppc, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
+
+ if (status < 0)
+ goto fail;
+
+ rc = 0;
+fail:
+ mppc_context_free(mppc);
+ return rc;
+}
+
+static int test_MppcDecompressBufferRdp5(const uint8_t* Data, size_t Size)
+{
+ if (Size > UINT32_MAX)
+ return -1;
+ int rc = -1;
+ int status = 0;
+ UINT32 Flags = PACKET_AT_FRONT | PACKET_COMPRESSED | 1;
+ const BYTE* pSrcData = (const BYTE*)Data;
+ UINT32 SrcSize = (UINT32)Size;
+ UINT32 DstSize = 0;
+ const BYTE* pDstData = NULL;
+ MPPC_CONTEXT* mppc = mppc_context_new(1, FALSE);
+
+ if (!mppc)
+ return -1;
+
+ status = mppc_decompress(mppc, pSrcData, SrcSize, &pDstData, &DstSize, Flags);
+
+ if (status < 0)
+ goto fail;
+
+ rc = 0;
+fail:
+ mppc_context_free(mppc);
+ return rc;
+}
+
+static int TestFreeRDPCodecMppc(const uint8_t* Data, size_t Size)
+{
+ test_MppcDecompressBellsRdp5(Data, Size);
+ test_MppcDecompressBellsRdp4(Data, Size);
+ test_MppcDecompressBufferRdp5(Data, Size);
+ return 0;
+}
+
+static BOOL progressive_decode(const uint8_t* Data, size_t Size)
+{
+ BOOL res = FALSE;
+ int rc = 0;
+ BYTE* resultData = NULL;
+ UINT32 ColorFormat = PIXEL_FORMAT_BGRX32;
+ REGION16 invalidRegion = { 0 };
+ UINT32 scanline = 4240;
+ UINT32 width = 1060;
+ UINT32 height = 827;
+ if (Size > UINT32_MAX)
+ return FALSE;
+
+ PROGRESSIVE_CONTEXT* progressiveDec = progressive_context_new(FALSE);
+
+ region16_init(&invalidRegion);
+ if (!progressiveDec)
+ goto fail;
+
+ resultData = calloc(scanline, height);
+ if (!resultData)
+ goto fail;
+
+ rc = progressive_create_surface_context(progressiveDec, 0, width, height);
+ if (rc <= 0)
+ goto fail;
+
+ rc = progressive_decompress(progressiveDec, Data, (UINT32)Size, resultData, ColorFormat,
+ scanline, 0, 0, &invalidRegion, 0, 0);
+ if (rc < 0)
+ goto fail;
+
+ res = TRUE;
+fail:
+ region16_uninit(&invalidRegion);
+ progressive_context_free(progressiveDec);
+ free(resultData);
+ return res;
+}
+
+static int TestFreeRDPCodecProgressive(const uint8_t* Data, size_t Size)
+{
+ progressive_decode(Data, Size);
+ return 0;
+}
+
+static BOOL i_run_encode_decode(UINT16 bpp, BITMAP_INTERLEAVED_CONTEXT* encoder,
+ BITMAP_INTERLEAVED_CONTEXT* decoder, const uint8_t* Data,
+ size_t Size)
+{
+ BOOL rc2 = FALSE;
+ BOOL rc = 0;
+ const UINT32 w = 64;
+ const UINT32 h = 64;
+ const UINT32 x = 0;
+ const UINT32 y = 0;
+ const UINT32 format = PIXEL_FORMAT_RGBX32;
+ const size_t step = (w + 13ull) * 4ull;
+ const size_t SrcSize = step * h;
+ BYTE* pSrcData = calloc(1, SrcSize);
+ BYTE* pDstData = calloc(1, SrcSize);
+ BYTE* tmp = calloc(1, SrcSize);
+
+ WINPR_UNUSED(encoder);
+ if (!pSrcData || !pDstData || !tmp)
+ goto fail;
+
+ if (Size > UINT32_MAX)
+ goto fail;
+
+ winpr_RAND(pSrcData, SrcSize);
+
+ if (!bitmap_interleaved_context_reset(decoder))
+ goto fail;
+
+ rc = interleaved_decompress(decoder, Data, (UINT32)Size, w, h, bpp, pDstData, format, step, x,
+ y, w, h, NULL);
+
+ if (!rc)
+ goto fail;
+
+ rc2 = TRUE;
+fail:
+ free(pSrcData);
+ free(pDstData);
+ free(tmp);
+ return rc2;
+}
+
+static int TestFreeRDPCodecInterleaved(const uint8_t* Data, size_t Size)
+{
+ int rc = -1;
+ BITMAP_INTERLEAVED_CONTEXT* decoder = bitmap_interleaved_context_new(FALSE);
+
+ if (!decoder)
+ goto fail;
+
+ i_run_encode_decode(24, NULL, decoder, Data, Size);
+ i_run_encode_decode(16, NULL, decoder, Data, Size);
+ i_run_encode_decode(15, NULL, decoder, Data, Size);
+ rc = 0;
+fail:
+ bitmap_interleaved_context_free(decoder);
+ return rc;
+}
+
+static BOOL RunTestPlanar(BITMAP_PLANAR_CONTEXT* planar, const BYTE* srcBitmap,
+ const UINT32 srcFormat, const UINT32 dstFormat, const UINT32 width,
+ const UINT32 height, const uint8_t* Data, size_t Size)
+{
+ BOOL rc = FALSE;
+ WINPR_UNUSED(srcBitmap);
+ WINPR_UNUSED(srcFormat);
+ if (Size > UINT32_MAX)
+ return FALSE;
+ UINT32 dstSize = (UINT32)Size;
+ const BYTE* compressedBitmap = Data;
+ BYTE* decompressedBitmap =
+ (BYTE*)calloc(height, 1ull * width * FreeRDPGetBytesPerPixel(dstFormat));
+ rc = TRUE;
+
+ if (!decompressedBitmap)
+ goto fail;
+
+ if (!planar_decompress(planar, compressedBitmap, dstSize, width, height, decompressedBitmap,
+ dstFormat, 0, 0, 0, width, height, FALSE))
+ {
+ goto fail;
+ }
+
+ rc = TRUE;
+fail:
+ free(decompressedBitmap);
+ return rc;
+}
+
+static BOOL TestPlanar(const UINT32 format, const uint8_t* Data, size_t Size)
+{
+ BOOL rc = FALSE;
+ const DWORD planarFlags = PLANAR_FORMAT_HEADER_NA | PLANAR_FORMAT_HEADER_RLE;
+ BITMAP_PLANAR_CONTEXT* planar = freerdp_bitmap_planar_context_new(planarFlags, 64, 64);
+
+ if (!planar)
+ goto fail;
+
+ RunTestPlanar(planar, NULL, PIXEL_FORMAT_RGBX32, format, 64, 64, Data, Size);
+
+ RunTestPlanar(planar, NULL, PIXEL_FORMAT_RGB16, format, 32, 32, Data, Size);
+
+ rc = TRUE;
+fail:
+ freerdp_bitmap_planar_context_free(planar);
+ return rc;
+}
+
+static int TestFreeRDPCodecPlanar(const uint8_t* Data, size_t Size)
+{
+ TestPlanar(0, Data, Size);
+ return 0;
+}
+
+int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size)
+{
+ if (Size < 4)
+ return 0;
+
+ int i = 0;
+ winpr_RAND(&i, sizeof(i));
+ i = i % 18;
+
+ if (i < 2)
+ TestFreeRDPCodecClear(Data, Size);
+ else if (i < 4)
+ TestFreeRDPCodecXCrush(Data, Size);
+ else if (i < 6)
+ TestFreeRDPCodecZGfx(Data, Size);
+ else if (i < 8)
+ TestFreeRDPCodecNCrush(Data, Size);
+ else if (i < 10)
+ TestFreeRDPCodecRemoteFX(Data, Size);
+ else if (i < 12)
+ TestFreeRDPCodecMppc(Data, Size);
+ else if (i < 14)
+ TestFreeRDPCodecProgressive(Data, Size);
+ else if (i < 16)
+ TestFreeRDPCodecInterleaved(Data, Size);
+ else if (i < 18)
+ TestFreeRDPCodecPlanar(Data, Size);
+
+ return 0;
+}
diff --git a/libfreerdp/codec/zgfx.c b/libfreerdp/codec/zgfx.c
index 881823a..b7ee275 100644
--- a/libfreerdp/codec/zgfx.c
+++ b/libfreerdp/codec/zgfx.c
@@ -227,7 +227,10 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
BYTE* pbSegment = NULL;
size_t cbSegment = 0;
- if (!zgfx || !stream || (segmentSize < 2))
+ WINPR_ASSERT(zgfx);
+ WINPR_ASSERT(stream);
+
+ if (segmentSize < 2)
return FALSE;
cbSegment = segmentSize - 1;
@@ -346,8 +349,9 @@ static BOOL zgfx_decompress_segment(ZGFX_CONTEXT* zgfx, wStream* stream, size_t
if (count > sizeof(zgfx->OutputBuffer) - zgfx->OutputCount)
return FALSE;
-
- if (count > zgfx->cBitsRemaining / 8)
+ else if (count > zgfx->cBitsRemaining / 8)
+ return FALSE;
+ else if (zgfx->pbInputCurrent + count > zgfx->pbInputEnd)
return FALSE;
CopyMemory(&(zgfx->OutputBuffer[zgfx->OutputCount]), zgfx->pbInputCurrent,
@@ -386,8 +390,8 @@ int zgfx_decompress(ZGFX_CONTEXT* zgfx, const BYTE* pSrcData, UINT32 SrcSize, BY
wStream sbuffer = { 0 };
wStream* stream = Stream_StaticConstInit(&sbuffer, pSrcData, SrcSize);
- if (!stream)
- return -1;
+ WINPR_ASSERT(zgfx);
+ WINPR_ASSERT(stream);
if (!Stream_CheckAndLogRequiredLength(TAG, stream, 1))
goto fail;
diff --git a/libfreerdp/common/settings.c b/libfreerdp/common/settings.c
index 34712c8..3beba43 100644
--- a/libfreerdp/common/settings.c
+++ b/libfreerdp/common/settings.c
@@ -237,6 +237,33 @@ BOOL freerdp_device_collection_add(rdpSettings* settings, RDPDR_DEVICE* device)
return TRUE;
}
+BOOL freerdp_device_collection_del(rdpSettings* settings, const RDPDR_DEVICE* device)
+{
+ WINPR_ASSERT(settings);
+
+ if (!device)
+ return FALSE;
+
+ const UINT32 count = settings->DeviceCount;
+ for (size_t x = 0; x < count; x++)
+ {
+ const RDPDR_DEVICE* cur = settings->DeviceArray[x];
+ if (cur == device)
+ {
+ for (size_t y = x + 1; y < count; y++)
+ {
+ RDPDR_DEVICE* next = settings->DeviceArray[y];
+ settings->DeviceArray[y - 1] = next;
+ }
+ settings->DeviceArray[count - 1] = NULL;
+ settings->DeviceCount--;
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
RDPDR_DEVICE* freerdp_device_collection_find(rdpSettings* settings, const char* name)
{
RDPDR_DEVICE* device = NULL;
@@ -392,6 +419,9 @@ fail:
void freerdp_device_free(RDPDR_DEVICE* device)
{
+ if (!device)
+ return;
+
union
{
RDPDR_DEVICE* dev;
@@ -403,8 +433,6 @@ void freerdp_device_free(RDPDR_DEVICE* device)
} cnv;
cnv.dev = device;
- if (!cnv.dev)
- return;
switch (device->Type)
{
@@ -1166,8 +1194,10 @@ BOOL freerdp_settings_set_value_for_name(rdpSettings* settings, const char* name
case RDP_SETTINGS_TYPE_BOOL:
{
- BOOL val = _strnicmp(value, "TRUE", 5) == 0;
- if (!val && _strnicmp(value, "FALSE", 6) != 0)
+ const BOOL val = (_strnicmp(value, "TRUE", 5) == 0) || (_strnicmp(value, "ON", 5) == 0);
+ const BOOL nval =
+ (_strnicmp(value, "FALSE", 6) == 0) || (_strnicmp(value, "OFF", 6) == 0);
+ if (!val && !nval)
return parsing_fail(name, "BOOL", value);
return freerdp_settings_set_bool(settings, (FreeRDP_Settings_Keys_Bool)index, val);
}
diff --git a/libfreerdp/common/settings_getters.c b/libfreerdp/common/settings_getters.c
index ecec044..88f1fcb 100644
--- a/libfreerdp/common/settings_getters.c
+++ b/libfreerdp/common/settings_getters.c
@@ -105,6 +105,9 @@ BOOL freerdp_settings_get_bool(const rdpSettings* settings, FreeRDP_Settings_Key
case FreeRDP_AutoReconnectionEnabled:
return settings->AutoReconnectionEnabled;
+ case FreeRDP_AutoReconnectionPacketSupported:
+ return settings->AutoReconnectionPacketSupported;
+
case FreeRDP_BitmapCacheEnabled:
return settings->BitmapCacheEnabled;
@@ -252,6 +255,9 @@ BOOL freerdp_settings_get_bool(const rdpSettings* settings, FreeRDP_Settings_Key
case FreeRDP_GatewayHttpUseWebsockets:
return settings->GatewayHttpUseWebsockets;
+ case FreeRDP_GatewayIgnoreRedirectionPolicy:
+ return settings->GatewayIgnoreRedirectionPolicy;
+
case FreeRDP_GatewayRpcTransport:
return settings->GatewayRpcTransport;
@@ -712,6 +718,10 @@ BOOL freerdp_settings_set_bool(rdpSettings* settings, FreeRDP_Settings_Keys_Bool
settings->AutoReconnectionEnabled = cnv.c;
break;
+ case FreeRDP_AutoReconnectionPacketSupported:
+ settings->AutoReconnectionPacketSupported = cnv.c;
+ break;
+
case FreeRDP_BitmapCacheEnabled:
settings->BitmapCacheEnabled = cnv.c;
break;
@@ -908,6 +918,10 @@ BOOL freerdp_settings_set_bool(rdpSettings* settings, FreeRDP_Settings_Keys_Bool
settings->GatewayHttpUseWebsockets = cnv.c;
break;
+ case FreeRDP_GatewayIgnoreRedirectionPolicy:
+ settings->GatewayIgnoreRedirectionPolicy = cnv.c;
+ break;
+
case FreeRDP_GatewayRpcTransport:
settings->GatewayRpcTransport = cnv.c;
break;
diff --git a/libfreerdp/common/settings_str.h b/libfreerdp/common/settings_str.h
index a3c71fb..27939bd 100644
--- a/libfreerdp/common/settings_str.h
+++ b/libfreerdp/common/settings_str.h
@@ -50,6 +50,8 @@ static const struct settings_str_entry settings_map[] = {
{ FreeRDP_AutoLogonEnabled, FREERDP_SETTINGS_TYPE_BOOL, "FreeRDP_AutoLogonEnabled" },
{ FreeRDP_AutoReconnectionEnabled, FREERDP_SETTINGS_TYPE_BOOL,
"FreeRDP_AutoReconnectionEnabled" },
+ { FreeRDP_AutoReconnectionPacketSupported, FREERDP_SETTINGS_TYPE_BOOL,
+ "FreeRDP_AutoReconnectionPacketSupported" },
{ FreeRDP_BitmapCacheEnabled, FREERDP_SETTINGS_TYPE_BOOL, "FreeRDP_BitmapCacheEnabled" },
{ FreeRDP_BitmapCachePersistEnabled, FREERDP_SETTINGS_TYPE_BOOL,
"FreeRDP_BitmapCachePersistEnabled" },
@@ -114,6 +116,8 @@ static const struct settings_str_entry settings_map[] = {
{ FreeRDP_GatewayHttpTransport, FREERDP_SETTINGS_TYPE_BOOL, "FreeRDP_GatewayHttpTransport" },
{ FreeRDP_GatewayHttpUseWebsockets, FREERDP_SETTINGS_TYPE_BOOL,
"FreeRDP_GatewayHttpUseWebsockets" },
+ { FreeRDP_GatewayIgnoreRedirectionPolicy, FREERDP_SETTINGS_TYPE_BOOL,
+ "FreeRDP_GatewayIgnoreRedirectionPolicy" },
{ FreeRDP_GatewayRpcTransport, FREERDP_SETTINGS_TYPE_BOOL, "FreeRDP_GatewayRpcTransport" },
{ FreeRDP_GatewayUdpTransport, FREERDP_SETTINGS_TYPE_BOOL, "FreeRDP_GatewayUdpTransport" },
{ FreeRDP_GatewayUseSameCredentials, FREERDP_SETTINGS_TYPE_BOOL,
diff --git a/libfreerdp/common/test/CMakeLists.txt b/libfreerdp/common/test/CMakeLists.txt
index c1f871b..da832a8 100644
--- a/libfreerdp/common/test/CMakeLists.txt
+++ b/libfreerdp/common/test/CMakeLists.txt
@@ -8,7 +8,7 @@ set(${MODULE_PREFIX}_TESTS
TestAddinArgv.c
TestCommonAssistance.c)
-set(${MODULE_PREFIX}_FUZZERS
+set(FUZZERS
TestFuzzCommonAssistanceParseFileBuffer.c
TestFuzzCommonAssistanceBinToHexString.c
TestFuzzCommonAssistanceHexStringToBin.c)
@@ -21,17 +21,8 @@ add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
target_link_libraries(${MODULE_NAME} freerdp winpr)
-if (BUILD_FUZZERS)
- foreach(test ${${MODULE_PREFIX}_FUZZERS})
- get_filename_component(TestName ${test} NAME_WE)
- add_executable(${TestName} ${test})
- # Use PUBLIC to force 'fuzzer_config' for all dependent targets.
- target_link_libraries(${TestName} PUBLIC freerdp winpr fuzzer_config)
- add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
- set_target_properties(${TestName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
- add_dependencies(fuzzers ${TestName})
- endforeach()
-endif (BUILD_FUZZERS)
+include (AddFuzzerTest)
+add_fuzzer_test("${FUZZERS}" "freerdp winpr")
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
diff --git a/libfreerdp/core/aad.c b/libfreerdp/core/aad.c
index 72204d7..15eabed 100644
--- a/libfreerdp/core/aad.c
+++ b/libfreerdp/core/aad.c
@@ -210,8 +210,8 @@ cJSON* cJSON_ParseWithLength(const char* value, size_t buffer_length)
static INLINE const char* aad_auth_result_to_string(DWORD code)
{
-#define ERROR_CASE(cd, x) \
- if (cd == (DWORD)(x)) \
+#define ERROR_CASE(cd, x) \
+ if ((cd) == (DWORD)(x)) \
return #x;
ERROR_CASE(code, S_OK)
diff --git a/libfreerdp/core/capabilities.c b/libfreerdp/core/capabilities.c
index 427e434..e8df920 100644
--- a/libfreerdp/core/capabilities.c
+++ b/libfreerdp/core/capabilities.c
@@ -168,7 +168,7 @@ static BOOL rdp_apply_general_capability_set(rdpSettings* settings, const rdpSet
settings->NoBitmapCompressionHeader = src->NoBitmapCompressionHeader;
settings->LongCredentialsSupported = src->LongCredentialsSupported;
- settings->AutoReconnectionEnabled = src->AutoReconnectionEnabled;
+ settings->AutoReconnectionPacketSupported = src->AutoReconnectionPacketSupported;
if (!src->FastPathOutput)
settings->FastPathOutput = FALSE;
@@ -223,7 +223,8 @@ static BOOL rdp_read_general_capability_set(wStream* s, rdpSettings* settings)
settings->NoBitmapCompressionHeader = (extraFlags & NO_BITMAP_COMPRESSION_HDR) ? TRUE : FALSE;
settings->LongCredentialsSupported = (extraFlags & LONG_CREDENTIALS_SUPPORTED) ? TRUE : FALSE;
- settings->AutoReconnectionEnabled = (extraFlags & AUTORECONNECT_SUPPORTED) ? TRUE : FALSE;
+ settings->AutoReconnectionPacketSupported =
+ (extraFlags & AUTORECONNECT_SUPPORTED) ? TRUE : FALSE;
settings->FastPathOutput = (extraFlags & FASTPATH_OUTPUT_SUPPORTED) ? TRUE : FALSE;
settings->SaltedChecksum = (extraFlags & ENC_SALTED_CHECKSUM) ? TRUE : FALSE;
settings->RefreshRect = refreshRectSupport;
@@ -252,7 +253,7 @@ static BOOL rdp_write_general_capability_set(wStream* s, const rdpSettings* sett
if (settings->NoBitmapCompressionHeader)
extraFlags |= NO_BITMAP_COMPRESSION_HDR;
- if (settings->AutoReconnectionEnabled)
+ if (settings->AutoReconnectionPacketSupported)
extraFlags |= AUTORECONNECT_SUPPORTED;
if (settings->FastPathOutput)
diff --git a/libfreerdp/core/childsession.c b/libfreerdp/core/childsession.c
index 3bed262..f9d5b2c 100644
--- a/libfreerdp/core/childsession.c
+++ b/libfreerdp/core/childsession.c
@@ -2,7 +2,7 @@
* FreeRDP: A Remote Desktop Protocol Implementation
* Named pipe transport
*
- * Copyright 2023 David Fort <contact@hardening-consulting.com>
+ * Copyright 2023-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.
@@ -18,15 +18,29 @@
*/
#include "tcp.h"
+
#include <winpr/library.h>
#include <winpr/assert.h>
+#include <winpr/print.h>
+#include <winpr/sysinfo.h>
+
+#include <freerdp/utils/ringbuffer.h>
+
#include "childsession.h"
#define TAG FREERDP_TAG("childsession")
typedef struct
{
+ OVERLAPPED readOverlapped;
HANDLE hFile;
+ BOOL opInProgress;
+ BOOL lastOpClosed;
+ RingBuffer readBuffer;
+ BOOL blocking;
+ BYTE tmpReadBuffer[4096];
+
+ HANDLE readEvent;
} WINPR_BIO_NAMED;
static int transport_bio_named_uninit(BIO* bio);
@@ -44,47 +58,192 @@ static int transport_bio_named_write(BIO* bio, const char* buf, int size)
BIO_clear_flags(bio, BIO_FLAGS_WRITE);
DWORD written = 0;
+ UINT64 start = GetTickCount64();
BOOL ret = WriteFile(ptr->hFile, buf, size, &written, NULL);
- WLog_VRB(TAG, "transport_bio_named_write(%d)=%d written=%d", size, ret, written);
+ // winpr_HexDump(TAG, WLOG_DEBUG, buf, size);
if (!ret)
- return -1;
+ {
+ WLog_VRB(TAG, "error or deferred");
+ return 0;
+ }
+
+ WLog_VRB(TAG, "(%d)=%d written=%d duration=%d", size, ret, written, GetTickCount64() - start);
if (written == 0)
- return -1;
+ {
+ WLog_VRB(TAG, "closed on write");
+ return 0;
+ }
return written;
}
+static BOOL treatReadResult(WINPR_BIO_NAMED* ptr, DWORD readBytes)
+{
+ WLog_VRB(TAG, "treatReadResult(readBytes=%" PRIu32 ")", readBytes);
+ ptr->opInProgress = FALSE;
+ if (readBytes == 0)
+ {
+ WLog_VRB(TAG, "readBytes == 0");
+ return TRUE;
+ }
+
+ if (!ringbuffer_write(&ptr->readBuffer, ptr->tmpReadBuffer, readBytes))
+ {
+ WLog_VRB(TAG, "ringbuffer_write()");
+ return FALSE;
+ }
+
+ return SetEvent(ptr->readEvent);
+}
+
+static BOOL doReadOp(WINPR_BIO_NAMED* ptr)
+{
+ DWORD readBytes;
+
+ if (!ResetEvent(ptr->readEvent))
+ return FALSE;
+
+ ptr->opInProgress = TRUE;
+ if (!ReadFile(ptr->hFile, ptr->tmpReadBuffer, sizeof(ptr->tmpReadBuffer), &readBytes,
+ &ptr->readOverlapped))
+ {
+ DWORD error = GetLastError();
+ switch (error)
+ {
+ case ERROR_NO_DATA:
+ WLog_VRB(TAG, "No Data, unexpected");
+ return TRUE;
+ case ERROR_IO_PENDING:
+ WLog_VRB(TAG, "ERROR_IO_PENDING");
+ return TRUE;
+ case ERROR_BROKEN_PIPE:
+ WLog_VRB(TAG, "broken pipe");
+ ptr->lastOpClosed = TRUE;
+ return TRUE;
+ default:
+ return FALSE;
+ }
+ }
+
+ return treatReadResult(ptr, readBytes);
+}
+
static int transport_bio_named_read(BIO* bio, char* buf, int size)
{
WINPR_ASSERT(bio);
WINPR_ASSERT(buf);
WINPR_BIO_NAMED* ptr = (WINPR_BIO_NAMED*)BIO_get_data(bio);
-
if (!buf)
return 0;
- BIO_clear_flags(bio, BIO_FLAGS_READ);
+ BIO_clear_flags(bio, BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_READ);
- DWORD readBytes = 0;
- BOOL ret = ReadFile(ptr->hFile, buf, size, &readBytes, NULL);
- WLog_VRB(TAG, "transport_bio_named_read(%d)=%d read=%d", size, ret, readBytes);
- if (!ret)
+ if (ptr->blocking)
{
- if (GetLastError() == ERROR_NO_DATA)
- BIO_set_flags(bio, (BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_READ));
- return -1;
+ while (!ringbuffer_used(&ptr->readBuffer))
+ {
+ if (ptr->lastOpClosed)
+ return 0;
+
+ if (ptr->opInProgress)
+ {
+ DWORD status = WaitForSingleObjectEx(ptr->readEvent, 500, TRUE);
+ switch (status)
+ {
+ case WAIT_TIMEOUT:
+ case WAIT_IO_COMPLETION:
+ continue;
+ case WAIT_OBJECT_0:
+ break;
+ default:
+ return -1;
+ }
+
+ DWORD readBytes;
+ if (!GetOverlappedResult(ptr->hFile, &ptr->readOverlapped, &readBytes, FALSE))
+ {
+ WLog_ERR(TAG, "GetOverlappedResult blocking(lastError=%" PRIu32 ")",
+ GetLastError());
+ return -1;
+ }
+
+ if (!treatReadResult(ptr, readBytes))
+ {
+ WLog_ERR(TAG, "treatReadResult blocking");
+ return -1;
+ }
+ }
+ }
+ }
+ else
+ {
+ if (ptr->opInProgress)
+ {
+ DWORD status = WaitForSingleObject(ptr->readEvent, 0);
+ switch (status)
+ {
+ case WAIT_OBJECT_0:
+ break;
+ case WAIT_TIMEOUT:
+ BIO_set_flags(bio, (BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_READ));
+ return -1;
+ default:
+ WLog_ERR(TAG, "error WaitForSingleObject(readEvent)=0x%" PRIx32 "", status);
+ return -1;
+ }
+
+ DWORD readBytes;
+ if (!GetOverlappedResult(ptr->hFile, &ptr->readOverlapped, &readBytes, FALSE))
+ {
+ WLog_ERR(TAG, "GetOverlappedResult non blocking(lastError=%" PRIu32 ")",
+ GetLastError());
+ return -1;
+ }
+
+ if (!treatReadResult(ptr, readBytes))
+ {
+ WLog_ERR(TAG, "error treatReadResult non blocking");
+ return -1;
+ }
+ }
}
- if (readBytes == 0)
+ int ret = MIN(size, ringbuffer_used(&ptr->readBuffer));
+ if (ret)
{
- BIO_set_flags(bio, (BIO_FLAGS_READ | BIO_FLAGS_SHOULD_RETRY));
- return 0;
+ DataChunk chunks[2];
+ int nchunks = ringbuffer_peek(&ptr->readBuffer, chunks, ret);
+ for (int i = 0; i < nchunks; i++)
+ {
+ memcpy(buf, chunks[i].data, chunks[i].size);
+ buf += chunks[i].size;
+ }
+
+ ringbuffer_commit_read_bytes(&ptr->readBuffer, ret);
+
+ WLog_VRB(TAG, "(%d)=%d nchunks=%d", size, ret, nchunks);
+ }
+ else
+ {
+ ret = -1;
+ }
+
+ if (!ringbuffer_used(&ptr->readBuffer))
+ {
+ if (!ptr->opInProgress && !doReadOp(ptr))
+ {
+ WLog_ERR(TAG, "error rearming read");
+ return -1;
+ }
}
- return readBytes;
+ if (ret <= 0)
+ BIO_set_flags(bio, (BIO_FLAGS_SHOULD_RETRY | BIO_FLAGS_READ));
+
+ return ret;
}
static int transport_bio_named_puts(BIO* bio, const char* str)
@@ -100,7 +259,7 @@ static int transport_bio_named_gets(BIO* bio, char* str, int size)
WINPR_ASSERT(bio);
WINPR_ASSERT(str);
- return transport_bio_named_write(bio, str, size);
+ return transport_bio_named_read(bio, str, size);
}
static long transport_bio_named_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
@@ -119,7 +278,7 @@ static long transport_bio_named_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
if (!BIO_get_init(bio) || !arg2)
return 0;
- *((HANDLE*)arg2) = ptr->hFile;
+ *((HANDLE*)arg2) = ptr->readEvent;
return 1;
case BIO_C_SET_HANDLE:
BIO_set_init(bio, 1);
@@ -127,18 +286,25 @@ static long transport_bio_named_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
return 0;
ptr->hFile = (HANDLE)arg2;
+ ptr->blocking = TRUE;
+ if (!doReadOp(ptr))
+ return -1;
return 1;
case BIO_C_SET_NONBLOCK:
{
+ WLog_DBG(TAG, "BIO_C_SET_NONBLOCK");
+ ptr->blocking = FALSE;
return 1;
}
case BIO_C_WAIT_READ:
{
+ WLog_DBG(TAG, "BIO_C_WAIT_READ");
return 1;
}
case BIO_C_WAIT_WRITE:
{
+ WLog_DBG(TAG, "BIO_C_WAIT_WRITE");
return 1;
}
@@ -173,17 +339,34 @@ static long transport_bio_named_ctrl(BIO* bio, int cmd, long arg1, void* arg2)
return status;
}
-static int transport_bio_named_uninit(BIO* bio)
+static void BIO_NAMED_free(WINPR_BIO_NAMED* ptr)
{
- WINPR_ASSERT(bio);
- WINPR_BIO_NAMED* ptr = (WINPR_BIO_NAMED*)BIO_get_data(bio);
+ if (!ptr)
+ return;
- if (ptr && ptr->hFile)
+ if (ptr->hFile)
{
CloseHandle(ptr->hFile);
ptr->hFile = NULL;
}
+ if (ptr->readEvent)
+ {
+ CloseHandle(ptr->readEvent);
+ ptr->readEvent = NULL;
+ }
+
+ ringbuffer_destroy(&ptr->readBuffer);
+ free(ptr);
+}
+
+static int transport_bio_named_uninit(BIO* bio)
+{
+ WINPR_ASSERT(bio);
+ WINPR_BIO_NAMED* ptr = (WINPR_BIO_NAMED*)BIO_get_data(bio);
+
+ BIO_NAMED_free(ptr);
+
BIO_set_init(bio, 0);
BIO_set_flags(bio, 0);
return 1;
@@ -192,15 +375,27 @@ static int transport_bio_named_uninit(BIO* bio)
static int transport_bio_named_new(BIO* bio)
{
WINPR_ASSERT(bio);
- BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
WINPR_BIO_NAMED* ptr = (WINPR_BIO_NAMED*)calloc(1, sizeof(WINPR_BIO_NAMED));
if (!ptr)
return 0;
+ if (!ringbuffer_init(&ptr->readBuffer, 0xfffff))
+ goto error;
+
+ ptr->readEvent = CreateEventA(NULL, TRUE, FALSE, NULL);
+ if (!ptr->readEvent || ptr->readEvent == INVALID_HANDLE_VALUE)
+ goto error;
+
+ ptr->readOverlapped.hEvent = ptr->readEvent;
+
BIO_set_data(bio, ptr);
BIO_set_flags(bio, BIO_FLAGS_SHOULD_RETRY);
return 1;
+
+error:
+ BIO_NAMED_free(ptr);
+ return 0;
}
static int transport_bio_named_free(BIO* bio)
@@ -211,13 +406,10 @@ static int transport_bio_named_free(BIO* bio)
return 0;
transport_bio_named_uninit(bio);
- ptr = (WINPR_BIO_NAMED*)BIO_get_data(bio);
+ ptr = (WINPR_BIO_NAMED*)BIO_get_data(bio);
if (ptr)
- {
BIO_set_data(bio, NULL);
- free(ptr);
- }
return 1;
}
@@ -292,10 +484,28 @@ static BOOL createChildSessionTransport(HANDLE* pFile)
goto out;
}
+ const BYTE startOfPath[] = { '\\', 0, '\\', 0, '.', 0, '\\', 0 };
+ if (_wcsncmp(pipePath, (WCHAR*)startOfPath, 4))
+ {
+ /* when compiled under 32 bits, the path may miss "\\.\" at the beginning of the string
+ * so add it if it's not there
+ */
+ size_t len = _wcslen(pipePath);
+ if (len > 0x80 - (4 + 1))
+ {
+ WLog_ERR(TAG, "pipePath is too long to be adjusted");
+ goto out;
+ }
+
+ memmove(pipePath + 4, pipePath, (len + 1) * sizeof(WCHAR));
+ memcpy(pipePath, startOfPath, 8);
+ }
+
ConvertWCharNToUtf8(pipePath, 0x80, pipePathA, sizeof(pipePathA));
WLog_DBG(TAG, "child session is at '%s'", pipePathA);
- HANDLE f = CreateFileW(pipePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
+ HANDLE f = CreateFileW(pipePath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
+ FILE_FLAG_OVERLAPPED, NULL);
if (f == INVALID_HANDLE_VALUE)
{
WLog_ERR(TAG, "error when connecting to local named pipe");
diff --git a/libfreerdp/core/client.c b/libfreerdp/core/client.c
index 1bfc617..7898a9d 100644
--- a/libfreerdp/core/client.c
+++ b/libfreerdp/core/client.c
@@ -661,6 +661,8 @@ static int freerdp_channels_process_sync(rdpChannels* channels, freerdp* instanc
int status = TRUE;
wMessage message = { 0 };
+ WINPR_ASSERT(channels);
+
while (MessageQueue_Peek(channels->queue, &message, TRUE))
{
freerdp_channels_process_message(instance, &message);
@@ -728,6 +730,8 @@ int freerdp_channels_process_pending_messages(freerdp* instance)
*/
BOOL freerdp_channels_check_fds(rdpChannels* channels, freerdp* instance)
{
+ WINPR_ASSERT(channels);
+
if (WaitForSingleObject(MessageQueue_Event(channels->queue), 0) == WAIT_OBJECT_0)
{
freerdp_channels_process_sync(channels, instance);
@@ -742,6 +746,8 @@ UINT freerdp_channels_disconnect(rdpChannels* channels, freerdp* instance)
CHANNEL_OPEN_DATA* pChannelOpenData = NULL;
CHANNEL_CLIENT_DATA* pChannelClientData = NULL;
+ WINPR_ASSERT(channels);
+
if (!channels->connected)
return 0;
@@ -808,8 +814,6 @@ void freerdp_channels_close(rdpChannels* channels, freerdp* instance)
}
}
- channels->clientDataCount = 0;
-
for (int index = 0; index < channels->openDataCount; index++)
{
pChannelOpenData = &channels->openDataList[index];
@@ -818,6 +822,7 @@ void freerdp_channels_close(rdpChannels* channels, freerdp* instance)
channels->openDataCount = 0;
channels->initDataCount = 0;
+ channels->clientDataCount = 0;
WINPR_ASSERT(instance->context);
WINPR_ASSERT(instance->context->settings);
diff --git a/libfreerdp/core/connection.c b/libfreerdp/core/connection.c
index 3abfa93..240a29f 100644
--- a/libfreerdp/core/connection.c
+++ b/libfreerdp/core/connection.c
@@ -622,11 +622,10 @@ BOOL rdp_client_redirect(rdpRdp* rdp)
if (!rdp_client_disconnect_and_clear(rdp))
return FALSE;
+ /* Only disconnect & close the channels here.
+ * they will be discarded and recreated after the new settings have been applied. */
freerdp_channels_disconnect(rdp->context->channels, rdp->context->instance);
freerdp_channels_close(rdp->context->channels, rdp->context->instance);
- freerdp_channels_free(rdp->context->channels);
- rdp->context->channels = freerdp_channels_new(rdp->context->instance);
- WINPR_ASSERT(rdp->context->channels);
if (rdp_redirection_apply_settings(rdp) != 0)
return FALSE;
@@ -684,14 +683,10 @@ BOOL rdp_client_redirect(rdpRdp* rdp)
if (!IFCALLRESULT(TRUE, rdp->context->instance->Redirect, rdp->context->instance))
return FALSE;
- BOOL ok = IFCALLRESULT(TRUE, rdp->context->instance->LoadChannels, rdp->context->instance);
+ BOOL ok = utils_reload_channels(rdp->context);
if (!ok)
return FALSE;
- if (CHANNEL_RC_OK !=
- freerdp_channels_pre_connect(rdp->context->channels, rdp->context->instance))
- return FALSE;
-
status = rdp_client_connect(rdp);
if (status)
@@ -782,7 +777,6 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
Stream_Zero(s, 8);
Stream_SealLength(s);
status = transport_write(rdp->mcs->transport, s);
- Stream_Free(s, TRUE);
if (status < 0)
goto end;
@@ -829,6 +823,7 @@ static BOOL rdp_client_establish_keys(rdpRdp* rdp)
ret = TRUE;
end:
+ Stream_Free(s, TRUE);
free(crypt_client_random);
if (!ret)
diff --git a/libfreerdp/core/credssp_auth.c b/libfreerdp/core/credssp_auth.c
index c14dbe1..8b4c0cb 100644
--- a/libfreerdp/core/credssp_auth.c
+++ b/libfreerdp/core/credssp_auth.c
@@ -808,6 +808,7 @@ static SecurityFunctionTable* auth_resolve_sspi_table(const rdpSettings* setting
if (!hSSPI)
{
WLog_ERR(TAG, "Failed to load SSPI module: %s", module_name);
+ free(sspi_module);
return FALSE;
}
diff --git a/libfreerdp/core/freerdp.c b/libfreerdp/core/freerdp.c
index 29d907a..3660e24 100644
--- a/libfreerdp/core/freerdp.c
+++ b/libfreerdp/core/freerdp.c
@@ -84,7 +84,6 @@ static void sig_abort_connect(int signum, const char* signame, void* ctx)
static int freerdp_connect_begin(freerdp* instance)
{
BOOL rc = 0;
- UINT status2 = CHANNEL_RC_OK;
rdpRdp* rdp = NULL;
BOOL status = TRUE;
rdpSettings* settings = NULL;
@@ -121,16 +120,9 @@ static int freerdp_connect_begin(freerdp* instance)
freerdp_settings_print_warnings(settings);
if (status)
- {
- if (!rdp_set_backup_settings(rdp))
- return 0;
-
- WINPR_ASSERT(instance->LoadChannels);
- if (!instance->LoadChannels(instance))
- return 0;
-
- status2 = freerdp_channels_pre_connect(instance->context->channels, instance);
- }
+ status = rdp_set_backup_settings(rdp);
+ if (status)
+ status = utils_reload_channels(instance->context);
KeyboardLayout = freerdp_settings_get_uint32(settings, FreeRDP_KeyboardLayout);
switch (KeyboardLayout)
@@ -151,7 +143,7 @@ static int freerdp_connect_begin(freerdp* instance)
break;
}
- if (!status || (status2 != CHANNEL_RC_OK))
+ if (!status)
{
rdpContext* context = instance->context;
WINPR_ASSERT(context);
@@ -413,8 +405,8 @@ static BOOL freerdp_prevent_session_lock(rdpContext* context)
if (now - in->lastInputTimestamp > FakeMouseMotionInterval)
{
WLog_Print(context->log, WLOG_DEBUG,
- "fake mouse move: x=%d y=%d lastInputTimestamp=%d "
- "FakeMouseMotionInterval=%d",
+ "fake mouse move: x=%d y=%d lastInputTimestamp=%" PRIu64 " "
+ "FakeMouseMotionInterval=%" PRIu32,
in->lastX, in->lastY, in->lastInputTimestamp, FakeMouseMotionInterval);
BOOL status = freerdp_input_send_mouse_event(context->input, PTR_FLAGS_MOVE, in->lastX,
diff --git a/libfreerdp/core/gateway/arm.c b/libfreerdp/core/gateway/arm.c
index 9848c48..d506c75 100644
--- a/libfreerdp/core/gateway/arm.c
+++ b/libfreerdp/core/gateway/arm.c
@@ -549,6 +549,7 @@ static BOOL arm_pick_base64Utf16Field(const cJSON* json, const char* name, BYTE*
if (!output1 || !len1)
{
WLog_ERR(TAG, "error when first unbase64 for %s", name);
+ free(output1);
return FALSE;
}
@@ -558,6 +559,7 @@ static BOOL arm_pick_base64Utf16Field(const cJSON* json, const char* name, BYTE*
if (!output2 || !len2)
{
WLog_ERR(TAG, "error when decode('utf-16') for %s", name);
+ free(output2);
return FALSE;
}
@@ -567,6 +569,7 @@ static BOOL arm_pick_base64Utf16Field(const cJSON* json, const char* name, BYTE*
if (!output || !*plen)
{
WLog_ERR(TAG, "error when second unbase64 for %s", name);
+ free(output);
return FALSE;
}
@@ -842,7 +845,11 @@ static BOOL arm_handle_bad_request(rdpArm* arm, const HttpResponse* response, BO
0)
{
*retry = TRUE;
- WLog_DBG(TAG, "Starting your VM. It may take up to 5 minutes");
+ const cJSON* message = cJSON_GetObjectItemCaseSensitive(json, "Message");
+ if (!cJSON_IsString(message) || !message->valuestring)
+ WLog_WARN(TAG, "Starting your VM. It may take up to 5 minutes");
+ else
+ WLog_WARN(TAG, "%s", message->valuestring);
}
else
{
diff --git a/libfreerdp/core/gateway/http.c b/libfreerdp/core/gateway/http.c
index cf70b3b..a7cdaab 100644
--- a/libfreerdp/core/gateway/http.c
+++ b/libfreerdp/core/gateway/http.c
@@ -322,8 +322,9 @@ static BOOL list_append(HttpContext* context, WINPR_FORMAT_ARG const char* str,
}
else
sstr = Pragma;
- free(context->Pragma);
+ Pragma = NULL;
+ free(context->Pragma);
context->Pragma = sstr;
rc = TRUE;
@@ -830,7 +831,10 @@ static BOOL http_response_parse_header_field(HttpResponse* response, const char*
const char* value)
{
BOOL status = TRUE;
- if (!response || !name)
+
+ WINPR_ASSERT(response);
+
+ if (!name)
return FALSE;
if (_stricmp(name, "Content-Length") == 0)
@@ -924,6 +928,10 @@ static BOOL http_response_parse_header_field(HttpResponse* response, const char*
*separator = '\0';
CookieName = value;
CookieValue = separator + 1;
+
+ if (!CookieName || !CookieValue)
+ return FALSE;
+
if (*CookieValue == '"')
{
char* p = CookieValue;
@@ -944,9 +952,6 @@ static BOOL http_response_parse_header_field(HttpResponse* response, const char*
}
*p = '\0';
}
-
- if (!CookieName || !CookieValue)
- return FALSE;
}
else
{
@@ -1053,12 +1058,13 @@ static void http_response_print(wLog* log, DWORD level, const HttpResponse* resp
freerdp_http_status_string_format(status, buffer, ARRAYSIZE(buffer)));
for (size_t i = 0; i < response->count; i++)
- WLog_Print(log, level, "[%" PRIuz "] %s", i, response->lines[i]);
+ WLog_Print(log, WLOG_DEBUG, "[%" PRIuz "] %s", i, response->lines[i]);
if (response->ReasonPhrase)
WLog_Print(log, level, "[reason] %s", response->ReasonPhrase);
- WLog_Print(log, level, "[body][%" PRIuz "] %s", response->BodyLength, response->BodyContent);
+ WLog_Print(log, WLOG_TRACE, "[body][%" PRIuz "] %s", response->BodyLength,
+ response->BodyContent);
}
static BOOL http_use_content_length(const char* cur)
diff --git a/libfreerdp/core/gateway/rdg.c b/libfreerdp/core/gateway/rdg.c
index c6d952b..484b599 100644
--- a/libfreerdp/core/gateway/rdg.c
+++ b/libfreerdp/core/gateway/rdg.c
@@ -89,15 +89,6 @@
#define HTTP_TUNNEL_PACKET_FIELD_PAA_COOKIE 0x1
#define HTTP_TUNNEL_PACKET_FIELD_REAUTH 0x2
-/* HTTP tunnel redir flags. */
-#define HTTP_TUNNEL_REDIR_ENABLE_ALL 0x80000000
-#define HTTP_TUNNEL_REDIR_DISABLE_ALL 0x40000000
-#define HTTP_TUNNEL_REDIR_DISABLE_DRIVE 0x1
-#define HTTP_TUNNEL_REDIR_DISABLE_PRINTER 0x2
-#define HTTP_TUNNEL_REDIR_DISABLE_PORT 0x4
-#define HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD 0x8
-#define HTTP_TUNNEL_REDIR_DISABLE_PNP 0x10
-
/* HTTP tunnel response fields present flags. */
#define HTTP_TUNNEL_RESPONSE_FIELD_TUNNEL_ID 0x1
#define HTTP_TUNNEL_RESPONSE_FIELD_CAPS 0x2
@@ -146,6 +137,7 @@ struct rdp_rdg
rdg_http_encoding_context transferEncoding;
SmartcardCertInfo* smartcard;
+ wLog* log;
};
enum
@@ -261,15 +253,17 @@ static const char* capabilities_enum_to_string(UINT32 capabilities)
return flags_to_string(capabilities, capabilities_enum, ARRAYSIZE(capabilities_enum));
}
-static BOOL rdg_read_http_unicode_string(wStream* s, const WCHAR** string, UINT16* lengthInBytes)
+static BOOL rdg_read_http_unicode_string(wLog* log, wStream* s, const WCHAR** string,
+ UINT16* lengthInBytes)
{
UINT16 strLenBytes = 0;
size_t rem = Stream_GetRemainingLength(s);
/* Read length of the string */
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
+ if (!Stream_CheckAndLogRequiredLengthWLog(log, s, 4))
{
- WLog_ERR(TAG, "Could not read stream length, only have %" PRIuz " bytes", rem);
+ WLog_Print(log, WLOG_ERROR, "Could not read stream length, only have %" PRIuz " bytes",
+ rem);
return FALSE;
}
Stream_Read_UINT16(s, strLenBytes);
@@ -280,8 +274,9 @@ static BOOL rdg_read_http_unicode_string(wStream* s, const WCHAR** string, UINT1
/* seek past the string - if this fails something is wrong */
if (!Stream_SafeSeek(s, strLenBytes))
{
- WLog_ERR(TAG, "Could not read stream data, only have %" PRIuz " bytes, expected %" PRIu16,
- rem - 4, strLenBytes);
+ WLog_Print(log, WLOG_ERROR,
+ "Could not read stream data, only have %" PRIuz " bytes, expected %" PRIu16,
+ rem - 4, strLenBytes);
return FALSE;
}
@@ -362,7 +357,13 @@ static int rdg_socket_read(BIO* bio, BYTE* pBuffer, size_t size,
}
}
-static BOOL rdg_read_all(rdpTls* tls, BYTE* buffer, size_t size,
+static BOOL rdg_shall_abort(rdpRdg* rdg)
+{
+ WINPR_ASSERT(rdg);
+ return freerdp_shall_disconnect_context(rdg->context);
+}
+
+static BOOL rdg_read_all(rdpContext* context, rdpTls* tls, BYTE* buffer, size_t size,
rdg_http_encoding_context* transferEncoding)
{
size_t readCount = 0;
@@ -370,6 +371,9 @@ static BOOL rdg_read_all(rdpTls* tls, BYTE* buffer, size_t size,
while (readCount < size)
{
+ if (freerdp_shall_disconnect_context(context))
+ return FALSE;
+
int status = rdg_socket_read(tls->bio, pBuffer, size - readCount, transferEncoding);
if (status <= 0)
{
@@ -396,7 +400,7 @@ static wStream* rdg_receive_packet(rdpRdg* rdg)
if (!s)
return NULL;
- if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s), header, &rdg->transferEncoding))
+ if (!rdg_read_all(rdg->context, rdg->tlsOut, Stream_Buffer(s), header, &rdg->transferEncoding))
{
Stream_Free(s, TRUE);
return NULL;
@@ -412,8 +416,8 @@ static wStream* rdg_receive_packet(rdpRdg* rdg)
return NULL;
}
- if (!rdg_read_all(rdg->tlsOut, Stream_Buffer(s) + header, (int)packetLength - (int)header,
- &rdg->transferEncoding))
+ if (!rdg_read_all(rdg->context, rdg->tlsOut, Stream_Buffer(s) + header,
+ (int)packetLength - (int)header, &rdg->transferEncoding))
{
Stream_Free(s, TRUE);
return NULL;
@@ -699,7 +703,7 @@ out:
return s;
}
-static BOOL rdg_recv_auth_token(rdpCredsspAuth* auth, HttpResponse* response)
+static BOOL rdg_recv_auth_token(wLog* log, rdpCredsspAuth* auth, HttpResponse* response)
{
size_t len = 0;
const char* token64 = NULL;
@@ -719,7 +723,7 @@ static BOOL rdg_recv_auth_token(rdpCredsspAuth* auth, HttpResponse* response)
case HTTP_STATUS_OK:
break;
default:
- http_response_log_error_status(WLog_Get(TAG), WLOG_WARN, response);
+ http_response_log_error_status(log, WLOG_WARN, response);
return FALSE;
}
@@ -738,6 +742,8 @@ static BOOL rdg_recv_auth_token(rdpCredsspAuth* auth, HttpResponse* response)
authToken.cbBuffer = authTokenLength;
credssp_auth_take_input_buffer(auth, &authToken);
}
+ else
+ free(authTokenData);
rc = credssp_auth_authenticate(auth);
if (rc < 0)
@@ -746,7 +752,7 @@ static BOOL rdg_recv_auth_token(rdpCredsspAuth* auth, HttpResponse* response)
return TRUE;
}
-static BOOL rdg_skip_seed_payload(rdpTls* tls, SSIZE_T lastResponseLength,
+static BOOL rdg_skip_seed_payload(rdpContext* context, rdpTls* tls, size_t lastResponseLength,
rdg_http_encoding_context* transferEncoding)
{
BYTE seed_payload[10] = { 0 };
@@ -755,9 +761,9 @@ static BOOL rdg_skip_seed_payload(rdpTls* tls, SSIZE_T lastResponseLength,
/* Per [MS-TSGU] 3.3.5.1 step 4, after final OK response RDG server sends
* random "seed" payload of limited size. In practice it's 10 bytes.
*/
- if (lastResponseLength < (SSIZE_T)size)
+ if (lastResponseLength < size)
{
- if (!rdg_read_all(tls, seed_payload, size - lastResponseLength, transferEncoding))
+ if (!rdg_read_all(context, tls, seed_payload, size - lastResponseLength, transferEncoding))
{
return FALSE;
}
@@ -774,14 +780,14 @@ static BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s)
BYTE verMajor = 0;
BYTE verMinor = 0;
const char* error = NULL;
- WLog_DBG(TAG, "Handshake response received");
+ WLog_Print(rdg->log, WLOG_DEBUG, "Handshake response received");
if (rdg->state != RDG_CLIENT_STATE_HANDSHAKE)
{
return FALSE;
}
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 10))
+ if (!Stream_CheckAndLogRequiredLengthWLog(rdg->log, s, 10))
return FALSE;
Stream_Read_UINT32(s, errorCode);
@@ -790,14 +796,14 @@ static BOOL rdg_process_handshake_response(rdpRdg* rdg, wStream* s)
Stream_Read_UINT16(s, serverVersion);
Stream_Read_UINT16(s, extendedAuth);
error = rpc_error_to_string(errorCode);
- WLog_DBG(TAG,
- "errorCode=%s, verMajor=%" PRId8 ", verMinor=%" PRId8 ", serverVersion=%" PRId16
- ", extendedAuth=%s",
- error, verMajor, verMinor, serverVersion, extended_auth_to_string(extendedAuth));
+ WLog_Print(rdg->log, WLOG_DEBUG,
+ "errorCode=%s, verMajor=%" PRId8 ", verMinor=%" PRId8 ", serverVersion=%" PRId16
+ ", extendedAuth=%s",
+ error, verMajor, verMinor, serverVersion, extended_auth_to_string(extendedAuth));
if (FAILED((HRESULT)errorCode))
{
- WLog_ERR(TAG, "Handshake error %s", error);
+ WLog_Print(rdg->log, WLOG_ERROR, "Handshake error %s", error);
freerdp_set_last_error_log(rdg->context, errorCode);
return FALSE;
}
@@ -815,8 +821,8 @@ static BOOL rdg_process_tunnel_response_optional(rdpRdg* rdg, wStream* s, UINT16
/* Seek over tunnelId (4 bytes) */
if (!Stream_SafeSeek(s, 4))
{
- WLog_ERR(TAG, "Short tunnelId, got %" PRIuz ", expected 4",
- Stream_GetRemainingLength(s));
+ WLog_Print(rdg->log, WLOG_ERROR, "Short tunnelId, got %" PRIuz ", expected 4",
+ Stream_GetRemainingLength(s));
return FALSE;
}
}
@@ -824,11 +830,11 @@ static BOOL rdg_process_tunnel_response_optional(rdpRdg* rdg, wStream* s, UINT16
if (fieldsPresent & HTTP_TUNNEL_RESPONSE_FIELD_CAPS)
{
UINT32 caps = 0;
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
+ if (!Stream_CheckAndLogRequiredLengthWLog(rdg->log, s, 4))
return FALSE;
Stream_Read_UINT32(s, caps);
- WLog_DBG(TAG, "capabilities=%s", capabilities_enum_to_string(caps));
+ WLog_Print(rdg->log, WLOG_DEBUG, "capabilities=%s", capabilities_enum_to_string(caps));
}
if (fieldsPresent & HTTP_TUNNEL_RESPONSE_FIELD_SOH_REQ)
@@ -836,14 +842,15 @@ static BOOL rdg_process_tunnel_response_optional(rdpRdg* rdg, wStream* s, UINT16
/* Seek over nonce (20 bytes) */
if (!Stream_SafeSeek(s, 20))
{
- WLog_ERR(TAG, "Short nonce, got %" PRIuz ", expected 20", Stream_GetRemainingLength(s));
+ WLog_Print(rdg->log, WLOG_ERROR, "Short nonce, got %" PRIuz ", expected 20",
+ Stream_GetRemainingLength(s));
return FALSE;
}
/* Read serverCert */
- if (!rdg_read_http_unicode_string(s, NULL, NULL))
+ if (!rdg_read_http_unicode_string(rdg->log, s, NULL, NULL))
{
- WLog_ERR(TAG, "Failed to read server certificate");
+ WLog_Print(rdg->log, WLOG_ERROR, "Failed to read server certificate");
return FALSE;
}
}
@@ -858,9 +865,9 @@ static BOOL rdg_process_tunnel_response_optional(rdpRdg* rdg, wStream* s, UINT16
WINPR_ASSERT(context->instance);
/* Read message string and invoke callback */
- if (!rdg_read_http_unicode_string(s, &msg, &msgLenBytes))
+ if (!rdg_read_http_unicode_string(rdg->log, s, &msg, &msgLenBytes))
{
- WLog_ERR(TAG, "Failed to read consent message");
+ WLog_Print(rdg->log, WLOG_ERROR, "Failed to read consent message");
return FALSE;
}
@@ -877,14 +884,14 @@ static BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s)
UINT16 fieldsPresent = 0;
UINT32 errorCode = 0;
const char* error = NULL;
- WLog_DBG(TAG, "Tunnel response received");
+ WLog_Print(rdg->log, WLOG_DEBUG, "Tunnel response received");
if (rdg->state != RDG_CLIENT_STATE_TUNNEL_CREATE)
{
return FALSE;
}
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 10))
+ if (!Stream_CheckAndLogRequiredLengthWLog(rdg->log, s, 10))
return FALSE;
Stream_Read_UINT16(s, serverVersion);
@@ -892,12 +899,12 @@ static BOOL rdg_process_tunnel_response(rdpRdg* rdg, wStream* s)
Stream_Read_UINT16(s, fieldsPresent);
Stream_Seek_UINT16(s); /* reserved */
error = rpc_error_to_string(errorCode);
- WLog_DBG(TAG, "serverVersion=%" PRId16 ", errorCode=%s, fieldsPresent=%s", serverVersion, error,
- tunnel_response_fields_present_to_string(fieldsPresent));
+ WLog_Print(rdg->log, WLOG_DEBUG, "serverVersion=%" PRId16 ", errorCode=%s, fieldsPresent=%s",
+ serverVersion, error, tunnel_response_fields_present_to_string(fieldsPresent));
if (FAILED((HRESULT)errorCode))
{
- WLog_ERR(TAG, "Tunnel creation error %s", error);
+ WLog_Print(rdg->log, WLOG_ERROR, "Tunnel creation error %s", error);
freerdp_set_last_error_log(rdg->context, errorCode);
return FALSE;
}
@@ -913,31 +920,66 @@ static BOOL rdg_process_tunnel_authorization_response(rdpRdg* rdg, wStream* s)
UINT32 errorCode = 0;
UINT16 fieldsPresent = 0;
const char* error = NULL;
- WLog_DBG(TAG, "Tunnel authorization received");
+ WLog_Print(rdg->log, WLOG_DEBUG, "Tunnel authorization received");
if (rdg->state != RDG_CLIENT_STATE_TUNNEL_AUTHORIZE)
{
return FALSE;
}
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
+ if (!Stream_CheckAndLogRequiredLengthWLog(rdg->log, s, 8))
return FALSE;
Stream_Read_UINT32(s, errorCode);
Stream_Read_UINT16(s, fieldsPresent);
Stream_Seek_UINT16(s); /* reserved */
error = rpc_error_to_string(errorCode);
- WLog_DBG(TAG, "errorCode=%s, fieldsPresent=%s", error,
- tunnel_authorization_response_fields_present_to_string(fieldsPresent));
+ WLog_Print(rdg->log, WLOG_DEBUG, "errorCode=%s, fieldsPresent=%s", error,
+ tunnel_authorization_response_fields_present_to_string(fieldsPresent));
/* [MS-TSGU] 3.7.5.2.7 */
if (errorCode != S_OK && errorCode != E_PROXY_QUARANTINE_ACCESSDENIED)
{
- WLog_ERR(TAG, "Tunnel authorization error %s", error);
+ WLog_Print(rdg->log, WLOG_ERROR, "Tunnel authorization error %s", error);
freerdp_set_last_error_log(rdg->context, errorCode);
return FALSE;
}
+ if (fieldsPresent & HTTP_TUNNEL_AUTH_RESPONSE_FIELD_REDIR_FLAGS)
+ {
+ UINT32 redirFlags = 0;
+ if (!Stream_CheckAndLogRequiredCapacityWLog(rdg->log, s, 4))
+ return FALSE;
+ Stream_Read_UINT32(s, redirFlags);
+
+ rdpContext* context = rdg->context;
+ if (!utils_apply_gateway_policy(rdg->log, context, redirFlags, "RDG"))
+ return FALSE;
+ }
+
+ if (fieldsPresent & HTTP_TUNNEL_AUTH_RESPONSE_FIELD_IDLE_TIMEOUT)
+ {
+ UINT32 idleTimeout = 0;
+ if (!Stream_CheckAndLogRequiredCapacityWLog(rdg->log, s, 4))
+ return FALSE;
+ Stream_Read_UINT32(s, idleTimeout);
+ WLog_Print(rdg->log, WLOG_DEBUG, "[IDLE_TIMEOUT] idleTimeout=%" PRIu32 ": TODO: unused",
+ idleTimeout);
+ }
+
+ if (fieldsPresent & HTTP_TUNNEL_AUTH_RESPONSE_FIELD_SOH_RESPONSE)
+ {
+ UINT16 cbLen = 0;
+ if (!Stream_CheckAndLogRequiredCapacityWLog(rdg->log, s, 2))
+ return FALSE;
+ Stream_Read_UINT16(s, cbLen);
+
+ WLog_Print(rdg->log, WLOG_DEBUG, "[SOH_RESPONSE] cbLen=%" PRIu16 ": TODO: unused", cbLen);
+ if (!Stream_CheckAndLogRequiredLengthWLog(rdg->log, s, cbLen))
+ return FALSE;
+ Stream_Seek(s, cbLen);
+ }
+
return rdg_send_channel_create(rdg);
}
@@ -955,8 +997,8 @@ static BOOL rdg_process_extauth_sspi(rdpRdg* rdg, wStream* s)
if (errorCode != ERROR_SUCCESS)
{
- WLog_ERR(TAG, "EXTAUTH_SSPI_NTLM failed with error %s [0x%08X]",
- GetSecurityStatusString(errorCode), errorCode);
+ WLog_Print(rdg->log, WLOG_ERROR, "EXTAUTH_SSPI_NTLM failed with error %s [0x%08X]",
+ GetSecurityStatusString(errorCode), errorCode);
return FALSE;
}
@@ -972,6 +1014,8 @@ static BOOL rdg_process_extauth_sspi(rdpRdg* rdg, wStream* s)
}
authTokenData = malloc(authBlobLen);
+ if (authTokenData == NULL)
+ return FALSE;
Stream_Read(s, authTokenData, authBlobLen);
authToken.pvBuffer = authTokenData;
@@ -993,27 +1037,27 @@ static BOOL rdg_process_channel_response(rdpRdg* rdg, wStream* s)
UINT16 fieldsPresent = 0;
UINT32 errorCode = 0;
const char* error = NULL;
- WLog_DBG(TAG, "Channel response received");
+ WLog_Print(rdg->log, WLOG_DEBUG, "Channel response received");
if (rdg->state != RDG_CLIENT_STATE_CHANNEL_CREATE)
{
return FALSE;
}
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
+ if (!Stream_CheckAndLogRequiredLengthWLog(rdg->log, s, 8))
return FALSE;
Stream_Read_UINT32(s, errorCode);
Stream_Read_UINT16(s, fieldsPresent);
Stream_Seek_UINT16(s); /* reserved */
error = rpc_error_to_string(errorCode);
- WLog_DBG(TAG, "channel response errorCode=%s, fieldsPresent=%s", error,
- channel_response_fields_present_to_string(fieldsPresent));
+ WLog_Print(rdg->log, WLOG_DEBUG, "channel response errorCode=%s, fieldsPresent=%s", error,
+ channel_response_fields_present_to_string(fieldsPresent));
if (FAILED((HRESULT)errorCode))
{
- WLog_ERR(TAG, "channel response errorCode=%s, fieldsPresent=%s", error,
- channel_response_fields_present_to_string(fieldsPresent));
+ WLog_Print(rdg->log, WLOG_ERROR, "channel response errorCode=%s, fieldsPresent=%s", error,
+ channel_response_fields_present_to_string(fieldsPresent));
freerdp_set_last_error_log(rdg->context, errorCode);
return FALSE;
}
@@ -1029,7 +1073,7 @@ static BOOL rdg_process_packet(rdpRdg* rdg, wStream* s)
UINT32 packetLength = 0;
Stream_SetPosition(s, 0);
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 8))
+ if (!Stream_CheckAndLogRequiredLengthWLog(rdg->log, s, 8))
return FALSE;
Stream_Read_UINT16(s, type);
@@ -1038,7 +1082,8 @@ static BOOL rdg_process_packet(rdpRdg* rdg, wStream* s)
if (Stream_Length(s) < packetLength)
{
- WLog_ERR(TAG, "Short packet %" PRIuz ", expected %" PRIuz, Stream_Length(s), packetLength);
+ WLog_Print(rdg->log, WLOG_ERROR, "Short packet %" PRIuz ", expected %" PRIuz,
+ Stream_Length(s), packetLength);
return FALSE;
}
@@ -1061,7 +1106,7 @@ static BOOL rdg_process_packet(rdpRdg* rdg, wStream* s)
break;
case PKT_TYPE_DATA:
- WLog_ERR(TAG, "Unexpected packet type DATA");
+ WLog_Print(rdg->log, WLOG_ERROR, "Unexpected packet type DATA");
return FALSE;
case PKT_TYPE_EXTENDED_AUTH_MSG:
@@ -1069,7 +1114,7 @@ static BOOL rdg_process_packet(rdpRdg* rdg, wStream* s)
break;
default:
- WLog_ERR(TAG, "PKG TYPE 0x%x not implemented", type);
+ WLog_Print(rdg->log, WLOG_ERROR, "PKG TYPE 0x%x not implemented", type);
return FALSE;
}
@@ -1325,7 +1370,7 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
* sending an answer if it is not happy with the http request */
if (!response)
{
- WLog_INFO(TAG, "RD Gateway HTTP transport broken.");
+ WLog_Print(rdg->log, WLOG_INFO, "RD Gateway HTTP transport broken.");
*rpcFallback = TRUE;
return FALSE;
}
@@ -1336,7 +1381,7 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
{
case HTTP_STATUS_NOT_FOUND:
{
- WLog_INFO(TAG, "RD Gateway does not support HTTP transport.");
+ WLog_Print(rdg->log, WLOG_INFO, "RD Gateway does not support HTTP transport.");
*rpcFallback = TRUE;
http_response_free(response);
@@ -1345,13 +1390,13 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
case HTTP_STATUS_OK:
break;
default:
- http_response_log_error_status(WLog_Get(TAG), WLOG_WARN, response);
+ http_response_log_error_status(rdg->log, WLOG_WARN, response);
break;
}
while (!credssp_auth_is_complete(rdg->auth))
{
- if (!rdg_recv_auth_token(rdg->auth, response))
+ if (!rdg_recv_auth_token(rdg->log, rdg->auth, response))
{
http_response_free(response);
return FALSE;
@@ -1367,7 +1412,7 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
response = http_response_recv(tls, TRUE);
if (!response)
{
- WLog_INFO(TAG, "RD Gateway HTTP transport broken.");
+ WLog_Print(rdg->log, WLOG_INFO, "RD Gateway HTTP transport broken.");
*rpcFallback = TRUE;
return FALSE;
}
@@ -1388,7 +1433,7 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
if (!response)
{
- WLog_INFO(TAG, "RD Gateway HTTP transport broken.");
+ WLog_Print(rdg->log, WLOG_INFO, "RD Gateway HTTP transport broken.");
*rpcFallback = TRUE;
return FALSE;
}
@@ -1398,9 +1443,9 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
const size_t bodyLength = http_response_get_body_length(response);
const TRANSFER_ENCODING encoding = http_response_get_transfer_encoding(response);
const BOOL isWebsocket = http_response_is_websocket(rdg->http, response);
- http_response_free(response);
- WLog_DBG(TAG, "%s authorization result: %s", method,
- freerdp_http_status_string_format(statusCode, buffer, ARRAYSIZE(buffer)));
+
+ WLog_Print(rdg->log, WLOG_DEBUG, "%s authorization result: %s", method,
+ freerdp_http_status_string_format(statusCode, buffer, ARRAYSIZE(buffer)));
switch (statusCode)
{
@@ -1408,11 +1453,14 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
/* old rdg endpoint without websocket support, don't request websocket for RDG_IN_DATA
*/
http_context_enable_websocket_upgrade(rdg->http, FALSE);
+ http_response_free(response);
break;
case HTTP_STATUS_DENIED:
freerdp_set_last_error_log(rdg->context, FREERDP_ERROR_CONNECT_ACCESS_DENIED);
+ http_response_free(response);
return FALSE;
case HTTP_STATUS_SWITCH_PROTOCOLS:
+ http_response_free(response);
if (!isWebsocket)
{
/*
@@ -1442,7 +1490,8 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
}
return TRUE;
default:
- http_response_log_error_status(WLog_Get(TAG), WLOG_WARN, response);
+ http_response_log_error_status(rdg->log, WLOG_WARN, response);
+ http_response_free(response);
return FALSE;
}
@@ -1455,7 +1504,7 @@ static BOOL rdg_establish_data_connection(rdpRdg* rdg, rdpTls* tls, const char*
rdg->transferEncoding.context.chunked.headerFooterPos = 0;
rdg->transferEncoding.context.chunked.state = ChunkStateLenghHeader;
}
- if (!rdg_skip_seed_payload(tls, bodyLength, &rdg->transferEncoding))
+ if (!rdg_skip_seed_payload(rdg->context, tls, bodyLength, &rdg->transferEncoding))
{
return FALSE;
}
@@ -1522,7 +1571,7 @@ BOOL rdg_connect(rdpRdg* rdg, DWORD timeout, BOOL* rpcFallback)
{
if (rdg->transferEncoding.isWebsocketTransport)
{
- WLog_DBG(TAG, "Upgraded to websocket. RDG_IN_DATA not required");
+ WLog_Print(rdg->log, WLOG_DEBUG, "Upgraded to websocket. RDG_IN_DATA not required");
}
else
{
@@ -1717,7 +1766,7 @@ static BOOL rdg_process_close_packet(rdpRdg* rdg, wStream* s)
UINT32 packetSize = 12;
/* Read error code */
- if (!Stream_CheckAndLogRequiredLength(TAG, s, 4))
+ if (!Stream_CheckAndLogRequiredLengthWLog(rdg->log, s, 4))
return FALSE;
Stream_Read_UINT32(s, errorCode);
@@ -1769,9 +1818,9 @@ static BOOL rdg_process_service_message(rdpRdg* rdg, wStream* s)
WINPR_ASSERT(context->instance);
/* Read message string */
- if (!rdg_read_http_unicode_string(s, &msg, &msgLenBytes))
+ if (!rdg_read_http_unicode_string(rdg->log, s, &msg, &msgLenBytes))
{
- WLog_ERR(TAG, "Failed to read string");
+ WLog_Print(rdg->log, WLOG_ERROR, "Failed to read string");
return FALSE;
}
@@ -1783,7 +1832,7 @@ static BOOL rdg_process_unknown_packet(rdpRdg* rdg, int type)
{
WINPR_UNUSED(rdg);
WINPR_UNUSED(type);
- WLog_WARN(TAG, "Unknown Control Packet received: %X", type);
+ WLog_Print(rdg->log, WLOG_WARN, "Unknown Control Packet received: %X", type);
return TRUE;
}
@@ -1808,6 +1857,11 @@ static BOOL rdg_process_control_packet(rdpRdg* rdg, int type, size_t packetLengt
while (readCount < payloadSize)
{
+ if (rdg_shall_abort(rdg))
+ {
+ Stream_Free(s, TRUE);
+ return FALSE;
+ }
status = rdg_socket_read(rdg->tlsOut->bio, Stream_Pointer(s), payloadSize - readCount,
&rdg->transferEncoding);
@@ -1852,7 +1906,8 @@ static BOOL rdg_process_control_packet(rdpRdg* rdg, int type, size_t packetLengt
case PKT_TYPE_SERVICE_MESSAGE:
if (!s)
{
- WLog_ERR(TAG, "PKT_TYPE_SERVICE_MESSAGE requires payload but none was sent");
+ WLog_Print(rdg->log, WLOG_ERROR,
+ "PKT_TYPE_SERVICE_MESSAGE requires payload but none was sent");
return FALSE;
}
status = rdg_process_service_message(rdg, s);
@@ -1880,6 +1935,9 @@ static int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
while (readCount < sizeof(RdgPacketHeader))
{
+ if (rdg_shall_abort(rdg))
+ return -1;
+
status = rdg_socket_read(rdg->tlsOut->bio, (BYTE*)(&header) + readCount,
(int)sizeof(RdgPacketHeader) - (int)readCount,
&rdg->transferEncoding);
@@ -1916,6 +1974,8 @@ static int rdg_read_data_packet(rdpRdg* rdg, BYTE* buffer, int size)
while (readCount < 2)
{
+ if (rdg_shall_abort(rdg))
+ return -1;
status =
rdg_socket_read(rdg->tlsOut->bio, (BYTE*)(&rdg->packetRemainingCount) + readCount,
2 - (int)readCount, &rdg->transferEncoding);
@@ -2153,6 +2213,7 @@ rdpRdg* rdg_new(rdpContext* context)
if (rdg)
{
+ rdg->log = WLog_Get(TAG);
rdg->state = RDG_CLIENT_STATE_INITIAL;
rdg->context = context;
rdg->settings = rdg->context->settings;
@@ -2212,8 +2273,8 @@ rdpRdg* rdg_new(rdpContext* context)
break;
default:
- WLog_DBG(TAG, "RDG extended authentication method %d not supported",
- rdg->extAuth);
+ WLog_Print(rdg->log, WLOG_DEBUG,
+ "RDG extended authentication method %d not supported", rdg->extAuth);
}
}
diff --git a/libfreerdp/core/gateway/tsg.c b/libfreerdp/core/gateway/tsg.c
index 3ab833a..8101e53 100644
--- a/libfreerdp/core/gateway/tsg.c
+++ b/libfreerdp/core/gateway/tsg.c
@@ -35,6 +35,7 @@
#include "rpc_bind.h"
#include "rpc_client.h"
#include "tsg.h"
+#include "../utils.h"
#include "../../crypto/opensslcompat.h"
#define TAG FREERDP_TAG("core.gateway.tsg")
@@ -1590,7 +1591,7 @@ fail:
return FALSE;
}
-static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, RPC_PDU* pdu,
+static BOOL TsProxyCreateTunnelReadResponse(rdpTsg* tsg, const RPC_PDU* pdu,
CONTEXT_HANDLE* tunnelContext, UINT32* tunnelId)
{
BOOL rc = FALSE;
@@ -1728,7 +1729,41 @@ fail:
return FALSE;
}
-static BOOL TsProxyAuthorizeTunnelReadResponse(wLog* log, RPC_PDU* pdu)
+static UINT32 tsg_redir_to_flags(const TSG_REDIRECTION_FLAGS* redirect)
+{
+ UINT32 flags = 0;
+ if (redirect->enableAllRedirections)
+ flags |= HTTP_TUNNEL_REDIR_ENABLE_ALL;
+ if (redirect->disableAllRedirections)
+ flags |= HTTP_TUNNEL_REDIR_DISABLE_ALL;
+
+ if (redirect->driveRedirectionDisabled)
+ flags |= HTTP_TUNNEL_REDIR_DISABLE_DRIVE;
+ if (redirect->printerRedirectionDisabled)
+ flags |= HTTP_TUNNEL_REDIR_DISABLE_PRINTER;
+ if (redirect->portRedirectionDisabled)
+ flags |= HTTP_TUNNEL_REDIR_DISABLE_PORT;
+ if (redirect->clipboardRedirectionDisabled)
+ flags |= HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD;
+ if (redirect->pnpRedirectionDisabled)
+ flags |= HTTP_TUNNEL_REDIR_DISABLE_PNP;
+ return flags;
+}
+
+static BOOL tsg_redirect_apply(rdpTsg* tsg, const TSG_REDIRECTION_FLAGS* redirect)
+{
+ WINPR_ASSERT(tsg);
+ WINPR_ASSERT(redirect);
+
+ rdpTransport* transport = tsg->transport;
+ WINPR_ASSERT(transport);
+
+ rdpContext* context = transport_get_context(transport);
+ UINT32 redirFlags = tsg_redir_to_flags(redirect);
+ return utils_apply_gateway_policy(tsg->log, context, redirFlags, "TSG");
+}
+
+static BOOL TsProxyAuthorizeTunnelReadResponse(rdpTsg* tsg, const RPC_PDU* pdu)
{
BOOL rc = FALSE;
UINT32 SwitchValue = 0;
@@ -1736,8 +1771,12 @@ static BOOL TsProxyAuthorizeTunnelReadResponse(wLog* log, RPC_PDU* pdu)
TSG_PACKET packet = { 0 };
UINT32 PacketPtr = 0;
UINT32 PacketResponsePtr = 0;
- if (!pdu)
- return FALSE;
+
+ WINPR_ASSERT(tsg);
+ WINPR_ASSERT(pdu);
+
+ wLog* log = tsg->log;
+ WINPR_ASSERT(log);
if (!tsg_ndr_pointer_read(log, pdu->s, &index, &PacketPtr, TRUE))
goto fail;
@@ -1773,6 +1812,9 @@ static BOOL TsProxyAuthorizeTunnelReadResponse(wLog* log, RPC_PDU* pdu)
goto fail;
rc = TRUE;
+
+ if (packet.tsgPacket.packetResponse.flags & TSG_PACKET_TYPE_QUARREQUEST)
+ rc = tsg_redirect_apply(tsg, &packet.tsgPacket.packetResponse.redirectionFlags);
fail:
return rc;
}
@@ -1846,7 +1888,7 @@ static BOOL TsProxyReadPacketSTringMessage(rdpTsg* tsg, wStream* s, TSG_PACKET_S
return tsg_ndr_read_string(tsg->log, s, &msg->msgBuffer, msg->msgBytes);
}
-static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, RPC_PDU* pdu)
+static BOOL TsProxyMakeTunnelCallReadResponse(rdpTsg* tsg, const RPC_PDU* pdu)
{
BOOL rc = FALSE;
UINT32 index = 0;
@@ -1991,20 +2033,20 @@ fail:
static BOOL TsProxyCreateChannelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* tunnelContext)
{
- size_t count = 0;
- wStream* s = NULL;
- rdpRpc* rpc = NULL;
+ WINPR_ASSERT(tsg);
+ WINPR_ASSERT(tunnelContext);
+
WLog_Print(tsg->log, WLOG_DEBUG, "TsProxyCreateChannelWriteRequest");
- if (!tsg || !tsg->rpc || !tunnelContext || !tsg->Hostname)
+ if (!tsg->rpc || !tsg->Hostname)
return FALSE;
- rpc = tsg->rpc;
- count = _wcslen(tsg->Hostname) + 1;
+ rdpRpc* rpc = tsg->rpc;
+ const size_t count = _wcslen(tsg->Hostname) + 1;
if (count > UINT32_MAX)
return FALSE;
- s = Stream_New(NULL, 60 + count * 2);
+ wStream* s = Stream_New(NULL, 60 + count * 2);
if (!s)
return FALSE;
@@ -2036,14 +2078,16 @@ fail:
return FALSE;
}
-static BOOL TsProxyCreateChannelReadResponse(wLog* log, RPC_PDU* pdu,
+static BOOL TsProxyCreateChannelReadResponse(wLog* log, const RPC_PDU* pdu,
CONTEXT_HANDLE* channelContext, UINT32* channelId)
{
BOOL rc = FALSE;
- WLog_Print(log, WLOG_DEBUG, "TsProxyCreateChannelReadResponse");
- if (!pdu)
- return FALSE;
+ WINPR_ASSERT(log);
+ WINPR_ASSERT(pdu);
+ WINPR_ASSERT(channelId);
+
+ WLog_Print(log, WLOG_DEBUG, "TsProxyCreateChannelReadResponse");
if (!Stream_CheckAndLogRequiredLengthWLog(log, pdu->s, 28))
goto fail;
@@ -2068,15 +2112,15 @@ fail:
static BOOL TsProxyCloseChannelWriteRequest(rdpTsg* tsg, CONTEXT_HANDLE* context)
{
- wStream* s = NULL;
- rdpRpc* rpc = NULL;
+ WINPR_ASSERT(tsg);
+ WINPR_ASSERT(context);
+
WLog_Print(tsg->log, WLOG_DEBUG, "TsProxyCloseChannelWriteRequest");
- if (!tsg || !tsg->rpc || !context)
- return FALSE;
+ rdpRpc* rpc = tsg->rpc;
+ WINPR_ASSERT(rpc);
- rpc = tsg->rpc;
- s = Stream_New(NULL, 20);
+ wStream* s = Stream_New(NULL, 20);
if (!s)
return FALSE;
@@ -2090,7 +2134,7 @@ fail:
return FALSE;
}
-static BOOL TsProxyCloseChannelReadResponse(wLog* log, RPC_PDU* pdu, CONTEXT_HANDLE* context)
+static BOOL TsProxyCloseChannelReadResponse(wLog* log, const RPC_PDU* pdu, CONTEXT_HANDLE* context)
{
BOOL rc = FALSE;
WLog_Print(log, WLOG_DEBUG, "TsProxyCloseChannelReadResponse");
@@ -2124,15 +2168,15 @@ fail:
static BOOL TsProxyCloseTunnelWriteRequest(rdpTsg* tsg, const CONTEXT_HANDLE* context)
{
- wStream* s = NULL;
- rdpRpc* rpc = NULL;
+ WINPR_ASSERT(tsg);
+ WINPR_ASSERT(context);
+
WLog_Print(tsg->log, WLOG_DEBUG, "TsProxyCloseTunnelWriteRequest");
- if (!tsg || !tsg->rpc || !context)
- return FALSE;
+ rdpRpc* rpc = tsg->rpc;
+ WINPR_ASSERT(rpc);
- rpc = tsg->rpc;
- s = Stream_New(NULL, 20);
+ wStream* s = Stream_New(NULL, 20);
if (!s)
return FALSE;
@@ -2146,13 +2190,15 @@ fail:
return FALSE;
}
-static BOOL TsProxyCloseTunnelReadResponse(wLog* log, RPC_PDU* pdu, CONTEXT_HANDLE* context)
+static BOOL TsProxyCloseTunnelReadResponse(wLog* log, const RPC_PDU* pdu, CONTEXT_HANDLE* context)
{
BOOL rc = FALSE;
- WLog_Print(log, WLOG_DEBUG, "TsProxyCloseTunnelReadResponse");
- if (!pdu || !context)
- return FALSE;
+ WINPR_ASSERT(log);
+ WINPR_ASSERT(pdu);
+ WINPR_ASSERT(context);
+
+ WLog_Print(log, WLOG_DEBUG, "TsProxyCloseTunnelReadResponse");
if (!Stream_CheckAndLogRequiredLengthWLog(log, pdu->s, 24))
goto fail;
@@ -2294,7 +2340,7 @@ static BOOL tsg_proxy_reauth(rdpTsg* tsg)
return tsg_transition_to_state(tsg, TSG_STATE_INITIAL);
}
-BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu)
+BOOL tsg_recv_pdu(rdpTsg* tsg, const RPC_PDU* pdu)
{
BOOL rc = FALSE;
RpcClientCall* call = NULL;
@@ -2342,10 +2388,10 @@ BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu)
case TSG_STATE_CONNECTED:
{
- CONTEXT_HANDLE* TunnelContext = NULL;
- TunnelContext = (tsg->reauthSequence) ? &tsg->NewTunnelContext : &tsg->TunnelContext;
+ CONTEXT_HANDLE* TunnelContext =
+ (tsg->reauthSequence) ? &tsg->NewTunnelContext : &tsg->TunnelContext;
- if (!TsProxyAuthorizeTunnelReadResponse(tsg->log, pdu))
+ if (!TsProxyAuthorizeTunnelReadResponse(tsg, pdu))
{
WLog_Print(tsg->log, WLOG_ERROR, "TsProxyAuthorizeTunnelReadResponse failure");
return FALSE;
diff --git a/libfreerdp/core/gateway/tsg.h b/libfreerdp/core/gateway/tsg.h
index 626a7ac..81b50a7 100644
--- a/libfreerdp/core/gateway/tsg.h
+++ b/libfreerdp/core/gateway/tsg.h
@@ -109,7 +109,7 @@ FREERDP_LOCAL BOOL tsg_proxy_begin(rdpTsg* tsg);
FREERDP_LOCAL BOOL tsg_connect(rdpTsg* tsg, const char* hostname, UINT16 port, DWORD timeout);
FREERDP_LOCAL BOOL tsg_disconnect(rdpTsg* tsg);
-FREERDP_LOCAL BOOL tsg_recv_pdu(rdpTsg* tsg, RPC_PDU* pdu);
+FREERDP_LOCAL BOOL tsg_recv_pdu(rdpTsg* tsg, const RPC_PDU* pdu);
FREERDP_LOCAL BOOL tsg_check_event_handles(rdpTsg* tsg);
FREERDP_LOCAL DWORD tsg_get_event_handles(rdpTsg* tsg, HANDLE* events, DWORD count);
diff --git a/libfreerdp/core/gateway/wst.c b/libfreerdp/core/gateway/wst.c
index 00581d3..87194da 100644
--- a/libfreerdp/core/gateway/wst.c
+++ b/libfreerdp/core/gateway/wst.c
@@ -199,6 +199,8 @@ static BOOL wst_recv_auth_token(rdpCredsspAuth* auth, HttpResponse* response)
authToken.cbBuffer = authTokenLength;
credssp_auth_take_input_buffer(auth, &authToken);
}
+ else
+ free(authTokenData);
rc = credssp_auth_authenticate(auth);
if (rc < 0)
diff --git a/libfreerdp/core/gcc.c b/libfreerdp/core/gcc.c
index d99ee86..733a763 100644
--- a/libfreerdp/core/gcc.c
+++ b/libfreerdp/core/gcc.c
@@ -1704,7 +1704,13 @@ BOOL gcc_read_server_security_data(wStream* s, rdpMcs* mcs)
Stream_Read_UINT32(s, settings->ServerCertificateLength); /* serverCertLen */
if ((settings->ServerRandomLength == 0) || (settings->ServerCertificateLength == 0))
+ {
+ WLog_ERR(TAG,
+ "Invalid ServerRandom (length=%" PRIu32 ") or ServerCertificate (length=%" PRIu32
+ ")",
+ settings->ServerRandomLength, settings->ServerCertificateLength);
return FALSE;
+ }
if (!Stream_CheckAndLogRequiredLength(TAG, s, settings->ServerRandomLength))
return FALSE;
diff --git a/libfreerdp/core/info.c b/libfreerdp/core/info.c
index 0d8e90e..7d6eec1 100644
--- a/libfreerdp/core/info.c
+++ b/libfreerdp/core/info.c
@@ -469,8 +469,12 @@ static BOOL rdp_write_extended_info_packet(rdpRdp* rdp, wStream* s)
rdpSettings* settings = rdp->settings;
WINPR_ASSERT(settings);
- const UINT16 clientAddressFamily =
- settings->IPv6Enabled ? ADDRESS_FAMILY_INET6 : ADDRESS_FAMILY_INET;
+ UINT16 clientAddressFamily = ADDRESS_FAMILY_INET;
+ if (settings->ConnectChildSession)
+ clientAddressFamily = 0x0000;
+ else if (settings->IPv6Enabled)
+ clientAddressFamily = ADDRESS_FAMILY_INET6;
+
WCHAR* clientAddress = ConvertUtf8ToWCharAlloc(settings->ClientAddress, &cbClientAddress);
if (cbClientAddress > (UINT16_MAX / sizeof(WCHAR)))
diff --git a/libfreerdp/core/input.h b/libfreerdp/core/input.h
index c67153b..9a1585d 100644
--- a/libfreerdp/core/input.h
+++ b/libfreerdp/core/input.h
@@ -38,7 +38,7 @@ typedef struct
rdpInputProxy* proxy;
wMessageQueue* queue;
- UINT32 lastInputTimestamp;
+ UINT64 lastInputTimestamp;
UINT16 lastX;
UINT16 lastY;
} rdp_input_internal;
diff --git a/libfreerdp/core/license.c b/libfreerdp/core/license.c
index 99d4fa2..aeb7bb2 100644
--- a/libfreerdp/core/license.c
+++ b/libfreerdp/core/license.c
@@ -1114,10 +1114,9 @@ BOOL license_generate_hwid(rdpLicense* license)
const char* hostname = license->rdp->settings->ClientHostname;
wStream* s = Stream_StaticInit(&buffer, license->HardwareId, 4);
Stream_Write_UINT32(s, license->PlatformId);
- Stream_Free(s, TRUE);
hashTarget = (const BYTE*)hostname;
- targetLen = strlen(hostname);
+ targetLen = hostname ? strlen(hostname) : 0;
}
/* Allow FIPS override for use of MD5 here, really this does not have to be MD5 as we are just
@@ -1723,14 +1722,15 @@ void license_free_scope_list(SCOPE_LIST* scopeList)
BOOL license_send_license_info(rdpLicense* license, const LICENSE_BLOB* calBlob,
const BYTE* signature, size_t signature_length)
{
- wStream* s = license_send_stream_init(license);
-
WINPR_ASSERT(calBlob);
WINPR_ASSERT(signature);
WINPR_ASSERT(license->certificate);
const rdpCertInfo* info = freerdp_certificate_get_info(license->certificate);
+ if (!info)
+ return FALSE;
+ wStream* s = license_send_stream_init(license);
if (!s)
return FALSE;
@@ -2802,18 +2802,25 @@ BOOL license_server_send_request(rdpLicense* license)
return license_set_state(license, LICENSE_STATE_REQUEST);
}
-static BOOL license_set_string(const char* what, const char* value, WCHAR** dst, UINT32* dstLen)
+static BOOL license_set_string(const char* what, const char* value, BYTE** bdst, UINT32* dstLen)
{
WINPR_ASSERT(what);
WINPR_ASSERT(value);
- WINPR_ASSERT(dst);
+ WINPR_ASSERT(bdst);
WINPR_ASSERT(dstLen);
+ union
+ {
+ WCHAR** w;
+ BYTE** b;
+ } cnv;
+ cnv.b = bdst;
+
size_t len = 0;
- *dst = (BYTE*)ConvertUtf8ToWCharAlloc(value, &len);
- if (!*dst || (len > UINT32_MAX / sizeof(WCHAR)))
+ *cnv.w = ConvertUtf8ToWCharAlloc(value, &len);
+ if (!*cnv.w || (len > UINT32_MAX / sizeof(WCHAR)))
{
- WLog_ERR(TAG, "license->ProductInfo: %s == %p || %" PRIu32 " > UINT32_MAX", what, *dst,
+ WLog_ERR(TAG, "license->ProductInfo: %s == %p || %" PRIu32 " > UINT32_MAX", what, *cnv.w,
len);
return FALSE;
}
diff --git a/libfreerdp/core/listener.c b/libfreerdp/core/listener.c
index 5a9c1e2..a7592da 100644
--- a/libfreerdp/core/listener.c
+++ b/libfreerdp/core/listener.c
@@ -188,10 +188,11 @@ static BOOL freerdp_listener_open(freerdp_listener* instance, const char* bind_a
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void*)&option_value,
sizeof(option_value)) == -1)
- WLog_ERR(TAG, "setsockopt");
+ WLog_ERR(TAG, "setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR)");
#ifndef _WIN32
- fcntl(sockfd, F_SETFL, O_NONBLOCK);
+ if (fcntl(sockfd, F_SETFL, O_NONBLOCK) != 0)
+ WLog_ERR(TAG, "fcntl(sockfd, F_SETFL, O_NONBLOCK)");
#else
arg = 1;
ioctlsocket(sockfd, FIONBIO, &arg);
@@ -256,7 +257,14 @@ static BOOL freerdp_listener_open_local(freerdp_listener* instance, const char*
return FALSE;
}
- fcntl(sockfd, F_SETFL, O_NONBLOCK);
+ int rc = fcntl(sockfd, F_SETFL, O_NONBLOCK);
+ if (rc != 0)
+ {
+ WLog_ERR(TAG, "fcntl(sockfd, F_SETFL, O_NONBLOCK)");
+ closesocket((SOCKET)sockfd);
+ return FALSE;
+ }
+
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, path, sizeof(addr.sun_path) - 1);
unlink(path);
diff --git a/libfreerdp/core/nla.c b/libfreerdp/core/nla.c
index ddee306..577e0b4 100644
--- a/libfreerdp/core/nla.c
+++ b/libfreerdp/core/nla.c
@@ -1148,6 +1148,11 @@ static BOOL nla_read_TSCspDataDetail(WinPrAsn1Decoder* dec, rdpSettings* setting
static BOOL nla_read_KERB_TICKET_LOGON(rdpNla* nla, wStream* s, KERB_TICKET_LOGON* ticket)
{
+ WINPR_ASSERT(nla);
+
+ if (!ticket)
+ return FALSE;
+
/* mysterious extra 16 bytes before TGS/TGT content */
if (!Stream_CheckAndLogRequiredLength(TAG, s, 16 + 16))
return FALSE;
@@ -1244,7 +1249,7 @@ static BOOL nla_read_ts_credentials(rdpNla* nla, SecBuffer* data)
WinPrAsn1_OctetString credentials = { 0 };
BOOL error = FALSE;
WinPrAsn1_INTEGER credType = -1;
- BOOL ret = true;
+ BOOL ret = TRUE;
WINPR_ASSERT(nla);
WINPR_ASSERT(data);
diff --git a/libfreerdp/core/peer.c b/libfreerdp/core/peer.c
index 9d00c66..42c4c21 100644
--- a/libfreerdp/core/peer.c
+++ b/libfreerdp/core/peer.c
@@ -1495,7 +1495,8 @@ void freerdp_peer_free(freerdp_peer* client)
return;
sspi_FreeAuthIdentity(&client->identity);
- closesocket((SOCKET)client->sockfd);
+ if (client->sockfd >= 0)
+ closesocket((SOCKET)client->sockfd);
free(client);
}
@@ -1511,6 +1512,7 @@ static BOOL freerdp_peer_transport_setup(freerdp_peer* client)
if (!transport_attach(rdp->transport, client->sockfd))
return FALSE;
+ client->sockfd = -1;
if (!transport_set_recv_callbacks(rdp->transport, peer_recv_callback, client))
return FALSE;
diff --git a/libfreerdp/core/proxy.c b/libfreerdp/core/proxy.c
index 9312c22..ecb9b34 100644
--- a/libfreerdp/core/proxy.c
+++ b/libfreerdp/core/proxy.c
@@ -284,14 +284,12 @@ static BOOL check_no_proxy(rdpSettings* settings, const char* no_proxy)
void proxy_read_environment(rdpSettings* settings, char* envname)
{
- DWORD envlen = 0;
- char* env = NULL;
- envlen = GetEnvironmentVariableA(envname, NULL, 0);
+ const DWORD envlen = GetEnvironmentVariableA(envname, NULL, 0);
- if (!envlen)
+ if (!envlen || (envlen <= 1))
return;
- env = calloc(1, envlen);
+ char* env = calloc(1, envlen);
if (!env)
{
diff --git a/libfreerdp/core/rdp.c b/libfreerdp/core/rdp.c
index c1f6d3a..466a9a7 100644
--- a/libfreerdp/core/rdp.c
+++ b/libfreerdp/core/rdp.c
@@ -261,7 +261,7 @@ BOOL rdp_read_share_control_header(rdpRdp* rdp, wStream* s, UINT16* tpktLength,
WLog_Print(rdp->log, WLOG_DEBUG,
"[Flow control PDU] type=%s, tpktLength=%" PRIuz ", remainingLength=%" PRIuz,
pdu_type_to_str(*type, buffer, sizeof(buffer)), tpktLength ? *tpktLength : 0,
- *remainingLength);
+ remainingLength ? *remainingLength : 0);
return TRUE;
}
@@ -2259,7 +2259,7 @@ rdpRdp* rdp_new(rdpContext* context)
/* Keep a backup copy of settings for later comparisons */
if (!rdp_set_backup_settings(rdp))
- return FALSE;
+ goto fail;
rdp->settings->instance = context->instance;
diff --git a/libfreerdp/core/security.c b/libfreerdp/core/security.c
index 653bf0a..96cf00b 100644
--- a/libfreerdp/core/security.c
+++ b/libfreerdp/core/security.c
@@ -592,6 +592,7 @@ static void fips_expand_key_bits(const BYTE* in, size_t in_len, BYTE* out, size_
}
else
{
+ WINPR_ASSERT(p + 1 < sizeof(buf));
/* c is accumulator */
BYTE c = (BYTE)(buf[p] << r) & 0xFF;
c |= buf[p + 1] >> (8 - r);
diff --git a/libfreerdp/core/smartcardlogon.c b/libfreerdp/core/smartcardlogon.c
index d5907cf..f3f5581 100644
--- a/libfreerdp/core/smartcardlogon.c
+++ b/libfreerdp/core/smartcardlogon.c
@@ -222,11 +222,14 @@ static BOOL set_info_certificate(SmartcardCertInfo* cert, BYTE* certBytes, DWORD
return FALSE;
}
- if (userFilter && cert->userHint && strcmp(cert->userHint, userFilter) != 0)
+ if (userFilter && (!cert->upn || (strcmp(cert->upn, userFilter) != 0)))
{
- WLog_DBG(TAG, "discarding non matching cert by user %s@%s", cert->userHint,
- cert->domainHint);
- return FALSE;
+ if (cert->userHint && strcmp(cert->userHint, userFilter) != 0)
+ {
+ WLog_DBG(TAG, "discarding non matching cert by user %s@%s", cert->userHint,
+ cert->domainHint);
+ return FALSE;
+ }
}
if (domainFilter && cert->domainHint && strcmp(cert->domainHint, domainFilter) != 0)
diff --git a/libfreerdp/core/test/CMakeLists.txt b/libfreerdp/core/test/CMakeLists.txt
index 3e0a652..ebd8fef 100644
--- a/libfreerdp/core/test/CMakeLists.txt
+++ b/libfreerdp/core/test/CMakeLists.txt
@@ -9,8 +9,9 @@ set(${MODULE_PREFIX}_TESTS
TestStreamDump.c
TestSettings.c)
-set(${MODULE_PREFIX}_FUZZERS
- TestFuzzCryptoCertificateDataSetPEM.c)
+set(FUZZERS
+ TestFuzzCryptoCertificateDataSetPEM.c
+)
if(WITH_SAMPLE AND WITH_SERVER AND NOT WIN32)
add_definitions(-DCMAKE_EXECUTABLE_SUFFIX="${CMAKE_EXECUTABLE_SUFFIX}")
@@ -32,16 +33,8 @@ add_definitions(-DTESTING_SRC_DIRECTORY="${PROJECT_SOURCE_DIR}")
target_link_libraries(${MODULE_NAME} freerdp winpr freerdp-client)
-if (BUILD_FUZZERS)
- foreach(test ${${MODULE_PREFIX}_FUZZERS})
- get_filename_component(TestName ${test} NAME_WE)
- add_executable(${TestName} ${test})
- target_link_libraries(${TestName} freerdp winpr freerdp-client fuzzer_config)
- add_test(${TestName} ${TESTING_OUTPUT_DIRECTORY}/${MODULE_NAME} ${TestName})
- set_target_properties(${TestName} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
- add_dependencies(fuzzers ${TestName})
- endforeach()
-endif (BUILD_FUZZERS)
+include (AddFuzzerTest)
+add_fuzzer_test("${FUZZERS}" "freerdp winpr")
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
diff --git a/libfreerdp/core/test/settings_property_lists.h b/libfreerdp/core/test/settings_property_lists.h
index fb280e6..d966242 100644
--- a/libfreerdp/core/test/settings_property_lists.h
+++ b/libfreerdp/core/test/settings_property_lists.h
@@ -19,6 +19,7 @@ static const size_t bool_list_indices[] = {
FreeRDP_AutoDenyCertificate,
FreeRDP_AutoLogonEnabled,
FreeRDP_AutoReconnectionEnabled,
+ FreeRDP_AutoReconnectionPacketSupported,
FreeRDP_BitmapCacheEnabled,
FreeRDP_BitmapCachePersistEnabled,
FreeRDP_BitmapCacheV3Enabled,
@@ -68,6 +69,7 @@ static const size_t bool_list_indices[] = {
FreeRDP_GatewayHttpExtAuthSspiNtlm,
FreeRDP_GatewayHttpTransport,
FreeRDP_GatewayHttpUseWebsockets,
+ FreeRDP_GatewayIgnoreRedirectionPolicy,
FreeRDP_GatewayRpcTransport,
FreeRDP_GatewayUdpTransport,
FreeRDP_GatewayUseSameCredentials,
diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c
index e4cc570..a2a899b 100644
--- a/libfreerdp/core/transport.c
+++ b/libfreerdp/core/transport.c
@@ -197,8 +197,6 @@ static BOOL transport_default_attach(rdpTransport* transport, int sockfd)
if (!socketBio)
goto fail;
-
- BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
}
bufferedBio = BIO_new(BIO_s_buffered_socket());
@@ -206,8 +204,18 @@ static BOOL transport_default_attach(rdpTransport* transport, int sockfd)
goto fail;
if (socketBio)
+ {
bufferedBio = BIO_push(bufferedBio, socketBio);
- WINPR_ASSERT(bufferedBio);
+ if (!bufferedBio)
+ goto fail;
+
+ /* Attach the socket only when this function can no longer fail.
+ * This ensures solid ownership:
+ * - if this function fails, the caller is responsible to clean up
+ * - if this function is successful, the caller MUST NOT close the socket any more.
+ */
+ BIO_set_fd(socketBio, sockfd, BIO_CLOSE);
+ }
transport->frontBio = bufferedBio;
return TRUE;
fail:
diff --git a/libfreerdp/core/transport.h b/libfreerdp/core/transport.h
index 8b5c5c6..912fffd 100644
--- a/libfreerdp/core/transport.h
+++ b/libfreerdp/core/transport.h
@@ -58,6 +58,21 @@ FREERDP_LOCAL wStream* transport_send_stream_init(rdpTransport* transport, size_
FREERDP_LOCAL BOOL transport_connect(rdpTransport* transport, const char* hostname, UINT16 port,
DWORD timeout);
FREERDP_LOCAL BOOL transport_connect_childsession(rdpTransport* transport);
+
+/**! \brief Attach a socket to the transport layer
+ *
+ * The ownership of the socket provided by \b sockfd is taken if and only if the function is
+ * successful. In such a case the caller must no longer close or otherwise use the socket. If the
+ * function fails it is up to the caller to close the socket.
+ *
+ * The implementation can be overridden by
+ * transport_set_io_callbacks(rdpTransportIo::TransportAttach)
+ *
+ * \param transport The transport instance to attach the socket to
+ * \param sockfd The socket to attach to the transport
+ *
+ * \return \b TRUE in case of success, \b FALSE otherwise.
+ */
FREERDP_LOCAL BOOL transport_attach(rdpTransport* transport, int sockfd);
FREERDP_LOCAL BOOL transport_disconnect(rdpTransport* transport);
FREERDP_LOCAL BOOL transport_connect_rdp(rdpTransport* transport);
diff --git a/libfreerdp/core/update.c b/libfreerdp/core/update.c
index db8ddef..cfc0abc 100644
--- a/libfreerdp/core/update.c
+++ b/libfreerdp/core/update.c
@@ -3322,6 +3322,10 @@ BOOL update_begin_paint(rdpUpdate* update)
WINPR_ASSERT(update->context);
+ BOOL rc = IFCALLRESULT(TRUE, update->BeginPaint, update->context);
+ if (!rc)
+ WLog_WARN(TAG, "BeginPaint call failed");
+
/* Reset the invalid regions, we start a new frame here. */
rdpGdi* gdi = update->context->gdi;
WINPR_ASSERT(gdi);
@@ -3335,10 +3339,6 @@ BOOL update_begin_paint(rdpUpdate* update)
hwnd->ninvalid = 0;
}
- BOOL rc = IFCALLRESULT(TRUE, update->BeginPaint, update->context);
- if (!rc)
- WLog_WARN(TAG, "BeginPaint call failed");
-
return rc;
}
diff --git a/libfreerdp/core/utils.c b/libfreerdp/core/utils.c
index 1bcb090..f414611 100644
--- a/libfreerdp/core/utils.c
+++ b/libfreerdp/core/utils.c
@@ -25,6 +25,8 @@
#include <winpr/assert.h>
#include <freerdp/freerdp.h>
+#include <freerdp/channels/cliprdr.h>
+#include <freerdp/channels/rdpdr.h>
#include <freerdp/log.h>
#define TAG FREERDP_TAG("core.gateway.utils")
@@ -299,3 +301,182 @@ const char* utils_is_vsock(const char* hostname)
return &hostname[sizeof(vsock)];
return NULL;
}
+
+static BOOL remove_rdpdr_type(rdpSettings* settings, UINT32 type)
+{
+ RDPDR_DEVICE* printer = NULL;
+ do
+ {
+ printer = freerdp_device_collection_find_type(settings, type);
+ freerdp_device_collection_del(settings, printer);
+ freerdp_device_free(printer);
+ } while (printer);
+ return TRUE;
+}
+
+static BOOL disable_clipboard(rdpSettings* settings)
+{
+ if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectClipboard, FALSE))
+ return FALSE;
+ freerdp_static_channel_collection_del(settings, CLIPRDR_SVC_CHANNEL_NAME);
+ return TRUE;
+}
+
+static BOOL disable_drive(rdpSettings* settings)
+{
+ if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectDrives, FALSE))
+ return FALSE;
+ if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectHomeDrive, FALSE))
+ return FALSE;
+
+ return remove_rdpdr_type(settings, RDPDR_DTYP_FILESYSTEM);
+}
+
+static BOOL disable_printers(rdpSettings* settings)
+{
+ if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectPrinters, FALSE))
+ return FALSE;
+
+ return remove_rdpdr_type(settings, RDPDR_DTYP_PRINT);
+}
+
+static BOOL disable_port(rdpSettings* settings)
+{
+ if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectParallelPorts, FALSE))
+ return FALSE;
+ if (!freerdp_settings_set_bool(settings, FreeRDP_RedirectSerialPorts, FALSE))
+ return FALSE;
+ if (!remove_rdpdr_type(settings, RDPDR_DTYP_SERIAL))
+ return FALSE;
+ return remove_rdpdr_type(settings, RDPDR_DTYP_PARALLEL);
+}
+
+static BOOL disable_pnp(rdpSettings* settings)
+{
+ // TODO(akallabeth): [MS-RDPEPNP] related stuff is disabled.
+ return TRUE;
+}
+
+static BOOL apply_gw_policy(rdpContext* context)
+{
+ WINPR_ASSERT(context);
+ return utils_reload_channels(context);
+}
+
+BOOL utils_apply_gateway_policy(wLog* log, rdpContext* context, UINT32 flags, const char* module)
+{
+ WINPR_ASSERT(log);
+ WINPR_ASSERT(context);
+
+ rdpSettings* settings = context->settings;
+ WINPR_ASSERT(settings);
+
+ if (flags & HTTP_TUNNEL_REDIR_ENABLE_ALL)
+ {
+ WLog_Print(log, WLOG_DEBUG, "[%s] policy allows all redirections", module);
+ }
+ else if (freerdp_settings_get_bool(settings, FreeRDP_GatewayIgnoreRedirectionPolicy))
+ {
+ char buffer[128] = { 0 };
+ WLog_Print(log, WLOG_INFO, "[%s] policy ignored on user request %s", module,
+ utils_redir_flags_to_string(flags, buffer, sizeof(buffer)));
+ }
+ else if (flags & HTTP_TUNNEL_REDIR_DISABLE_ALL)
+ {
+ WLog_Print(log, WLOG_INFO, "[%s] policy denies all redirections", module);
+ if (!disable_drive(settings))
+ return FALSE;
+ if (!disable_printers(settings))
+ return FALSE;
+ if (!disable_clipboard(settings))
+ return FALSE;
+ if (!disable_port(settings))
+ return FALSE;
+ if (!disable_pnp(settings))
+ return FALSE;
+ if (!apply_gw_policy(context))
+ return FALSE;
+ }
+ else
+ {
+ if (flags & HTTP_TUNNEL_REDIR_DISABLE_DRIVE)
+ {
+ WLog_Print(log, WLOG_INFO, "[%s] policy denies drive redirections", module);
+ if (!disable_drive(settings))
+ return FALSE;
+ }
+ if (flags & HTTP_TUNNEL_REDIR_DISABLE_PRINTER)
+ {
+ WLog_Print(log, WLOG_INFO, "[%s] policy denies printer redirections", module);
+ if (!disable_printers(settings))
+ return FALSE;
+ }
+ if (flags & HTTP_TUNNEL_REDIR_DISABLE_PORT)
+ {
+ WLog_Print(log, WLOG_INFO, "[%s] policy denies port redirections", module);
+ if (!disable_port(settings))
+ return FALSE;
+ }
+ if (flags & HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD)
+ {
+ WLog_Print(log, WLOG_INFO, "[%s] policy denies clipboard redirections", module);
+ if (!disable_clipboard(settings))
+ return FALSE;
+ }
+ if (flags & HTTP_TUNNEL_REDIR_DISABLE_PNP)
+ {
+ WLog_Print(log, WLOG_INFO, "[%s] policy denies PNP redirections", module);
+ if (!disable_pnp(settings))
+ return FALSE;
+ }
+ if (flags != 0)
+ {
+ if (!apply_gw_policy(context))
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+char* utils_redir_flags_to_string(UINT32 flags, char* buffer, size_t size)
+{
+ winpr_str_append("{", buffer, size, "");
+ if (flags & HTTP_TUNNEL_REDIR_ENABLE_ALL)
+ winpr_str_append("ENABLE_ALL", buffer, size, "|");
+ if (flags & HTTP_TUNNEL_REDIR_DISABLE_ALL)
+ winpr_str_append("DISABLE_ALL", buffer, size, "|");
+ if (flags & HTTP_TUNNEL_REDIR_DISABLE_DRIVE)
+ winpr_str_append("DISABLE_DRIVE", buffer, size, "|");
+ if (flags & HTTP_TUNNEL_REDIR_DISABLE_PRINTER)
+ winpr_str_append("DISABLE_PRINTER", buffer, size, "|");
+ if (flags & HTTP_TUNNEL_REDIR_DISABLE_PORT)
+ winpr_str_append("DISABLE_PORT", buffer, size, "|");
+ if (flags & HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD)
+ winpr_str_append("DISABLE_CLIPBOARD", buffer, size, "|");
+ if (flags & HTTP_TUNNEL_REDIR_DISABLE_PNP)
+ winpr_str_append("DISABLE_PNP", buffer, size, "|");
+
+ char fbuffer[16] = { 0 };
+ _snprintf(fbuffer, sizeof(fbuffer), "[0x%08" PRIx32 "]", flags);
+
+ winpr_str_append(fbuffer, buffer, size, " ");
+ winpr_str_append("{", buffer, size, "}");
+ return buffer;
+}
+
+BOOL utils_reload_channels(rdpContext* context)
+{
+ WINPR_ASSERT(context);
+
+ freerdp_channels_disconnect(context->channels, context->instance);
+ freerdp_channels_close(context->channels, context->instance);
+ freerdp_channels_free(context->channels);
+ context->channels = freerdp_channels_new(context->instance);
+ WINPR_ASSERT(context->channels);
+
+ BOOL rc = TRUE;
+ IFCALLRET(context->instance->LoadChannels, rc, context->instance);
+ if (rc)
+ return freerdp_channels_pre_connect(context->channels, context->instance) == CHANNEL_RC_OK;
+ return rc;
+}
diff --git a/libfreerdp/core/utils.h b/libfreerdp/core/utils.h
index 87fa272..54a7856 100644
--- a/libfreerdp/core/utils.h
+++ b/libfreerdp/core/utils.h
@@ -24,6 +24,15 @@
#include <winpr/winpr.h>
#include <freerdp/freerdp.h>
+/* HTTP tunnel redir flags. */
+#define HTTP_TUNNEL_REDIR_ENABLE_ALL 0x80000000
+#define HTTP_TUNNEL_REDIR_DISABLE_ALL 0x40000000
+#define HTTP_TUNNEL_REDIR_DISABLE_DRIVE 0x1
+#define HTTP_TUNNEL_REDIR_DISABLE_PRINTER 0x2
+#define HTTP_TUNNEL_REDIR_DISABLE_PORT 0x4
+#define HTTP_TUNNEL_REDIR_DISABLE_CLIPBOARD 0x8
+#define HTTP_TUNNEL_REDIR_DISABLE_PNP 0x10
+
typedef enum
{
AUTH_SUCCESS,
@@ -47,4 +56,9 @@ BOOL utils_str_copy(const char* value, char** dst);
const char* utils_is_vsock(const char* hostname);
+BOOL utils_apply_gateway_policy(wLog* log, rdpContext* context, UINT32 flags, const char* module);
+char* utils_redir_flags_to_string(UINT32 flags, char* buffer, size_t size);
+
+BOOL utils_reload_channels(rdpContext* context);
+
#endif /* FREERDP_LIB_CORE_UTILS_H */
diff --git a/libfreerdp/crypto/cert_common.c b/libfreerdp/crypto/cert_common.c
index 60ef60f..bd0abad 100644
--- a/libfreerdp/crypto/cert_common.c
+++ b/libfreerdp/crypto/cert_common.c
@@ -144,7 +144,10 @@ BOOL cert_info_allocate(rdpCertInfo* info, size_t size)
info->Modulus = (BYTE*)malloc(size);
if (!info->Modulus && (size > 0))
+ {
+ WLog_ERR(TAG, "Failed to allocate info->Modulus of size %" PRIuz, size);
return FALSE;
+ }
info->ModulusLength = (UINT32)size;
return TRUE;
}
@@ -154,7 +157,10 @@ BOOL cert_info_read_modulus(rdpCertInfo* info, size_t size, wStream* s)
if (!Stream_CheckAndLogRequiredLength(TAG, s, size))
return FALSE;
if (size > UINT32_MAX)
+ {
+ WLog_ERR(TAG, "modulus size %" PRIuz " exceeds limit of %" PRIu32, size, UINT32_MAX);
return FALSE;
+ }
if (!cert_info_allocate(info, size))
return FALSE;
Stream_Read(s, info->Modulus, info->ModulusLength);
@@ -166,9 +172,15 @@ BOOL cert_info_read_exponent(rdpCertInfo* info, size_t size, wStream* s)
if (!Stream_CheckAndLogRequiredLength(TAG, s, size))
return FALSE;
if (size > 4)
+ {
+ WLog_ERR(TAG, "exponent size %" PRIuz " exceeds limit of %" PRIu32, size, 4);
return FALSE;
+ }
if (!info->Modulus || (info->ModulusLength == 0))
+ {
+ WLog_ERR(TAG, "invalid modulus=%p [%" PRIu32 "]", info->Modulus, info->ModulusLength);
return FALSE;
+ }
Stream_Read(s, &info->exponent[4 - size], size);
crypto_reverse(info->Modulus, info->ModulusLength);
crypto_reverse(info->exponent, 4);
diff --git a/libfreerdp/crypto/certificate.c b/libfreerdp/crypto/certificate.c
index ddfe776..896b605 100644
--- a/libfreerdp/crypto/certificate.c
+++ b/libfreerdp/crypto/certificate.c
@@ -301,8 +301,8 @@ static BOOL certificate_read_x509_certificate(const rdpCertBlob* cert, rdpCertIn
size_t exponent_length = 0;
int error = 0;
- if (!cert || !info)
- return FALSE;
+ WINPR_ASSERT(cert);
+ WINPR_ASSERT(info);
cert_info_free(info);
@@ -571,6 +571,9 @@ fail2:
rc = TRUE;
fail:
+ if (!rc)
+ WLog_ERR(TAG, "failed to update x509 from rdpCertInfo");
+
#if !defined(OPENSSL_VERSION_MAJOR) || (OPENSSL_VERSION_MAJOR < 3)
if (rsa)
RSA_free(rsa);
@@ -600,7 +603,7 @@ static BOOL certificate_process_server_public_key(rdpCertificate* cert, wStream*
if (memcmp(magic, rsa_magic, sizeof(magic)) != 0)
{
- WLog_ERR(TAG, "magic error");
+ WLog_ERR(TAG, "invalid RSA magic bytes");
return FALSE;
}
@@ -612,14 +615,33 @@ static BOOL certificate_process_server_public_key(rdpCertificate* cert, wStream*
Stream_Read_UINT32(s, datalen);
Stream_Read(s, info->exponent, 4);
- if ((keylen <= 8) || (!Stream_CheckAndLogRequiredLength(TAG, s, keylen)))
+ if (keylen <= 8)
+ {
+ WLog_ERR(TAG, "Invalid RSA keylen=%" PRIu32 " <= 8", keylen);
return FALSE;
-
+ }
+ if (!Stream_CheckAndLogRequiredLength(TAG, s, keylen))
+ return FALSE;
+ if (keylen != (bitlen / 8ull) + 8ull)
+ {
+ WLog_ERR(TAG, "Invalid RSA key bitlen %" PRIu32 ", expected %" PRIu32, bitlen,
+ (keylen - 8) * 8);
+ return FALSE;
+ }
+ if (datalen != (bitlen / 8ull) - 1ull)
+ {
+ WLog_ERR(TAG, "Invalid RSA key datalen %" PRIu32 ", expected %" PRIu32, datalen,
+ (bitlen / 8ull) - 1ull);
+ return FALSE;
+ }
info->ModulusLength = keylen - 8;
BYTE* tmp = realloc(info->Modulus, info->ModulusLength);
if (!tmp)
+ {
+ WLog_ERR(TAG, "Failed to reallocate modulus of length %" PRIu32, info->ModulusLength);
return FALSE;
+ }
info->Modulus = tmp;
Stream_Read(s, info->Modulus, info->ModulusLength);
@@ -957,6 +979,7 @@ static BOOL certificate_read_server_x509_certificate_chain(rdpCertificate* cert,
if (!res)
{
+ WLog_ERR(TAG, "Failed to read x509 certificate");
return FALSE;
}
@@ -1592,6 +1615,8 @@ BOOL freerdp_certificate_publickey_encrypt(const rdpCertificate* cert, const BYT
size_t outputSize = EVP_PKEY_size(pkey);
output = malloc(outputSize);
+ if (output == NULL)
+ goto out;
*pcbOutput = outputSize;
if (EVP_PKEY_encrypt_init(ctx) != 1 ||
diff --git a/libfreerdp/crypto/certificate_data.c b/libfreerdp/crypto/certificate_data.c
index a48beb4..04b5432 100644
--- a/libfreerdp/crypto/certificate_data.c
+++ b/libfreerdp/crypto/certificate_data.c
@@ -50,11 +50,21 @@ struct rdp_certificate_data
char* cached_pem;
};
+/* ensure our hostnames (and therefore filenames) always use the same capitalization.
+ * the user might have input random case, but we always need to have a sane
+ * baseline to compare against. */
+static char* ensure_lowercase(char* str, size_t length)
+{
+ const size_t len = strnlen(str, length);
+ for (size_t x = 0; x < len; x++)
+ str[x] = tolower(str[x]);
+ return str;
+}
static const char* freerdp_certificate_data_hash_(const char* hostname, UINT16 port, char* name,
size_t length)
{
_snprintf(name, length, "%s_%" PRIu16 ".pem", hostname, port);
- return name;
+ return ensure_lowercase(name, length);
}
static BOOL freerdp_certificate_data_load_cache(rdpCertificateData* data)
@@ -107,8 +117,7 @@ static rdpCertificateData* freerdp_certificate_data_new_nocopy(const char* hostn
certdata->hostname = _strdup(hostname);
if (!certdata->hostname)
goto fail;
- for (size_t i = 0; i < strlen(hostname); i++)
- certdata->hostname[i] = tolower(certdata->hostname[i]);
+ ensure_lowercase(certdata->hostname, strlen(certdata->hostname));
certdata->cert = xcert;
if (!freerdp_certificate_data_load_cache(certdata))
@@ -176,43 +185,44 @@ void freerdp_certificate_data_free(rdpCertificateData* data)
const char* freerdp_certificate_data_get_host(const rdpCertificateData* cert)
{
- WINPR_ASSERT(cert);
+ if (!cert)
+ return NULL;
return cert->hostname;
}
UINT16 freerdp_certificate_data_get_port(const rdpCertificateData* cert)
{
- WINPR_ASSERT(cert);
+ if (!cert)
+ return 0;
return cert->port;
}
const char* freerdp_certificate_data_get_pem(const rdpCertificateData* cert)
{
- WINPR_ASSERT(cert);
- WINPR_ASSERT(cert->cached_pem);
-
+ if (!cert)
+ return NULL;
return cert->cached_pem;
}
const char* freerdp_certificate_data_get_subject(const rdpCertificateData* cert)
{
- WINPR_ASSERT(cert);
- WINPR_ASSERT(cert->cached_subject);
+ if (!cert)
+ return NULL;
return cert->cached_subject;
}
const char* freerdp_certificate_data_get_issuer(const rdpCertificateData* cert)
{
- WINPR_ASSERT(cert);
- WINPR_ASSERT(cert->cached_issuer);
+ if (!cert)
+ return NULL;
return cert->cached_issuer;
}
const char* freerdp_certificate_data_get_fingerprint(const rdpCertificateData* cert)
{
- WINPR_ASSERT(cert);
- WINPR_ASSERT(cert->cached_fingerprint);
+ if (!cert)
+ return NULL;
return cert->cached_fingerprint;
}
@@ -241,8 +251,8 @@ BOOL freerdp_certificate_data_equal(const rdpCertificateData* a, const rdpCertif
const char* freerdp_certificate_data_get_hash(const rdpCertificateData* cert)
{
- WINPR_ASSERT(cert);
- WINPR_ASSERT(cert->cached_hash);
+ if (!cert)
+ return NULL;
return cert->cached_hash;
}
diff --git a/libfreerdp/crypto/privatekey.c b/libfreerdp/crypto/privatekey.c
index 159157c..55379d4 100644
--- a/libfreerdp/crypto/privatekey.c
+++ b/libfreerdp/crypto/privatekey.c
@@ -482,13 +482,19 @@ char* freerdp_key_get_param(const rdpPrivateKey* key, enum FREERDP_KEY_PARAM par
switch (param)
{
case FREERDP_KEY_PARAM_RSA_D:
+#if OPENSSL_VERSION_NUMBER >= 0x10101007L
cbn = RSA_get0_d(rsa);
+#endif
break;
case FREERDP_KEY_PARAM_RSA_E:
+#if OPENSSL_VERSION_NUMBER >= 0x10101007L
cbn = RSA_get0_e(rsa);
+#endif
break;
case FREERDP_KEY_PARAM_RSA_N:
+#if OPENSSL_VERSION_NUMBER >= 0x10101007L
cbn = RSA_get0_n(rsa);
+#endif
break;
default:
return NULL;
diff --git a/libfreerdp/crypto/tls.c b/libfreerdp/crypto/tls.c
index 371b81b..2d40038 100644
--- a/libfreerdp/crypto/tls.c
+++ b/libfreerdp/crypto/tls.c
@@ -985,6 +985,7 @@ static int pollAndHandshake(rdpTls* tls)
case WAIT_OBJECT_0:
break;
case WAIT_TIMEOUT:
+ case WAIT_IO_COMPLETION:
continue;
default:
WLog_ERR(TAG, "error during WaitForSingleObject(): 0x%08" PRIX32 "", status);
@@ -1107,7 +1108,7 @@ TlsHandshakeResult freerdp_tls_accept_ex(rdpTls* tls, BIO* underlying, rdpSettin
* Disable SSL client site renegotiation.
*/
-#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && (OPENSSL_VERSION_NUMBER < 0x30000000L) && \
+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) && (OPENSSL_VERSION_NUMBER < 0x30000000L) && \
!defined(LIBRESSL_VERSION_NUMBER)
options |= SSL_OP_NO_RENEGOTIATION;
#endif
diff --git a/libfreerdp/emu/scard/smartcard_emulate.c b/libfreerdp/emu/scard/smartcard_emulate.c
index b2809c3..d517bd6 100644
--- a/libfreerdp/emu/scard/smartcard_emulate.c
+++ b/libfreerdp/emu/scard/smartcard_emulate.c
@@ -19,6 +19,7 @@
*/
#include <freerdp/config.h>
+#include <freerdp/freerdp.h>
#include <winpr/crt.h>
#include <winpr/wlog.h>
@@ -1362,6 +1363,10 @@ LONG WINAPI Emulate_SCardGetStatusChangeA(SmartcardEmulationContext* smartcard,
SCardContext* value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
WINPR_ASSERT(value); /* Must be valid after Emulate_SCardIsValidContext */
+ freerdp* inst =
+ freerdp_settings_get_pointer_writable(smartcard->settings, FreeRDP_instance);
+ WINPR_ASSERT(inst);
+
status = SCARD_E_TIMEOUT;
do
{
@@ -1410,6 +1415,11 @@ LONG WINAPI Emulate_SCardGetStatusChangeA(SmartcardEmulationContext* smartcard,
Sleep(diff);
if (dwTimeout != INFINITE)
dwTimeout -= MIN(dwTimeout, diff);
+ if (freerdp_shall_disconnect_context(inst->context))
+ {
+ status = SCARD_E_CANCELLED;
+ break;
+ }
} while (dwTimeout > 0);
}
@@ -1436,6 +1446,10 @@ LONG WINAPI Emulate_SCardGetStatusChangeW(SmartcardEmulationContext* smartcard,
SCardContext* value = HashTable_GetItemValue(smartcard->contexts, (const void*)hContext);
WINPR_ASSERT(value); /* Must be valid after Emulate_SCardIsValidContext */
+ freerdp* inst =
+ freerdp_settings_get_pointer_writable(smartcard->settings, FreeRDP_instance);
+ WINPR_ASSERT(inst);
+
status = SCARD_E_TIMEOUT;
do
{
@@ -1483,6 +1497,11 @@ LONG WINAPI Emulate_SCardGetStatusChangeW(SmartcardEmulationContext* smartcard,
Sleep(diff);
if (dwTimeout != INFINITE)
dwTimeout -= MIN(dwTimeout, diff);
+ if (freerdp_shall_disconnect_context(inst->context))
+ {
+ status = SCARD_E_CANCELLED;
+ break;
+ }
} while (dwTimeout > 0);
}
diff --git a/libfreerdp/emu/scard/smartcard_virtual_gids.c b/libfreerdp/emu/scard/smartcard_virtual_gids.c
index 3d4dda3..4f29c25 100644
--- a/libfreerdp/emu/scard/smartcard_virtual_gids.c
+++ b/libfreerdp/emu/scard/smartcard_virtual_gids.c
@@ -842,14 +842,14 @@ static BOOL vgids_get_public_key(vgidsContext* context, UINT16 doTag)
/* set response data */
Stream_SetPosition(response, 0);
context->responseData = response;
+ response = NULL;
rc = TRUE;
handle_error:
free(n);
free(e);
Stream_Free(pubKey, TRUE);
- if (!rc)
- Stream_Free(response, TRUE);
+ Stream_Free(response, TRUE);
return rc;
}
@@ -1047,8 +1047,10 @@ static BOOL vgids_perform_digital_signature(vgidsContext* context)
{ g_PKCS1_SHA256, sizeof(g_PKCS1_SHA256), EVP_sha256() },
{ g_PKCS1_SHA384, sizeof(g_PKCS1_SHA384), EVP_sha384() },
{ g_PKCS1_SHA512, sizeof(g_PKCS1_SHA512), EVP_sha512() },
+#if OPENSSL_VERSION_NUMBER >= 0x10101000L
{ g_PKCS1_SHA512_224, sizeof(g_PKCS1_SHA512_224), EVP_sha512_224() },
{ g_PKCS1_SHA512_256, sizeof(g_PKCS1_SHA512_256), EVP_sha512_256() }
+#endif
};
if (!pk)
diff --git a/libfreerdp/freerdp.pc.in b/libfreerdp/freerdp.pc.in
index 7555957..185ec98 100644
--- a/libfreerdp/freerdp.pc.in
+++ b/libfreerdp/freerdp.pc.in
@@ -14,7 +14,7 @@ Description: FreeRDP: A Remote Desktop Protocol Implementation
URL: http://www.freerdp.com/
Version: @FREERDP_VERSION@
Requires:
-Requires.private: winpr@FREERDP_API_VERSION@
+Requires.private: winpr@FREERDP_API_VERSION@ @FREERDP_REQUIRES_PRIVATE@
Libs: -L${libdir} ${libs}
-Libs.private: -ldl -lpthread
+Libs.private: -ldl -lpthread @FREERDP_PC_PRIVATE_LIBS@
Cflags: -I${includedir}
diff --git a/libfreerdp/locale/keyboard_xkbfile.c b/libfreerdp/locale/keyboard_xkbfile.c
index a64cac9..2b80aa4 100644
--- a/libfreerdp/locale/keyboard_xkbfile.c
+++ b/libfreerdp/locale/keyboard_xkbfile.c
@@ -47,265 +47,254 @@ typedef struct
} XKB_KEY_NAME_SCANCODE;
static const XKB_KEY_NAME_SCANCODE XKB_KEY_NAME_SCANCODE_TABLE[] = {
- { "AB00", RDP_SCANCODE_LSHIFT },
- { "AB01", RDP_SCANCODE_KEY_Z }, // evdev 52
- { "AB02", RDP_SCANCODE_KEY_X }, // evdev 53
- { "AB03", RDP_SCANCODE_KEY_C }, // evdev 54
- { "AB04", RDP_SCANCODE_KEY_V }, // evdev 55
- { "AB05", RDP_SCANCODE_KEY_B }, // evdev 56
- { "AB06", RDP_SCANCODE_KEY_N }, // evdev 57
- { "AB07", RDP_SCANCODE_KEY_M }, // evdev 58
- { "AB08", RDP_SCANCODE_OEM_COMMA }, // evdev 59
- { "AB09", RDP_SCANCODE_OEM_PERIOD }, // evdev 60
- { "AB10", RDP_SCANCODE_OEM_2 }, // evdev 61. Not KP, not RDP_SCANCODE_DIVIDE
- { "AB11", RDP_SCANCODE_ABNT_C1 }, // evdev 97. Brazil backslash/underscore.
- { "AC01", RDP_SCANCODE_KEY_A }, // evdev 38
- { "AC02", RDP_SCANCODE_KEY_S }, // evdev 39
- { "AC03", RDP_SCANCODE_KEY_D }, // evdev 40
- { "AC04", RDP_SCANCODE_KEY_F }, // evdev 41
- { "AC05", RDP_SCANCODE_KEY_G }, // evdev 42
- { "AC06", RDP_SCANCODE_KEY_H }, // evdev 43
- { "AC07", RDP_SCANCODE_KEY_J }, // evdev 44
- { "AC08", RDP_SCANCODE_KEY_K }, // evdev 45
- { "AC09", RDP_SCANCODE_KEY_L }, // evdev 46
- { "AC10", RDP_SCANCODE_OEM_1 }, // evdev 47
- { "AC11", RDP_SCANCODE_OEM_7 }, // evdev 48
- { "AC12", RDP_SCANCODE_OEM_5 }, // alias of evdev 51 backslash
- { "AD01", RDP_SCANCODE_KEY_Q }, // evdev 24
- { "AD02", RDP_SCANCODE_KEY_W }, // evdev 25
- { "AD03", RDP_SCANCODE_KEY_E }, // evdev 26
- { "AD04", RDP_SCANCODE_KEY_R }, // evdev 27
- { "AD05", RDP_SCANCODE_KEY_T }, // evdev 28
- { "AD06", RDP_SCANCODE_KEY_Y }, // evdev 29
- { "AD07", RDP_SCANCODE_KEY_U }, // evdev 30
- { "AD08", RDP_SCANCODE_KEY_I }, // evdev 31
- { "AD09", RDP_SCANCODE_KEY_O }, // evdev 32
- { "AD10", RDP_SCANCODE_KEY_P }, // evdev 33
- { "AD11", RDP_SCANCODE_OEM_4 }, // evdev 34
- { "AD12", RDP_SCANCODE_OEM_6 }, // evdev 35
- { "AE00", RDP_SCANCODE_OEM_3 },
- { "AE01", RDP_SCANCODE_KEY_1 }, // evdev 10
- { "AE02", RDP_SCANCODE_KEY_2 }, // evdev 11
- { "AE03", RDP_SCANCODE_KEY_3 }, // evdev 12
- { "AE04", RDP_SCANCODE_KEY_4 }, // evdev 13
- { "AE05", RDP_SCANCODE_KEY_5 }, // evdev 14
- { "AE06", RDP_SCANCODE_KEY_6 }, // evdev 15
- { "AE07", RDP_SCANCODE_KEY_7 }, // evdev 16
- { "AE08", RDP_SCANCODE_KEY_8 }, // evdev 17
- { "AE09", RDP_SCANCODE_KEY_9 }, // evdev 18
- { "AE10", RDP_SCANCODE_KEY_0 }, // evdev 19
- { "AE11", RDP_SCANCODE_OEM_MINUS }, // evdev 20
- { "AE12", RDP_SCANCODE_OEM_PLUS }, // evdev 21
- { "AE13", RDP_SCANCODE_BACKSLASH_JP }, // JP 132 Yen next to backspace
- // { "AGAI", RDP_SCANCODE_ }, // evdev 137
- { "ALGR", RDP_SCANCODE_RMENU }, // alias of evdev 108 RALT
- { "ALT", RDP_SCANCODE_LMENU }, // evdev 204, fake keycode for virtual key
- { "BKSL", RDP_SCANCODE_OEM_5 }, // evdev 51
- { "BKSP", RDP_SCANCODE_BACKSPACE }, // evdev 22
- // { "BRK", RDP_SCANCODE_ }, // evdev 419
- { "CAPS", RDP_SCANCODE_CAPSLOCK }, // evdev 66
- { "COMP", RDP_SCANCODE_APPS }, // evdev 135
- // { "COPY", RDP_SCANCODE_ }, // evdev 141
- // { "CUT", RDP_SCANCODE_ }, // evdev 145
- { "DELE", RDP_SCANCODE_DELETE }, // evdev 119
- { "DOWN", RDP_SCANCODE_DOWN }, // evdev 116
- { "END", RDP_SCANCODE_END }, // evdev 115
- { "ESC", RDP_SCANCODE_ESCAPE }, // evdev 9
- // { "FIND", RDP_SCANCODE_ }, // evdev 144
- { "FK01", RDP_SCANCODE_F1 }, // evdev 67
- { "FK02", RDP_SCANCODE_F2 }, // evdev 68
- { "FK03", RDP_SCANCODE_F3 }, // evdev 69
- { "FK04", RDP_SCANCODE_F4 }, // evdev 70
- { "FK05", RDP_SCANCODE_F5 }, // evdev 71
- { "FK06", RDP_SCANCODE_F6 }, // evdev 72
- { "FK07", RDP_SCANCODE_F7 }, // evdev 73
- { "FK08", RDP_SCANCODE_F8 }, // evdev 74
- { "FK09", RDP_SCANCODE_F9 }, // evdev 75
- { "FK10", RDP_SCANCODE_F10 }, // evdev 76
- { "FK11", RDP_SCANCODE_F11 }, // evdev 95
- { "FK12", RDP_SCANCODE_F12 }, // evdev 96
- { "FK13", RDP_SCANCODE_F13 }, // evdev 191
- { "FK14", RDP_SCANCODE_F14 }, // evdev 192
- { "FK15", RDP_SCANCODE_F15 }, // evdev 193
- { "FK16", RDP_SCANCODE_F16 }, // evdev 194
- { "FK17", RDP_SCANCODE_F17 }, // evdev 195
- { "FK18", RDP_SCANCODE_F18 }, // evdev 196
- { "FK19", RDP_SCANCODE_F19 }, // evdev 197
- { "FK20", RDP_SCANCODE_F20 }, // evdev 198
- { "FK21", RDP_SCANCODE_F21 }, // evdev 199
- { "FK22", RDP_SCANCODE_F22 }, // evdev 200
- { "FK23", RDP_SCANCODE_F23 }, // evdev 201
- { "FK24", RDP_SCANCODE_F24 }, // evdev 202
- // { "FRNT", RDP_SCANCODE_ }, // evdev 140
- { "HANJ", RDP_SCANCODE_HANJA },
- { "HELP", RDP_SCANCODE_HELP }, // evdev 146
- { "HENK", RDP_SCANCODE_CONVERT_JP }, // JP evdev 100 Henkan
- { "HIRA", RDP_SCANCODE_HIRAGANA }, // JP evdev 99 Hiragana
- { "HJCV", RDP_SCANCODE_HANJA }, // KR evdev 131 Hangul->Hanja
- { "HKTG", RDP_SCANCODE_HIRAGANA }, // JP evdev 101 Hiragana/Katakana toggle
- { "HNGL", RDP_SCANCODE_HANGUL }, // KR evdev 130 Hangul/Latin toggle
- { "HOME", RDP_SCANCODE_HOME }, // evdev 110
- { "HYPR", RDP_SCANCODE_LWIN }, // evdev 207, fake keycode for virtual key
- { "HZTG", RDP_SCANCODE_OEM_3 }, // JP alias of evdev 49
- // { "I120", RDP_SCANCODE_ }, // evdev 120 KEY_MACRO
- // { "I126", RDP_SCANCODE_ }, // evdev 126 KEY_KPPLUSMINUS
- // { "I128", RDP_SCANCODE_ }, // evdev 128 KEY_SCALE
- { "I129", RDP_SCANCODE_ABNT_C2 }, // evdev 129 KEY_KPCOMMA Brazil
- // { "I147", RDP_SCANCODE_ }, // evdev 147 KEY_MENU
- // { "I148", RDP_SCANCODE_ }, // evdev 148 KEY_CALC
- // { "I149", RDP_SCANCODE_ }, // evdev 149 KEY_SETUP
- { "I150", RDP_SCANCODE_SLEEP }, // evdev 150 KEY_SLEEP
- // { "I151", RDP_SCANCODE_ }, // evdev 151 KEY_WAKEUP
- // { "I152", RDP_SCANCODE_ }, // evdev 152 KEY_FILE
- // { "I153", RDP_SCANCODE_ }, // evdev 153 KEY_SENDFILE
- // { "I154", RDP_SCANCODE_ }, // evdev 154 KEY_DELETEFILE
- // { "I155", RDP_SCANCODE_ }, // evdev 155 KEY_XFER
- // { "I156", RDP_SCANCODE_ }, // evdev 156 KEY_PROG1 VK_LAUNCH_APP1
- // { "I157", RDP_SCANCODE_ }, // evdev 157 KEY_PROG2 VK_LAUNCH_APP2
- // { "I158", RDP_SCANCODE_ }, // evdev 158 KEY_WWW
- // { "I159", RDP_SCANCODE_ }, // evdev 159 KEY_MSDOS
- // { "I160", RDP_SCANCODE_ }, // evdev 160 KEY_COFFEE
- // { "I161", RDP_SCANCODE_ }, // evdev 161 KEY_DIRECTION
- // { "I162", RDP_SCANCODE_ }, // evdev 162 KEY_CYCLEWINDOWS
- { "I163", RDP_SCANCODE_LAUNCH_MAIL }, // evdev 163 KEY_MAIL
- { "I164", RDP_SCANCODE_BROWSER_FAVORITES }, // evdev 164 KEY_BOOKMARKS
- // { "I165", RDP_SCANCODE_ }, // evdev 165 KEY_COMPUTER
- { "I166", RDP_SCANCODE_BROWSER_BACK }, // evdev 166 KEY_BACK
- { "I167", RDP_SCANCODE_BROWSER_FORWARD }, // evdev 167 KEY_FORWARD
- // { "I168", RDP_SCANCODE_ }, // evdev 168 KEY_CLOSECD
- // { "I169", RDP_SCANCODE_ }, // evdev 169 KEY_EJECTCD
- // { "I170", RDP_SCANCODE_ }, // evdev 170 KEY_EJECTCLOSECD
- { "I171", RDP_SCANCODE_MEDIA_NEXT_TRACK }, // evdev 171 KEY_NEXTSONG
- { "I172", RDP_SCANCODE_MEDIA_PLAY_PAUSE }, // evdev 172 KEY_PLAYPAUSE
- { "I173", RDP_SCANCODE_MEDIA_PREV_TRACK }, // evdev 173 KEY_PREVIOUSSONG
- { "I174", RDP_SCANCODE_MEDIA_STOP }, // evdev 174 KEY_STOPCD
- // { "I175", RDP_SCANCODE_ }, // evdev 175 KEY_RECORD 167
- // { "I176", RDP_SCANCODE_ }, // evdev 176 KEY_REWIND
- // { "I177", RDP_SCANCODE_ }, // evdev 177 KEY_PHONE
- // { "I178", RDP_SCANCODE_ }, // evdev 178 KEY_ISO
- // { "I179", RDP_SCANCODE_ }, // evdev 179 KEY_CONFIG
- { "I180", RDP_SCANCODE_BROWSER_HOME }, // evdev 180 KEY_HOMEPAGE
- { "I181", RDP_SCANCODE_BROWSER_REFRESH }, // evdev 181 KEY_REFRESH
- // { "I182", RDP_SCANCODE_ }, // evdev 182 KEY_EXIT
- // { "I183", RDP_SCANCODE_ }, // evdev 183 KEY_MOVE
- // { "I184", RDP_SCANCODE_ }, // evdev 184 KEY_EDIT
- // { "I185", RDP_SCANCODE_ }, // evdev 185 KEY_SCROLLUP
- // { "I186", RDP_SCANCODE_ }, // evdev 186 KEY_SCROLLDOWN
- // { "I187", RDP_SCANCODE_ }, // evdev 187 KEY_KPLEFTPAREN
- // { "I188", RDP_SCANCODE_ }, // evdev 188 KEY_KPRIGHTPAREN
- // { "I189", RDP_SCANCODE_ }, // evdev 189 KEY_NEW
- // { "I190", RDP_SCANCODE_ }, // evdev 190 KEY_REDO
- // { "I208", RDP_SCANCODE_ }, // evdev 208 KEY_PLAYCD
- // { "I209", RDP_SCANCODE_ }, // evdev 209 KEY_PAUSECD
- // { "I210", RDP_SCANCODE_ }, // evdev 210 KEY_PROG3
- // { "I211", RDP_SCANCODE_ }, // evdev 211 KEY_PROG4
- // { "I212", RDP_SCANCODE_ }, // evdev 212 KEY_DASHBOARD
- // { "I213", RDP_SCANCODE_ }, // evdev 213 KEY_SUSPEND
- // { "I214", RDP_SCANCODE_ }, // evdev 214 KEY_CLOSE
- // { "I215", RDP_SCANCODE_ }, // evdev 215 KEY_PLAY
- // { "I216", RDP_SCANCODE_ }, // evdev 216 KEY_FASTFORWARD
- // { "I217", RDP_SCANCODE_ }, // evdev 217 KEY_BASSBOOST
- // { "I218", RDP_SCANCODE_ }, // evdev 218 KEY_PRINT
- // { "I219", RDP_SCANCODE_ }, // evdev 219 KEY_HP
- // { "I220", RDP_SCANCODE_ }, // evdev 220 KEY_CAMERA
- // { "I221", RDP_SCANCODE_ }, // evdev 221 KEY_SOUND
- // { "I222", RDP_SCANCODE_ }, // evdev 222 KEY_QUESTION
- // { "I223", RDP_SCANCODE_ }, // evdev 223 KEY_EMAIL
- // { "I224", RDP_SCANCODE_ }, // evdev 224 KEY_CHAT
- { "I225", RDP_SCANCODE_BROWSER_SEARCH }, // evdev 225 KEY_SEARCH
- // { "I226", RDP_SCANCODE_ }, // evdev 226 KEY_CONNECT
- // { "I227", RDP_SCANCODE_ }, // evdev 227 KEY_FINANCE
- // { "I228", RDP_SCANCODE_ }, // evdev 228 KEY_SPORT
- // { "I229", RDP_SCANCODE_ }, // evdev 229 KEY_SHOP
- // { "I230", RDP_SCANCODE_ }, // evdev 230 KEY_ALTERASE
- // { "I231", RDP_SCANCODE_ }, // evdev 231 KEY_CANCEL
- // { "I232", RDP_SCANCODE_ }, // evdev 232 KEY_BRIGHTNESSDOWN
- // { "I233", RDP_SCANCODE_ }, // evdev 233 KEY_BRIGHTNESSUP
- // { "I234", RDP_SCANCODE_ }, // evdev 234 KEY_MEDIA
- // { "I235", RDP_SCANCODE_ }, // evdev 235 KEY_SWITCHVIDEOMODE
- // { "I236", RDP_SCANCODE_ }, // evdev 236 KEY_KBDILLUMTOGGLE
- // { "I237", RDP_SCANCODE_ }, // evdev 237 KEY_KBDILLUMDOWN
- // { "I238", RDP_SCANCODE_ }, // evdev 238 KEY_KBDILLUMUP
- // { "I239", RDP_SCANCODE_ }, // evdev 239 KEY_SEND
- // { "I240", RDP_SCANCODE_ }, // evdev 240 KEY_REPLY
- // { "I241", RDP_SCANCODE_ }, // evdev 241 KEY_FORWARDMAIL
- // { "I242", RDP_SCANCODE_ }, // evdev 242 KEY_SAVE
- // { "I243", RDP_SCANCODE_ }, // evdev 243 KEY_DOCUMENTS
- // { "I244", RDP_SCANCODE_ }, // evdev 244 KEY_BATTERY
- // { "I245", RDP_SCANCODE_ }, // evdev 245 KEY_BLUETOOTH
- // { "I246", RDP_SCANCODE_ }, // evdev 246 KEY_WLAN
- // { "I247", RDP_SCANCODE_ }, // evdev 247 KEY_UWB
- // { "I248", RDP_SCANCODE_ }, // evdev 248 KEY_UNKNOWN
- // { "I249", RDP_SCANCODE_ }, // evdev 249 KEY_VIDEO_NEXT
- // { "I250", RDP_SCANCODE_ }, // evdev 250 KEY_VIDEO_PREV
- // { "I251", RDP_SCANCODE_ }, // evdev 251 KEY_BRIGHTNESS_CYCLE
- // { "I252", RDP_SCANCODE_ }, // evdev 252 KEY_BRIGHTNESS_ZERO
- // { "I253", RDP_SCANCODE_ }, // evdev 253 KEY_DISPLAY_OFF
- { "INS", RDP_SCANCODE_INSERT }, // evdev 118
- // { "JPCM", RDP_SCANCODE_ }, // evdev 103 KPJPComma
- // { "KATA", RDP_SCANCODE_ }, // evdev 98 Katakana VK_DBE_KATAKANA
- { "KP0", RDP_SCANCODE_NUMPAD0 }, // evdev 90
- { "KP1", RDP_SCANCODE_NUMPAD1 }, // evdev 87
- { "KP2", RDP_SCANCODE_NUMPAD2 }, // evdev 88
- { "KP3", RDP_SCANCODE_NUMPAD3 }, // evdev 89
- { "KP4", RDP_SCANCODE_NUMPAD4 }, // evdev 83
- { "KP5", RDP_SCANCODE_NUMPAD5 }, // evdev 84
- { "KP6", RDP_SCANCODE_NUMPAD6 }, // evdev 85
- { "KP7", RDP_SCANCODE_NUMPAD7 }, // evdev 79
- { "KP8", RDP_SCANCODE_NUMPAD8 }, // evdev 80
- { "KP9", RDP_SCANCODE_NUMPAD9 }, // evdev 81
- { "KPAD", RDP_SCANCODE_ADD }, // evdev 86
- { "KPDL", RDP_SCANCODE_DECIMAL }, // evdev 91
- { "KPDV", RDP_SCANCODE_DIVIDE }, // evdev 106
- { "KPEN", RDP_SCANCODE_RETURN_KP }, // evdev 104 KP!
- // { "KPEQ", RDP_SCANCODE_ }, // evdev 125
- { "KPMU", RDP_SCANCODE_MULTIPLY }, // evdev 63
- { "KPPT", RDP_SCANCODE_ABNT_C2 }, // BR alias of evdev 129
- { "KPSU", RDP_SCANCODE_SUBTRACT }, // evdev 82
- { "LALT", RDP_SCANCODE_LMENU }, // evdev 64
- { "LCTL", RDP_SCANCODE_LCONTROL }, // evdev 37
- { "LEFT", RDP_SCANCODE_LEFT }, // evdev 113
- { "LFSH", RDP_SCANCODE_LSHIFT }, // evdev 50
- { "LMTA", RDP_SCANCODE_LWIN }, // alias of evdev 133 LWIN
- // { "LNFD", RDP_SCANCODE_ }, // evdev 109 KEY_LINEFEED
- { "LSGT", RDP_SCANCODE_OEM_102 }, // evdev 94
- { "LVL3", RDP_SCANCODE_RMENU }, // evdev 92, fake keycode for virtual key
- { "LWIN", RDP_SCANCODE_LWIN }, // evdev 133
- { "MDSW", RDP_SCANCODE_RMENU }, // evdev 203, fake keycode for virtual key
- { "MENU", RDP_SCANCODE_APPS }, // alias of evdev 135 COMP
- { "META", RDP_SCANCODE_LMENU }, // evdev 205, fake keycode for virtual key
- { "MUHE", RDP_SCANCODE_NONCONVERT_JP }, // JP evdev 102 Muhenkan
- { "MUTE", RDP_SCANCODE_VOLUME_MUTE }, // evdev 121
- { "NFER", RDP_SCANCODE_NONCONVERT_JP }, // JP alias of evdev 102 Muhenkan
- { "NMLK", RDP_SCANCODE_NUMLOCK }, // evdev 77
- // { "OPEN", RDP_SCANCODE_ }, // evdev 142
- // { "PAST", RDP_SCANCODE_ }, // evdev 143
- { "PAUS", RDP_SCANCODE_PAUSE }, // evdev 127
- { "PGDN", RDP_SCANCODE_NEXT }, // evdev 117
- { "PGUP", RDP_SCANCODE_PRIOR }, // evdev 112
- // { "POWR", RDP_SCANCODE_ }, // evdev 124
- // { "PROP", RDP_SCANCODE_ }, // evdev 138
- { "PRSC", RDP_SCANCODE_PRINTSCREEN }, // evdev 107
- { "RALT", RDP_SCANCODE_RMENU }, // evdev 108 RALT
- { "RCTL", RDP_SCANCODE_RCONTROL }, // evdev 105
- { "RGHT", RDP_SCANCODE_RIGHT }, // evdev 114
- { "RMTA", RDP_SCANCODE_RWIN }, // alias of evdev 134 RWIN
- // { "RO", RDP_SCANCODE_ }, // JP evdev 97 Romaji
- { "RTRN", RDP_SCANCODE_RETURN }, // not KP, evdev 36
- { "RTSH", RDP_SCANCODE_RSHIFT }, // evdev 62
- { "RWIN", RDP_SCANCODE_RWIN }, // evdev 134
- { "SCLK", RDP_SCANCODE_SCROLLLOCK }, // evdev 78
- { "SPCE", RDP_SCANCODE_SPACE }, // evdev 65
- { "STOP", RDP_SCANCODE_BROWSER_STOP }, // evdev 136
- { "SUPR", RDP_SCANCODE_LWIN }, // evdev 206, fake keycode for virtual key
- { "SYRQ", RDP_SCANCODE_SYSREQ }, // evdev 107
- { "TAB", RDP_SCANCODE_TAB }, // evdev 23
- { "TLDE", RDP_SCANCODE_OEM_3 }, // evdev 49
- // { "UNDO", RDP_SCANCODE_ }, // evdev 139
- { "UP", RDP_SCANCODE_UP }, // evdev 111
- { "VOL-", RDP_SCANCODE_VOLUME_DOWN }, // evdev 122
- { "VOL+", RDP_SCANCODE_VOLUME_UP }, // evdev 123
- { "XFER", RDP_SCANCODE_CONVERT_JP }, // JP alias of evdev 100 Henkan
+ { "", RDP_SCANCODE_UNKNOWN }, /* 008: [(null)] */
+ { "ESC", RDP_SCANCODE_ESCAPE }, /* 009: ESC [Escape] */
+ { "AE01", RDP_SCANCODE_KEY_1 }, /* 010: AE01 [1] */
+ { "AE02", RDP_SCANCODE_KEY_2 }, /* 011: AE02 [2] */
+ { "AE03", RDP_SCANCODE_KEY_3 }, /* 012: AE03 [3] */
+ { "AE04", RDP_SCANCODE_KEY_4 }, /* 013: AE04 [4] */
+ { "AE05", RDP_SCANCODE_KEY_5 }, /* 014: AE05 [5] */
+ { "AE06", RDP_SCANCODE_KEY_6 }, /* 015: AE06 [6] */
+ { "AE07", RDP_SCANCODE_KEY_7 }, /* 016: AE07 [7] */
+ { "AE08", RDP_SCANCODE_KEY_8 }, /* 017: AE08 [8] */
+ { "AE09", RDP_SCANCODE_KEY_9 }, /* 018: AE09 [9] */
+ { "AE10", RDP_SCANCODE_KEY_0 }, /* 019: AE10 [0] */
+ { "AE11", RDP_SCANCODE_OEM_MINUS }, /* 020: AE11 [minus] */
+ { "AE12", RDP_SCANCODE_OEM_PLUS }, /* 021: AE12 [equal] */
+ { "BKSP", RDP_SCANCODE_BACKSPACE }, /* 022: BKSP [BackSpace] */
+ { "TAB", RDP_SCANCODE_TAB }, /* 023: TAB [Tab] */
+ { "AD01", RDP_SCANCODE_KEY_Q }, /* 024: AD01 [q] */
+ { "AD02", RDP_SCANCODE_KEY_W }, /* 025: AD02 [w] */
+ { "AD03", RDP_SCANCODE_KEY_E }, /* 026: AD03 [e] */
+ { "AD04", RDP_SCANCODE_KEY_R }, /* 027: AD04 [r] */
+ { "AD05", RDP_SCANCODE_KEY_T }, /* 028: AD05 [t] */
+ { "AD06", RDP_SCANCODE_KEY_Y }, /* 029: AD06 [y] */
+ { "AD07", RDP_SCANCODE_KEY_U }, /* 030: AD07 [u] */
+ { "AD08", RDP_SCANCODE_KEY_I }, /* 031: AD08 [i] */
+ { "AD09", RDP_SCANCODE_KEY_O }, /* 032: AD09 [o] */
+ { "AD10", RDP_SCANCODE_KEY_P }, /* 033: AD10 [p] */
+ { "AD11", RDP_SCANCODE_OEM_4 }, /* 034: AD11 [bracketleft] */
+ { "AD12", RDP_SCANCODE_OEM_6 }, /* 035: AD12 [bracketright] */
+ { "RTRN", RDP_SCANCODE_RETURN }, /* 036: RTRN [Return] */
+ { "LCTL", RDP_SCANCODE_LCONTROL }, /* 037: LCTL [Control_L] */
+ { "AC01", RDP_SCANCODE_KEY_A }, /* 038: AC01 [a] */
+ { "AC02", RDP_SCANCODE_KEY_S }, /* 039: AC02 [s] */
+ { "AC03", RDP_SCANCODE_KEY_D }, /* 040: AC03 [d] */
+ { "AC04", RDP_SCANCODE_KEY_F }, /* 041: AC04 [f] */
+ { "AC05", RDP_SCANCODE_KEY_G }, /* 042: AC05 [g] */
+ { "AC06", RDP_SCANCODE_KEY_H }, /* 043: AC06 [h] */
+ { "AC07", RDP_SCANCODE_KEY_J }, /* 044: AC07 [j] */
+ { "AC08", RDP_SCANCODE_KEY_K }, /* 045: AC08 [k] */
+ { "AC09", RDP_SCANCODE_KEY_L }, /* 046: AC09 [l] */
+ { "AC10", RDP_SCANCODE_OEM_1 }, /* 047: AC10 [semicolon] */
+ { "AC11", RDP_SCANCODE_OEM_7 }, /* 048: AC11 [dead_acute] */
+ { "TLDE", RDP_SCANCODE_OEM_3 }, /* 049: TLDE [dead_grave] */
+ { "LFSH", RDP_SCANCODE_LSHIFT }, /* 050: LFSH [Shift_L] */
+ { "BKSL", RDP_SCANCODE_OEM_5 }, /* 051: BKSL [backslash] */
+ { "AB01", RDP_SCANCODE_KEY_Z }, /* 052: AB01 [z] */
+ { "AB02", RDP_SCANCODE_KEY_X }, /* 053: AB02 [x] */
+ { "AB03", RDP_SCANCODE_KEY_C }, /* 054: AB03 [c] */
+ { "AB04", RDP_SCANCODE_KEY_V }, /* 055: AB04 [v] */
+ { "AB05", RDP_SCANCODE_KEY_B }, /* 056: AB05 [b] */
+ { "AB06", RDP_SCANCODE_KEY_N }, /* 057: AB06 [n] */
+ { "AB07", RDP_SCANCODE_KEY_M }, /* 058: AB07 [m] */
+ { "AB08", RDP_SCANCODE_OEM_COMMA }, /* 059: AB08 [comma] */
+ { "AB09", RDP_SCANCODE_OEM_PERIOD }, /* 060: AB09 [period] */
+ { "AB10", RDP_SCANCODE_OEM_2 }, /* 061: AB10 [slash] */
+ { "RTSH", RDP_SCANCODE_RSHIFT }, /* 062: RTSH [Shift_R] */
+ { "KPMU", RDP_SCANCODE_MULTIPLY }, /* 063: KPMU [KP_Multiply] */
+ { "LALT", RDP_SCANCODE_LMENU }, /* 064: LALT [Alt_L] */
+ { "SPCE", RDP_SCANCODE_SPACE }, /* 065: SPCE [space] */
+ { "CAPS", RDP_SCANCODE_CAPSLOCK }, /* 066: CAPS [Caps_Lock] */
+ { "FK01", RDP_SCANCODE_F1 }, /* 067: FK01 [F1] */
+ { "FK02", RDP_SCANCODE_F2 }, /* 068: FK02 [F2] */
+ { "FK03", RDP_SCANCODE_F3 }, /* 069: FK03 [F3] */
+ { "FK04", RDP_SCANCODE_F4 }, /* 070: FK04 [F4] */
+ { "FK05", RDP_SCANCODE_F5 }, /* 071: FK05 [F5] */
+ { "FK06", RDP_SCANCODE_F6 }, /* 072: FK06 [F6] */
+ { "FK07", RDP_SCANCODE_F7 }, /* 073: FK07 [F7] */
+ { "FK08", RDP_SCANCODE_F8 }, /* 074: FK08 [F8] */
+ { "FK09", RDP_SCANCODE_F9 }, /* 075: FK09 [F9] */
+ { "FK10", RDP_SCANCODE_F10 }, /* 076: FK10 [F10] */
+ { "NMLK", RDP_SCANCODE_NUMLOCK }, /* 077: NMLK [Num_Lock] */
+ { "SCLK", RDP_SCANCODE_SCROLLLOCK }, /* 078: SCLK [Multi_key] */
+ { "KP7", RDP_SCANCODE_NUMPAD7 }, /* 079: KP7 [KP_Home] */
+ { "KP8", RDP_SCANCODE_NUMPAD8 }, /* 080: KP8 [KP_Up] */
+ { "KP9", RDP_SCANCODE_NUMPAD9 }, /* 081: KP9 [KP_Prior] */
+ { "KPSU", RDP_SCANCODE_SUBTRACT }, /* 082: KPSU [KP_Subtract] */
+ { "KP4", RDP_SCANCODE_NUMPAD4 }, /* 083: KP4 [KP_Left] */
+ { "KP5", RDP_SCANCODE_NUMPAD5 }, /* 084: KP5 [KP_Begin] */
+ { "KP6", RDP_SCANCODE_NUMPAD6 }, /* 085: KP6 [KP_Right] */
+ { "KPAD", RDP_SCANCODE_ADD }, /* 086: KPAD [KP_Add] */
+ { "KP1", RDP_SCANCODE_NUMPAD1 }, /* 087: KP1 [KP_End] */
+ { "KP2", RDP_SCANCODE_NUMPAD2 }, /* 088: KP2 [KP_Down] */
+ { "KP3", RDP_SCANCODE_NUMPAD3 }, /* 089: KP3 [KP_Next] */
+ { "KP0", RDP_SCANCODE_NUMPAD0 }, /* 090: KP0 [KP_Insert] */
+ { "KPDL", RDP_SCANCODE_DECIMAL }, /* 091: KPDL [KP_Delete] */
+ { "LVL3", RDP_SCANCODE_RMENU }, /* 092: LVL3 [ISO_Level3_Shift] */
+ { "", RDP_SCANCODE_UNKNOWN }, /* 093: [(null)] */
+ { "LSGT", RDP_SCANCODE_OEM_102 }, /* 094: LSGT [backslash] */
+ { "FK11", RDP_SCANCODE_F11 }, /* 095: FK11 [F11] */
+ { "FK12", RDP_SCANCODE_F12 }, /* 096: FK12 [F12] */
+ { "AB11", RDP_SCANCODE_ABNT_C1 }, /* 097: AB11 [(null)] */
+ { "KATA", RDP_SCANCODE_KANA_HANGUL }, /* 098: KATA [Katakana] */
+ { "HIRA", RDP_SCANCODE_HIRAGANA }, /* 099: HIRA [Hiragana] */
+ { "HENK", RDP_SCANCODE_CONVERT_JP }, /* 100: HENK [Henkan_Mode] */
+ { "HKTG", RDP_SCANCODE_HIRAGANA }, /* 101: HKTG [Hiragana_Katakana] */
+ { "MUHE", RDP_SCANCODE_NONCONVERT_JP }, /* 102: MUHE [Muhenkan] */
+ { "JPCM", RDP_SCANCODE_UNKNOWN }, /* 103: JPCM [(null)] */
+ { "KPEN", RDP_SCANCODE_RETURN_KP }, /* 104: KPEN [KP_Enter] */
+ { "RCTL", RDP_SCANCODE_RCONTROL }, /* 105: RCTL [Control_R] */
+ { "KPDV", RDP_SCANCODE_DIVIDE }, /* 106: KPDV [KP_Divide] */
+ { "PRSC", RDP_SCANCODE_PRINTSCREEN }, /* 107: PRSC [Print] */
+ { "RALT", RDP_SCANCODE_RMENU }, /* 108: RALT [ISO_Level3_Shift] */
+ { "LNFD", RDP_SCANCODE_UNKNOWN }, /* 109: LNFD [Linefeed] */
+ { "HOME", RDP_SCANCODE_HOME }, /* 110: HOME [Home] */
+ { "UP", RDP_SCANCODE_UP }, /* 111: UP [Up] */
+ { "PGUP", RDP_SCANCODE_PRIOR }, /* 112: PGUP [Prior] */
+ { "LEFT", RDP_SCANCODE_LEFT }, /* 113: LEFT [Left] */
+ { "RGHT", RDP_SCANCODE_RIGHT }, /* 114: RGHT [Right] */
+ { "END", RDP_SCANCODE_END }, /* 115: END [End] */
+ { "DOWN", RDP_SCANCODE_DOWN }, /* 116: DOWN [Down] */
+ { "PGDN", RDP_SCANCODE_NEXT }, /* 117: PGDN [Next] */
+ { "INS", RDP_SCANCODE_INSERT }, /* 118: INS [Insert] */
+ { "DELE", RDP_SCANCODE_DELETE }, /* 119: DELE [Delete] */
+ { "I120", RDP_SCANCODE_UNKNOWN }, /* 120: I120 [(null)] */
+ { "MUTE", RDP_SCANCODE_VOLUME_MUTE }, /* 121: MUTE [XF86AudioMute] */
+ { "VOL-", RDP_SCANCODE_VOLUME_DOWN }, /* 122: VOL- [XF86AudioLowerVolume] */
+ { "VOL+", RDP_SCANCODE_VOLUME_UP }, /* 123: VOL+ [XF86AudioRaiseVolume] */
+ { "POWR", RDP_SCANCODE_UNKNOWN }, /* 124: POWR [XF86PowerOff] */
+ { "KPEQ", RDP_SCANCODE_UNKNOWN }, /* 125: KPEQ [KP_Equal] */
+ { "I126", RDP_SCANCODE_UNKNOWN }, /* 126: I126 [plusminus] */
+ { "PAUS", RDP_SCANCODE_PAUSE }, /* 127: PAUS [Pause] */
+ { "I128", RDP_SCANCODE_LAUNCH_MEDIA_SELECT }, /* 128: I128 [XF86LaunchA] */
+ { "I129", RDP_SCANCODE_ABNT_C2 }, /* 129: I129 [KP_Decimal] */
+ { "HNGL", RDP_SCANCODE_HANGUL }, /* 130: HNGL [Hangul] */
+ { "HJCV", RDP_SCANCODE_HANJA }, /* 131: HJCV [Hangul_Hanja] */
+ { "AE13", RDP_SCANCODE_BACKSLASH_JP }, /* 132: AE13 [(null)] */
+ { "LWIN", RDP_SCANCODE_LWIN }, /* 133: LWIN [Super_L] */
+ { "RWIN", RDP_SCANCODE_RWIN }, /* 134: RWIN [Super_R] */
+ { "COMP", RDP_SCANCODE_APPS }, /* 135: COMP [Menu] */
+ { "STOP", RDP_SCANCODE_BROWSER_STOP }, /* 136: STOP [Cancel] */
+ { "AGAI", RDP_SCANCODE_UNKNOWN }, /* 137: AGAI [Redo] */
+ { "PROP", RDP_SCANCODE_UNKNOWN }, /* 138: PROP [SunProps] */
+ { "UNDO", RDP_SCANCODE_UNKNOWN }, /* 139: UNDO [Undo] */
+ { "FRNT", RDP_SCANCODE_UNKNOWN }, /* 140: FRNT [SunFront] */
+ { "COPY", RDP_SCANCODE_UNKNOWN }, /* 141: COPY [XF86Copy] */
+ { "OPEN", RDP_SCANCODE_UNKNOWN }, /* 142: OPEN [XF86Open] */
+ { "PAST", RDP_SCANCODE_UNKNOWN }, /* 143: PAST [XF86Paste] */
+ { "FIND", RDP_SCANCODE_UNKNOWN }, /* 144: FIND [Find] */
+ { "CUT", RDP_SCANCODE_UNKNOWN }, /* 145: CUT [XF86Cut] */
+ { "HELP", RDP_SCANCODE_HELP }, /* 146: HELP [Help] */
+ { "I147", RDP_SCANCODE_UNKNOWN }, /* 147: I147 [XF86MenuKB] */
+ { "I148", RDP_SCANCODE_UNKNOWN }, /* 148: I148 [XF86Calculator] */
+ { "I149", RDP_SCANCODE_UNKNOWN }, /* 149: I149 [(null)] */
+ { "I150", RDP_SCANCODE_SLEEP }, /* 150: I150 [XF86Sleep] */
+ { "I151", RDP_SCANCODE_UNKNOWN }, /* 151: I151 [XF86WakeUp] */
+ { "I152", RDP_SCANCODE_UNKNOWN }, /* 152: I152 [XF86Explorer] */
+ { "I153", RDP_SCANCODE_UNKNOWN }, /* 153: I153 [XF86Send] */
+ { "I154", RDP_SCANCODE_UNKNOWN }, /* 154: I154 [(null)] */
+ { "I155", RDP_SCANCODE_UNKNOWN }, /* 155: I155 [XF86Xfer] */
+ { "I156", RDP_SCANCODE_LAUNCH_APP1 }, /* 156: I156 [XF86Launch1] */
+ { "I157", RDP_SCANCODE_LAUNCH_APP2 }, /* 157: I157 [XF86Launch2] */
+ { "I158", RDP_SCANCODE_BROWSER_HOME }, /* 158: I158 [XF86WWW] */
+ { "I159", RDP_SCANCODE_UNKNOWN }, /* 159: I159 [XF86DOS] */
+ { "I160", RDP_SCANCODE_UNKNOWN }, /* 160: I160 [XF86ScreenSaver] */
+ { "I161", RDP_SCANCODE_UNKNOWN }, /* 161: I161 [XF86RotateWindows] */
+ { "I162", RDP_SCANCODE_UNKNOWN }, /* 162: I162 [XF86TaskPane] */
+ { "I163", RDP_SCANCODE_LAUNCH_MAIL }, /* 163: I163 [XF86Mail] */
+ { "I164", RDP_SCANCODE_BROWSER_FAVORITES }, /* 164: I164 [XF86Favorites] */
+ { "I165", RDP_SCANCODE_UNKNOWN }, /* 165: I165 [XF86MyComputer] */
+ { "I166", RDP_SCANCODE_BROWSER_BACK }, /* 166: I166 [XF86Back] */
+ { "I167", RDP_SCANCODE_BROWSER_FORWARD }, /* 167: I167 [XF86Forward] */
+ { "I168", RDP_SCANCODE_UNKNOWN }, /* 168: I168 [(null)] */
+ { "I169", RDP_SCANCODE_UNKNOWN }, /* 169: I169 [XF86Eject] */
+ { "I170", RDP_SCANCODE_UNKNOWN }, /* 170: I170 [XF86Eject] */
+ { "I171", RDP_SCANCODE_MEDIA_NEXT_TRACK }, /* 171: I171 [XF86AudioNext] */
+ { "I172", RDP_SCANCODE_MEDIA_PLAY_PAUSE }, /* 172: I172 [XF86AudioPlay] */
+ { "I173", RDP_SCANCODE_MEDIA_PREV_TRACK }, /* 173: I173 [XF86AudioPrev] */
+ { "I174", RDP_SCANCODE_MEDIA_STOP }, /* 174: I174 [XF86AudioStop] */
+ { "I175", RDP_SCANCODE_UNKNOWN }, /* 175: I175 [XF86AudioRecord] */
+ { "I176", RDP_SCANCODE_UNKNOWN }, /* 176: I176 [XF86AudioRewind] */
+ { "I177", RDP_SCANCODE_UNKNOWN }, /* 177: I177 [XF86Phone] */
+ { "I178", RDP_SCANCODE_UNKNOWN }, /* 178: I178 [(null)] */
+ { "I179", RDP_SCANCODE_UNKNOWN }, /* 179: I179 [XF86Tools] */
+ { "I180", RDP_SCANCODE_BROWSER_HOME }, /* 180: I180 [XF86HomePage] */
+ { "I181", RDP_SCANCODE_BROWSER_REFRESH }, /* 181: I181 [XF86Reload] */
+ { "I182", RDP_SCANCODE_UNKNOWN }, /* 182: I182 [XF86Close] */
+ { "I183", RDP_SCANCODE_UNKNOWN }, /* 183: I183 [(null)] */
+ { "I184", RDP_SCANCODE_UNKNOWN }, /* 184: I184 [(null)] */
+ { "I185", RDP_SCANCODE_UNKNOWN }, /* 185: I185 [XF86ScrollUp] */
+ { "I186", RDP_SCANCODE_UNKNOWN }, /* 186: I186 [XF86ScrollDown] */
+ { "I187", RDP_SCANCODE_UNKNOWN }, /* 187: I187 [parenleft] */
+ { "I188", RDP_SCANCODE_UNKNOWN }, /* 188: I188 [parenright] */
+ { "I189", RDP_SCANCODE_UNKNOWN }, /* 189: I189 [XF86New] */
+ { "I190", RDP_SCANCODE_UNKNOWN }, /* 190: I190 [Redo] */
+ { "FK13", RDP_SCANCODE_F13 }, /* 191: FK13 [XF86Tools] */
+ { "FK14", RDP_SCANCODE_F14 }, /* 192: FK14 [XF86Launch5] */
+ { "FK15", RDP_SCANCODE_F15 }, /* 193: FK15 [XF86Launch6] */
+ { "FK16", RDP_SCANCODE_F16 }, /* 194: FK16 [XF86Launch7] */
+ { "FK17", RDP_SCANCODE_F17 }, /* 195: FK17 [XF86Launch8] */
+ { "FK18", RDP_SCANCODE_F18 }, /* 196: FK18 [XF86Launch9] */
+ { "FK19", RDP_SCANCODE_F19 }, /* 197: FK19 [(null)] */
+ { "FK20", RDP_SCANCODE_F20 }, /* 198: FK20 [XF86AudioMicMute] */
+ { "FK21", RDP_SCANCODE_F21 }, /* 199: FK21 [XF86TouchpadToggle] */
+ { "FK22", RDP_SCANCODE_F22 }, /* 200: FK22 [XF86TouchpadOn] */
+ { "FK23", RDP_SCANCODE_F23 }, /* 201: FK23 [XF86TouchpadOff] */
+ { "FK24", RDP_SCANCODE_F24 }, /* 202: FK24 [(null)] */
+ { "LVL5", RDP_SCANCODE_UNKNOWN }, /* 203: LVL5 [ISO_Level5_Shift] */
+ { "ALT", RDP_SCANCODE_LMENU }, /* 204: ALT [(null)] */
+ { "META", RDP_SCANCODE_LMENU }, /* 205: META [(null)] */
+ { "SUPR", RDP_SCANCODE_LWIN }, /* 206: SUPR [(null)] */
+ { "HYPR", RDP_SCANCODE_LWIN }, /* 207: HYPR [(null)] */
+ { "I208", RDP_SCANCODE_MEDIA_PLAY_PAUSE }, /* 208: I208 [XF86AudioPlay] */
+ { "I209", RDP_SCANCODE_MEDIA_PLAY_PAUSE }, /* 209: I209 [XF86AudioPause] */
+ { "I210", RDP_SCANCODE_UNKNOWN }, /* 210: I210 [XF86Launch3] */
+ { "I211", RDP_SCANCODE_UNKNOWN }, /* 211: I211 [XF86Launch4] */
+ { "I212", RDP_SCANCODE_UNKNOWN }, /* 212: I212 [XF86LaunchB] */
+ { "I213", RDP_SCANCODE_UNKNOWN }, /* 213: I213 [XF86Suspend] */
+ { "I214", RDP_SCANCODE_UNKNOWN }, /* 214: I214 [XF86Close] */
+ { "I215", RDP_SCANCODE_MEDIA_PLAY_PAUSE }, /* 215: I215 [XF86AudioPlay] */
+ { "I216", RDP_SCANCODE_MEDIA_NEXT_TRACK }, /* 216: I216 [XF86AudioForward] */
+ { "I217", RDP_SCANCODE_UNKNOWN }, /* 217: I217 [(null)] */
+ { "I218", RDP_SCANCODE_UNKNOWN }, /* 218: I218 [Print] */
+ { "I219", RDP_SCANCODE_UNKNOWN }, /* 219: I219 [(null)] */
+ { "I220", RDP_SCANCODE_UNKNOWN }, /* 220: I220 [XF86WebCam] */
+ { "I221", RDP_SCANCODE_UNKNOWN }, /* 221: I221 [XF86AudioPreset] */
+ { "I222", RDP_SCANCODE_UNKNOWN }, /* 222: I222 [(null)] */
+ { "I223", RDP_SCANCODE_LAUNCH_MAIL }, /* 223: I223 [XF86Mail] */
+ { "I224", RDP_SCANCODE_UNKNOWN }, /* 224: I224 [XF86Messenger] */
+ { "I225", RDP_SCANCODE_BROWSER_SEARCH }, /* 225: I225 [XF86Search] */
+ { "I226", RDP_SCANCODE_UNKNOWN }, /* 226: I226 [XF86Go] */
+ { "I227", RDP_SCANCODE_UNKNOWN }, /* 227: I227 [XF86Finance] */
+ { "I228", RDP_SCANCODE_UNKNOWN }, /* 228: I228 [XF86Game] */
+ { "I229", RDP_SCANCODE_UNKNOWN }, /* 229: I229 [XF86Shop] */
+ { "I230", RDP_SCANCODE_UNKNOWN }, /* 230: I230 [(null)] */
+ { "I231", RDP_SCANCODE_UNKNOWN }, /* 231: I231 [Cancel] */
+ { "I232", RDP_SCANCODE_UNKNOWN }, /* 232: I232 [XF86MonBrightnessDown] */
+ { "I233", RDP_SCANCODE_UNKNOWN }, /* 233: I233 [XF86MonBrightnessUp] */
+ { "I234", RDP_SCANCODE_LAUNCH_MEDIA_SELECT }, /* 234: I234 [XF86AudioMedia] */
+ { "I235", RDP_SCANCODE_UNKNOWN }, /* 235: I235 [XF86Display] */
+ { "I236", RDP_SCANCODE_UNKNOWN }, /* 236: I236 [XF86KbdLightOnOff] */
+ { "I237", RDP_SCANCODE_UNKNOWN }, /* 237: I237 [XF86KbdBrightnessDown] */
+ { "I238", RDP_SCANCODE_UNKNOWN }, /* 238: I238 [XF86KbdBrightnessUp] */
+ { "I239", RDP_SCANCODE_UNKNOWN }, /* 239: I239 [XF86Send] */
+ { "I240", RDP_SCANCODE_UNKNOWN }, /* 240: I240 [XF86Reply] */
+ { "I241", RDP_SCANCODE_UNKNOWN }, /* 241: I241 [XF86MailForward] */
+ { "I242", RDP_SCANCODE_UNKNOWN }, /* 242: I242 [XF86Save] */
+ { "I243", RDP_SCANCODE_UNKNOWN }, /* 243: I243 [XF86Documents] */
+ { "I244", RDP_SCANCODE_UNKNOWN }, /* 244: I244 [XF86Battery] */
+ { "I245", RDP_SCANCODE_UNKNOWN }, /* 245: I245 [XF86Bluetooth] */
+ { "I246", RDP_SCANCODE_UNKNOWN }, /* 246: I246 [XF86WLAN] */
+ { "I247", RDP_SCANCODE_UNKNOWN }, /* 247: I247 [XF86UWB] */
+ { "I248", RDP_SCANCODE_UNKNOWN }, /* 248: I248 [(null)] */
+ { "I249", RDP_SCANCODE_UNKNOWN }, /* 249: I249 [XF86Next_VMode] */
+ { "I250", RDP_SCANCODE_UNKNOWN }, /* 250: I250 [XF86Prev_VMode] */
+ { "I251", RDP_SCANCODE_UNKNOWN }, /* 251: I251 [XF86MonBrightnessCycle] */
+ { "I252", RDP_SCANCODE_UNKNOWN }, /* 252: I252 [XF86BrightnessAuto] */
+ { "I253", RDP_SCANCODE_UNKNOWN }, /* 253: I253 [XF86DisplayOff] */
+ { "I254", RDP_SCANCODE_UNKNOWN }, /* 254: I254 [XF86WWAN] */
+ { "I255", RDP_SCANCODE_UNKNOWN } /* 255: I255 [XF86RFKill] */
};
static int detect_keyboard_layout_from_xkbfile(void* display, DWORD* keyboardLayoutId);
@@ -428,6 +417,46 @@ int detect_keyboard_layout_from_xkbfile(void* display, DWORD* keyboardLayoutId)
return 0;
}
+static int xkb_cmp(const void* pva, const void* pvb)
+{
+ const XKB_KEY_NAME_SCANCODE* a = pva;
+ const XKB_KEY_NAME_SCANCODE* b = pvb;
+ if (!a)
+ return 1;
+ if (!b)
+ return -1;
+ if (!a && !b)
+ return 0;
+ return strcmp(a->xkb_keyname, b->xkb_keyname);
+}
+
+static BOOL try_add(size_t offset, const char* xkb_keyname, DWORD* x11_keycode_to_rdp_scancode,
+
+ size_t count)
+{
+ static BOOL initialized = FALSE;
+ static XKB_KEY_NAME_SCANCODE copy[ARRAYSIZE(XKB_KEY_NAME_SCANCODE_TABLE)] = { 0 };
+ if (!initialized)
+ {
+ memcpy(copy, XKB_KEY_NAME_SCANCODE_TABLE, sizeof(copy));
+ qsort(copy, ARRAYSIZE(copy), sizeof(XKB_KEY_NAME_SCANCODE), xkb_cmp);
+ initialized = TRUE;
+ }
+
+ XKB_KEY_NAME_SCANCODE key = { 0 };
+ key.xkb_keyname = xkb_keyname;
+ XKB_KEY_NAME_SCANCODE* found =
+ bsearch(&key, copy, ARRAYSIZE(copy), sizeof(XKB_KEY_NAME_SCANCODE), xkb_cmp);
+ if (found)
+ {
+ DEBUG_KBD("%4s: keycode: 0x%02" PRIuz " -> rdp scancode: 0x%08" PRIx32 "", xkb_keyname,
+ offset, found->rdp_scancode);
+ x11_keycode_to_rdp_scancode[offset] = found->rdp_scancode;
+ return TRUE;
+ }
+ return FALSE;
+}
+
int freerdp_keyboard_load_map_from_xkbfile(void* display, DWORD* x11_keycode_to_rdp_scancode,
size_t count)
{
@@ -463,22 +492,7 @@ int freerdp_keyboard_load_map_from_xkbfile(void* display, DWORD* x11_keycode_to_
if (strnlen(xkb_keyname, ARRAYSIZE(xkb_keyname)) < 1)
continue;
- for (size_t j = 0; j < ARRAYSIZE(XKB_KEY_NAME_SCANCODE_TABLE); j++)
- {
- if (!strcmp(xkb_keyname, XKB_KEY_NAME_SCANCODE_TABLE[j].xkb_keyname))
- {
- DEBUG_KBD("%4s: keycode: 0x%02X -> rdp scancode: 0x%08" PRIX32 "", xkb_keyname,
- i, XKB_KEY_NAME_SCANCODE_TABLE[j].rdp_scancode);
-
- if (found)
- {
- DEBUG_KBD("Internal error! duplicate key %s!", xkb_keyname);
- }
-
- x11_keycode_to_rdp_scancode[i] = XKB_KEY_NAME_SCANCODE_TABLE[j].rdp_scancode;
- found = TRUE;
- }
- }
+ found = try_add(i, xkb_keyname, x11_keycode_to_rdp_scancode, count);
if (!found)
{
diff --git a/libfreerdp/primitives/prim_YUV_neon.c b/libfreerdp/primitives/prim_YUV_neon.c
index 5e2039e..107ced2 100644
--- a/libfreerdp/primitives/prim_YUV_neon.c
+++ b/libfreerdp/primitives/prim_YUV_neon.c
@@ -157,7 +157,8 @@ static INLINE pstatus_t neon_YUV420ToX(const BYTE* const WINPR_RESTRICT pSrc[3],
uint8_t* pRGB2 = pRGB1 + dstStep;
const BOOL lastY = y >= nHeight - 1;
- for (UINT32 x = 0; x < nWidth - pad;)
+ UINT32 x = 0;
+ for (; x < nWidth - pad;)
{
const uint8x8_t Uraw = vld1_u8(pU);
const uint8x8x2_t Uu = vzip_u8(Uraw, Uraw);
@@ -409,7 +410,8 @@ static pstatus_t neon_LumaToYUV444(const BYTE* const WINPR_RESTRICT pSrcRaw[3],
BYTE* pU1 = pU + dstStep[1];
BYTE* pV1 = pV + dstStep[2];
- for (UINT32 x = 0; x + 16 < halfWidth; x += 16)
+ UINT32 x = 0;
+ for (; x + 16 < halfWidth; x += 16)
{
{
const uint8x16_t u = vld1q_u8(Um);
@@ -477,7 +479,8 @@ static pstatus_t neon_ChromaFilter(BYTE* WINPR_RESTRICT pDst[3], const UINT32 ds
if (val2y1 > nHeight)
continue;
- for (UINT32 x = roi->left / 2; x < halfWidth + roi->left / 2 - halfPad; x += 16)
+ UINT32 x = roi->left / 2;
+ for (; x < halfWidth + roi->left / 2 - halfPad; x += 16)
{
{
/* U = (U2x,2y << 2) - U2x1,2y - U2x,2y1 - U2x1,2y1 */
@@ -597,7 +600,8 @@ static pstatus_t neon_ChromaV1ToYUV444(const BYTE* const WINPR_RESTRICT pSrcRaw[
BYTE* pU = pDst[1] + dstStep[1] * val2y;
BYTE* pV = pDst[2] + dstStep[2] * val2y;
- for (UINT32 x = 0; x < halfWidth - halfPad; x += 16)
+ UINT32 x = 0;
+ for (; x < halfWidth - halfPad; x += 16)
{
{
uint8x16x2_t u = vld2q_u8(&pU[2 * x]);
@@ -646,7 +650,8 @@ static pstatus_t neon_ChromaV2ToYUV444(const BYTE* const WINPR_RESTRICT pSrc[3],
BYTE* pU = pDst[1] + dstStep[1] * yTop + roi->left;
BYTE* pV = pDst[2] + dstStep[2] * yTop + roi->left;
- for (UINT32 x = 0; x < halfWidth - halfPad; x += 16)
+ UINT32 x = 0;
+ for (; x < halfWidth - halfPad; x += 16)
{
{
uint8x16x2_t u = vld2q_u8(&pU[2 * x]);
@@ -678,7 +683,8 @@ static pstatus_t neon_ChromaV2ToYUV444(const BYTE* const WINPR_RESTRICT pSrc[3],
BYTE* pU = pDst[1] + dstStep[1] * (2 * y + 1 + roi->top) + roi->left;
BYTE* pV = pDst[2] + dstStep[2] * (2 * y + 1 + roi->top) + roi->left;
- for (UINT32 x = 0; x < quaterWidth - quaterPad; x += 16)
+ UINT32 x = 0;
+ for (; x < quaterWidth - quaterPad; x += 16)
{
{
uint8x16x4_t u = vld4q_u8(&pU[4 * x]);
diff --git a/libfreerdp/primitives/prim_alphaComp.c b/libfreerdp/primitives/prim_alphaComp.c
index fe4f8dc..ae4917d 100644
--- a/libfreerdp/primitives/prim_alphaComp.c
+++ b/libfreerdp/primitives/prim_alphaComp.c
@@ -17,7 +17,6 @@
* newval = alpha1*val1 + (1-alpha1)*val2
* rather than
* newval = alpha1*val1 + (1-alpha1)*alpha2*val2
- * The IPP gives other options.
*/
#include <freerdp/config.h>
diff --git a/libfreerdp/primitives/prim_copy.c b/libfreerdp/primitives/prim_copy.c
index f140c20..14b936d 100644
--- a/libfreerdp/primitives/prim_copy.c
+++ b/libfreerdp/primitives/prim_copy.c
@@ -18,10 +18,6 @@
#include <string.h>
#include <freerdp/types.h>
#include <freerdp/primitives.h>
-#ifdef WITH_IPP
-#include <ipps.h>
-#include <ippi.h>
-#endif /* WITH_IPP */
#include "prim_internal.h"
static primitives_t* generic = NULL;
@@ -132,19 +128,6 @@ static pstatus_t general_copy_8u_AC4r(const BYTE* pSrc, INT32 srcStep, BYTE* pDs
return PRIMITIVES_SUCCESS;
}
-#ifdef WITH_IPP
-/* ------------------------------------------------------------------------- */
-/* This is just ippiCopy_8u_AC4R without the IppiSize structure parameter. */
-static pstatus_t ippiCopy_8u_AC4r(const BYTE* pSrc, INT32 srcStep, BYTE* pDst, INT32 dstStep,
- INT32 width, INT32 height)
-{
- IppiSize roi;
- roi.width = width;
- roi.height = height;
- return (pstatus_t)ippiCopy_8u_AC4R(pSrc, srcStep, pDst, dstStep, roi);
-}
-#endif /* WITH_IPP */
-
/* ------------------------------------------------------------------------- */
void primitives_init_copy(primitives_t* prims)
{
@@ -161,10 +144,6 @@ void primitives_init_copy_opt(primitives_t* prims)
generic = primitives_get_generic();
primitives_init_copy(prims);
/* Pick tuned versions if possible. */
-#ifdef WITH_IPP
- prims->copy_8u = (__copy_8u_t)ippsCopy_8u;
- prims->copy_8u_AC4r = (__copy_8u_AC4r_t)ippiCopy_8u_AC4r;
-#endif
/* Performance with an SSE2 version with no prefetch seemed to be
* all over the map vs. memcpy.
* Sometimes it was significantly faster, sometimes dreadfully slower,
diff --git a/libfreerdp/primitives/test/measure.h b/libfreerdp/primitives/test/measure.h
index ee04abd..2d4f36e 100644
--- a/libfreerdp/primitives/test/measure.h
+++ b/libfreerdp/primitives/test/measure.h
@@ -29,6 +29,7 @@
#include <time.h>
#include <winpr/string.h>
+#include <winpr/sysinfo.h>
#ifndef _WIN32
#include <sys/param.h>
@@ -69,28 +70,24 @@
#define PROFILER_STOP
#endif // GOOGLE_PROFILER
-extern float _delta_time(const struct timespec* t0, const struct timespec* t1);
-extern void _floatprint(float t, char* output);
-
-#ifndef CLOCK_MONOTONIC_RAW
-#define CLOCK_MONOTONIC_RAW 4
-#endif // !CLOCK_MONOTONIC_RAW
-
-#define MEASURE_LOOP_START(_prefix_, _count_) \
- { \
- struct timespec _start, _stop; \
- char* _prefix; \
- int _count = (_count_); \
- int _loop; \
- float _delta; \
- char _str1[32], _str2[32]; \
- _prefix = _strdup(_prefix_); \
- _str1[0] = '\0'; \
- _str2[0] = '\0'; \
- clock_gettime(CLOCK_MONOTONIC_RAW, &_start); \
- PROFILER_START(_prefix); \
- _loop = (_count); \
- do \
+extern float measure_delta_time(UINT64 t0, UINT64 t1);
+extern void measure_floatprint(float t, char* output);
+
+#define MEASURE_LOOP_START(_prefix_, _count_) \
+ { \
+ UINT64 _start, _stop; \
+ char* _prefix; \
+ int _count = (_count_); \
+ int _loop; \
+ float _delta; \
+ char _str1[32], _str2[32]; \
+ _prefix = _strdup(_prefix_); \
+ _str1[0] = '\0'; \
+ _str2[0] = '\0'; \
+ _start = winpr_GetTickCount64NS(); \
+ PROFILER_START(_prefix); \
+ _loop = (_count); \
+ do \
{
#define MEASURE_LOOP_STOP \
@@ -100,28 +97,28 @@ extern void _floatprint(float t, char* output);
#define MEASURE_GET_RESULTS(_result_) \
PROFILER_STOP; \
- clock_gettime(CLOCK_MONOTONIC_RAW, &_stop); \
- _delta = _delta_time(&_start, &_stop); \
+ _stop = winpr_GetTickCount64NS(); \
+ _delta = measure_delta_time(_start, _stop); \
(_result_) = (float)_count / _delta; \
free(_prefix); \
}
#define MEASURE_SHOW_RESULTS(_result_) \
PROFILER_STOP; \
- clock_gettime(CLOCK_MONOTONIC_RAW, &_stop); \
- _delta = _delta_time(&_start, &_stop); \
+ _stop = winpr_GetTickCount64NS(); \
+ _delta = measure_delta_time(_start, _stop); \
(_result_) = (float)_count / _delta; \
- _floatprint((float)_count / _delta, _str1); \
+ measure_floatprint((float)_count / _delta, _str1); \
printf("%s: %9d iterations in %5.1f seconds = %s/s \n", _prefix, _count, _delta, _str1); \
free(_prefix); \
}
#define MEASURE_SHOW_RESULTS_SCALED(_scale_, _label_) \
PROFILER_STOP; \
- clock_gettime(CLOCK_MONOTONIC_RAW, &_stop); \
- _delta = _delta_time(&_start, &_stop); \
- _floatprint((float)_count / _delta, _str1); \
- _floatprint((float)_count / _delta * (_scale_), _str2); \
+ _stop = winpr_GetTickCount64NS(); \
+ _delta = measure_delta_time(_start, _stop); \
+ measure_floatprint((float)_count / _delta, _str1); \
+ measure_floatprint((float)_count / _delta * (_scale_), _str2); \
printf("%s: %9d iterations in %5.1f seconds = %s/s = %s%s \n", _prefix, _count, _delta, _str1, \
_str2, _label_); \
free(_prefix); \
diff --git a/libfreerdp/primitives/test/prim_test.c b/libfreerdp/primitives/test/prim_test.c
index ede8316..5ec85f8 100644
--- a/libfreerdp/primitives/test/prim_test.c
+++ b/libfreerdp/primitives/test/prim_test.c
@@ -36,31 +36,15 @@ int test_sizes[] = { 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 };
/* ------------------------------------------------------------------------- */
-#ifdef _WIN32
-float _delta_time(const struct timespec* t0, const struct timespec* t1)
+float measure_delta_time(UINT64 t0, UINT64 t1)
{
- return 0.0f;
+ INT64 diff = (INT64)(t1 - t0);
+ double retval = diff / 1000000000.0;
+ return (retval < 0.0) ? 0.0f : (float)retval;
}
-#else
-float _delta_time(const struct timespec* t0, const struct timespec* t1)
-{
- INT64 secs = (INT64)(t1->tv_sec) - (INT64)(t0->tv_sec);
- long nsecs = t1->tv_nsec - t0->tv_nsec;
- double retval = NAN;
-
- if (nsecs < 0)
- {
- --secs;
- nsecs += 1000000000;
- }
-
- retval = (double)secs + (double)nsecs / (double)1000000000.0;
- return (retval < 0.0) ? 0.0 : (float)retval;
-}
-#endif
/* ------------------------------------------------------------------------- */
-void _floatprint(float t, char* output)
+void measure_floatprint(float t, char* output)
{
/* I don't want to link against -lm, so avoid log,exp,... */
float f = 10.0;
diff --git a/libfreerdp/utils/CMakeLists.txt b/libfreerdp/utils/CMakeLists.txt
index 52690bf..d644837 100644
--- a/libfreerdp/utils/CMakeLists.txt
+++ b/libfreerdp/utils/CMakeLists.txt
@@ -47,10 +47,6 @@ if(WIN32)
freerdp_library_add(cfgmgr32)
endif()
-if(${CMAKE_SYSTEM_NAME} MATCHES SunOS)
- freerdp_library_add(rt)
-endif()
-
if(BUILD_TESTING)
add_subdirectory(test)
endif()
diff --git a/libfreerdp/utils/encoded_types.c b/libfreerdp/utils/encoded_types.c
index 68e6e4d..efce694 100644
--- a/libfreerdp/utils/encoded_types.c
+++ b/libfreerdp/utils/encoded_types.c
@@ -123,8 +123,95 @@ BOOL freerdp_read_four_byte_signed_integer(wStream* s, INT32* value)
return TRUE;
}
+BOOL freerdp_write_four_byte_signed_integer(wStream* s, INT32 value)
+{
+ FOUR_BYTE_SIGNED_INTEGER si = { 0 };
+
+ WINPR_ASSERT(s);
+ if (value > FREERDP_FOUR_BYTE_SIGNED_INT_MAX)
+ return FALSE;
+ if (value < FREERDP_FOUR_BYTE_SIGNED_INT_MIN)
+ return FALSE;
+
+ if (value < 0)
+ {
+ si.s = NEGATIVE_VAL;
+ value = -value;
+ }
+
+ if (value <= 0x1F)
+ {
+ si.c = ONE_BYTE_VAL;
+ si.val1 = value & 0x1f;
+ }
+ else if (value <= 0x1FFF)
+ {
+ si.c = TWO_BYTE_VAL;
+ si.val1 = (value >> 8) & 0x1f;
+ si.val2 = value & 0xff;
+ }
+ else if (value <= 0x1FFFFF)
+ {
+ si.c = THREE_BYTE_VAL;
+ si.val1 = (value >> 16) & 0x1f;
+ si.val2 = (value >> 8) & 0xff;
+ si.val3 = value & 0xff;
+ }
+ else if (value <= 0x1FFFFFFF)
+ {
+ si.c = FOUR_BYTE_VAL;
+ si.val1 = (value >> 24) & 0x1f;
+ si.val2 = (value >> 16) & 0xff;
+ si.val3 = (value >> 8) & 0xff;
+ si.val4 = value & 0xff;
+ }
+ else
+ {
+ WLog_ERR(TAG, "Invalid byte count for value %" PRId32, value);
+ return FALSE;
+ }
+
+ if (!Stream_EnsureRemainingCapacity(s, si.c + 1))
+ return FALSE;
+
+ const BYTE byte = ((si.c << 6) & 0xC0) | ((si.s << 5) & 0x20) | (si.val1 & 0x1F);
+ Stream_Write_UINT8(s, byte);
+
+ switch (si.c)
+ {
+ case ONE_BYTE_VAL:
+ break;
+ case TWO_BYTE_VAL:
+ Stream_Write_UINT8(s, si.val2);
+ break;
+ case THREE_BYTE_VAL:
+ Stream_Write_UINT8(s, si.val2);
+ Stream_Write_UINT8(s, si.val3);
+ break;
+ case FOUR_BYTE_VAL:
+ Stream_Write_UINT8(s, si.val2);
+ Stream_Write_UINT8(s, si.val3);
+ Stream_Write_UINT8(s, si.val4);
+ break;
+ case FIVE_BYTE_VAL:
+ case SIX_BYTE_VAL:
+ case SEVEN_BYTE_VAL:
+ case EIGHT_BYTE_VAL:
+ default:
+ WLog_ERR(TAG, "Invalid byte count value in si.c: %u", si.c);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
BOOL freerdp_read_four_byte_float(wStream* s, double* value)
{
+ return freerdp_read_four_byte_float_exp(s, value, NULL);
+}
+
+BOOL freerdp_read_four_byte_float_exp(wStream* s, double* value, BYTE* exp)
+{
FOUR_BYTE_FLOAT f = { 0 };
UINT32 base = 0;
BYTE byte = 0;
@@ -183,5 +270,132 @@ BOOL freerdp_read_four_byte_float(wStream* s, double* value)
if (f.s == NEGATIVE_VAL)
*value *= -1.0;
+ if (exp)
+ *exp = f.e;
+
+ return TRUE;
+}
+
+BOOL freerdp_write_four_byte_float(wStream* s, double value)
+{
+ FOUR_BYTE_FLOAT si = { 0 };
+
+ WINPR_ASSERT(s);
+
+ if (value > FREERDP_FOUR_BYTE_FLOAT_MAX)
+ return FALSE;
+ if (value < FREERDP_FOUR_BYTE_FLOAT_MIN)
+ return FALSE;
+
+ if (value < 0)
+ {
+ si.s = NEGATIVE_VAL;
+ value = -value;
+ }
+
+ int exp = 0;
+ double ival = FP_NAN;
+ const double aval = fabs(value);
+ const double frac = modf(aval, &ival);
+ if (frac != 0.0)
+ {
+ const double maxfrac = frac * 10000000.0;
+ if (maxfrac <= 1.0)
+ exp = 0;
+ else if (maxfrac <= 10.0)
+ exp = 1;
+ else if (maxfrac <= 100.0)
+ exp = 2;
+ else if (maxfrac <= 1000.0)
+ exp = 3;
+ else if (maxfrac <= 10000.0)
+ exp = 4;
+ else if (maxfrac <= 100000.0)
+ exp = 5;
+ else if (maxfrac <= 1000000.0)
+ exp = 6;
+ else
+ exp = 7;
+ }
+
+ UINT64 base = aval;
+ while (exp >= 0)
+ {
+ const double div = pow(10.0, exp);
+ const double dval = (aval * div);
+ base = (UINT64)dval;
+ if (base <= 0x03ffffff)
+ break;
+ exp--;
+ }
+
+ if (exp < 0)
+ return FALSE;
+
+ si.e = (BYTE)exp;
+ if (base <= 0x03)
+ {
+ si.c = ONE_BYTE_VAL;
+ si.val1 = base & 0x03;
+ }
+ else if (base <= 0x03ff)
+ {
+ si.c = TWO_BYTE_VAL;
+ si.val1 = (base >> 8) & 0x03;
+ si.val2 = base & 0xff;
+ }
+ else if (base <= 0x03ffff)
+ {
+ si.c = THREE_BYTE_VAL;
+ si.val1 = (base >> 16) & 0x03;
+ si.val2 = (base >> 8) & 0xff;
+ si.val3 = base & 0xff;
+ }
+ else if (base <= 0x03ffffff)
+ {
+ si.c = FOUR_BYTE_VAL;
+ si.val1 = (base >> 24) & 0x03;
+ si.val2 = (base >> 16) & 0xff;
+ si.val3 = (base >> 8) & 0xff;
+ si.val4 = base & 0xff;
+ }
+ else
+ {
+ WLog_ERR(TAG, "Invalid byte count for value %ld", value);
+ return FALSE;
+ }
+
+ if (!Stream_EnsureRemainingCapacity(s, si.c + 1))
+ return FALSE;
+
+ const BYTE byte =
+ ((si.c << 6) & 0xC0) | ((si.s << 5) & 0x20) | ((si.e << 2) & 0x1c) | (si.val1 & 0x03);
+ Stream_Write_UINT8(s, byte);
+
+ switch (si.c)
+ {
+ case ONE_BYTE_VAL:
+ break;
+ case TWO_BYTE_VAL:
+ Stream_Write_UINT8(s, si.val2);
+ break;
+ case THREE_BYTE_VAL:
+ Stream_Write_UINT8(s, si.val2);
+ Stream_Write_UINT8(s, si.val3);
+ break;
+ case FOUR_BYTE_VAL:
+ Stream_Write_UINT8(s, si.val2);
+ Stream_Write_UINT8(s, si.val3);
+ Stream_Write_UINT8(s, si.val4);
+ break;
+ case FIVE_BYTE_VAL:
+ case SIX_BYTE_VAL:
+ case SEVEN_BYTE_VAL:
+ case EIGHT_BYTE_VAL:
+ default:
+ WLog_ERR(TAG, "Invalid byte count value in si.c: %u", si.c);
+ return FALSE;
+ }
+
return TRUE;
}
diff --git a/libfreerdp/utils/http.c b/libfreerdp/utils/http.c
index 70963f0..5c34439 100644
--- a/libfreerdp/utils/http.c
+++ b/libfreerdp/utils/http.c
@@ -126,12 +126,18 @@ BOOL freerdp_http_request(const char* url, const char* body, long* status_code,
{
blen = strlen(body);
if (winpr_asprintf(&headers, &size, post_header_fmt, path, hostname, blen) < 0)
+ {
+ free(hostname);
return FALSE;
+ }
}
else
{
if (winpr_asprintf(&headers, &size, get_header_fmt, path, hostname) < 0)
+ {
+ free(hostname);
return FALSE;
+ }
}
ssl_ctx = SSL_CTX_new(TLS_client_method());
diff --git a/libfreerdp/utils/pcap.c b/libfreerdp/utils/pcap.c
index db50909..c18caf2 100644
--- a/libfreerdp/utils/pcap.c
+++ b/libfreerdp/utils/pcap.c
@@ -27,27 +27,11 @@
#include <winpr/assert.h>
#include <winpr/file.h>
#include <winpr/crt.h>
+#include <winpr/sysinfo.h>
#include <freerdp/log.h>
#define TAG FREERDP_TAG("utils")
-#ifndef _WIN32
-#include <sys/time.h>
-#else
-#include <time.h>
-#include <sys/timeb.h>
-#include <winpr/windows.h>
-
-int gettimeofday(struct timeval* tp, void* tz)
-{
- struct _timeb timebuffer;
- _ftime(&timebuffer);
- tp->tv_sec = (long)timebuffer.time;
- tp->tv_usec = timebuffer.millitm * 1000;
- return 0;
-}
-#endif
-
#include <freerdp/types.h>
#include <freerdp/utils/pcap.h>
@@ -131,14 +115,11 @@ static BOOL pcap_write_record(rdpPcap* pcap, const pcap_record* record)
BOOL pcap_add_record(rdpPcap* pcap, const void* data, size_t length)
{
- pcap_record* record = NULL;
- struct timeval tp;
-
WINPR_ASSERT(pcap);
WINPR_ASSERT(data || (length == 0));
WINPR_ASSERT(length <= UINT32_MAX);
- record = (pcap_record*)calloc(1, sizeof(pcap_record));
+ pcap_record* record = (pcap_record*)calloc(1, sizeof(pcap_record));
if (!record)
return FALSE;
@@ -147,9 +128,10 @@ BOOL pcap_add_record(rdpPcap* pcap, const void* data, size_t length)
record->header.incl_len = (UINT32)length;
record->header.orig_len = (UINT32)length;
- gettimeofday(&tp, 0);
- record->header.ts_sec = (UINT32)tp.tv_sec;
- record->header.ts_usec = (UINT32)tp.tv_usec;
+ const UINT64 ns = winpr_GetUnixTimeNS();
+
+ record->header.ts_sec = WINPR_TIME_NS_TO_S(ns);
+ record->header.ts_usec = WINPR_TIME_NS_REM_US(ns);
if (pcap->tail == NULL)
{
diff --git a/libfreerdp/utils/stopwatch.c b/libfreerdp/utils/stopwatch.c
index 3989638..70b60b3 100644
--- a/libfreerdp/utils/stopwatch.c
+++ b/libfreerdp/utils/stopwatch.c
@@ -22,38 +22,18 @@
#include <stdio.h>
#include <stdlib.h>
+#include <winpr/sysinfo.h>
#include <freerdp/utils/stopwatch.h>
-#ifdef _WIN32
-LARGE_INTEGER stopwatch_freq = { 0 };
-#else
-#include <sys/time.h>
-#endif
-
static void stopwatch_set_time(UINT64* usecs)
{
-#ifdef _WIN32
- LARGE_INTEGER perfcount;
- QueryPerformanceCounter(&perfcount);
- *usecs = (perfcount.QuadPart * 1000000) / stopwatch_freq.QuadPart;
-#else
- struct timeval tv;
- gettimeofday(&tv, NULL);
- *usecs = tv.tv_sec * 1000000 + tv.tv_usec;
-#endif
+ const UINT64 ns = winpr_GetTickCount64NS();
+ *usecs = WINPR_TIME_NS_TO_US(ns);
}
STOPWATCH* stopwatch_create(void)
{
- STOPWATCH* sw = NULL;
-#ifdef _WIN32
- if (stopwatch_freq.QuadPart == 0)
- {
- QueryPerformanceFrequency(&stopwatch_freq);
- }
-#endif
-
- sw = (STOPWATCH*)malloc(sizeof(STOPWATCH));
+ STOPWATCH* sw = (STOPWATCH*)calloc(1, sizeof(STOPWATCH));
if (!sw)
return NULL;
stopwatch_reset(sw);
diff --git a/libfreerdp/utils/test/CMakeLists.txt b/libfreerdp/utils/test/CMakeLists.txt
index f2b6977..a7a84fc 100644
--- a/libfreerdp/utils/test/CMakeLists.txt
+++ b/libfreerdp/utils/test/CMakeLists.txt
@@ -7,6 +7,7 @@ set(${MODULE_PREFIX}_DRIVER ${MODULE_NAME}.c)
set(${MODULE_PREFIX}_TESTS
TestRingBuffer.c
TestPodArrays.c
+ TestEncodedTypes.c
)
create_test_sourcelist(${MODULE_PREFIX}_SRCS
@@ -15,7 +16,10 @@ create_test_sourcelist(${MODULE_PREFIX}_SRCS
add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
-target_link_libraries(${MODULE_NAME} freerdp winpr)
+target_link_libraries(${MODULE_NAME} PRIVATE freerdp winpr)
+if (NOT WIN32)
+ target_link_libraries(${MODULE_NAME} PRIVATE m)
+endif()
set_target_properties(${MODULE_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${TESTING_OUTPUT_DIRECTORY}")
diff --git a/libfreerdp/utils/test/TestEncodedTypes.c b/libfreerdp/utils/test/TestEncodedTypes.c
new file mode 100644
index 0000000..f051d9c
--- /dev/null
+++ b/libfreerdp/utils/test/TestEncodedTypes.c
@@ -0,0 +1,212 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ *
+ * Copyright 2024 Thincast Technologies GmbH
+ * Copyright 2024 Armin Novak <anovak@thincast.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 <stdio.h>
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+
+#include <winpr/crypto.h>
+#include <freerdp/utils/encoded_types.h>
+
+#define MIN(x, y) ((x) < (y)) ? (x) : (y)
+#define MAX(x, y) ((x) > (y)) ? (x) : (y)
+
+static BOOL test_signed_integer_read_write_equal(INT32 value)
+{
+ INT32 rvalue = 0;
+ BYTE buffer[32] = { 0 };
+ wStream sbuffer = { 0 };
+ wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
+ WINPR_ASSERT(s);
+
+ if (!freerdp_write_four_byte_signed_integer(s, value))
+ {
+ fprintf(stderr, "[%s(%" PRId32 ")] failed to write to stream\n", __func__, value);
+ return FALSE;
+ }
+ if (!Stream_SetPosition(s, 0))
+ {
+ fprintf(stderr, "[%s(%" PRId32 ")] failed to reset stream position\n", __func__, value);
+ return FALSE;
+ }
+ if (!freerdp_read_four_byte_signed_integer(s, &rvalue))
+ {
+ fprintf(stderr, "[%s(%" PRId32 ")] failed to read from stream\n", __func__, value);
+ return FALSE;
+ }
+ if (value != rvalue)
+ {
+ fprintf(stderr, "[%s(%" PRId32 ")] read invalid value %" PRId32 " from stream\n", __func__,
+ value, rvalue);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static BOOL test_signed_integer_write_oor(INT32 value)
+{
+ BYTE buffer[32] = { 0 };
+ wStream sbuffer = { 0 };
+ wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
+ WINPR_ASSERT(s);
+
+ if (freerdp_write_four_byte_signed_integer(s, value))
+ {
+ fprintf(stderr, "[%s(%" PRId32 ")] out of range value not detected and written to stream\n",
+ __func__, value);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static BOOL test_signed_integers(void)
+{
+ const INT32 outofrange[] = { FREERDP_FOUR_BYTE_SIGNED_INT_MAX + 1,
+ FREERDP_FOUR_BYTE_SIGNED_INT_MIN - 1, INT32_MAX, INT32_MIN };
+ const INT32 limits[] = { 1, 0, -1, FREERDP_FOUR_BYTE_SIGNED_INT_MAX,
+ FREERDP_FOUR_BYTE_SIGNED_INT_MIN };
+
+ for (size_t x = 0; x < ARRAYSIZE(limits); x++)
+ {
+ if (!test_signed_integer_read_write_equal(limits[x]))
+ return FALSE;
+ }
+ for (size_t x = 0; x < ARRAYSIZE(outofrange); x++)
+ {
+ if (!test_signed_integer_write_oor(outofrange[x]))
+ return FALSE;
+ }
+ for (size_t x = 0; x < 100000; x++)
+ {
+ INT32 val = 0;
+ winpr_RAND(&val, sizeof(val));
+ val = MAX(val, 0);
+ val = MIN(val, FREERDP_FOUR_BYTE_SIGNED_INT_MAX);
+
+ const INT32 nval = -val;
+ if (!test_signed_integer_read_write_equal(val))
+ return FALSE;
+ if (!test_signed_integer_read_write_equal(nval))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static BOOL test_float_read_write_equal(double value)
+{
+ BYTE exp = 0;
+ double rvalue = FP_NAN;
+ BYTE buffer[32] = { 0 };
+ wStream sbuffer = { 0 };
+ wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
+ WINPR_ASSERT(s);
+
+ if (!freerdp_write_four_byte_float(s, value))
+ {
+ fprintf(stderr, "[%s(%lf)] failed to write to stream\n", __func__, value);
+ return FALSE;
+ }
+ if (!Stream_SetPosition(s, 0))
+ {
+ fprintf(stderr, "[%s(%lf)] failed to reset stream position\n", __func__, value);
+ return FALSE;
+ }
+ if (!freerdp_read_four_byte_float_exp(s, &rvalue, &exp))
+ {
+ fprintf(stderr, "[%s(%lf)] failed to read from stream\n", __func__, value);
+ return FALSE;
+ }
+ const double diff = fabs(value - rvalue);
+ const UINT64 expdiff = diff * pow(10, exp);
+ if (expdiff > 0)
+ {
+ fprintf(stderr, "[%s(%lf)] read invalid value %lf from stream\n", __func__, value, rvalue);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static BOOL test_floag_write_oor(double value)
+{
+ BYTE buffer[32] = { 0 };
+ wStream sbuffer = { 0 };
+ wStream* s = Stream_StaticInit(&sbuffer, buffer, sizeof(buffer));
+ WINPR_ASSERT(s);
+
+ if (freerdp_write_four_byte_float(s, value))
+ {
+ fprintf(stderr, "[%s(%lf)] out of range value not detected and written to stream\n",
+ __func__, value);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+static double get(void)
+{
+ double val = NAN;
+ do
+ {
+ winpr_RAND(&val, sizeof(val));
+ } while ((val < 0.0) || (val > FREERDP_FOUR_BYTE_FLOAT_MAX) || isnan(val) || isinf(val));
+ return val;
+}
+
+static BOOL test_floats(void)
+{
+ const double outofrange[] = { FREERDP_FOUR_BYTE_FLOAT_MAX + 1, FREERDP_FOUR_BYTE_FLOAT_MIN - 1,
+ DBL_MAX, -DBL_MAX };
+ const double limits[] = { 100045.26129238126, 1, 0, -1, FREERDP_FOUR_BYTE_FLOAT_MAX,
+ FREERDP_FOUR_BYTE_FLOAT_MIN };
+
+ for (size_t x = 0; x < ARRAYSIZE(limits); x++)
+ {
+ if (!test_float_read_write_equal(limits[x]))
+ return FALSE;
+ }
+ for (size_t x = 0; x < ARRAYSIZE(outofrange); x++)
+ {
+ if (!test_floag_write_oor(outofrange[x]))
+ return FALSE;
+ }
+ for (size_t x = 0; x < 100000; x++)
+ {
+ double val = get();
+
+ const double nval = -val;
+ if (!test_float_read_write_equal(val))
+ return FALSE;
+ if (!test_float_read_write_equal(nval))
+ return FALSE;
+ }
+ return TRUE;
+}
+
+int TestEncodedTypes(int argc, char* argv[])
+{
+ WINPR_UNUSED(argc);
+ WINPR_UNUSED(argv);
+
+ if (!test_signed_integers())
+ return -1;
+ if (!test_floats())
+ return -1;
+ return 0;
+}
diff --git a/rdtk/librdtk/CMakeLists.txt b/rdtk/librdtk/CMakeLists.txt
index 03e0418..e872c23 100644
--- a/rdtk/librdtk/CMakeLists.txt
+++ b/rdtk/librdtk/CMakeLists.txt
@@ -36,35 +36,13 @@ set(${MODULE_PREFIX}_SRCS
rdtk_engine.c
rdtk_engine.h)
-# On windows create dll version information.
-# Vendor, product and year are already set in top level CMakeLists.txt
-if (WIN32)
- set (RC_VERSION_MAJOR ${RDTK_VERSION_MAJOR})
- set (RC_VERSION_MINOR ${RDTK_VERSION_MINOR})
- set (RC_VERSION_BUILD ${RDTK_VERSION_REVISION})
- set (RC_VERSION_FILE "${CMAKE_SHARED_LIBRARY_PREFIX}${MODULE_NAME}${RDTK_API_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}" )
-
- configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
- list (APPEND ${MODULE_PREFIX}_SRCS ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-endif()
-
-add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
+AddTargetWithResourceFile(${MODULE_NAME} FALSE "${RDTK_VERSION}" ${MODULE_PREFIX}_SRCS)
list(APPEND ${MODULE_PREFIX}_LIBS winpr)
target_include_directories(${MODULE_NAME} INTERFACE $<INSTALL_INTERFACE:include>)
target_link_libraries(${MODULE_NAME} PRIVATE ${${MODULE_PREFIX}_LIBS})
-set_target_properties(${MODULE_NAME} PROPERTIES LINKER_LANGUAGE C)
-set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME ${MODULE_NAME}${RDTK_API_VERSION})
-if (WITH_LIBRARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${RDTK_VERSION} SOVERSION ${RDTK_API_VERSION})
-endif()
-
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "RdTk")
if(BUILD_TESTING)
@@ -76,9 +54,4 @@ if (NOT RDTK_FORCE_STATIC_BUILD)
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-
- if (WITH_DEBUG_SYMBOLS AND MSVC AND BUILD_SHARED_LIBS)
- get_target_property(OUTPUT_FILENAME ${MODULE_NAME} OUTPUT_NAME)
- install(FILES ${CMAKE_PDB_BINARY_DIR}/${OUTPUT_FILENAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT symbols)
- endif()
endif()
diff --git a/rdtk/librdtk/rdtk_font.c b/rdtk/librdtk/rdtk_font.c
index ccd8f46..c44e952 100644
--- a/rdtk/librdtk/rdtk_font.c
+++ b/rdtk/librdtk/rdtk_font.c
@@ -410,7 +410,7 @@ static int rdtk_font_parse_descriptor_buffer(rdtkFont* font, uint8_t* buffer, si
*r = '\0';
/* start parsing glyph */
- if (index > font->glyphCount)
+ if (index >= font->glyphCount)
return -1;
rdtkGlyph* glyph = &font->glyphs[index];
diff --git a/rdtk/sample/CMakeLists.txt b/rdtk/sample/CMakeLists.txt
index 1b4f025..05f44f8 100644
--- a/rdtk/sample/CMakeLists.txt
+++ b/rdtk/sample/CMakeLists.txt
@@ -25,10 +25,7 @@ include_directories(${X11_INCLUDE_DIR})
set(SRCS
rdtk_x11.c)
-add_executable(${MODULE_NAME} ${SRCS})
-if (WITH_BINARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "${MODULE_NAME}${RDTK_API_VERSION}")
-endif()
+AddTargetWithResourceFile(${MODULE_NAME} TRUE "${RDTK_VERSION}" SRCS)
set(LIBS rdtk)
diff --git a/scripts/abi-suppr.txt b/scripts/abi-suppr.txt
new file mode 100644
index 0000000..98780dd
--- /dev/null
+++ b/scripts/abi-suppr.txt
@@ -0,0 +1,9 @@
+# settings are opaque, ignore all changes
+[suppress_type]
+type_kind = struct
+name = rdp_settings
+
+# allow insertions at end of structs
+[suppress_type]
+type_kind = struct
+has_data_members_inserted_at = end
diff --git a/scripts/bundle-mac-os.sh b/scripts/bundle-mac-os.sh
index 8bb1986..8bd387d 100755
--- a/scripts/bundle-mac-os.sh
+++ b/scripts/bundle-mac-os.sh
@@ -22,6 +22,22 @@ usage () {
echo "target [$DEPLOYMENT_TARGET]"
}
+check_tools() {
+ for TOOL in mkdir rm mv git dirname pwd find cut basename grep xargs cmake ninja autoconf automake aclocal autoheader glibtoolize lipo otool install_name_tool;
+ do
+ set +e
+ TOOL_PATH=$(which "$TOOL")
+ set -e
+ echo "$TOOL: $TOOL_PATH"
+
+ if [ ! -f "$TOOL_PATH" ];
+ then
+ echo "Missing $TOOL! please install and add to PATH."
+ exit 1
+ fi
+ done
+}
+
while [[ $# -gt 0 ]]; do
case $1 in
-a|--arch)
@@ -49,6 +65,8 @@ while [[ $# -gt 0 ]]; do
esac
done
+check_tools
+
fix_rpath() {
SEARCH_PATH=$1
FIX_PATH=$1
@@ -94,7 +112,7 @@ replace_rpath() {
}
CMAKE_ARCHS=
-OSSL_FLAGS="-mmacosx-version-min=$DEPLOYMENT_TARGET"
+OSSL_FLAGS="-mmacosx-version-min=$DEPLOYMENT_TARGET -I$INSTALL/include -L$INSTALL/lib"
for ARCH in $DEPLOYMENT_ARCH;
do
OSSL_FLAGS="$OSSL_FLAGS -arch $ARCH"
diff --git a/scripts/mingw-meson.conf b/scripts/mingw-meson.conf
new file mode 100644
index 0000000..d91c184
--- /dev/null
+++ b/scripts/mingw-meson.conf
@@ -0,0 +1,15 @@
+[binaries]
+c = 'x86_64-w64-mingw32-gcc'
+cpp = 'x86_64-w64-mingw32-g++'
+ar = 'x86_64-w64-mingw32-ar'
+strip = 'x86_64-w64-mingw32-strip'
+exe_wrapper = 'wine64'
+
+[host_machine]
+system = 'windows'
+cpu_family = 'x86_64'
+cpu = 'x86_64'
+endian = 'little'
+
+[properties]
+sysroot = '/usr/x86_64-w64-mingw32'
diff --git a/scripts/mingw.sh b/scripts/mingw.sh
new file mode 100755
index 0000000..420dd47
--- /dev/null
+++ b/scripts/mingw.sh
@@ -0,0 +1,185 @@
+#!/bin/bash -xe
+
+SCRIPT_PATH=$(dirname "${BASH_SOURCE[0]}")
+SCRIPT_PATH=$(realpath "$SCRIPT_PATH")
+
+SRC_BASE="$SCRIPT_PATH/../build-mingw/src"
+BUILD_BASE="$SCRIPT_PATH/../build-mingw/build"
+INSTALL_BASE="$SCRIPT_PATH/../build-mingw/install"
+
+mkdir -p "$SRC_BASE"
+mkdir -p "$BUILD_BASE"
+
+cd "$SRC_BASE"
+git clone -b v3.8.2 https://github.com/libressl/portable.git libressl
+(
+ cd libressl
+ ./update.sh
+)
+cmake \
+ -GNinja \
+ -DCMAKE_TOOLCHAIN_FILE="$SCRIPT_PATH/mingw64.cmake" \
+ -DCMAKE_PREFIX_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_MODULE_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_INSTALL_PREFIX="$INSTALL_BASE" \
+ -S libressl \
+ -B "$BUILD_BASE/libressl" \
+ -DLIBRESSL_APPS=OFF \
+ -DLIBRESSL_TESTS=OFF
+cmake --build "$BUILD_BASE/libressl"
+cmake --install "$BUILD_BASE/libressl"
+
+git clone --depth 1 -b v1.3.1 https://github.com/madler/zlib.git
+cmake \
+ -GNinja \
+ -DCMAKE_TOOLCHAIN_FILE="$SCRIPT_PATH/mingw64.cmake" \
+ -DCMAKE_PREFIX_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_MODULE_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_INSTALL_PREFIX="$INSTALL_BASE" \
+ -S zlib \
+ -B "$BUILD_BASE/zlib"
+cmake --build "$BUILD_BASE/zlib"
+cmake --install "$BUILD_BASE/zlib"
+
+git clone --depth 1 -b uriparser-0.9.7 https://github.com/uriparser/uriparser.git
+cmake \
+ -GNinja \
+ -DCMAKE_TOOLCHAIN_FILE="$SCRIPT_PATH/mingw64.cmake" \
+ -DCMAKE_PREFIX_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_MODULE_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_INSTALL_PREFIX="$INSTALL_BASE" \
+ -S uriparser \
+ -B "$BUILD_BASE/uriparser" \
+ -DURIPARSER_BUILD_DOCS=OFF \
+ -DURIPARSER_BUILD_TESTS=OFF
+cmake --build "$BUILD_BASE/uriparser"
+cmake --install "$BUILD_BASE/uriparser"
+
+git clone --depth 1 -b v1.7.17 https://github.com/DaveGamble/cJSON.git
+cmake \
+ -GNinja \
+ -DCMAKE_TOOLCHAIN_FILE="$SCRIPT_PATH/mingw64.cmake" \
+ -DCMAKE_PREFIX_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_MODULE_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_INSTALL_PREFIX="$INSTALL_BASE" \
+ -S cJSON \
+ -B "$BUILD_BASE/cJSON" \
+ -DENABLE_CJSON_TEST=OFF \
+ -DBUILD_SHARED_AND_STATIC_LIBS=ON
+cmake --build "$BUILD_BASE/cJSON"
+cmake --install "$BUILD_BASE/cJSON"
+
+git clone --depth 1 -b release-2.30.0 https://github.com/libsdl-org/SDL.git
+cmake \
+ -GNinja \
+ -DCMAKE_TOOLCHAIN_FILE="$SCRIPT_PATH/mingw64.cmake" \
+ -DCMAKE_PREFIX_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_MODULE_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_INSTALL_PREFIX="$INSTALL_BASE" \
+ -S SDL \
+ -B "$BUILD_BASE/SDL" \
+ -DSDL_TEST=OFF \
+ -DSDL_TESTS=OFF \
+ -DSDL_STATIC_PIC=ON
+cmake --build "$BUILD_BASE/SDL"
+cmake --install "$BUILD_BASE/SDL"
+
+git clone --depth 1 --shallow-submodules --recurse-submodules -b release-2.22.0 https://github.com/libsdl-org/SDL_ttf.git
+cmake \
+ -GNinja \
+ -DCMAKE_TOOLCHAIN_FILE="$SCRIPT_PATH/mingw64.cmake" \
+ -DCMAKE_PREFIX_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_MODULE_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_INSTALL_PREFIX="$INSTALL_BASE" \
+ -S SDL_ttf \
+ -B "$BUILD_BASE/SDL_ttf" \
+ -DSDL2TTF_HARFBUZZ=ON \
+ -DSDL2TTF_FREETYPE=ON \
+ -DSDL2TTF_VENDORED=ON \
+ -DFT_DISABLE_ZLIB=OFF \
+ -DSDL2TTF_SAMPLES=OFF
+cmake --build "$BUILD_BASE/SDL_ttf"
+cmake --install "$BUILD_BASE/SDL_ttf"
+
+git clone --depth 1 --shallow-submodules --recurse-submodules -b release-2.8.2 https://github.com/libsdl-org/SDL_image.git
+cmake \
+ -GNinja \
+ -DCMAKE_TOOLCHAIN_FILE="$SCRIPT_PATH/mingw64.cmake" \
+ -DCMAKE_PREFIX_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_MODULE_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_INSTALL_PREFIX="$INSTALL_BASE" \
+ -S SDL_image \
+ -B "$BUILD_BASE/SDL_image" \
+ -DSDL2IMAGE_SAMPLES=OFF \
+ -DSDL2IMAGE_DEPS_SHARED=OFF
+cmake --build "$BUILD_BASE/SDL_image"
+cmake --install "$BUILD_BASE/SDL_image"
+
+git clone --depth 1 --shallow-submodules --recurse-submodules -b v1.0.27 https://github.com/libusb/libusb-cmake.git
+cmake \
+ -GNinja \
+ -DCMAKE_TOOLCHAIN_FILE="$SCRIPT_PATH/mingw64.cmake" \
+ -DCMAKE_PREFIX_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_MODULE_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_INSTALL_PREFIX="$INSTALL_BASE" \
+ -S libusb-cmake \
+ -B "$BUILD_BASE/libusb-cmake" \
+ -DLIBUSB_BUILD_EXAMPLES=OFF \
+ -DLIBUSB_BUILD_TESTING=OFF \
+ -DLIBUSB_ENABLE_DEBUG_LOGGING=OFF
+cmake --build "$BUILD_BASE/libusb-cmake"
+cmake --install "$BUILD_BASE/libusb-cmake"
+
+# TODO: This takes ages to compile, disable
+#git clone --depth 1 -b n6.1.1 https://github.com/FFmpeg/FFmpeg.git
+#(
+# cd "$BUILD_BASE"
+# mkdir -p FFmpeg
+# cd FFmpeg
+# "$SRC_BASE/FFmpeg/configure" \
+# --arch=x86_64 \
+# --target-os=mingw64 \
+# --cross-prefix=x86_64-w64-mingw32- \
+# --prefix="$INSTALL_BASE"
+# make -j
+# make -j install
+#)
+
+git clone --depth 1 -b v2.4.1 https://github.com/cisco/openh264.git
+meson setup --cross-file "$SCRIPT_PATH/mingw-meson.conf" \
+ -Dprefix="$INSTALL_BASE" \
+ -Db_pie=true \
+ -Db_lto=true \
+ -Dbuildtype=release \
+ -Dtests=disabled \
+ -Ddefault_library=both \
+ "$BUILD_BASE/openh264" \
+ openh264
+ninja -C "$BUILD_BASE/openh264"
+ninja -C "$BUILD_BASE/openh264" install
+
+cmake \
+ -GNinja \
+ -DCMAKE_TOOLCHAIN_FILE="$SCRIPT_PATH/mingw64.cmake" \
+ -DCMAKE_PREFIX_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_MODULE_PATH="$INSTALL_BASE/lib/cmake;$INSTALL_BASE/lib;$INSTALL_BASE" \
+ -DCMAKE_INSTALL_PREFIX="$INSTALL_BASE" \
+ -S "$SCRIPT_PATH/.." \
+ -B "$BUILD_BASE/freerdp" \
+ -DWITH_SERVER=ON \
+ -DWITH_SHADOW=OFF \
+ -DWITH_PLATFORM_SERVER=OFF \
+ -DWITH_SAMPLE=ON \
+ -DWITH_PLATFORM_SERVER=OFF \
+ -DUSE_UNWIND=OFF \
+ -DSDL_USE_COMPILED_RESOURCES=OFF \
+ -DWITH_SWSCALE=OFF \
+ -DWITH_FFMPEG=OFF \
+ -DWITH_OPENH264=ON \
+ -DWITH_WEBVIEW=OFF \
+ -DWITH_LIBRESSL=ON \
+ -DWITH_MANPAGES=OFF \
+ -DZLIB_INCLUDE_DIR="$INSTALL_BASE/include" \
+ -DZLIB_LIBRARY="$INSTALL_BASE/lib/libzlibstatic.a"
+cmake --build "$BUILD_BASE/freerdp"
+cmake --install "$BUILD_BASE/freerdp"
diff --git a/scripts/mingw64.cmake b/scripts/mingw64.cmake
new file mode 100644
index 0000000..42612dd
--- /dev/null
+++ b/scripts/mingw64.cmake
@@ -0,0 +1,35 @@
+SET(CMAKE_SYSTEM_NAME Windows CACHE STRING "toolchain default")
+
+SET(CMAKE_SYSTEM_PROCESSOR amd64 CACHE STRING "toolchain default")
+
+# https://github.com/meganz/mingw-std-threads
+#
+# we simply compile with the POSIX C++ primitives, but faster is using the wrapper
+SET(CMAKE_C_COMPILER /usr/bin/x86_64-w64-mingw32-gcc-posix CACHE STRING "toolchain default")
+SET(CMAKE_CXX_COMPILER /usr/bin/x86_64-w64-mingw32-g++-posix CACHE STRING "toolchain default")
+SET(CMAKE_RC_COMPILER_INIT /usr/bin/x86_64-w64-mingw32-windres CACHE STRING "toolchain default")
+SET(CMAKE_RC_COMPILER /usr/bin/x86_64-w64-mingw32-windres CACHE STRING "toolchain default")
+SET(CMAKE_AR /usr/bin/x86_64-w64-mingw32-gcc-ar-posix CACHE STRING "toolchain default")
+SET(CMAKE_C_COMPILER_AR /usr/bin/x86_64-w64-mingw32-gcc-ar-posix CACHE STRING "toolchain default")
+SET(CMAKE_CXX_COMPILER_AR /usr/bin/x86_64-w64-mingw32-gcc-ar-posix CACHE STRING "toolchain default")
+SET(CMAKE_RANLIB /usr/bin/x86_64-w64-mingw32-gcc-ranlib-posix CACHE STRING "toolchain default")
+SET(CMAKE_C_COMPILER_RANLIB /usr/bin/x86_64-w64-mingw32-gcc-ranlib-posix CACHE STRING "toolchain default")
+SET(CMAKE_CXX_COMPILER_RANLIB /usr/bin/x86_64-w64-mingw32-gcc-ranlib-posix CACHE STRING "toolchain default")
+SET(CMAKE_LINKER /usr/bin/x86_64-w64-mingw32-ld-posix CACHE STRING "toolchain default")
+SET(CMAKE_NM /usr/bin/x86_64-w64-mingw32-nm-posix CACHE STRING "toolchain default")
+SET(CMAKE_READELF /usr/bin/x86_64-w64-mingw32-readelf CACHE STRING "toolchain default")
+SET(CMAKE_OBJCOPY /usr/bin/x86_64-w64-mingw32-objcopy CACHE STRING "toolchain default")
+SET(CMAKE_OBJDUMP /usr/bin/x86_64-w64-mingw32-objdump CACHE STRING "toolchain default")
+
+SET(CMAKE_SYSROOT /usr/x86_64-w64-mingw32 CACHE STRING "toolchain default")
+
+#set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER CACHE STRING "toolchain default")
+#set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY CACHE STRING "toolchain default")
+#set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY CACHE STRING "toolchain default")
+#set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY CACHE STRING "toolchain default")
+
+set(CMAKE_WINDOWS_VERSION "WIN10" CACHE STRING "toolchain default")
+set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "toolchain default")
+set(CMAKE_SKIP_INSTALL_ALL_DEPENDENCY ON CACHE BOOL "toolchain default")
+set(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "toolchain default")
+set(THREADS_PREFER_PTHREAD_FLAG ON CACHE BOOL "toolchain default")
diff --git a/server/Sample/CMakeLists.txt b/server/Sample/CMakeLists.txt
index e23f65c..9a59d8b 100644
--- a/server/Sample/CMakeLists.txt
+++ b/server/Sample/CMakeLists.txt
@@ -32,22 +32,6 @@ if (CHANNEL_AINPUT_SERVER)
list(APPEND SRCS sf_ainput.c sf_ainput.h)
endif()
- # On windows create dll version information.
-# Vendor, product and year are already set in top level CMakeLists.txt
-if (WIN32)
- set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
- set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR})
- set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION})
- set (RC_VERSION_FILE "${MODULE_NAME}${CMAKE_EXECUTABLE_SUFFIX}" )
-
- configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
- set ( SRCS ${SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-endif()
-
if (WITH_BINARY_VERSIONING)
set(SAMPLE_RESOURCE_ROOT ${CMAKE_INSTALL_FULL_DATAROOTDIR}/FreeRDP${FREERDP_VERSION_MAJOR}/images)
else()
@@ -65,10 +49,7 @@ install(FILES ${SAMPLE_ICONS} DESTINATION ${SAMPLE_RESOURCE_ROOT})
# We need this in runtime path for TestConnect
file(COPY test_icon.bmp DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
-add_executable(${MODULE_NAME} ${SRCS})
-if (WITH_BINARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "${MODULE_NAME}${FREERDP_API_VERSION}")
-endif()
+AddTargetWithResourceFile(${MODULE_NAME} TRUE "${FREERDP_VERSION}" SRCS)
target_compile_definitions(${MODULE_NAME}
PRIVATE
@@ -79,8 +60,5 @@ list(APPEND LIBS winpr freerdp)
target_link_libraries(${MODULE_NAME} ${LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT server)
-if (WITH_DEBUG_SYMBOLS AND MSVC)
- install(FILES ${CMAKE_PDB_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT symbols)
-endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/Sample")
diff --git a/server/Sample/sfreerdp.c b/server/Sample/sfreerdp.c
index f39a747..fbdd1c3 100644
--- a/server/Sample/sfreerdp.c
+++ b/server/Sample/sfreerdp.c
@@ -537,6 +537,7 @@ static BOOL test_sleep_tsdiff(UINT32* old_sec, UINT32* old_usec, UINT32 new_sec,
static BOOL tf_peer_dump_rfx(freerdp_peer* client)
{
+ BOOL rc = FALSE;
wStream* s = NULL;
UINT32 prev_seconds = 0;
UINT32 prev_useconds = 0;
@@ -559,8 +560,9 @@ static BOOL tf_peer_dump_rfx(freerdp_peer* client)
update = client->context->update;
WINPR_ASSERT(update);
- if (!(pcap_rfx = pcap_open(info->test_pcap_file, FALSE)))
- return FALSE;
+ pcap_rfx = pcap_open(info->test_pcap_file, FALSE);
+ if (!pcap_rfx)
+ goto fail;
prev_seconds = prev_useconds = 0;
@@ -589,9 +591,11 @@ static BOOL tf_peer_dump_rfx(freerdp_peer* client)
break;
}
+ rc = TRUE;
+fail:
Stream_Free(s, TRUE);
pcap_close(pcap_rfx);
- return TRUE;
+ return rc;
}
static DWORD WINAPI tf_debug_channel_thread_func(LPVOID arg)
diff --git a/server/Windows/CMakeLists.txt b/server/Windows/CMakeLists.txt
index 2744b65..20f1518 100644
--- a/server/Windows/CMakeLists.txt
+++ b/server/Windows/CMakeLists.txt
@@ -61,37 +61,12 @@ if(CHANNEL_RDPSND AND WITH_RDPSND_DSOUND)
)
endif()
-# On windows create dll version information.
-# Vendor, product and year are already set in top level CMakeLists.txt
-set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
-set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR})
-set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION})
if(WITH_SERVER_INTERFACE)
- set (RC_VERSION_FILE "${CMAKE_SHARED_LIBRARY_PREFIX}${MODULE_NAME}${FREERDP_API_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}" )
-else()
- set (RC_VERSION_FILE "${MODULE_NAME}${CMAKE_EXECUTABLE_SUFFIX}" )
-endif()
-
-configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
-set (${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-
-if(WITH_SERVER_INTERFACE)
- add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
- set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME ${MODULE_NAME}${FREERDP_API_VERSION})
- if (WITH_LIBRARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION})
- endif()
+ AddTargetWithResourceFile(${MODULE_NAME} FALSE "${FREERDP_VERSION}" ${MODULE_PREFIX}_SRCS)
target_include_directories(${MODULE_NAME} INTERFACE $<INSTALL_INTERFACE:include>)
else()
- set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} cli/wfreerdp.c cli/wfreerdp.h)
- add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
- if (WITH_BINARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "${MODULE_NAME}${FREERDP_API_VERSION}")
- endif()
+ list(APPEND ${MODULE_PREFIX}_SRCS cli/wfreerdp.c cli/wfreerdp.h)
+ AddTargetWithResourceFile(${MODULE_NAME} TRUE "${FREERDP_VERSION}" ${MODULE_PREFIX}_SRCS)
endif()
@@ -109,16 +84,8 @@ if(WITH_SERVER_INTERFACE)
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-
- if (WITH_DEBUG_SYMBOLS AND MSVC AND BUILD_SHARED_LIBS)
- install(FILES ${PROJECT_BINARY_DIR}/${MODULE_NAME}${FREERDP_VERSION_MAJOR}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT symbols)
- endif()
else()
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT server)
-
- if (WITH_DEBUG_SYMBOLS AND MSVC)
- install(FILES ${PROJECT_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT symbols)
- endif()
endif()
if(WITH_SERVER_INTERFACE)
diff --git a/server/Windows/cli/CMakeLists.txt b/server/Windows/cli/CMakeLists.txt
index e125ac3..c362f66 100644
--- a/server/Windows/cli/CMakeLists.txt
+++ b/server/Windows/cli/CMakeLists.txt
@@ -16,7 +16,7 @@
# limitations under the License.
set(MODULE_NAME "wfreerdp-server-cli")
-set(OUTPUT_NAME " wfreerdp-server")
+set(OUTPUT_NAME "wfreerdp-server")
set(MODULE_PREFIX "FREERDP_SERVER_WINDOWS_CLI")
include_directories(..)
@@ -25,27 +25,7 @@ set(${MODULE_PREFIX}_SRCS
wfreerdp.c
wfreerdp.h)
-# On windows create dll version information.
-# Vendor, product and year are already set in top level CMakeLists.txt
-set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
-set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR})
-set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION})
-set (RC_VERSION_FILE "${MODULE_NAME}${CMAKE_EXECUTABLE_SUFFIX}" )
-
-configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
-set (${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-
-add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
-
-if (WITH_BINARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "${OUTPUT_NAME}${FREERDP_API_VERSION}")
-else()
- set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "${OUTPUT_NAME}")
-endif()
+AddTargetWithResourceFile(${MODULE_NAME} TRUE "${FREERDP_VERSION}" ${MODULE_PREFIX}_SRCS)
set(${MODULE_PREFIX}_LIBS wfreerdp-server)
@@ -53,8 +33,4 @@ target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT server)
-if (WITH_DEBUG_SYMBOLS AND MSVC)
- install(FILES ${PROJECT_BINARY_DIR}/${OUTPUT_NAME}.pdb DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT symbols)
-endif()
-
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/Windows")
diff --git a/server/Windows/wf_rdpsnd.c b/server/Windows/wf_rdpsnd.c
index b313c35..cb961e5 100644
--- a/server/Windows/wf_rdpsnd.c
+++ b/server/Windows/wf_rdpsnd.c
@@ -49,7 +49,8 @@ static void wf_peer_rdpsnd_activated(RdpsndServerContext* context)
wfi->agreed_format = NULL;
WLog_DBG(TAG, "Client supports the following %d formats:", context->num_client_formats);
- for (size_t i = 0; i < context->num_client_formats; i++)
+ size_t i = 0;
+ for (; i < context->num_client_formats; i++)
{
// TODO: improve the way we agree on a format
for (size_t j = 0; j < context->num_server_formats; j++)
diff --git a/server/common/CMakeLists.txt b/server/common/CMakeLists.txt
index 5552688..6795ba9 100644
--- a/server/common/CMakeLists.txt
+++ b/server/common/CMakeLists.txt
@@ -36,29 +36,7 @@ if(MSVC)
set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS})
endif()
-
-# On windows create dll version information.
-# Vendor, product and year are already set in top level CMakeLists.txt
-if (WIN32)
- set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
- set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR})
- set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION})
- set (RC_VERSION_FILE "${CMAKE_SHARED_LIBRARY_PREFIX}${MODULE_NAME}${FREERDP_API_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}" )
-
- configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
- set (${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-endif()
-
-add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
-set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME ${MODULE_NAME}${FREERDP_API_VERSION})
-
-if (WITH_LIBRARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION})
-endif()
+AddTargetWithResourceFile(${MODULE_NAME} FALSE "${FREERDP_VERSION}" ${MODULE_PREFIX}_SRCS)
target_include_directories(${MODULE_NAME} INTERFACE $<INSTALL_INTERFACE:include>)
target_link_libraries(${MODULE_NAME} PRIVATE ${FREERDP_CHANNELS_SERVER_LIBS})
@@ -69,9 +47,4 @@ install(TARGETS ${MODULE_NAME} COMPONENT libraries EXPORT FreeRDP-ServerTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-if (WITH_DEBUG_SYMBOLS AND MSVC AND BUILD_SHARED_LIBS)
- get_target_property(OUTPUT_FILENAME ${MODULE_NAME} OUTPUT_NAME)
- install(FILES ${CMAKE_PDB_BINARY_DIR}/${OUTPUT_FILENAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT symbols)
-endif()
-
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/Common")
diff --git a/server/proxy/CMakeLists.txt b/server/proxy/CMakeLists.txt
index 4693b17..8a262dd 100644
--- a/server/proxy/CMakeLists.txt
+++ b/server/proxy/CMakeLists.txt
@@ -47,29 +47,7 @@ set(PROXY_APP_SRCS freerdp_proxy.c)
option(WITH_PROXY_EMULATE_SMARTCARD "Compile proxy smartcard emulation" OFF)
add_subdirectory("channels")
-# On windows create dll version information.
-# Vendor, product and year are already set in top level CMakeLists.txt
-if (WIN32)
- set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
- set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR})
- set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION})
- set (RC_VERSION_FILE "${MODULE_NAME}${CMAKE_EXECUTABLE_SUFFIX}" )
-
- configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
- set ( ${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
- list(APPEND PROXY_APP_SRCS ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-endif()
-
-add_library(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
-set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME ${MODULE_NAME}${FREERDP_API_VERSION})
-
-if (WITH_LIBRARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION})
-endif()
+AddTargetWithResourceFile(${MODULE_NAME} FALSE "${FREERDP_VERSION}" ${MODULE_PREFIX}_SRCS)
set(PRIVATE_LIBS
freerdp-client
@@ -89,11 +67,6 @@ install(TARGETS ${MODULE_NAME} COMPONENT server EXPORT FreeRDP-ProxyTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-if (WITH_DEBUG_SYMBOLS AND MSVC AND BUILD_SHARED_LIBS)
- get_target_property(OUTPUT_FILENAME ${MODULE_NAME} OUTPUT_NAME)
- install(FILES ${CMAKE_PDB_BINARY_DIR}/${OUTPUT_FILENAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT symbols)
-endif()
-
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/Proxy")
# pkg-config
diff --git a/server/proxy/cli/CMakeLists.txt b/server/proxy/cli/CMakeLists.txt
index 1416b4a..a532f90 100644
--- a/server/proxy/cli/CMakeLists.txt
+++ b/server/proxy/cli/CMakeLists.txt
@@ -18,43 +18,12 @@
set(PROXY_APP_SRCS freerdp_proxy.c)
-# On windows create dll version information.
-# Vendor, product and year are already set in top level CMakeLists.txt
-if (WIN32)
- set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
- set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR})
- set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION})
- set (RC_VERSION_FILE "${MODULE_NAME}${CMAKE_EXECUTABLE_SUFFIX}" )
-
- configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
- list(APPEND PROXY_APP_SRCS ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-endif()
-
set(APP_NAME "freerdp-proxy")
-add_executable(${APP_NAME}
- ${PROXY_APP_SRCS}
-)
-
-set(MANPAGE_NAME ${APP_NAME}.1)
-if (WITH_BINARY_VERSIONING)
- set_target_properties(${APP_NAME}
- PROPERTIES
- OUTPUT_NAME "${APP_NAME}${FREERDP_API_VERSION}"
- )
- set(MANPAGE_NAME ${APP_NAME}${FREERDP_API_VERSION}.1)
-endif()
+AddTargetWithResourceFile(${APP_NAME} TRUE "${FREERDP_VERSION}" PROXY_APP_SRCS)
target_link_libraries(${APP_NAME} ${MODULE_NAME})
install(TARGETS ${APP_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT server)
-if (WITH_DEBUG_SYMBOLS AND MSVC)
- install(FILES ${CMAKE_PDB_BINARY_DIR}/${APP_NAME}.pdb DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT symbols)
-endif()
set_property(TARGET ${APP_NAME} PROPERTY FOLDER "Server/proxy")
-configure_file(${APP_NAME}.1.in ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE_NAME})
-install_freerdp_man(${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE_NAME} 1)
+generate_and_install_freerdp_man_from_template(${APP_NAME} "1" "${FREERDP_API_VERSION}")
diff --git a/server/proxy/modules/bitmap-filter/CMakeLists.txt b/server/proxy/modules/bitmap-filter/CMakeLists.txt
index d2cc03b..e51853f 100644
--- a/server/proxy/modules/bitmap-filter/CMakeLists.txt
+++ b/server/proxy/modules/bitmap-filter/CMakeLists.txt
@@ -48,13 +48,11 @@ include(CommonConfigOptions)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
-add_library(${PROJECT_NAME} SHARED
+set(SRCS
bitmap-filter.cpp
)
+AddTargetWithResourceFile(${PROJECT_NAME} FALSE "${PROJECT_VERSION}" SRCS FALSE)
target_link_libraries(${PROJECT_NAME} winpr freerdp)
-set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
-set_target_properties(${PROJECT_NAME} PROPERTIES NO_SONAME 1)
-
install(TARGETS ${PROJECT_NAME} DESTINATION ${FREERDP_PROXY_PLUGINDIR})
diff --git a/server/proxy/modules/demo/CMakeLists.txt b/server/proxy/modules/demo/CMakeLists.txt
index bdd85a3..ba1382b 100644
--- a/server/proxy/modules/demo/CMakeLists.txt
+++ b/server/proxy/modules/demo/CMakeLists.txt
@@ -41,13 +41,11 @@ include(CommonConfigOptions)
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
-add_library(${PROJECT_NAME} SHARED
+set(SRCS
demo.cpp
)
+AddTargetWithResourceFile(${PROJECT_NAME} FALSE "${PROJECT_VERSION}" SRCS FALSE)
target_link_libraries(${PROJECT_NAME} winpr)
-set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
-set_target_properties(${PROJECT_NAME} PROPERTIES NO_SONAME 1)
-
install(TARGETS ${PROJECT_NAME} DESTINATION ${FREERDP_PROXY_PLUGINDIR})
diff --git a/server/proxy/modules/dyn-channel-dump/CMakeLists.txt b/server/proxy/modules/dyn-channel-dump/CMakeLists.txt
index dc0fc53..dff349c 100644
--- a/server/proxy/modules/dyn-channel-dump/CMakeLists.txt
+++ b/server/proxy/modules/dyn-channel-dump/CMakeLists.txt
@@ -40,9 +40,10 @@ include(CommonConfigOptions)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
-add_library(${PROJECT_NAME} SHARED
+set(SRCS
dyn-channel-dump.cpp
)
+AddTargetWithResourceFile(${PROJECT_NAME} FALSE "${PROJECT_VERSION}" SRCS FALSE)
target_link_libraries(${PROJECT_NAME} PRIVATE
winpr
@@ -52,7 +53,4 @@ target_link_libraries(${PROJECT_NAME} PRIVATE
freerdp-server-proxy
)
-set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "")
-set_target_properties(${PROJECT_NAME} PROPERTIES NO_SONAME 1)
-
install(TARGETS ${PROJECT_NAME} DESTINATION ${FREERDP_PROXY_PLUGINDIR})
diff --git a/server/proxy/pf_server.c b/server/proxy/pf_server.c
index 545ab93..5a4828b 100644
--- a/server/proxy/pf_server.c
+++ b/server/proxy/pf_server.c
@@ -190,6 +190,7 @@ static BOOL pf_server_get_target_info(rdpContext* context, rdpSettings* settings
static BOOL pf_server_setup_channels(freerdp_peer* peer)
{
+ BOOL rc = FALSE;
char** accepted_channels = NULL;
size_t accepted_channels_count = 0;
pServerContext* ps = (pServerContext*)peer->context;
@@ -209,7 +210,7 @@ static BOOL pf_server_setup_channels(freerdp_peer* peer)
if (!channelContext)
{
PROXY_LOG_ERR(TAG, ps, "error seting up channelContext for '%s'", cname);
- return FALSE;
+ goto fail;
}
if (strcmp(cname, DRDYNVC_SVC_CHANNEL_NAME) == 0)
@@ -218,7 +219,7 @@ static BOOL pf_server_setup_channels(freerdp_peer* peer)
{
PROXY_LOG_ERR(TAG, ps, "error while setting up dynamic channel");
StaticChannelContext_free(channelContext);
- return FALSE;
+ goto fail;
}
}
else if (strcmp(cname, RDPDR_SVC_CHANNEL_NAME) == 0 &&
@@ -228,7 +229,7 @@ static BOOL pf_server_setup_channels(freerdp_peer* peer)
{
PROXY_LOG_ERR(TAG, ps, "error while setting up redirection channel");
StaticChannelContext_free(channelContext);
- return FALSE;
+ goto fail;
}
}
else
@@ -237,7 +238,7 @@ static BOOL pf_server_setup_channels(freerdp_peer* peer)
{
PROXY_LOG_ERR(TAG, ps, "error while setting up generic channel");
StaticChannelContext_free(channelContext);
- return FALSE;
+ goto fail;
}
}
@@ -246,12 +247,14 @@ static BOOL pf_server_setup_channels(freerdp_peer* peer)
{
StaticChannelContext_free(channelContext);
PROXY_LOG_ERR(TAG, ps, "error inserting channelContext in byId table for '%s'", cname);
- return FALSE;
+ goto fail;
}
}
+ rc = TRUE;
+fail:
free(accepted_channels);
- return TRUE;
+ return rc;
}
/* Event callbacks */
diff --git a/server/shadow/CMakeLists.txt b/server/shadow/CMakeLists.txt
index 72adcca..159b6b6 100644
--- a/server/shadow/CMakeLists.txt
+++ b/server/shadow/CMakeLists.txt
@@ -64,24 +64,7 @@ else()
include_directories(${PROJECT_BINARY_DIR}/rdtk/include)
endif()
-# On windows create dll version information.
-# Vendor, product and year are already set in top level CMakeLists.txt
-if (WIN32)
- set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
- set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR})
- set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION})
- set (RC_VERSION_PATCH 0)
- set (RC_VERSION_FILE "${CMAKE_SHARED_LIBRARY_PREFIX}${MODULE_NAME}${FREERDP_API_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}" )
-
- configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
-list (APPEND SRCS ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-endif()
-
-add_library(${MODULE_NAME} ${SRCS})
+AddTargetWithResourceFile(${MODULE_NAME} "FALSE" "${FREERDP_VERSION}" SRCS)
list(APPEND LIBS
freerdp
@@ -94,21 +77,11 @@ list(APPEND LIBS
target_include_directories(${MODULE_NAME} INTERFACE $<INSTALL_INTERFACE:include>)
target_link_libraries(${MODULE_NAME} PRIVATE ${LIBS})
-set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME ${MODULE_NAME}${FREERDP_VERSION_MAJOR})
-if (WITH_LIBRARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION})
-endif()
-
install(TARGETS ${MODULE_NAME} COMPONENT server EXPORT FreeRDP-ShadowTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-if (WITH_DEBUG_SYMBOLS AND MSVC)
- get_target_property(OUTPUT_FILENAME ${MODULE_NAME} OUTPUT_NAME)
- install(FILES ${PROJECT_BINARY_DIR}/${OUTPUT_FILENAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT symbols)
-endif()
-
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow")
# subsystem library
@@ -126,21 +99,7 @@ elseif(APPLE AND NOT IOS)
add_subdirectory(Mac)
endif()
-if (WIN32)
- set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
- set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR})
- set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION})
- set (RC_VERSION_FILE "${MODULE_NAME}${CMAKE_EXECUTABLE_SUFFIX}" )
-
- configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
- set ( SRCS ${SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-endif()
-
-add_library(${MODULE_NAME} ${SRCS})
+AddTargetWithResourceFile(${MODULE_NAME} FALSE "${FREERDP_VERSION}" SRCS)
list(APPEND LIBS
freerdp-shadow-subsystem-impl
@@ -152,11 +111,6 @@ list(APPEND LIBS
target_include_directories(${MODULE_NAME} INTERFACE $<INSTALL_INTERFACE:include>)
target_link_libraries(${MODULE_NAME} PRIVATE ${LIBS})
-set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME ${MODULE_NAME}${FREERDP_API_VERSION})
-if (WITH_LIBRARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${FREERDP_VERSION} SOVERSION ${FREERDP_API_VERSION})
-endif()
-
if (NOT BUILD_SHARED_LIBS)
install(TARGETS freerdp-shadow-subsystem-impl
DESTINATION ${CMAKE_INSTALL_LIBDIR}
@@ -169,12 +123,6 @@ install(TARGETS ${MODULE_NAME} COMPONENT server EXPORT FreeRDP-ShadowTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-if (WITH_DEBUG_SYMBOLS AND MSVC)
- get_target_property(OUTPUT_FILENAME ${MODULE_NAME} OUTPUT_NAME)
- install(FILES ${PROJECT_BINARY_DIR}/${OUTPUT_FILENAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR}
- COMPONENT symbols)
-endif()
-
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow")
# command-line executable
@@ -184,46 +132,20 @@ set(MODULE_NAME "freerdp-shadow-cli")
set(SRCS
shadow.c)
-# On windows create dll version information.
-# Vendor, product and year are already set in top level CMakeLists.txt
-if (WIN32)
- set (RC_VERSION_MAJOR ${FREERDP_VERSION_MAJOR})
- set (RC_VERSION_MINOR ${FREERDP_VERSION_MINOR})
- set (RC_VERSION_BUILD ${FREERDP_VERSION_REVISION})
- set (RC_VERSION_FILE "${MODULE_NAME}${CMAKE_EXECUTABLE_SUFFIX}" )
-
- configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
- set ( SRCS ${SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-endif()
-
-add_executable(${MODULE_NAME} ${SRCS})
-
-set(MANPAGE_NAME "${MODULE_NAME}")
-if (WITH_BINARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "${MODULE_NAME}${FREERDP_API_VERSION}")
- set(MANPAGE_NAME "${MODULE_NAME}${FREERDP_API_VERSION}")
-endif()
+AddTargetWithResourceFile(${MODULE_NAME} TRUE "${FREERDP_VERSION}" SRCS)
list(APPEND LIBS freerdp-shadow-subsystem freerdp-shadow freerdp winpr)
target_link_libraries(${MODULE_NAME} PRIVATE ${LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT server)
-if (WITH_DEBUG_SYMBOLS AND MSVC)
- install(FILES ${PROJECT_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${CMAKE_INSTALL_BINDIR}
- COMPONENT symbols)
-endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Server/shadow")
include(pkg-config-install-prefix)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/freerdp-shadow.pc.in ${CMAKE_CURRENT_BINARY_DIR}/freerdp-shadow${FREERDP_VERSION_MAJOR}.pc @ONLY)
-configure_file(freerdp-shadow-cli.1.in ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE_NAME}.1)
-install_freerdp_man(${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE_NAME}.1 1)
+
+generate_and_install_freerdp_man_from_template(${MODULE_NAME} "1" "${FREERDP_API_VERSION}")
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/freerdp-shadow${FREERDP_VERSION_MAJOR}.pc DESTINATION ${PKG_CONFIG_PC_INSTALL_DIR})
diff --git a/server/shadow/X11/x11_shadow.c b/server/shadow/X11/x11_shadow.c
index 5c1fab1..1e4f945 100644
--- a/server/shadow/X11/x11_shadow.c
+++ b/server/shadow/X11/x11_shadow.c
@@ -409,7 +409,7 @@ static int x11_shadow_pointer_position_update(x11ShadowSubsystem* subsystem)
{
UINT32 msgId = SHADOW_MSG_OUT_POINTER_POSITION_UPDATE_ID;
rdpShadowServer* server = NULL;
- SHADOW_MSG_OUT_POINTER_POSITION_UPDATE templateMsg;
+ SHADOW_MSG_OUT_POINTER_POSITION_UPDATE templateMsg = { 0 };
int count = 0;
if (!subsystem || !subsystem->common.server || !subsystem->common.server->clients)
@@ -463,8 +463,8 @@ static int x11_shadow_pointer_alpha_update(x11ShadowSubsystem* subsystem)
msg->width = subsystem->cursorWidth;
msg->height = subsystem->cursorHeight;
- if (shadow_subsystem_pointer_convert_alpha_pointer_data(subsystem->cursorPixels, TRUE,
- msg->width, msg->height, msg) < 0)
+ if (shadow_subsystem_pointer_convert_alpha_pointer_data_to_format(
+ subsystem->cursorPixels, subsystem->format, TRUE, msg->width, msg->height, msg) < 0)
{
free(msg);
return -1;
@@ -796,9 +796,10 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
subsystem->xshm_gc, 0, 0, subsystem->width, subsystem->height, 0, 0);
EnterCriticalSection(&surface->lock);
- status = shadow_capture_compare(surface->data, surface->scanline, surface->width,
- surface->height, (BYTE*)&(image->data[surface->width * 4]),
- image->bytes_per_line, &invalidRect);
+ status = shadow_capture_compare_with_format(
+ surface->data, surface->format, surface->scanline, surface->width, surface->height,
+ (BYTE*)&(image->data[surface->width * 4ull]), subsystem->format, image->bytes_per_line,
+ &invalidRect);
LeaveCriticalSection(&surface->lock);
}
else
@@ -810,9 +811,9 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
if (image)
{
- status = shadow_capture_compare(surface->data, surface->scanline, surface->width,
- surface->height, (BYTE*)image->data,
- image->bytes_per_line, &invalidRect);
+ status = shadow_capture_compare_with_format(
+ surface->data, surface->format, surface->scanline, surface->width, surface->height,
+ (BYTE*)image->data, subsystem->format, image->bytes_per_line, &invalidRect);
}
LeaveCriticalSection(&surface->lock);
if (!image)
@@ -854,7 +855,7 @@ static int x11_shadow_screen_grab(x11ShadowSubsystem* subsystem)
WINPR_ASSERT(height >= 0);
success = freerdp_image_copy(surface->data, surface->format, surface->scanline, x, y,
(UINT32)width, (UINT32)height, (BYTE*)image->data,
- PIXEL_FORMAT_BGRX32, (UINT32)image->bytes_per_line, x, y,
+ subsystem->format, (UINT32)image->bytes_per_line, x, y,
NULL, FREERDP_FLIP_NONE);
LeaveCriticalSection(&surface->lock);
if (!success)
@@ -1036,7 +1037,10 @@ static int x11_shadow_xinerama_init(x11ShadowSubsystem* subsystem)
#ifdef WITH_XINERAMA
int xinerama_event = 0;
int xinerama_error = 0;
- x11_shadow_subsystem_base_init(subsystem);
+
+ const int rc = x11_shadow_subsystem_base_init(subsystem);
+ if (rc < 0)
+ return rc;
if (!XineramaQueryExtension(subsystem->display, &xinerama_event, &xinerama_error))
return -1;
@@ -1270,7 +1274,12 @@ static int x11_shadow_subsystem_init(rdpShadowSubsystem* sub)
return -1;
subsystem->common.numMonitors = x11_shadow_enum_monitors(subsystem->common.monitors, 16);
- x11_shadow_subsystem_base_init(subsystem);
+ const int rc = x11_shadow_subsystem_base_init(subsystem);
+ if (rc < 0)
+ return rc;
+
+ subsystem->format = (ImageByteOrder(subsystem->display) == LSBFirst) ? PIXEL_FORMAT_BGRA32
+ : PIXEL_FORMAT_ARGB32;
if ((subsystem->depth != 24) && (subsystem->depth != 32))
{
@@ -1392,6 +1401,7 @@ static int x11_shadow_subsystem_init(rdpShadowSubsystem* sub)
subsystem->use_xfixes, subsystem->use_xinerama, subsystem->use_xdamage,
subsystem->use_xshm);
}
+
return 1;
}
diff --git a/server/shadow/X11/x11_shadow.h b/server/shadow/X11/x11_shadow.h
index aca2d63..5ab8beb 100644
--- a/server/shadow/X11/x11_shadow.h
+++ b/server/shadow/X11/x11_shadow.h
@@ -100,6 +100,7 @@ struct x11_shadow_subsystem
#ifdef WITH_XFIXES
int xfixes_cursor_notify_event;
#endif
+ UINT32 format;
};
#ifdef __cplusplus
diff --git a/server/shadow/freerdp-shadow-cli.1.in b/server/shadow/freerdp-shadow-cli.1.in
index 890fb7a..ddea924 100644
--- a/server/shadow/freerdp-shadow-cli.1.in
+++ b/server/shadow/freerdp-shadow-cli.1.in
@@ -64,6 +64,14 @@ Print the version and exit.
.IP /help
Print the help and exit.
+.SH USAGE
+
+#MANPAGE_NAME@ - start the shadow server on port 3389 with NLA security, SAM database at /etc/winpr/SAM
+.br
+@MANPAGE_NAME@ /sam-file:SAM.db - same as above, but a custom SAM database provided as argument
+.br
+@MANPAGE_NAME@ -sec-nla - start the shadow server on port 3380 with TLS/NLA security. This allows authenticating against PAM with unix users. Be aware that the password is transmitted plain text like with basic HTTP auth
+
.SH EXAMPLES
@MANPAGE_NAME@ /port:12345
diff --git a/server/shadow/shadow_capture.c b/server/shadow/shadow_capture.c
index 4711ded..887f229 100644
--- a/server/shadow/shadow_capture.c
+++ b/server/shadow/shadow_capture.c
@@ -29,7 +29,7 @@
#define TAG SERVER_TAG("shadow")
-int shadow_capture_align_clip_rect(RECTANGLE_16* rect, RECTANGLE_16* clip)
+int shadow_capture_align_clip_rect(RECTANGLE_16* rect, const RECTANGLE_16* clip)
{
int dx = 0;
int dy = 0;
@@ -78,59 +78,151 @@ int shadow_capture_align_clip_rect(RECTANGLE_16* rect, RECTANGLE_16* clip)
return 1;
}
-int shadow_capture_compare(BYTE* pData1, UINT32 nStep1, UINT32 nWidth, UINT32 nHeight, BYTE* pData2,
- UINT32 nStep2, RECTANGLE_16* rect)
+int shadow_capture_compare(const BYTE* WINPR_RESTRICT pData1, UINT32 nStep1, UINT32 nWidth,
+ UINT32 nHeight, const BYTE* WINPR_RESTRICT pData2, UINT32 nStep2,
+ RECTANGLE_16* WINPR_RESTRICT rect)
{
- BOOL equal = 0;
- BOOL allEqual = 0;
+ return shadow_capture_compare_with_format(pData1, PIXEL_FORMAT_BGRX32, nStep1, nWidth, nHeight,
+ pData2, PIXEL_FORMAT_BGRX32, nStep2, rect);
+}
+
+static BOOL color_equal(UINT32 colorA, UINT32 formatA, UINT32 colorB, UINT32 formatB)
+{
+ BYTE ar = 0;
+ BYTE ag = 0;
+ BYTE ab = 0;
+ BYTE aa = 0;
+ BYTE br = 0;
+ BYTE bg = 0;
+ BYTE bb = 0;
+ BYTE ba = 0;
+ FreeRDPSplitColor(colorA, formatA, &ar, &ag, &ab, &aa, NULL);
+ FreeRDPSplitColor(colorB, formatB, &br, &bg, &bb, &ba, NULL);
+
+ if (ar != br)
+ return FALSE;
+ if (ag != bg)
+ return FALSE;
+ if (ab != bb)
+ return FALSE;
+ if (aa != ba)
+ return FALSE;
+ return TRUE;
+}
+
+static BOOL pixel_equal(const BYTE* WINPR_RESTRICT a, UINT32 formatA, const BYTE* WINPR_RESTRICT b,
+ UINT32 formatB, size_t count)
+{
+ const size_t bppA = FreeRDPGetBytesPerPixel(formatA);
+ const size_t bppB = FreeRDPGetBytesPerPixel(formatB);
+
+ for (size_t x = 0; x < count; x++)
+ {
+ const UINT32 colorA = FreeRDPReadColor(&a[bppA * x], formatA);
+ const UINT32 colorB = FreeRDPReadColor(&b[bppB * x], formatB);
+ if (!color_equal(colorA, formatA, colorB, formatB))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static BOOL color_equal_no_alpha(UINT32 colorA, UINT32 formatA, UINT32 colorB, UINT32 formatB)
+{
+ BYTE ar = 0;
+ BYTE ag = 0;
+ BYTE ab = 0;
+ BYTE br = 0;
+ BYTE bg = 0;
+ BYTE bb = 0;
+ FreeRDPSplitColor(colorA, formatA, &ar, &ag, &ab, NULL, NULL);
+ FreeRDPSplitColor(colorB, formatB, &br, &bg, &bb, NULL, NULL);
+
+ if (ar != br)
+ return FALSE;
+ if (ag != bg)
+ return FALSE;
+ if (ab != bb)
+ return FALSE;
+ return TRUE;
+}
+
+static BOOL pixel_equal_no_alpha(const BYTE* WINPR_RESTRICT a, UINT32 formatA,
+ const BYTE* WINPR_RESTRICT b, UINT32 formatB, size_t count)
+{
+ const size_t bppA = FreeRDPGetBytesPerPixel(formatA);
+ const size_t bppB = FreeRDPGetBytesPerPixel(formatB);
+
+ for (size_t x = 0; x < count; x++)
+ {
+ const UINT32 colorA = FreeRDPReadColor(&a[bppA * x], formatA);
+ const UINT32 colorB = FreeRDPReadColor(&b[bppB * x], formatB);
+ if (!color_equal_no_alpha(colorA, formatA, colorB, formatB))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static BOOL pixel_equal_same_format(const BYTE* WINPR_RESTRICT a, UINT32 formatA,
+ const BYTE* WINPR_RESTRICT b, UINT32 formatB, size_t count)
+{
+ if (formatA != formatB)
+ return FALSE;
+ const size_t bppA = FreeRDPGetBytesPerPixel(formatA);
+ return memcmp(a, b, count * bppA) == 0;
+}
+
+int shadow_capture_compare_with_format(const BYTE* WINPR_RESTRICT pData1, UINT32 format1,
+ UINT32 nStep1, UINT32 nWidth, UINT32 nHeight,
+ const BYTE* WINPR_RESTRICT pData2, UINT32 format2,
+ UINT32 nStep2, RECTANGLE_16* WINPR_RESTRICT rect)
+{
+ BOOL(*pixel_equal_fn)
+ (const BYTE* a, UINT32 formatA, const BYTE* b, UINT32 formatB, size_t count) = pixel_equal;
+
+ if (format1 == format2)
+ pixel_equal_fn = pixel_equal_same_format;
+ else if (!FreeRDPColorHasAlpha(format1) || !FreeRDPColorHasAlpha(format2))
+ pixel_equal_fn = pixel_equal_no_alpha;
+
+ BOOL allEqual = TRUE;
UINT32 tw = 0;
- UINT32 th = 0;
- UINT32 nrow = 0;
- UINT32 ncol = 0;
- UINT32 l = 0;
- UINT32 t = 0;
+ const UINT32 nrow = (nHeight + 15) / 16;
+ const UINT32 ncol = (nWidth + 15) / 16;
+ UINT32 l = ncol + 1;
+ UINT32 t = nrow + 1;
UINT32 r = 0;
UINT32 b = 0;
- BYTE* p1 = NULL;
- BYTE* p2 = NULL;
- BOOL rows[1024];
-#ifdef WITH_DEBUG_SHADOW_CAPTURE
- BOOL cols[1024] = { FALSE };
-#endif
- allEqual = TRUE;
- ZeroMemory(rect, sizeof(RECTANGLE_16));
- FillMemory(rows, sizeof(rows), 0xFF);
-#ifdef WITH_DEBUG_SHADOW_CAPTURE
- FillMemory(cols, sizeof(cols), 0xFF);
-#endif
- nrow = (nHeight + 15) / 16;
- ncol = (nWidth + 15) / 16;
- l = ncol + 1;
- r = 0;
- t = nrow + 1;
- b = 0;
-
- for (UINT32 ty = 0; ty < nrow; ty++)
+ const size_t bppA = FreeRDPGetBytesPerPixel(format1);
+ const size_t bppB = FreeRDPGetBytesPerPixel(format2);
+ const RECTANGLE_16 empty = { 0 };
+ WINPR_ASSERT(rect);
+
+ *rect = empty;
+
+ for (size_t ty = 0; ty < nrow; ty++)
{
- th = ((ty + 1) == nrow) ? (nHeight % 16) : 16;
+ BOOL rowEqual = TRUE;
+ size_t th = ((ty + 1) == nrow) ? (nHeight % 16) : 16;
if (!th)
th = 16;
- for (UINT32 tx = 0; tx < ncol; tx++)
+ for (size_t tx = 0; tx < ncol; tx++)
{
- equal = TRUE;
+ BOOL equal = TRUE;
tw = ((tx + 1) == ncol) ? (nWidth % 16) : 16;
if (!tw)
tw = 16;
- p1 = &pData1[(ty * 16 * nStep1) + (tx * 16 * 4)];
- p2 = &pData2[(ty * 16 * nStep2) + (tx * 16 * 4)];
+ const BYTE* p1 = &pData1[(ty * 16 * nStep1) + (tx * 16ull * bppA)];
+ const BYTE* p2 = &pData2[(ty * 16 * nStep2) + (tx * 16ull * bppB)];
- for (UINT32 k = 0; k < th; k++)
+ for (size_t k = 0; k < th; k++)
{
- if (memcmp(p1, p2, tw * 4) != 0)
+ if (!pixel_equal_fn(p1, format1, p2, format2, tw))
{
equal = FALSE;
break;
@@ -142,11 +234,7 @@ int shadow_capture_compare(BYTE* pData1, UINT32 nStep1, UINT32 nWidth, UINT32 nH
if (!equal)
{
- rows[ty] = FALSE;
-#ifdef WITH_DEBUG_SHADOW_CAPTURE
- cols[tx] = FALSE;
-#endif
-
+ rowEqual = FALSE;
if (l > tx)
l = tx;
@@ -155,7 +243,7 @@ int shadow_capture_compare(BYTE* pData1, UINT32 nStep1, UINT32 nWidth, UINT32 nH
}
}
- if (!rows[ty])
+ if (!rowEqual)
{
allEqual = FALSE;
@@ -187,46 +275,6 @@ int shadow_capture_compare(BYTE* pData1, UINT32 nStep1, UINT32 nWidth, UINT32 nH
if (rect->bottom > nHeight)
rect->bottom = (UINT16)nHeight;
-#ifdef WITH_DEBUG_SHADOW_CAPTURE
- size_t size = ncol + 1;
- char* col_str = calloc(size, sizeof(char));
-
- if (!col_str)
- {
- WLog_ERR(TAG, "calloc failed!");
- return 1;
- }
-
- for (UINT32 tx = 0; tx < ncol; tx++)
- sprintf_s(&col_str[tx], size - tx, "-");
-
- WLog_INFO(TAG, "%s", col_str);
-
- for (UINT32 tx = 0; tx < ncol; tx++)
- sprintf_s(&col_str[tx], size - tx, "%c", cols[tx] ? 'O' : 'X');
-
- WLog_INFO(TAG, "%s", col_str);
-
- for (UINT32 tx = 0; tx < ncol; tx++)
- sprintf_s(&col_str[tx], size - tx, "-");
-
- WLog_INFO(TAG, "%s", col_str);
-
- for (UINT32 ty = 0; ty < nrow; ty++)
- {
- for (UINT32 tx = 0; tx < ncol; tx++)
- sprintf_s(&col_str[tx], size - tx, "%c", cols[tx] ? 'O' : 'X');
-
- WLog_INFO(TAG, "%s", col_str);
- WLog_INFO(TAG, "|%s|", rows[ty] ? "O" : "X");
- }
-
- WLog_INFO(TAG,
- "left: %" PRIu32 " top: %" PRIu32 " right: %" PRIu32 " bottom: %" PRIu32
- " ncol: %" PRIu32 " nrow: %" PRIu32,
- l, t, r, b, ncol, nrow);
- free(col_str);
-#endif
return 1;
}
diff --git a/server/shadow/shadow_client.c b/server/shadow/shadow_client.c
index 0fd5236..f0b4dc4 100644
--- a/server/shadow/shadow_client.c
+++ b/server/shadow/shadow_client.c
@@ -252,7 +252,7 @@ static BOOL shadow_client_context_new(freerdp_peer* peer, rdpContext* context)
goto fail;
region16_init(&(client->invalidRegion));
- client->vcm = WTSOpenServerA(peer->context);
+ client->vcm = WTSOpenServerA((LPSTR)peer->context);
if (!client->vcm || client->vcm == INVALID_HANDLE_VALUE)
goto fail;
@@ -1444,7 +1444,6 @@ static BOOL shadow_client_send_surface_bits(rdpShadowClient* client, BYTE* pSrcD
const RFX_MESSAGE* msg = rfx_message_list_get(messages, i);
if (!rfx_write_message(encoder->rfx, s, msg))
{
- rfx_message_list_free(messages);
WLog_ERR(TAG, "rfx_write_message failed");
ret = FALSE;
break;
@@ -1982,7 +1981,10 @@ static INLINE BOOL shadow_client_no_surface_update(rdpShadowClient* client,
server = client->server;
WINPR_ASSERT(server);
surface = client->inLobby ? server->lobby : server->surface;
- return shadow_client_surface_update(client, &(surface->invalidRegion));
+ EnterCriticalSection(&surface->lock);
+ const BOOL rc = shadow_client_surface_update(client, &(surface->invalidRegion));
+ LeaveCriticalSection(&surface->lock);
+ return rc;
}
static int shadow_client_subsystem_process_message(rdpShadowClient* client, wMessage* message)
diff --git a/server/shadow/shadow_lobby.c b/server/shadow/shadow_lobby.c
index 8a9fade..f28408d 100644
--- a/server/shadow/shadow_lobby.c
+++ b/server/shadow/shadow_lobby.c
@@ -27,9 +27,9 @@
BOOL shadow_client_init_lobby(rdpShadowServer* server)
{
+ BOOL rc = FALSE;
int width = 0;
int height = 0;
- rdtkEngine* engine = NULL;
rdtkSurface* surface = NULL;
RECTANGLE_16 invalidRect;
rdpShadowSurface* lobby = server->lobby;
@@ -37,17 +37,14 @@ BOOL shadow_client_init_lobby(rdpShadowServer* server)
if (!lobby)
return FALSE;
- if (!(engine = rdtk_engine_new()))
- {
+ rdtkEngine* engine = rdtk_engine_new();
+ if (!engine)
return FALSE;
- }
- if (!(surface =
- rdtk_surface_new(engine, lobby->data, lobby->width, lobby->height, lobby->scanline)))
- {
- rdtk_engine_free(engine);
- return FALSE;
- }
+ EnterCriticalSection(&lobby->lock);
+ surface = rdtk_surface_new(engine, lobby->data, lobby->width, lobby->height, lobby->scanline);
+ if (!surface)
+ goto fail;
invalidRect.left = 0;
invalidRect.top = 0;
@@ -77,9 +74,11 @@ BOOL shadow_client_init_lobby(rdpShadowServer* server)
rdtk_surface_free(surface);
- rdtk_engine_free(engine);
-
region16_union_rect(&(lobby->invalidRegion), &(lobby->invalidRegion), &invalidRect);
- return TRUE;
+ rc = TRUE;
+fail:
+ LeaveCriticalSection(&lobby->lock);
+ rdtk_engine_free(engine);
+ return rc;
}
diff --git a/server/shadow/shadow_server.c b/server/shadow/shadow_server.c
index 067dcc6..751f460 100644
--- a/server/shadow/shadow_server.c
+++ b/server/shadow/shadow_server.c
@@ -55,6 +55,14 @@ static int shadow_server_print_command_line_help(int argc, char** argv,
printf("Usage: %s [options]\n", argv[0]);
printf("\n");
+ printf("Notes: By default NLA security is active.\n");
+ printf("\tIn this mode a SAM database is required.\n");
+ printf("\tProvide one with /sam-file:<file with path>\n");
+ printf("\telse the default path /etc/winpr/SAM is used.\n");
+ printf("\tIf there is no existing SAM file authentication for all users will fail.\n");
+ printf(
+ "\n\tIf authentication against PAM is desired, start with -sec-nla (requires compiled in "
+ "support for PAM)\n\n");
printf("Syntax:\n");
printf(" /flag (enables flag)\n");
printf(" /option:<value> (specifies option with value)\n");
diff --git a/server/shadow/shadow_subsystem.c b/server/shadow/shadow_subsystem.c
index ca73c72..bbdb568 100644
--- a/server/shadow/shadow_subsystem.c
+++ b/server/shadow/shadow_subsystem.c
@@ -190,20 +190,23 @@ UINT32 shadow_enum_monitors(MONITOR_DEF* monitors, UINT32 maxMonitors)
* Caller should free the andMaskData and xorMaskData later.
*/
int shadow_subsystem_pointer_convert_alpha_pointer_data(
- BYTE* pixels, BOOL premultiplied, UINT32 width, UINT32 height,
+ const BYTE* WINPR_RESTRICT pixels, BOOL premultiplied, UINT32 width, UINT32 height,
+ SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* WINPR_RESTRICT pointerColor)
+{
+ return shadow_subsystem_pointer_convert_alpha_pointer_data_to_format(
+ pixels, PIXEL_FORMAT_BGRX32, premultiplied, width, height, pointerColor);
+}
+
+int shadow_subsystem_pointer_convert_alpha_pointer_data_to_format(
+ const BYTE* pixels, UINT32 format, BOOL premultiplied, UINT32 width, UINT32 height,
SHADOW_MSG_OUT_POINTER_ALPHA_UPDATE* pointerColor)
{
- BYTE* pSrc8 = NULL;
- BYTE* pDst8 = NULL;
UINT32 xorStep = 0;
UINT32 andStep = 0;
UINT32 andBit = 0;
BYTE* andBits = NULL;
UINT32 andPixel = 0;
- BYTE A = 0;
- BYTE R = 0;
- BYTE G = 0;
- BYTE B = 0;
+ const size_t bpp = FreeRDPGetBytesPerPixel(format);
xorStep = (width * 3);
xorStep += (xorStep % 2);
@@ -227,20 +230,23 @@ int shadow_subsystem_pointer_convert_alpha_pointer_data(
return -1;
}
- for (UINT32 y = 0; y < height; y++)
+ for (size_t y = 0; y < height; y++)
{
- pSrc8 = &pixels[(width * 4) * (height - 1 - y)];
- pDst8 = &(pointerColor->xorMaskData[y * xorStep]);
+ const BYTE* pSrc8 = &pixels[(width * bpp) * (height - 1 - y)];
+ BYTE* pDst8 = &(pointerColor->xorMaskData[y * xorStep]);
andBit = 0x80;
andBits = &(pointerColor->andMaskData[andStep * y]);
- for (UINT32 x = 0; x < width; x++)
+ for (size_t x = 0; x < width; x++)
{
- B = *pSrc8++;
- G = *pSrc8++;
- R = *pSrc8++;
- A = *pSrc8++;
+ BYTE B = 0;
+ BYTE G = 0;
+ BYTE R = 0;
+ BYTE A = 0;
+
+ const UINT32 color = FreeRDPReadColor(&pSrc8[x * bpp], format);
+ FreeRDPSplitColor(color, format, &R, &G, &B, &A, NULL);
andPixel = 0;
diff --git a/uwac/libuwac/uwac-input.c b/uwac/libuwac/uwac-input.c
index 5ad52ae..b11b1a4 100644
--- a/uwac/libuwac/uwac-input.c
+++ b/uwac/libuwac/uwac-input.c
@@ -818,6 +818,8 @@ static void pointer_handle_motion(void* data, struct wl_pointer* pointer, uint32
assert(input);
UwacWindow* window = input->pointer_focus;
+ if (!window || !window->display)
+ return;
int scale = window->display->actual_scale;
int sx_i = wl_fixed_to_int(sx_w) * scale;
@@ -825,7 +827,7 @@ static void pointer_handle_motion(void* data, struct wl_pointer* pointer, uint32
double sx_d = wl_fixed_to_double(sx_w) * scale;
double sy_d = wl_fixed_to_double(sy_w) * scale;
- if (!window || (sx_i < 0) || (sy_i < 0))
+ if ((sx_i < 0) || (sy_i < 0))
return;
input->sx = sx_d;
diff --git a/uwac/libuwac/uwac-window.c b/uwac/libuwac/uwac-window.c
index 49728bd..90669aa 100644
--- a/uwac/libuwac/uwac-window.c
+++ b/uwac/libuwac/uwac-window.c
@@ -379,6 +379,8 @@ int UwacWindowShmAllocBuffers(UwacWindow* w, int nbuffers, int allocSize, uint32
wl_shm_pool_destroy(pool);
w->nbuffers += nbuffers;
+ munmap(data, 1ull * allocSize * nbuffers);
+
error_mmap:
close(fd);
return ret;
diff --git a/winpr/CMakeLists.txt b/winpr/CMakeLists.txt
index c21668f..f06aaf7 100644
--- a/winpr/CMakeLists.txt
+++ b/winpr/CMakeLists.txt
@@ -137,7 +137,7 @@ endif()
# Soname versioning
set(VERSION_REGEX "^(.*)([0-9]+)\\.([0-9]+)\\.([0-9]+)-?(.*)")
-set(RAW_VERSION_STRING "3.3.0")
+set(RAW_VERSION_STRING "3.5.0")
if(EXISTS "${PROJECT_SOURCE_DIR}/.source_tag")
file(READ ${PROJECT_SOURCE_DIR}/.source_tag RAW_VERSION_STRING)
elseif(USE_VERSION_FROM_GIT_TAG)
@@ -323,11 +323,6 @@ endif()
add_definitions(-DWINPR_EXPORTS)
-# Enable 64bit file support on linux and FreeBSD.
-if("${CMAKE_SYSTEM_NAME}" MATCHES "Linux" OR FREEBSD)
- add_definitions("-D_FILE_OFFSET_BITS=64")
-endif()
-
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include)
@@ -346,12 +341,7 @@ endif()
add_subdirectory(include)
-set(MANPAGE_NAME wlog)
-if (WITH_BINARY_VERSIONING)
- set(MANPAGE_NAME wlog${WINPR_API_VERSION})
-endif()
-configure_file(wlog.7.in ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE_NAME}.7 @ONLY)
-install_freerdp_man(${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE_NAME}.7 7)
+generate_and_install_freerdp_man_from_template("wlog" "7" "${WINPR_API_VERSION}")
# Exporting
export(PACKAGE winpr)
diff --git a/winpr/include/winpr/comm.h b/winpr/include/winpr/comm.h
index 9eb535c..2dbc4fd 100644
--- a/winpr/include/winpr/comm.h
+++ b/winpr/include/winpr/comm.h
@@ -25,8 +25,6 @@
#include <winpr/collections.h>
#include <winpr/file.h>
-#include <winpr/winpr.h>
-#include <winpr/wtypes.h>
#if defined __linux__ && !defined ANDROID
@@ -392,6 +390,7 @@ extern "C"
* also ensures that CommCreateFileA() has been registered through
* RegisterHandleCreator().
*/
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CommCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
diff --git a/winpr/include/winpr/crt.h b/winpr/include/winpr/crt.h
index 6c155ee..f42c953 100644
--- a/winpr/include/winpr/crt.h
+++ b/winpr/include/winpr/crt.h
@@ -190,27 +190,34 @@ extern "C"
{
#endif
+ WINPR_API void winpr_aligned_free(void* memblock);
+
+ WINPR_ATTR_MALLOC(winpr_aligned_free, 1)
WINPR_API void* winpr_aligned_malloc(size_t size, size_t alignment);
+ WINPR_ATTR_MALLOC(winpr_aligned_free, 1)
WINPR_API void* winpr_aligned_calloc(size_t count, size_t size, size_t alignment);
+ WINPR_ATTR_MALLOC(winpr_aligned_free, 1)
WINPR_API void* winpr_aligned_realloc(void* memblock, size_t size, size_t alignment);
+ WINPR_ATTR_MALLOC(winpr_aligned_free, 1)
WINPR_API void* winpr_aligned_recalloc(void* memblock, size_t num, size_t size,
size_t alignment);
+ WINPR_ATTR_MALLOC(winpr_aligned_free, 1)
WINPR_API void* winpr_aligned_offset_malloc(size_t size, size_t alignment, size_t offset);
+ WINPR_ATTR_MALLOC(winpr_aligned_free, 1)
WINPR_API void* winpr_aligned_offset_realloc(void* memblock, size_t size, size_t alignment,
size_t offset);
+ WINPR_ATTR_MALLOC(winpr_aligned_free, 1)
WINPR_API void* winpr_aligned_offset_recalloc(void* memblock, size_t num, size_t size,
size_t alignment, size_t offset);
WINPR_API size_t winpr_aligned_msize(void* memblock, size_t alignment, size_t offset);
- WINPR_API void winpr_aligned_free(void* memblock);
-
#ifdef __cplusplus
}
#endif
diff --git a/winpr/include/winpr/environment.h b/winpr/include/winpr/environment.h
index f530d59..c963f8c 100644
--- a/winpr/include/winpr/environment.h
+++ b/winpr/include/winpr/environment.h
@@ -87,7 +87,13 @@ extern "C"
* http://blogs.msdn.com/b/oldnewthing/archive/2013/01/17/10385718.aspx
*/
+ WINPR_API BOOL FreeEnvironmentStringsA(LPCH lpszEnvironmentBlock);
+ WINPR_API BOOL FreeEnvironmentStringsW(LPWCH lpszEnvironmentBlock);
+
+ WINPR_ATTR_MALLOC(FreeEnvironmentStringsA, 1)
WINPR_API LPCH GetEnvironmentStrings(VOID);
+
+ WINPR_ATTR_MALLOC(FreeEnvironmentStringsW, 1)
WINPR_API LPWCH GetEnvironmentStringsW(VOID);
WINPR_API BOOL SetEnvironmentStringsA(LPCH NewEnvironment);
@@ -96,9 +102,6 @@ extern "C"
WINPR_API DWORD ExpandEnvironmentStringsA(LPCSTR lpSrc, LPSTR lpDst, DWORD nSize);
WINPR_API DWORD ExpandEnvironmentStringsW(LPCWSTR lpSrc, LPWSTR lpDst, DWORD nSize);
- WINPR_API BOOL FreeEnvironmentStringsA(LPCH lpszEnvironmentBlock);
- WINPR_API BOOL FreeEnvironmentStringsW(LPWCH lpszEnvironmentBlock);
-
#ifdef __cplusplus
}
#endif
diff --git a/winpr/include/winpr/file.h b/winpr/include/winpr/file.h
index c455d74..09aa2c2 100644
--- a/winpr/include/winpr/file.h
+++ b/winpr/include/winpr/file.h
@@ -27,6 +27,7 @@
#include <winpr/nt.h>
#include <winpr/io.h>
#include <winpr/error.h>
+#include <winpr/handle.h>
#ifndef _WIN32
@@ -262,11 +263,13 @@ extern "C"
{
#endif
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
@@ -359,12 +362,20 @@ extern "C"
WINPR_API BOOL SetFileTime(HANDLE hFile, const FILETIME* lpCreationTime,
const FILETIME* lpLastAccessTime, const FILETIME* lpLastWriteTime);
+ WINPR_API BOOL FindClose(HANDLE hFindFile);
+
+ WINPR_ATTR_MALLOC(FindClose, 1)
WINPR_API HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData);
+
+ WINPR_ATTR_MALLOC(FindClose, 1)
WINPR_API HANDLE FindFirstFileW(LPCWSTR lpFileName, LPWIN32_FIND_DATAW lpFindFileData);
+ WINPR_ATTR_MALLOC(FindClose, 1)
WINPR_API HANDLE FindFirstFileExA(LPCSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId,
LPVOID lpFindFileData, FINDEX_SEARCH_OPS fSearchOp,
LPVOID lpSearchFilter, DWORD dwAdditionalFlags);
+
+ WINPR_ATTR_MALLOC(FindClose, 1)
WINPR_API HANDLE FindFirstFileExW(LPCWSTR lpFileName, FINDEX_INFO_LEVELS fInfoLevelId,
LPVOID lpFindFileData, FINDEX_SEARCH_OPS fSearchOp,
LPVOID lpSearchFilter, DWORD dwAdditionalFlags);
@@ -372,8 +383,6 @@ extern "C"
WINPR_API BOOL FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData);
WINPR_API BOOL FindNextFileW(HANDLE hFindFile, LPWIN32_FIND_DATAW lpFindFileData);
- WINPR_API BOOL FindClose(HANDLE hFindFile);
-
WINPR_API BOOL CreateDirectoryA(LPCSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
WINPR_API BOOL CreateDirectoryW(LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
diff --git a/winpr/include/winpr/intrin.h b/winpr/include/winpr/intrin.h
index 066f45f..0e61d4d 100644
--- a/winpr/include/winpr/intrin.h
+++ b/winpr/include/winpr/intrin.h
@@ -22,7 +22,7 @@
#ifndef WINPR_INTRIN_H
#define WINPR_INTRIN_H
-#if !defined(_WIN32) || defined(__MINGW32__)
+#if !defined(_WIN32) || defined(__MINGW32__) || defined(_M_ARM64)
/**
* __lzcnt16, __lzcnt, __lzcnt64:
diff --git a/winpr/include/winpr/io.h b/winpr/include/winpr/io.h
index 2a0e34c..2df2316 100644
--- a/winpr/include/winpr/io.h
+++ b/winpr/include/winpr/io.h
@@ -22,6 +22,7 @@
#include <winpr/winpr.h>
#include <winpr/wtypes.h>
+#include <winpr/handle.h>
#ifdef _WIN32
@@ -71,6 +72,7 @@ extern "C"
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped);
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateIoCompletionPort(HANDLE FileHandle, HANDLE ExistingCompletionPort,
ULONG_PTR CompletionKey,
DWORD NumberOfConcurrentThreads);
diff --git a/winpr/include/winpr/memory.h b/winpr/include/winpr/memory.h
index 850d6b2..09f83bd 100644
--- a/winpr/include/winpr/memory.h
+++ b/winpr/include/winpr/memory.h
@@ -37,14 +37,20 @@ extern "C"
{
#endif
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateFileMappingA(HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes,
DWORD flProtect, DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow, LPCSTR lpName);
+
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateFileMappingW(HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes,
DWORD flProtect, DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow, LPCWSTR lpName);
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE OpenFileMappingA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName);
+
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE OpenFileMappingW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName);
WINPR_API LPVOID MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess,
diff --git a/winpr/include/winpr/pipe.h b/winpr/include/winpr/pipe.h
index 932fda5..a31d5eb 100644
--- a/winpr/include/winpr/pipe.h
+++ b/winpr/include/winpr/pipe.h
@@ -73,10 +73,13 @@ extern "C"
* Named pipe
*/
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateNamedPipeA(LPCSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode,
DWORD nMaxInstances, DWORD nOutBufferSize,
DWORD nInBufferSize, DWORD nDefaultTimeOut,
LPSECURITY_ATTRIBUTES lpSecurityAttributes);
+
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateNamedPipeW(LPCWSTR lpName, DWORD dwOpenMode, DWORD dwPipeMode,
DWORD nMaxInstances, DWORD nOutBufferSize,
DWORD nInBufferSize, DWORD nDefaultTimeOut,
diff --git a/winpr/include/winpr/pool.h b/winpr/include/winpr/pool.h
index 3160ae3..efc467c 100644
--- a/winpr/include/winpr/pool.h
+++ b/winpr/include/winpr/pool.h
@@ -110,7 +110,7 @@ typedef VOID (*PTP_WIN32_IO_CALLBACK)(PTP_CALLBACK_INSTANCE Instance, PVOID Cont
#define WINPR_THREAD_POOL 1
#elif defined(_WIN32) && (_WIN32_WINNT < 0x0600)
#define WINPR_THREAD_POOL 1
-#elif defined(__MINGW32__) && (__MINGW64_VERSION_MAJOR < 8)
+#elif defined(__MINGW32__) && (__MINGW64_VERSION_MAJOR < 7)
#define WINPR_THREAD_POOL 1
#endif
diff --git a/winpr/include/winpr/synch.h b/winpr/include/winpr/synch.h
index b310a3b..c59c979 100644
--- a/winpr/include/winpr/synch.h
+++ b/winpr/include/winpr/synch.h
@@ -44,17 +44,26 @@ extern "C"
/* Mutex */
#define CREATE_MUTEX_INITIAL_OWNER 0x00000001
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateMutexA(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner,
LPCSTR lpName);
+
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateMutexW(LPSECURITY_ATTRIBUTES lpMutexAttributes, BOOL bInitialOwner,
LPCWSTR lpName);
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateMutexExA(LPSECURITY_ATTRIBUTES lpMutexAttributes, LPCSTR lpName,
DWORD dwFlags, DWORD dwDesiredAccess);
+
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateMutexExW(LPSECURITY_ATTRIBUTES lpMutexAttributes, LPCWSTR lpName,
DWORD dwFlags, DWORD dwDesiredAccess);
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE OpenMutexA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName);
+
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE OpenMutexW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName);
WINPR_API BOOL ReleaseMutex(HANDLE hMutex);
@@ -71,12 +80,18 @@ extern "C"
/* Semaphore */
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateSemaphoreA(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount, LONG lMaximumCount, LPCSTR lpName);
+
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateSemaphoreW(LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount, LONG lMaximumCount, LPCWSTR lpName);
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE OpenSemaphoreA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName);
+
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE OpenSemaphoreW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName);
#ifdef UNICODE
@@ -93,17 +108,26 @@ extern "C"
#define CREATE_EVENT_MANUAL_RESET 0x00000001
#define CREATE_EVENT_INITIAL_SET 0x00000002
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateEventA(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset,
BOOL bInitialState, LPCSTR lpName);
+
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateEventW(LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset,
BOOL bInitialState, LPCWSTR lpName);
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateEventExA(LPSECURITY_ATTRIBUTES lpEventAttributes, LPCSTR lpName,
DWORD dwFlags, DWORD dwDesiredAccess);
+
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateEventExW(LPSECURITY_ATTRIBUTES lpEventAttributes, LPCWSTR lpName,
DWORD dwFlags, DWORD dwDesiredAccess);
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE OpenEventA(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName);
+
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE OpenEventW(DWORD dwDesiredAccess, BOOL bInheritHandle, LPCWSTR lpName);
WINPR_API BOOL SetEvent(HANDLE hEvent);
@@ -225,14 +249,20 @@ extern "C"
typedef VOID (*PTIMERAPCROUTINE)(LPVOID lpArgToCompletionRoutine, DWORD dwTimerLowValue,
DWORD dwTimerHighValue);
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateWaitableTimerA(LPSECURITY_ATTRIBUTES lpTimerAttributes,
BOOL bManualReset, LPCSTR lpTimerName);
+
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateWaitableTimerW(LPSECURITY_ATTRIBUTES lpTimerAttributes,
BOOL bManualReset, LPCWSTR lpTimerName);
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateWaitableTimerExA(LPSECURITY_ATTRIBUTES lpTimerAttributes,
LPCSTR lpTimerName, DWORD dwFlags,
DWORD dwDesiredAccess);
+
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateWaitableTimerExW(LPSECURITY_ATTRIBUTES lpTimerAttributes,
LPCWSTR lpTimerName, DWORD dwFlags,
DWORD dwDesiredAccess);
@@ -246,8 +276,11 @@ extern "C"
LPVOID lpArgToCompletionRoutine, PREASON_CONTEXT WakeContext,
ULONG TolerableDelay);
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE OpenWaitableTimerA(DWORD dwDesiredAccess, BOOL bInheritHandle,
LPCSTR lpTimerName);
+
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE OpenWaitableTimerW(DWORD dwDesiredAccess, BOOL bInheritHandle,
LPCWSTR lpTimerName);
@@ -282,7 +315,9 @@ extern "C"
typedef VOID (*WAITORTIMERCALLBACK)(PVOID lpParameter, BOOLEAN TimerOrWaitFired);
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateTimerQueue(void);
+
WINPR_API BOOL DeleteTimerQueue(HANDLE TimerQueue);
WINPR_API BOOL DeleteTimerQueueEx(HANDLE TimerQueue, HANDLE CompletionEvent);
@@ -395,13 +430,17 @@ extern "C"
WINPR_API VOID USleep(DWORD dwMicroseconds);
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateFileDescriptorEventW(LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset, BOOL bInitialState,
int FileDescriptor, ULONG mode);
+
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateFileDescriptorEventA(LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset, BOOL bInitialState,
int FileDescriptor, ULONG mode);
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateWaitObjectEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset, BOOL bInitialState, void* pObject);
diff --git a/winpr/include/winpr/sysinfo.h b/winpr/include/winpr/sysinfo.h
index d7d6dd8..61fadc3 100644
--- a/winpr/include/winpr/sysinfo.h
+++ b/winpr/include/winpr/sysinfo.h
@@ -322,6 +322,17 @@ extern "C"
#endif
+#define WINPR_TIME_NS_TO_S(ns) ((ns) / 1000000000ull)
+#define WINPR_TIME_NS_TO_MS(ns) ((ns) / 1000000ull)
+#define WINPR_TIME_NS_TO_US(ns) ((ns) / 1000ull)
+
+#define WINPR_TIME_NS_REM_NS(ns) ((ns) % 1000000000ull)
+#define WINPR_TIME_NS_REM_US(ns) (WINPR_TIME_NS_REM_NS(ns) / 1000ull)
+#define WINPR_TIME_NS_REM_MS(ns) (WINPR_TIME_NS_REM_US(ns) / 1000ull)
+
+ WINPR_API UINT64 winpr_GetTickCount64NS(void);
+ WINPR_API UINT64 winpr_GetUnixTimeNS(void);
+
WINPR_API DWORD GetTickCountPrecise(void);
WINPR_API BOOL IsProcessorFeaturePresentEx(DWORD ProcessorFeature);
diff --git a/winpr/include/winpr/thread.h b/winpr/include/winpr/thread.h
index 2f17603..b0bad74 100644
--- a/winpr/include/winpr/thread.h
+++ b/winpr/include/winpr/thread.h
@@ -198,10 +198,12 @@ extern "C"
#define CREATE_SUSPENDED 0x00000004
#define STACK_SIZE_PARAM_IS_A_RESERVATION 0x00010000
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter,
DWORD dwCreationFlags, LPDWORD lpThreadId);
+ WINPR_ATTR_MALLOC(CloseHandle, 1)
WINPR_API HANDLE CreateRemoteThread(HANDLE hProcess, LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter, DWORD dwCreationFlags,
diff --git a/winpr/include/winpr/winpr.h b/winpr/include/winpr/winpr.h
index 04311d8..a429c7a 100644
--- a/winpr/include/winpr/winpr.h
+++ b/winpr/include/winpr/winpr.h
@@ -119,6 +119,16 @@
#define INLINE inline
#endif
+#if defined(__GNUC__) || defined(__clang__)
+#define WINPR_ALIGN64 __attribute__((aligned(8)))
+#else
+#ifdef _WIN32
+#define WINPR_ALIGN64 __declspec(align(8))
+#else
+#define WINPR_ALIGN64
+#endif
+#endif
+
WINPR_API void winpr_get_version(int* major, int* minor, int* revision);
WINPR_API const char* winpr_get_version_string(void);
WINPR_API const char* winpr_get_build_revision(void);
diff --git a/winpr/include/winpr/winsock.h b/winpr/include/winpr/winsock.h
index 73dc9ae..dbf8462 100644
--- a/winpr/include/winpr/winsock.h
+++ b/winpr/include/winpr/winsock.h
@@ -297,10 +297,12 @@ extern "C"
WINPR_API void WSASetLastError(int iError);
WINPR_API int WSAGetLastError(void);
+ WINPR_API BOOL WSACloseEvent(HANDLE hEvent);
+
+ WINPR_ATTR_MALLOC(WSACloseEvent, 1)
WINPR_API HANDLE WSACreateEvent(void);
WINPR_API BOOL WSASetEvent(HANDLE hEvent);
WINPR_API BOOL WSAResetEvent(HANDLE hEvent);
- WINPR_API BOOL WSACloseEvent(HANDLE hEvent);
WINPR_API int WSAEventSelect(SOCKET s, WSAEVENT hEventObject, LONG lNetworkEvents);
diff --git a/winpr/include/winpr/wtsapi.h b/winpr/include/winpr/wtsapi.h
index bd5616f..9902ffe 100644
--- a/winpr/include/winpr/wtsapi.h
+++ b/winpr/include/winpr/wtsapi.h
@@ -1002,13 +1002,19 @@ extern "C"
WINPR_API BOOL WINAPI WTSEnumerateServersA(LPSTR pDomainName, DWORD Reserved, DWORD Version,
PWTS_SERVER_INFOA* ppServerInfo, DWORD* pCount);
+ WINPR_API VOID WINAPI WTSCloseServer(HANDLE hServer);
+
+ WINPR_ATTR_MALLOC(WTSCloseServer, 1)
WINPR_API HANDLE WINAPI WTSOpenServerW(LPWSTR pServerName);
+
+ WINPR_ATTR_MALLOC(WTSCloseServer, 1)
WINPR_API HANDLE WINAPI WTSOpenServerA(LPSTR pServerName);
+ WINPR_ATTR_MALLOC(WTSCloseServer, 1)
WINPR_API HANDLE WINAPI WTSOpenServerExW(LPWSTR pServerName);
- WINPR_API HANDLE WINAPI WTSOpenServerExA(LPSTR pServerName);
- WINPR_API VOID WINAPI WTSCloseServer(HANDLE hServer);
+ WINPR_ATTR_MALLOC(WTSCloseServer, 1)
+ WINPR_API HANDLE WINAPI WTSOpenServerExA(LPSTR pServerName);
WINPR_API BOOL WINAPI WTSEnumerateSessionsW(HANDLE hServer, DWORD Reserved, DWORD Version,
PWTS_SESSION_INFOW* ppSessionInfo, DWORD* pCount);
diff --git a/winpr/libwinpr/CMakeLists.txt b/winpr/libwinpr/CMakeLists.txt
index 4be2015..1c85d37 100644
--- a/winpr/libwinpr/CMakeLists.txt
+++ b/winpr/libwinpr/CMakeLists.txt
@@ -157,36 +157,13 @@ list(REMOVE_DUPLICATES WINPR_DEFINITIONS)
list(REMOVE_DUPLICATES WINPR_COMPILE_OPTIONS)
list(REMOVE_DUPLICATES WINPR_LINK_OPTIONS)
list(REMOVE_DUPLICATES WINPR_LINK_DIRS)
-list(REMOVE_DUPLICATES WINPR_LIBS_PRIVATE)
-list(REMOVE_DUPLICATES WINPR_LIBS_PUBLIC)
list(REMOVE_DUPLICATES WINPR_INCLUDES)
-# On windows create dll version information.
-# Vendor, product and year are already set in top level CMakeLists.txt
-if (WIN32)
- set (RC_VERSION_MAJOR ${WINPR_VERSION_MAJOR})
- set (RC_VERSION_MINOR ${WINPR_VERSION_MINOR})
- set (RC_VERSION_BUILD ${WINPR_VERSION_REVISION})
- set (RC_VERSION_FILE "${CMAKE_SHARED_LIBRARY_PREFIX}${MODULE_NAME}${WINPR_API_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}" )
-
- configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
- set (WINPR_SRCS ${WINPR_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
- winpr_library_add_public("shlwapi")
-endif()
+AddTargetWithResourceFile(${MODULE_NAME} FALSE "${WINPR_VERSION}" WINPR_SRCS)
-add_library(${MODULE_NAME} ${WINPR_SRCS})
if (APPLE)
set_target_properties(${MODULE_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION FALSE)
endif()
-set_target_properties(${MODULE_NAME} PROPERTIES LINKER_LANGUAGE C)
-set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME ${MODULE_NAME}${WINPR_API_VERSION})
-if (WITH_LIBRARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_VERSION} SOVERSION ${WINPR_API_VERSION})
-endif()
if (NOT BUILD_SHARED_LIBS)
set(LINK_OPTS_MODE PUBLIC)
@@ -206,8 +183,4 @@ install(TARGETS ${MODULE_NAME} COMPONENT libraries EXPORT WinPRTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-if (WITH_DEBUG_SYMBOLS AND MSVC AND BUILD_SHARED_LIBS)
- get_target_property(OUTPUT_FILENAME ${MODULE_NAME} OUTPUT_NAME)
- install(FILES ${CMAKE_PDB_BINARY_DIR}/${OUTPUT_FILENAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT symbols)
-endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/libwinpr")
diff --git a/winpr/libwinpr/clipboard/synthetic_file.c b/winpr/libwinpr/clipboard/synthetic_file.c
index 1421980..9a1084b 100644
--- a/winpr/libwinpr/clipboard/synthetic_file.c
+++ b/winpr/libwinpr/clipboard/synthetic_file.c
@@ -276,8 +276,14 @@ static BOOL add_directory_contents_to_list(wClipboard* clipboard, const WCHAR* l
const WCHAR* remote_name, wArrayList* files)
{
BOOL result = FALSE;
- const WCHAR* wildcard = "/\0*\0\0\0";
- const size_t wildcardLen = 3;
+ union
+ {
+ const char* c;
+ const WCHAR* w;
+ } wildcard;
+ const char buffer[6] = "/\0*\0\0\0";
+ wildcard.c = buffer;
+ const size_t wildcardLen = ARRAYSIZE(buffer) / sizeof(WCHAR);
WINPR_ASSERT(clipboard);
WINPR_ASSERT(local_name);
@@ -290,7 +296,7 @@ static BOOL add_directory_contents_to_list(wClipboard* clipboard, const WCHAR* l
return FALSE;
_wcsncat(namebuf, local_name, len);
- _wcsncat(namebuf, wildcard, wildcardLen);
+ _wcsncat(namebuf, wildcard.w, wildcardLen);
result = do_add_directory_contents_to_list(clipboard, local_name, remote_name, namebuf, files);
@@ -1079,7 +1085,6 @@ static UINT file_get_range(struct synthetic_file* file, UINT64 offset, UINT32 si
UINT error = NO_ERROR;
DWORD dwLow = 0;
DWORD dwHigh = 0;
- BYTE* buffer = NULL;
WINPR_ASSERT(file);
WINPR_ASSERT(actual_data);
@@ -1150,7 +1155,7 @@ static UINT file_get_range(struct synthetic_file* file, UINT64 offset, UINT32 si
}
}
- buffer = malloc(size);
+ BYTE* buffer = malloc(size);
if (!buffer)
{
error = ERROR_NOT_ENOUGH_MEMORY;
@@ -1158,6 +1163,7 @@ static UINT file_get_range(struct synthetic_file* file, UINT64 offset, UINT32 si
}
if (!ReadFile(file->fd, buffer, size, (LPDWORD)actual_size, NULL))
{
+ free(buffer);
error = GetLastError();
break;
}
@@ -1168,10 +1174,6 @@ static UINT file_get_range(struct synthetic_file* file, UINT64 offset, UINT32 si
*actual_size, file->offset);
} while (0);
- if (NO_ERROR != error)
- {
- free(buffer);
- }
synthetic_file_read_close(file, TRUE /* (error != NO_ERROR) && (size > 0) */);
return error;
}
diff --git a/winpr/libwinpr/comm/comm.c b/winpr/libwinpr/comm/comm.c
index c4e828e..cd68a40 100644
--- a/winpr/libwinpr/comm/comm.c
+++ b/winpr/libwinpr/comm/comm.c
@@ -1164,10 +1164,10 @@ HANDLE CommCreateFileA(LPCSTR lpDeviceName, DWORD dwDesiredAccess, DWORD dwShare
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
{
- CHAR devicePath[MAX_PATH];
- struct stat deviceStat;
+ CHAR devicePath[MAX_PATH] = { 0 };
+ struct stat deviceStat = { 0 };
WINPR_COMM* pComm = NULL;
- struct termios upcomingTermios;
+ struct termios upcomingTermios = { 0 };
if (!CommInitialized())
return INVALID_HANDLE_VALUE;
diff --git a/winpr/libwinpr/comm/comm_io.c b/winpr/libwinpr/comm/comm_io.c
index 9904eab..a89c452 100644
--- a/winpr/libwinpr/comm/comm_io.c
+++ b/winpr/libwinpr/comm/comm_io.c
@@ -186,8 +186,8 @@ BOOL CommReadFile(HANDLE hDevice, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
else
{
/* Tmax */
- Tmax = nNumberOfBytesToRead * pTimeouts->ReadTotalTimeoutMultiplier +
- pTimeouts->ReadTotalTimeoutConstant;
+ Tmax = 1ull * nNumberOfBytesToRead * pTimeouts->ReadTotalTimeoutMultiplier +
+ 1ull * pTimeouts->ReadTotalTimeoutConstant;
/* INDEFinitely */
if ((Tmax == 0) && (pTimeouts->ReadIntervalTimeout < MAXULONG) &&
@@ -398,8 +398,8 @@ BOOL CommWriteFile(HANDLE hDevice, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite
/* discard a possible and no more relevant event */
eventfd_read(pComm->fd_write_event, NULL);
/* ms */
- ULONGLONG Tmax = nNumberOfBytesToWrite * pComm->timeouts.WriteTotalTimeoutMultiplier +
- pComm->timeouts.WriteTotalTimeoutConstant;
+ ULONGLONG Tmax = 1ull * nNumberOfBytesToWrite * pComm->timeouts.WriteTotalTimeoutMultiplier +
+ 1ull * pComm->timeouts.WriteTotalTimeoutConstant;
/* NB: select() may update the timeout argument to indicate
* how much time was left. Keep the timeout variable out of
* the while() */
diff --git a/winpr/libwinpr/comm/comm_serial_sys.c b/winpr/libwinpr/comm/comm_serial_sys.c
index cae653c..185f017 100644
--- a/winpr/libwinpr/comm/comm_serial_sys.c
+++ b/winpr/libwinpr/comm/comm_serial_sys.c
@@ -1027,15 +1027,27 @@ static const ULONG _SERIAL_SYS_SUPPORTED_EV_MASK =
SERIAL_EV_EVENT2*/
;
+static BOOL is_wait_set(WINPR_COMM* pComm)
+{
+ WINPR_ASSERT(pComm);
+
+ EnterCriticalSection(&pComm->EventsLock);
+ const BOOL isWaiting = (pComm->PendingEvents & SERIAL_EV_WINPR_WAITING) != 0;
+ LeaveCriticalSection(&pComm->EventsLock);
+ return isWaiting;
+}
+
static BOOL _set_wait_mask(WINPR_COMM* pComm, const ULONG* pWaitMask)
{
ULONG possibleMask = 0;
+ WINPR_ASSERT(pComm);
+ WINPR_ASSERT(pWaitMask);
+
/* Stops pending IOCTL_SERIAL_WAIT_ON_MASK
* http://msdn.microsoft.com/en-us/library/ff546805%28v=vs.85%29.aspx
*/
-
- if (pComm->PendingEvents & SERIAL_EV_WINPR_WAITING)
+ if (is_wait_set(pComm))
{
/* FIXME: any doubt on reading PendingEvents out of a critical section? */
@@ -1044,7 +1056,7 @@ static BOOL _set_wait_mask(WINPR_COMM* pComm, const ULONG* pWaitMask)
LeaveCriticalSection(&pComm->EventsLock);
/* waiting the end of the pending _wait_on_mask() */
- while (pComm->PendingEvents & SERIAL_EV_WINPR_WAITING)
+ while (is_wait_set(pComm))
Sleep(10); /* 10ms */
}
diff --git a/winpr/libwinpr/crt/alignment.c b/winpr/libwinpr/crt/alignment.c
index e313c2d..71dd0e0 100644
--- a/winpr/libwinpr/crt/alignment.c
+++ b/winpr/libwinpr/crt/alignment.c
@@ -36,14 +36,6 @@
#include <stdlib.h>
-#if defined(__APPLE__)
-#include <malloc/malloc.h>
-#elif defined(__FreeBSD__) || defined(__OpenBSD__)
-#include <stdlib.h>
-#else
-#include <malloc.h>
-#endif
-
#include "../log.h"
#define TAG WINPR_TAG("crt")
@@ -108,7 +100,7 @@ void* winpr_aligned_offset_malloc(size_t size, size_t alignment, size_t offset)
/* malloc size + alignment to make sure we can align afterwards */
#if defined(_ISOC11_SOURCE)
base = aligned_alloc(alignment, alignsize);
-#elif _POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600
+#elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200112L) || (_XOPEN_SOURCE >= 600)
if (posix_memalign(&base, alignment, alignsize) != 0)
return NULL;
#else
diff --git a/winpr/libwinpr/crt/test/TestUnicodeConversion.c b/winpr/libwinpr/crt/test/TestUnicodeConversion.c
index a5c4c75..187a068 100644
--- a/winpr/libwinpr/crt/test/TestUnicodeConversion.c
+++ b/winpr/libwinpr/crt/test/TestUnicodeConversion.c
@@ -24,10 +24,12 @@ typedef struct
// TODO: The unit tests do not check for valid code points, so always end the test
// strings with a simple ASCII symbol for now.
static const testcase_t unit_testcases[] = {
- { "foo", 3, "f\x00o\x00o\x00\x00\x00", 3 },
- { "foo", 4, "f\x00o\x00o\x00\x00\x00", 4 },
+ { "foo", 3, (const WCHAR*)"f\x00o\x00o\x00\x00\x00", 3 },
+ { "foo", 4, (const WCHAR*)"f\x00o\x00o\x00\x00\x00", 4 },
{ "✊🎅ęʥ꣸𑗊a", 19,
- "\x0a\x27\x3c\xd8\x85\xdf\x19\x01\xa5\x02\xf8\xa8\x05\xd8\xca\xdd\x61\x00\x00\x00", 9 }
+ (const WCHAR*)"\x0a\x27\x3c\xd8\x85\xdf\x19\x01\xa5\x02\xf8\xa8\x05\xd8\xca\xdd\x61\x00\x00"
+ "\x00",
+ 9 }
};
static void create_prefix(char* prefix, size_t prefixlen, size_t buffersize, SSIZE_T rc,
diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c
index 01328b8..a016beb 100644
--- a/winpr/libwinpr/file/file.c
+++ b/winpr/libwinpr/file/file.c
@@ -21,11 +21,7 @@
#include <winpr/config.h>
#include <winpr/debug.h>
-
-#if defined(__FreeBSD_kernel__) && defined(__GLIBC__)
-#define _GNU_SOURCE
-#define KFREEBSD
-#endif
+#include <winpr/assert.h>
#include <winpr/wtypes.h>
#include <winpr/crt.h>
@@ -100,14 +96,15 @@ static BOOL FileCloseHandle(HANDLE handle)
static BOOL FileSetEndOfFile(HANDLE hFile)
{
WINPR_FILE* pFile = (WINPR_FILE*)hFile;
- INT64 size = 0;
if (!hFile)
return FALSE;
- size = _ftelli64(pFile->fp);
+ const INT64 size = _ftelli64(pFile->fp);
+ if (size < 0)
+ return FALSE;
- if (ftruncate(fileno(pFile->fp), size) < 0)
+ if (ftruncate(fileno(pFile->fp), (off_t)size) < 0)
{
char ebuffer[256] = { 0 };
WLog_ERR(TAG, "ftruncate %s failed with %s [0x%08X]", pFile->lpFileName,
@@ -565,100 +562,114 @@ static UINT64 FileTimeToUS(const FILETIME* ft)
return tmp;
}
+#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L)
+static struct timespec filetimeToTimespec(const FILETIME* ftime)
+{
+ WINPR_ASSERT(ftime);
+ UINT64 tmp = FileTimeToUS(ftime);
+ struct timespec ts = { 0 };
+ ts.tv_sec = tmp / 1000000ULL;
+ ts.tv_nsec = (tmp % 1000000ULL) * 1000ULL;
+ return ts;
+}
+
static BOOL FileSetFileTime(HANDLE hFile, const FILETIME* lpCreationTime,
const FILETIME* lpLastAccessTime, const FILETIME* lpLastWriteTime)
{
- int rc = 0;
-#if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) || defined(KFREEBSD)
- struct stat buf;
- /* OpenBSD, NetBSD and DragonflyBSD support POSIX futimens */
- struct timeval timevals[2];
-#else
- struct timespec times[2]; /* last access, last modification */
-#endif
+ struct timespec times[2] = { { UTIME_OMIT, UTIME_OMIT },
+ { UTIME_OMIT, UTIME_OMIT } }; /* last access, last modification */
WINPR_FILE* pFile = (WINPR_FILE*)hFile;
if (!hFile)
return FALSE;
-#if defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) || defined(KFREEBSD)
- rc = fstat(fileno(pFile->fp), &buf);
+ if (lpLastAccessTime)
+ times[0] = filetimeToTimespec(lpLastAccessTime);
- if (rc < 0)
+ if (lpLastWriteTime)
+ times[1] = filetimeToTimespec(lpLastWriteTime);
+
+ // TODO: Creation time can not be handled!
+ const int rc = futimens(fileno(pFile->fp), times);
+ if (rc != 0)
return FALSE;
-#endif
+ return TRUE;
+}
+#elif defined(__APPLE__) || defined(ANDROID) || defined(__FreeBSD__) || defined(KFREEBSD)
+static struct timeval filetimeToTimeval(const FILETIME* ftime)
+{
+ WINPR_ASSERT(ftime);
+ UINT64 tmp = FileTimeToUS(ftime);
+ struct timeval tv = { 0 };
+ tv.tv_sec = tmp / 1000000ULL;
+ tv.tv_usec = tmp % 1000000ULL;
+ return tv;
+}
- if (!lpLastAccessTime)
- {
+static struct timeval statToTimeval(const struct stat* sval)
+{
+ WINPR_ASSERT(sval);
+ struct timeval tv = { 0 };
#if defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD)
- timevals[0].tv_sec = buf.st_atime;
+ tv.tv_sec = sval->st_atime;
#ifdef _POSIX_SOURCE
- TIMESPEC_TO_TIMEVAL(&timevals[0], &buf.st_atim);
+ TIMESPEC_TO_TIMEVAL(&tv, &sval->st_atim);
#else
- TIMESPEC_TO_TIMEVAL(&timevals[0], &buf.st_atimespec);
+ TIMESPEC_TO_TIMEVAL(&tv, &sval->st_atimespec);
#endif
#elif defined(ANDROID)
- timevals[0].tv_sec = buf.st_atime;
- timevals[0].tv_usec = buf.st_atimensec / 1000UL;
-#else
- times[0].tv_sec = UTIME_OMIT;
- times[0].tv_nsec = UTIME_OMIT;
+ tv.tv_sec = sval->st_atime;
+ tv.tv_usec = sval->st_atimensec / 1000UL;
#endif
- }
- else
- {
- UINT64 tmp = FileTimeToUS(lpLastAccessTime);
-#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD)
- timevals[0].tv_sec = tmp / 1000000ULL;
- timevals[0].tv_usec = tmp % 1000000ULL;
-#else
- times[0].tv_sec = tmp / 1000000ULL;
- times[0].tv_nsec = (tmp % 1000000ULL) * 1000ULL;
-#endif
- }
+ return tv;
+}
- if (!lpLastWriteTime)
- {
-#if defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD)
- timevals[1].tv_sec = buf.st_mtime;
-#ifdef _POSIX_SOURCE
- TIMESPEC_TO_TIMEVAL(&timevals[1], &buf.st_mtim);
-#else
- TIMESPEC_TO_TIMEVAL(&timevals[1], &buf.st_mtimespec);
-#endif
-#elif defined(ANDROID)
- timevals[1].tv_sec = buf.st_mtime;
- timevals[1].tv_usec = buf.st_mtimensec / 1000UL;
-#else
- times[1].tv_sec = UTIME_OMIT;
- times[1].tv_nsec = UTIME_OMIT;
-#endif
- }
- else
+static BOOL FileSetFileTime(HANDLE hFile, const FILETIME* lpCreationTime,
+ const FILETIME* lpLastAccessTime, const FILETIME* lpLastWriteTime)
+{
+ struct stat buf = { 0 };
+ /* OpenBSD, NetBSD and DragonflyBSD support POSIX futimens */
+ WINPR_FILE* pFile = (WINPR_FILE*)hFile;
+
+ if (!hFile)
+ return FALSE;
+
+ const int rc = fstat(fileno(pFile->fp), &buf);
+ if (rc < 0)
+ return FALSE;
+
+ struct timeval timevals[2] = { statToTimeval(&buf), statToTimeval(&buf) };
+ if (lpLastAccessTime)
+ timevals[0] = filetimeToTimeval(lpLastAccessTime);
+
+ if (lpLastWriteTime)
+ timevals[1] = filetimeToTimeval(lpLastWriteTime);
+
+ // TODO: Creation time can not be handled!
{
- UINT64 tmp = FileTimeToUS(lpLastWriteTime);
-#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD)
- timevals[1].tv_sec = tmp / 1000000ULL;
- timevals[1].tv_usec = tmp % 1000000ULL;
-#else
- times[1].tv_sec = tmp / 1000000ULL;
- times[1].tv_nsec = (tmp % 1000000ULL) * 1000ULL;
-#endif
+ const int rc = utimes(pFile->lpFileName, timevals);
+ if (rc != 0)
+ return FALSE;
}
- // TODO: Creation time can not be handled!
-#if defined(ANDROID) || defined(__FreeBSD__) || defined(__APPLE__) || defined(KFREEBSD)
- rc = utimes(pFile->lpFileName, timevals);
+ return TRUE;
+}
#else
- rc = futimens(fileno(pFile->fp), times);
-#endif
+static BOOL FileSetFileTime(HANDLE hFile, const FILETIME* lpCreationTime,
+ const FILETIME* lpLastAccessTime, const FILETIME* lpLastWriteTime)
+{
+ WINPR_FILE* pFile = (WINPR_FILE*)hFile;
- if (rc != 0)
+ if (!hFile)
return FALSE;
+ WLog_WARN(TAG, "TODO: Creation, Access and Write time can not be handled!");
+ WLog_WARN(TAG,
+ "TODO: Define _POSIX_C_SOURCE >= 200809L or implement a platform specific handler!");
return TRUE;
}
+#endif
static HANDLE_OPS fileOps = {
FileIsHandled,
diff --git a/winpr/libwinpr/file/generic.c b/winpr/libwinpr/file/generic.c
index e1437ec..9318586 100644
--- a/winpr/libwinpr/file/generic.c
+++ b/winpr/libwinpr/file/generic.c
@@ -885,7 +885,7 @@ static WIN32_FILE_SEARCH* file_search_new(const char* name, size_t namelen, cons
WIN32_FILE_SEARCH* pFileSearch = (WIN32_FILE_SEARCH*)calloc(1, sizeof(WIN32_FILE_SEARCH));
if (!pFileSearch)
return NULL;
- strncpy(pFileSearch->magic, file_search_magic, sizeof(pFileSearch->magic));
+ strncpy(pFileSearch->magic, file_search_magic, sizeof(pFileSearch->magic) - 1);
pFileSearch->lpPath = strndup(name, namelen);
pFileSearch->lpPattern = strndup(pattern, patternlen);
diff --git a/winpr/libwinpr/handle/CMakeLists.txt b/winpr/libwinpr/handle/CMakeLists.txt
index 37c410e..48c7aea 100644
--- a/winpr/libwinpr/handle/CMakeLists.txt
+++ b/winpr/libwinpr/handle/CMakeLists.txt
@@ -18,6 +18,3 @@
winpr_module_add(handle.c handle.h nonehandle.c nonehandle.h)
-if(${CMAKE_SYSTEM_NAME} MATCHES SunOS)
- winpr_library_add_private(rt)
-endif()
diff --git a/winpr/libwinpr/library/library.c b/winpr/libwinpr/library/library.c
index 307dc20..0fa1fd1 100644
--- a/winpr/libwinpr/library/library.c
+++ b/winpr/libwinpr/library/library.c
@@ -274,18 +274,17 @@ DWORD GetModuleFileNameA(HMODULE hModule, LPSTR lpFilename, DWORD nSize)
if (!hModule)
{
- char buffer[4096];
+ char buffer[4096] = { 0 };
sprintf_s(path, ARRAYSIZE(path), "/proc/%d/exe", getpid());
- status = readlink(path, buffer, sizeof(buffer));
+ status = readlink(path, buffer, ARRAYSIZE(buffer) - 1);
- if (status < 0)
+ if ((status < 0) || (status >= ARRAYSIZE(buffer)))
{
SetLastError(ERROR_INTERNAL_ERROR);
return 0;
}
- buffer[status] = '\0';
- length = strnlen(buffer, sizeof(buffer));
+ length = strnlen(buffer, ARRAYSIZE(buffer));
if (length < nSize)
{
diff --git a/winpr/libwinpr/ncrypt/ncrypt_pkcs11.c b/winpr/libwinpr/ncrypt/ncrypt_pkcs11.c
index 08e6274..d579cb1 100644
--- a/winpr/libwinpr/ncrypt/ncrypt_pkcs11.c
+++ b/winpr/libwinpr/ncrypt/ncrypt_pkcs11.c
@@ -141,6 +141,7 @@ static BOOL attributes_have_unallocated_buffers(CK_ATTRIBUTE_PTR attributes, CK_
static BOOL attribute_allocate_attribute_array(CK_ATTRIBUTE_PTR attribute)
{
+ WINPR_ASSERT(attribute);
attribute->pValue = calloc(attribute->ulValueLen, sizeof(void*));
return !!attribute->pValue;
}
@@ -1189,11 +1190,7 @@ static SECURITY_STATUS initialize_pkcs11(HANDLE handle,
ret = (NCryptP11ProviderHandle*)ncrypt_new_handle(
WINPR_NCRYPT_PROVIDER, sizeof(*ret), NCryptP11GetProperty, NCryptP11StorageProvider_dtor);
if (!ret)
- {
- if (handle)
- FreeLibrary(handle);
return NTE_NO_MEMORY;
- }
ret->library = handle;
ret->baseProvider.enumKeysFn = NCryptP11EnumKeys;
@@ -1290,6 +1287,8 @@ SECURITY_STATUS NCryptOpenP11StorageProviderEx(NCRYPT_PROV_HANDLE* phProvider,
return ERROR_SUCCESS;
out_load_library:
+ if (library)
+ FreeLibrary(library);
modulePaths++;
}
diff --git a/winpr/libwinpr/nt/CMakeLists.txt b/winpr/libwinpr/nt/CMakeLists.txt
index ef335e4..6ad18d6 100644
--- a/winpr/libwinpr/nt/CMakeLists.txt
+++ b/winpr/libwinpr/nt/CMakeLists.txt
@@ -21,10 +21,6 @@ winpr_library_add_private(
${CMAKE_THREAD_LIBS_INIT}
${CMAKE_DL_LIBS})
-if(${CMAKE_SYSTEM_NAME} MATCHES SunOS)
- winpr_library_add_private(rt)
-endif()
-
if(BUILD_TESTING)
add_subdirectory(test)
endif()
diff --git a/winpr/libwinpr/path/CMakeLists.txt b/winpr/libwinpr/path/CMakeLists.txt
index 1e4ed92..a5a75c6 100644
--- a/winpr/libwinpr/path/CMakeLists.txt
+++ b/winpr/libwinpr/path/CMakeLists.txt
@@ -17,6 +17,10 @@
winpr_module_add(path.c shell.c)
+if (MSVC OR MINGW)
+ winpr_library_add_public(shlwapi)
+endif()
+
if (IOS)
winpr_module_add(shell_ios.m)
endif (IOS)
diff --git a/winpr/libwinpr/path/path.c b/winpr/libwinpr/path/path.c
index 82e6be1..3f20465 100644
--- a/winpr/libwinpr/path/path.c
+++ b/winpr/libwinpr/path/path.c
@@ -1002,7 +1002,7 @@ PCSTR PathGetSharedLibraryExtensionA(unsigned long dwFlags)
PCWSTR PathGetSharedLibraryExtensionW(unsigned long dwFlags)
{
- WCHAR buffer[6][16] = { 0 };
+ static WCHAR buffer[6][16] = { 0 };
const WCHAR* SharedLibraryExtensionDotDllW = InitializeConstWCharFromUtf8(
SharedLibraryExtensionDotDllA, buffer[0], ARRAYSIZE(buffer[0]));
const WCHAR* SharedLibraryExtensionDotSoW =
@@ -1131,11 +1131,12 @@ BOOL winpr_RemoveDirectory_RecursiveW(LPCWSTR lpPathName)
WCHAR starbuffer[8] = { 0 };
const WCHAR* star = InitializeConstWCharFromUtf8("*", starbuffer, ARRAYSIZE(starbuffer));
const HRESULT hr = NativePathCchAppendW(path_slash, path_slash_len, star);
+ HANDLE dir = INVALID_HANDLE_VALUE;
if (FAILED(hr))
goto fail;
WIN32_FIND_DATAW findFileData = { 0 };
- HANDLE dir = FindFirstFileW(path_slash, &findFileData);
+ dir = FindFirstFileW(path_slash, &findFileData);
if (dir == INVALID_HANDLE_VALUE)
goto fail;
@@ -1167,8 +1168,6 @@ BOOL winpr_RemoveDirectory_RecursiveW(LPCWSTR lpPathName)
break;
} while (ret && FindNextFileW(dir, &findFileData) != 0);
- FindClose(dir);
-
if (ret)
{
if (!RemoveDirectoryW(lpPathName))
@@ -1176,6 +1175,7 @@ BOOL winpr_RemoveDirectory_RecursiveW(LPCWSTR lpPathName)
}
fail:
+ FindClose(dir);
free(path_slash);
return ret;
}
diff --git a/winpr/libwinpr/path/shell.c b/winpr/libwinpr/path/shell.c
index 4380a9b..a1e7b4e 100644
--- a/winpr/libwinpr/path/shell.c
+++ b/winpr/libwinpr/path/shell.c
@@ -670,12 +670,6 @@ fail:
return ret;
}
-#else
-
-#ifdef _MSC_VER
-#pragma comment(lib, "shlwapi.lib")
-#endif
-
#endif
BOOL winpr_MoveFile(LPCSTR lpExistingFileName, LPCSTR lpNewFileName)
diff --git a/winpr/libwinpr/pool/CMakeLists.txt b/winpr/libwinpr/pool/CMakeLists.txt
index 2e25916..bf6a663 100644
--- a/winpr/libwinpr/pool/CMakeLists.txt
+++ b/winpr/libwinpr/pool/CMakeLists.txt
@@ -30,10 +30,6 @@ winpr_library_add_private(
${CMAKE_THREAD_LIBS_INIT}
${CMAKE_DL_LIBS})
-if(${CMAKE_SYSTEM_NAME} MATCHES SunOS)
- winpr_library_add_private(rt)
-endif()
-
if(BUILD_TESTING)
add_subdirectory(test)
endif()
diff --git a/winpr/libwinpr/smartcard/smartcard_pcsc.c b/winpr/libwinpr/smartcard/smartcard_pcsc.c
index fb04d56..0745f40 100644
--- a/winpr/libwinpr/smartcard/smartcard_pcsc.c
+++ b/winpr/libwinpr/smartcard/smartcard_pcsc.c
@@ -992,8 +992,14 @@ static LONG WINAPI PCSC_SCardListReadersW(SCARDCONTEXT hContext, LPCWSTR mszGrou
return SCARD_E_NO_MEMORY;
}
- status =
- PCSC_SCardListReaders_Internal(hContext, mszGroupsA, (LPSTR*)&mszReadersA, pcchReaders);
+ union
+ {
+ LPSTR* ppc;
+ LPSTR pc;
+ } cnv;
+ cnv.ppc = &mszReadersA;
+
+ status = PCSC_SCardListReaders_Internal(hContext, mszGroupsA, cnv.pc, pcchReaders);
if (status == SCARD_S_SUCCESS)
{
size_t size = 0;
@@ -2380,7 +2386,10 @@ static LONG WINAPI PCSC_SCardGetAttrib_Internal(SCARDHANDLE hCard, DWORD dwAttrI
status = g_PCSC.pfnSCardGetAttrib(hCard, pcsc_dwAttrId, tmp, &pcsc_cbAttrLen);
if (status != SCARD_S_SUCCESS)
+ {
free(tmp);
+ tmp = NULL;
+ }
else
PCSC_AddMemoryBlock(hContext, tmp);
*(BYTE**)pbAttr = tmp;
@@ -2768,6 +2777,9 @@ static LONG WINAPI PCSC_SCardReadCacheA(SCARDCONTEXT hContext, UUID* CardIdentif
{
PCSC_CACHE_ITEM* data = NULL;
PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
+ if (!ctx)
+ return SCARD_E_INVALID_HANDLE;
+
char* id = card_id_and_name_a(CardIdentifier, LookupName);
data = HashTable_GetItemValue(ctx->cache, id);
@@ -2811,6 +2823,9 @@ static LONG WINAPI PCSC_SCardReadCacheW(SCARDCONTEXT hContext, UUID* CardIdentif
{
PCSC_CACHE_ITEM* data = NULL;
PCSC_SCARDCONTEXT* ctx = PCSC_GetCardContextData(hContext);
+ if (!ctx)
+ return SCARD_E_INVALID_HANDLE;
+
char* id = card_id_and_name_w(CardIdentifier, LookupName);
data = HashTable_GetItemValue(ctx->cache, id);
diff --git a/winpr/libwinpr/sspi/Kerberos/kerberos.c b/winpr/libwinpr/sspi/Kerberos/kerberos.c
index b7b71f9..3cf7786 100644
--- a/winpr/libwinpr/sspi/Kerberos/kerberos.c
+++ b/winpr/libwinpr/sspi/Kerberos/kerberos.c
@@ -657,6 +657,7 @@ static BOOL kerberos_rd_tgt_token(const sspi_gss_data* token, char** target, krb
*buf++ = '@';
strcpy(buf, str);
+ free(str);
return TRUE;
}
else if (val == KRB_TGT_REP)
@@ -1303,6 +1304,9 @@ static KRB_CONTEXT* get_context(PCtxtHandle phContext)
return NULL;
TCHAR* name = sspi_SecureHandleGetUpperPointer(phContext);
+ if (!name)
+ return NULL;
+
if (_tcscmp(KERBEROS_SSP_NAME, name) != 0)
return NULL;
return sspi_SecureHandleGetLowerPointer(phContext);
diff --git a/winpr/libwinpr/sspi/Kerberos/krb5glue_mit.c b/winpr/libwinpr/sspi/Kerberos/krb5glue_mit.c
index 2638b22..619f029 100644
--- a/winpr/libwinpr/sspi/Kerberos/krb5glue_mit.c
+++ b/winpr/libwinpr/sspi/Kerberos/krb5glue_mit.c
@@ -183,7 +183,10 @@ krb5_error_code krb5glue_get_init_creds(krb5_context ctx, krb5_principal princ,
rv = ENOMEM;
if (winpr_asprintf(&kdc_url, &size, "https://%s/KdcProxy", krb_settings->kdcUrl) <= 0)
+ {
+ free(kdc_url);
goto cleanup;
+ }
realm = calloc(princ->realm.length + 1, 1);
if (!realm)
@@ -210,7 +213,7 @@ krb5_error_code krb5glue_get_init_creds(krb5_context ctx, krb5_principal princ,
if ((rv = profile_flush_to_file(profile, tmp_profile_path)))
goto cleanup;
- profile_release(profile);
+ profile_abandon(profile);
profile = NULL;
if ((rv = profile_init_path(tmp_profile_path, &profile)))
goto cleanup;
@@ -239,7 +242,7 @@ cleanup:
krb5_get_init_creds_opt_free(ctx, gic_opt);
if (is_temp_ctx)
krb5_free_context(ctx);
- profile_release(profile);
+ profile_abandon(profile);
winpr_DeleteFile(tmp_profile_path);
free(tmp_profile_path);
diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.c b/winpr/libwinpr/sspi/NTLM/ntlm.c
index 6a2ee6a..bc16a40 100644
--- a/winpr/libwinpr/sspi/NTLM/ntlm.c
+++ b/winpr/libwinpr/sspi/NTLM/ntlm.c
@@ -1255,7 +1255,10 @@ static SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle phContext, ULONG
WINPR_HMAC_CTX* hmac = winpr_HMAC_New();
if (!winpr_HMAC_Init(hmac, WINPR_MD_MD5, context->SendSigningKey, WINPR_MD5_DIGEST_LENGTH))
+ {
+ winpr_HMAC_Free(hmac);
return SEC_E_INTERNAL_ERROR;
+ }
Data_Write_UINT32(&seq_no, MessageSeqNo);
winpr_HMAC_Update(hmac, (BYTE*)&seq_no, 4);
@@ -1303,7 +1306,10 @@ static SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle phContext,
WINPR_HMAC_CTX* hmac = winpr_HMAC_New();
if (!winpr_HMAC_Init(hmac, WINPR_MD_MD5, context->RecvSigningKey, WINPR_MD5_DIGEST_LENGTH))
+ {
+ winpr_HMAC_Free(hmac);
return SEC_E_INTERNAL_ERROR;
+ }
Data_Write_UINT32(&seq_no, MessageSeqNo);
winpr_HMAC_Update(hmac, (BYTE*)&seq_no, 4);
diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c
index 881a743..b270947 100644
--- a/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c
+++ b/winpr/libwinpr/sspi/NTLM/ntlm_av_pairs.c
@@ -124,7 +124,6 @@ static INLINE BOOL ntlm_av_pair_get_id(const NTLM_AV_PAIR* pAvPair, size_t size,
ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList)
{
- size_t size = 0;
size_t cbAvPair = 0;
NTLM_AV_PAIR* pAvPair = NULL;
@@ -132,8 +131,12 @@ ULONG ntlm_av_pair_list_length(NTLM_AV_PAIR* pAvPairList, size_t cbAvPairList)
if (!pAvPair)
return 0;
- size = ((PBYTE)pAvPair - (PBYTE)pAvPairList) + sizeof(NTLM_AV_PAIR);
+ if (pAvPair < pAvPairList)
+ return 0;
+
+ const size_t size = ((PBYTE)pAvPair - (PBYTE)pAvPairList) + sizeof(NTLM_AV_PAIR);
WINPR_ASSERT(size <= ULONG_MAX);
+ WINPR_ASSERT(size >= 0);
return (ULONG)size;
}
diff --git a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c
index 9c6e818..69970c8 100644
--- a/winpr/libwinpr/sspi/NTLM/ntlm_compute.c
+++ b/winpr/libwinpr/sspi/NTLM/ntlm_compute.c
@@ -248,15 +248,12 @@ BOOL ntlm_write_ntlm_v2_response(wStream* s, const NTLMv2_RESPONSE* response)
void ntlm_current_time(BYTE* timestamp)
{
- FILETIME filetime = { 0 };
- ULARGE_INTEGER time64 = { 0 };
+ FILETIME ft = { 0 };
WINPR_ASSERT(timestamp);
- GetSystemTimeAsFileTime(&filetime);
- time64.u.LowPart = filetime.dwLowDateTime;
- time64.u.HighPart = filetime.dwHighDateTime;
- CopyMemory(timestamp, &(time64.QuadPart), 8);
+ GetSystemTimeAsFileTime(&ft);
+ CopyMemory(timestamp, &(ft), sizeof(ft));
}
/**
diff --git a/winpr/libwinpr/sspi/Negotiate/negotiate.c b/winpr/libwinpr/sspi/Negotiate/negotiate.c
index 7249399..66d8d53 100644
--- a/winpr/libwinpr/sspi/Negotiate/negotiate.c
+++ b/winpr/libwinpr/sspi/Negotiate/negotiate.c
@@ -97,13 +97,14 @@ static const WinPrAsn1_OID negoex_OID = { 10, (BYTE*)"\x2b\x06\x01\x04\x01\x82\x
#ifdef WITH_KRB5
static const SecPkg SecPkgTable[] = {
{ KERBEROS_SSP_NAME, &KERBEROS_SecurityFunctionTableA, &KERBEROS_SecurityFunctionTableW },
+ { KERBEROS_SSP_NAME, &KERBEROS_SecurityFunctionTableA, &KERBEROS_SecurityFunctionTableW },
{ NTLM_SSP_NAME, &NTLM_SecurityFunctionTableA, &NTLM_SecurityFunctionTableW }
};
static const Mech MechTable[] = {
{ &kerberos_u2u_OID, &SecPkgTable[0], ISC_REQ_INTEGRITY | ISC_REQ_USE_SESSION_KEY, TRUE },
- { &kerberos_OID, &SecPkgTable[0], ISC_REQ_INTEGRITY, TRUE },
- { &ntlm_OID, &SecPkgTable[1], 0, FALSE },
+ { &kerberos_OID, &SecPkgTable[1], ISC_REQ_INTEGRITY, TRUE },
+ { &ntlm_OID, &SecPkgTable[2], 0, FALSE },
};
#else
static const SecPkg SecPkgTable[] = { { NTLM_SSP_NAME, &NTLM_SecurityFunctionTableA,
@@ -599,7 +600,11 @@ static SECURITY_STATUS negotiate_mic_exchange(NEGOTIATE_CONTEXT* context, NegTok
}
/* When using NTLM cipher states need to be reset after mic exchange */
- if (_tcscmp(sspi_SecureHandleGetUpperPointer(&context->sub_context), NTLM_SSP_NAME) == 0)
+ const TCHAR* name = sspi_SecureHandleGetUpperPointer(&context->sub_context);
+ if (!name)
+ return SEC_E_INTERNAL_ERROR;
+
+ if (_tcscmp(name, NTLM_SSP_NAME) == 0)
{
if (!ntlm_reset_cipher_state(&context->sub_context))
return SEC_E_INTERNAL_ERROR;
@@ -674,6 +679,9 @@ static SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(
if (!init_context.mech)
{
/* Use the output buffer to store the optimistic token */
+ if (!output_buffer)
+ goto cleanup;
+
CopyMemory(&output_token.mechToken, output_buffer, sizeof(SecBuffer));
if (bindings_buffer)
@@ -1127,7 +1135,8 @@ static SECURITY_STATUS SEC_ENTRY negotiate_AcceptSecurityContext(
return SEC_E_INVALID_TOKEN;
/* Use the output buffer to store the optimistic token */
- CopyMemory(&output_token.mechToken, output_buffer, sizeof(SecBuffer));
+ if (output_buffer)
+ CopyMemory(&output_token.mechToken, output_buffer, sizeof(SecBuffer));
status = context->mech->pkg->table->AcceptSecurityContext(
sub_cred, &context->sub_context, &mech_input, fContextReq | context->mech->flags,
diff --git a/winpr/libwinpr/synch/timer.c b/winpr/libwinpr/synch/timer.c
index 8238a88..354382c 100644
--- a/winpr/libwinpr/synch/timer.c
+++ b/winpr/libwinpr/synch/timer.c
@@ -707,11 +707,11 @@ static void timespec_add_ms(struct timespec* tspec, UINT32 ms)
static void timespec_gettimeofday(struct timespec* tspec)
{
- struct timeval tval;
WINPR_ASSERT(tspec);
- gettimeofday(&tval, NULL);
- tspec->tv_sec = tval.tv_sec;
- tspec->tv_nsec = tval.tv_usec * 1000;
+
+ const UINT64 ns = winpr_GetUnixTimeNS();
+ tspec->tv_sec = WINPR_TIME_NS_TO_S(ns);
+ tspec->tv_nsec = WINPR_TIME_NS_REM_NS(ns);
}
static INT64 timespec_compare(const struct timespec* tspec1, const struct timespec* tspec2)
@@ -881,12 +881,13 @@ static void* TimerQueueThread(void* arg)
status = pthread_cond_timedwait(&(timerQueue->cond), &(timerQueue->cond_mutex), &timeout);
FireExpiredTimerQueueTimers(timerQueue);
+ const BOOL bCancelled = timerQueue->bCancelled;
pthread_mutex_unlock(&(timerQueue->cond_mutex));
if ((status != ETIMEDOUT) && (status != 0))
break;
- if (timerQueue->bCancelled)
+ if (bCancelled)
break;
}
diff --git a/winpr/libwinpr/synch/wait.c b/winpr/libwinpr/synch/wait.c
index 3bef657..865f583 100644
--- a/winpr/libwinpr/synch/wait.c
+++ b/winpr/libwinpr/synch/wait.c
@@ -59,60 +59,16 @@
#include "../pipe/pipe.h"
-/* clock_gettime is not implemented on OSX prior to 10.12 */
-#if defined(__MACH__) && defined(__APPLE__)
-
-#include <mach/mach_time.h>
-
-#ifndef CLOCK_REALTIME
-#define CLOCK_REALTIME 0
-#endif
-
-#ifndef CLOCK_MONOTONIC
-#define CLOCK_MONOTONIC 0
-#endif
-
-/* clock_gettime is not implemented on OSX prior to 10.12 */
-int _mach_clock_gettime(int clk_id, struct timespec* t);
-
-int _mach_clock_gettime(int clk_id, struct timespec* t)
-{
- UINT64 time = 0;
- double seconds = 0.0;
- double nseconds = 0.0;
- mach_timebase_info_data_t timebase = { 0 };
- mach_timebase_info(&timebase);
- time = mach_absolute_time();
- nseconds = ((double)time * (double)timebase.numer) / ((double)timebase.denom);
- seconds = ((double)time * (double)timebase.numer) / ((double)timebase.denom * 1e9);
- t->tv_sec = seconds;
- t->tv_nsec = nseconds;
- return 0;
-}
-
-/* if clock_gettime is declared, then __CLOCK_AVAILABILITY will be defined */
-#ifdef __CLOCK_AVAILABILITY
-/* If we compiled with Mac OSX 10.12 or later, then clock_gettime will be declared
- * * but it may be NULL at runtime. So we need to check before using it. */
-int _mach_safe_clock_gettime(int clk_id, struct timespec* t);
-
-int _mach_safe_clock_gettime(int clk_id, struct timespec* t)
+static struct timespec ts_from_ns(void)
{
- if (clock_gettime)
- {
- return clock_gettime(clk_id, t);
- }
-
- return _mach_clock_gettime(clk_id, t);
+ const UINT64 ns = winpr_GetUnixTimeNS();
+ struct timespec timeout = { 0 };
+ timeout.tv_sec = WINPR_TIME_NS_TO_S(ns);
+ timeout.tv_nsec = WINPR_TIME_NS_REM_NS(ns);
+ ;
+ return timeout;
}
-#define clock_gettime _mach_safe_clock_gettime
-#else
-#define clock_gettime _mach_clock_gettime
-#endif
-
-#endif
-
/**
* Drop in replacement for pthread_mutex_timedlock
* http://code.google.com/p/android/issues/detail?id=7807
@@ -148,14 +104,14 @@ STATIC_NEEDED int pthread_mutex_timedlock(pthread_mutex_t* mutex,
unsigned long long diff = 0;
int retcode = -1;
/* This is just to avoid a completely busy wait */
- clock_gettime(CLOCK_MONOTONIC, &timenow);
+ timenow = ts_from_ns();
diff = ts_difftime(&timenow, timeout);
sleepytime.tv_sec = diff / 1000000000LL;
sleepytime.tv_nsec = diff % 1000000000LL;
while ((retcode = pthread_mutex_trylock(mutex)) == EBUSY)
{
- clock_gettime(CLOCK_MONOTONIC, &timenow);
+ timenow = ts_from_ns();
if (ts_difftime(timeout, &timenow) >= 0)
{
@@ -237,8 +193,8 @@ DWORD WaitForSingleObjectEx(HANDLE hHandle, DWORD dwMilliseconds, BOOL bAlertabl
if (dwMilliseconds != INFINITE)
{
int status = 0;
- struct timespec timeout = { 0 };
- clock_gettime(CLOCK_MONOTONIC, &timeout);
+ struct timespec timeout = ts_from_ns();
+
ts_add_ms(&timeout, dwMilliseconds);
status = pthread_mutex_timedlock(&mutex->mutex, &timeout);
diff --git a/winpr/libwinpr/sysinfo/cpufeatures/cpu-features.c b/winpr/libwinpr/sysinfo/cpufeatures/cpu-features.c
index d43b588..854c93a 100644
--- a/winpr/libwinpr/sysinfo/cpufeatures/cpu-features.c
+++ b/winpr/libwinpr/sysinfo/cpufeatures/cpu-features.c
@@ -73,6 +73,7 @@
#include <sys/system_properties.h>
#include <unistd.h>
#include <winpr/wtypes.h>
+#include <winpr/debug.h>
static pthread_once_t g_once;
static int g_inited;
diff --git a/winpr/libwinpr/sysinfo/sysinfo.c b/winpr/libwinpr/sysinfo/sysinfo.c
index f12f4eb..bf81b8b 100644
--- a/winpr/libwinpr/sysinfo/sysinfo.c
+++ b/winpr/libwinpr/sysinfo/sysinfo.c
@@ -33,9 +33,43 @@
#include <fcntl.h>
#endif
+#if !defined(_WIN32)
+#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L)
+#include <time.h>
+#elif !defined(__APPLE__)
+#include <sys/time.h>
+#include <sys/sysinfo.h>
+#endif
+#endif
+
#include "../log.h"
#define TAG WINPR_TAG("sysinfo")
+#define FILETIME_TO_UNIX_OFFSET_S 11644473600UL
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#include <mach/mach_time.h>
+
+static UINT64 scaleHighPrecision(UINT64 i, UINT32 numer, UINT32 denom)
+{
+ UINT64 high = (i >> 32) * numer;
+ UINT64 low = (i & 0xffffffffull) * numer / denom;
+ UINT64 highRem = ((high % denom) << 32) / denom;
+ high /= denom;
+ return (high << 32) + highRem + low;
+}
+
+static UINT64 mac_get_time_ns(void)
+{
+ mach_timebase_info_data_t timebase = { 0 };
+ mach_timebase_info(&timebase);
+ UINT64 t = mach_absolute_time();
+ return scaleHighPrecision(t, timebase.numer, timebase.denom);
+}
+
+#endif
+
/**
* api-ms-win-core-sysinfo-l1-1-1.dll:
*
@@ -272,13 +306,14 @@ BOOL SetLocalTime(CONST SYSTEMTIME* lpSystemTime)
VOID GetSystemTimeAsFileTime(LPFILETIME lpSystemTimeAsFileTime)
{
- ULARGE_INTEGER time64;
- time64.u.HighPart = 0;
- /* time represented in tenths of microseconds since midnight of January 1, 1601 */
- time64.QuadPart = time(NULL) + 11644473600LL; /* Seconds since January 1, 1601 */
- time64.QuadPart *= 10000000; /* Convert timestamp to tenths of a microsecond */
- lpSystemTimeAsFileTime->dwLowDateTime = time64.u.LowPart;
- lpSystemTimeAsFileTime->dwHighDateTime = time64.u.HighPart;
+ union
+ {
+ UINT64 u64;
+ FILETIME ft;
+ } t;
+
+ t.u64 = (winpr_GetUnixTimeNS() / 100ull) + FILETIME_TO_UNIX_OFFSET_S * 10000000ull;
+ *lpSystemTimeAsFileTime = t.ft;
}
BOOL GetSystemTimeAdjustment(PDWORD lpTimeAdjustment, PDWORD lpTimeIncrement,
@@ -294,25 +329,7 @@ BOOL GetSystemTimeAdjustment(PDWORD lpTimeAdjustment, PDWORD lpTimeIncrement,
DWORD GetTickCount(void)
{
- DWORD ticks = 0;
-#ifdef __linux__
- struct timespec ts;
-
- if (!clock_gettime(CLOCK_MONOTONIC_RAW, &ts))
- ticks = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000);
-
-#else
- /**
- * FIXME: this is relative to the Epoch time, and we
- * need to return a value relative to the system uptime.
- */
- struct timeval tv;
-
- if (!gettimeofday(&tv, NULL))
- ticks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
-
-#endif
- return ticks;
+ return GetTickCount64();
}
#endif // _WIN32
@@ -553,35 +570,80 @@ DWORD GetTickCount(void)
ULONGLONG winpr_GetTickCount64(void)
{
- ULONGLONG ticks = 0;
-#if defined(__linux__)
- struct timespec ts;
+ const UINT64 ns = winpr_GetTickCount64NS();
+ return WINPR_TIME_NS_TO_MS(ns);
+}
- if (!clock_gettime(CLOCK_MONOTONIC_RAW, &ts))
- ticks = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000);
+#endif
+UINT64 winpr_GetTickCount64NS(void)
+{
+ UINT64 ticks = 0;
+#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L)
+ struct timespec ts = { 0 };
+
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &ts) == 0)
+ ticks = (ts.tv_sec * 1000000000ull) + ts.tv_nsec;
+#elif defined(__MACH__) && defined(__APPLE__)
+ ticks = mac_get_time_ns();
#elif defined(_WIN32)
- FILETIME ft;
- ULARGE_INTEGER ul;
- GetSystemTimeAsFileTime(&ft);
- ul.LowPart = ft.dwLowDateTime;
- ul.HighPart = ft.dwHighDateTime;
- ticks = ul.QuadPart;
+ LARGE_INTEGER li = { 0 };
+ LARGE_INTEGER freq = { 0 };
+ if (QueryPerformanceFrequency(&freq) && QueryPerformanceCounter(&li))
+ ticks = li.QuadPart * 1000000000ull / freq.QuadPart;
#else
- /**
- * FIXME: this is relative to the Epoch time, and we
- * need to return a value relative to the system uptime.
- */
- struct timeval tv;
+ struct timeval tv = { 0 };
- if (!gettimeofday(&tv, NULL))
- ticks = (tv.tv_sec * 1000) + (tv.tv_usec / 1000);
+ if (gettimeofday(&tv, NULL) == 0)
+ ticks = (tv.tv_sec * 1000000000ull) + (tv.tv_usec * 1000ull);
+
+ /* We need to trick here:
+ * this function should return the system uptime, but we need higher resolution.
+ * so on first call get the actual timestamp along with the system uptime.
+ *
+ * return the uptime measured from now on (e.g. current measure - first measure + uptime at
+ * first measure)
+ */
+ static UINT64 first = 0;
+ static UINT64 uptime = 0;
+ if (first == 0)
+ {
+ struct sysinfo info = { 0 };
+ if (sysinfo(&info) == 0)
+ {
+ first = ticks;
+ uptime = 1000000000ull * info.uptime;
+ }
+ }
+ ticks = ticks - first + uptime;
#endif
return ticks;
}
+UINT64 winpr_GetUnixTimeNS(void)
+{
+#if defined(_WIN32)
+
+ union
+ {
+ UINT64 u64;
+ FILETIME ft;
+ } t = { 0 };
+ GetSystemTimeAsFileTime(&t.ft);
+ return (t.u64 - FILETIME_TO_UNIX_OFFSET_S * 10000000ull) * 100ull;
+#elif defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 199309L)
+ struct timespec ts = { 0 };
+ if (clock_gettime(CLOCK_REALTIME, &ts) != 0)
+ return 0;
+ return ts.tv_sec * 1000000000ull + ts.tv_nsec;
+#else
+ struct timeval tv = { 0 };
+ if (gettimeofday(&tv, NULL) != 0)
+ return 0;
+ return tv.tv_sec * 1000000000ULL + tv.tv_usec * 1000ull;
#endif
+}
/* If x86 */
#ifdef _M_IX86_AMD64
diff --git a/winpr/libwinpr/thread/CMakeLists.txt b/winpr/libwinpr/thread/CMakeLists.txt
index bfc04dd..2e9cd05 100644
--- a/winpr/libwinpr/thread/CMakeLists.txt
+++ b/winpr/libwinpr/thread/CMakeLists.txt
@@ -25,10 +25,6 @@ winpr_module_add(
thread.h
tls.c)
-if(${CMAKE_SYSTEM_NAME} MATCHES SunOS)
- winpr_library_add_private(rt)
-endif()
-
if(BUILD_TESTING)
add_subdirectory(test)
endif()
diff --git a/winpr/libwinpr/thread/thread.h b/winpr/libwinpr/thread/thread.h
index aef9bc9..92d05d3 100644
--- a/winpr/libwinpr/thread/thread.h
+++ b/winpr/libwinpr/thread/thread.h
@@ -32,49 +32,39 @@
#include "../synch/event.h"
#include "apc.h"
-#ifdef __GNUC__
-#define ALIGN64 __attribute__((aligned(8)))
-#else
-#ifdef _WIN32
-#define ALIGN64 __declspec(align(8))
-#else
-#define ALIGN64
-#endif
-#endif
-
typedef void* (*pthread_start_routine)(void*);
typedef struct winpr_APC_item WINPR_APC_ITEM;
typedef struct
{
- ALIGN64 pthread_mutex_t mux;
- ALIGN64 pthread_cond_t cond;
- ALIGN64 BOOL val;
+ WINPR_ALIGN64 pthread_mutex_t mux;
+ WINPR_ALIGN64 pthread_cond_t cond;
+ WINPR_ALIGN64 BOOL val;
} mux_condition_bundle;
struct winpr_thread
{
WINPR_HANDLE common;
- ALIGN64 BOOL started;
- ALIGN64 WINPR_EVENT_IMPL event;
- ALIGN64 BOOL mainProcess;
- ALIGN64 BOOL detached;
- ALIGN64 BOOL joined;
- ALIGN64 BOOL exited;
- ALIGN64 DWORD dwExitCode;
- ALIGN64 pthread_t thread;
- ALIGN64 SIZE_T dwStackSize;
- ALIGN64 LPVOID lpParameter;
- ALIGN64 pthread_mutex_t mutex;
+ WINPR_ALIGN64 BOOL started;
+ WINPR_ALIGN64 WINPR_EVENT_IMPL event;
+ WINPR_ALIGN64 BOOL mainProcess;
+ WINPR_ALIGN64 BOOL detached;
+ WINPR_ALIGN64 BOOL joined;
+ WINPR_ALIGN64 BOOL exited;
+ WINPR_ALIGN64 DWORD dwExitCode;
+ WINPR_ALIGN64 pthread_t thread;
+ WINPR_ALIGN64 SIZE_T dwStackSize;
+ WINPR_ALIGN64 LPVOID lpParameter;
+ WINPR_ALIGN64 pthread_mutex_t mutex;
mux_condition_bundle isRunning;
mux_condition_bundle isCreated;
- ALIGN64 LPTHREAD_START_ROUTINE lpStartAddress;
- ALIGN64 LPSECURITY_ATTRIBUTES lpThreadAttributes;
- ALIGN64 APC_QUEUE apc;
+ WINPR_ALIGN64 LPTHREAD_START_ROUTINE lpStartAddress;
+ WINPR_ALIGN64 LPSECURITY_ATTRIBUTES lpThreadAttributes;
+ WINPR_ALIGN64 APC_QUEUE apc;
#if defined(WITH_DEBUG_THREADS)
- ALIGN64 void* create_stack;
- ALIGN64 void* exit_stack;
+ WINPR_ALIGN64 void* create_stack;
+ WINPR_ALIGN64 void* exit_stack;
#endif
};
diff --git a/winpr/libwinpr/timezone/timezone.c b/winpr/libwinpr/timezone/timezone.c
index f6d9874..6ca3e54 100644
--- a/winpr/libwinpr/timezone/timezone.c
+++ b/winpr/libwinpr/timezone/timezone.c
@@ -247,10 +247,11 @@ static char* winpr_get_unix_timezone_identifier_from_file(void)
#else
FILE* fp = NULL;
char* tzid = NULL;
-#if defined(__FreeBSD__) || defined(__OpenBSD__)
- fp = winpr_fopen("/var/db/zoneinfo", "r");
+#if !defined(WINPR_TIMEZONE_FILE)
+#error \
+ "Please define WINPR_TIMEZONE_FILE with the path to your timezone file (e.g. /etc/timezone or similar)"
#else
- fp = winpr_fopen("/etc/timezone", "r");
+ fp = winpr_fopen(WINPR_TIMEZONE_FILE, "r");
#endif
if (NULL == fp)
diff --git a/winpr/libwinpr/utils/cmdline.c b/winpr/libwinpr/utils/cmdline.c
index 3d93c0a..a524d62 100644
--- a/winpr/libwinpr/utils/cmdline.c
+++ b/winpr/libwinpr/utils/cmdline.c
@@ -515,13 +515,6 @@ static size_t get_element_count(const char* list, BOOL* failed, BOOL fullquoted)
if (!fullquoted)
{
int now = is_quoted(*it);
- if ((quoted == 0) && !first)
- {
- WLog_ERR(TAG, "Invalid argument (misplaced quote) '%s'", list);
- *failed = TRUE;
- return 0;
- }
-
if (now == quoted)
quoted = 0;
else if (quoted == 0)
diff --git a/winpr/libwinpr/utils/collections/CountdownEvent.c b/winpr/libwinpr/utils/collections/CountdownEvent.c
index fd23e0c..771ba54 100644
--- a/winpr/libwinpr/utils/collections/CountdownEvent.c
+++ b/winpr/libwinpr/utils/collections/CountdownEvent.c
@@ -48,7 +48,10 @@ struct CountdownEvent
size_t CountdownEvent_CurrentCount(wCountdownEvent* countdown)
{
WINPR_ASSERT(countdown);
- return countdown->count;
+ EnterCriticalSection(&countdown->lock);
+ const size_t rc = countdown->count;
+ LeaveCriticalSection(&countdown->lock);
+ return rc;
}
/**
@@ -58,7 +61,10 @@ size_t CountdownEvent_CurrentCount(wCountdownEvent* countdown)
size_t CountdownEvent_InitialCount(wCountdownEvent* countdown)
{
WINPR_ASSERT(countdown);
- return countdown->initialCount;
+ EnterCriticalSection(&countdown->lock);
+ const size_t rc = countdown->initialCount;
+ LeaveCriticalSection(&countdown->lock);
+ return rc;
}
/**
diff --git a/winpr/libwinpr/utils/collections/HashTable.c b/winpr/libwinpr/utils/collections/HashTable.c
index 7782b2b..8bbaf84 100644
--- a/winpr/libwinpr/utils/collections/HashTable.c
+++ b/winpr/libwinpr/utils/collections/HashTable.c
@@ -561,7 +561,8 @@ size_t HashTable_GetKeys(wHashTable* table, ULONG_PTR** ppKeys)
iKey = 0;
count = table->numOfElements;
- *ppKeys = NULL;
+ if (ppKeys)
+ *ppKeys = NULL;
if (count < 1)
{
diff --git a/winpr/libwinpr/utils/collections/PubSub.c b/winpr/libwinpr/utils/collections/PubSub.c
index 0efffb7..b95f26d 100644
--- a/winpr/libwinpr/utils/collections/PubSub.c
+++ b/winpr/libwinpr/utils/collections/PubSub.c
@@ -102,7 +102,7 @@ void PubSub_AddEventTypes(wPubSub* pubSub, wEventType* events, size_t count)
new_size = pubSub->size * 2;
new_event = (wEventType*)realloc(pubSub->events, new_size * sizeof(wEventType));
if (!new_event)
- return;
+ goto fail;
pubSub->size = new_size;
pubSub->events = new_event;
}
@@ -110,6 +110,7 @@ void PubSub_AddEventTypes(wPubSub* pubSub, wEventType* events, size_t count)
CopyMemory(&pubSub->events[pubSub->count], events, count * sizeof(wEventType));
pubSub->count += count;
+fail:
if (pubSub->synchronized)
PubSub_Unlock(pubSub);
}
diff --git a/winpr/libwinpr/utils/collections/StreamPool.c b/winpr/libwinpr/utils/collections/StreamPool.c
index 910309f..3ff113a 100644
--- a/winpr/libwinpr/utils/collections/StreamPool.c
+++ b/winpr/libwinpr/utils/collections/StreamPool.c
@@ -211,7 +211,7 @@ wStream* StreamPool_Take(wStreamPool* pool, size_t size)
if (!s)
goto out_fail;
}
- else
+ else if (s)
{
Stream_SetPosition(s, 0);
Stream_SetLength(s, Stream_Capacity(s));
diff --git a/winpr/libwinpr/utils/wlog/PacketMessage.c b/winpr/libwinpr/utils/wlog/PacketMessage.c
index cc1c812..17df1ec 100644
--- a/winpr/libwinpr/utils/wlog/PacketMessage.c
+++ b/winpr/libwinpr/utils/wlog/PacketMessage.c
@@ -29,27 +29,11 @@
#include <winpr/crt.h>
#include <winpr/file.h>
#include <winpr/stream.h>
+#include <winpr/sysinfo.h>
#include "../../log.h"
#define TAG WINPR_TAG("utils.wlog")
-#ifndef _WIN32
-#include <sys/time.h>
-#else
-#include <time.h>
-#include <sys/timeb.h>
-#include <winpr/windows.h>
-
-static int gettimeofday(struct timeval* tp, void* tz)
-{
- struct _timeb timebuffer;
- _ftime(&timebuffer);
- tp->tv_sec = (long)timebuffer.time;
- tp->tv_usec = timebuffer.millitm * 1000;
- return 0;
-}
-#endif
-
static BOOL Pcap_Read_Header(wPcap* pcap, wPcapHeader* header)
{
if (pcap && pcap->fp && fread((void*)header, sizeof(wPcapHeader), 1, pcap->fp) == 1)
@@ -89,8 +73,7 @@ static BOOL Pcap_Read_Record(wPcap* pcap, wPcapRecord* record)
static BOOL Pcap_Add_Record(wPcap* pcap, void* data, UINT32 length)
{
- wPcapRecord* record;
- struct timeval tp;
+ wPcapRecord* record = NULL;
if (!pcap->tail)
{
@@ -117,9 +100,10 @@ static BOOL Pcap_Add_Record(wPcap* pcap, void* data, UINT32 length)
record->length = length;
record->header.incl_len = length;
record->header.orig_len = length;
- gettimeofday(&tp, 0);
- record->header.ts_sec = tp.tv_sec;
- record->header.ts_usec = tp.tv_usec;
+
+ UINT64 ns = winpr_GetUnixTimeNS();
+ record->header.ts_sec = WINPR_TIME_NS_TO_S(ns);
+ record->header.ts_usec = WINPR_TIME_NS_REM_US(ns);
return TRUE;
}
@@ -380,7 +364,6 @@ BOOL WLog_PacketMessage_Write(wPcap* pcap, void* data, size_t length, DWORD flag
{
wTcpHeader tcp;
wIPv4Header ipv4;
- struct timeval tp;
wPcapRecord record;
wEthernetHeader ethernet;
ethernet.Type = 0x0800;
@@ -474,9 +457,11 @@ BOOL WLog_PacketMessage_Write(wPcap* pcap, void* data, size_t length, DWORD flag
record.header.incl_len = (UINT32)record.length + offset;
record.header.orig_len = (UINT32)record.length + offset;
record.next = NULL;
- gettimeofday(&tp, 0);
- record.header.ts_sec = tp.tv_sec;
- record.header.ts_usec = tp.tv_usec;
+
+ UINT64 ns = winpr_GetUnixTimeNS();
+ record.header.ts_sec = WINPR_TIME_NS_TO_S(ns);
+ record.header.ts_usec = WINPR_TIME_NS_REM_US(ns);
+
if (!Pcap_Write_RecordHeader(pcap, &record.header) ||
!WLog_PacketMessage_Write_EthernetHeader(pcap, &ethernet) ||
!WLog_PacketMessage_Write_IPv4Header(pcap, &ipv4) ||
diff --git a/winpr/tools/CMakeLists.txt b/winpr/tools/CMakeLists.txt
index ed7734d..d7446bc 100644
--- a/winpr/tools/CMakeLists.txt
+++ b/winpr/tools/CMakeLists.txt
@@ -82,32 +82,10 @@ add_subdirectory(makecert)
set(MODULE_NAME winpr-tools)
list(REMOVE_DUPLICATES WINPR_TOOLS_DEFINITIONS)
-list(REMOVE_DUPLICATES WINPR_TOOLS_LIBS)
list(REMOVE_DUPLICATES WINPR_TOOLS_INCLUDES)
include_directories(${WINPR_TOOLS_INCLUDES})
-# On windows create dll version information.
-# Vendor, product and year are already set in top level CMakeLists.txt
-if (WIN32)
- set (RC_VERSION_MAJOR ${WINPR_VERSION_MAJOR})
- set (RC_VERSION_MINOR ${WINPR_VERSION_MINOR})
- set (RC_VERSION_BUILD ${WINPR_VERSION_REVISION})
- set (RC_VERSION_FILE "${CMAKE_SHARED_LIBRARY_PREFIX}${MODULE_NAME}${WINPR_TOOLS_API_VERSION}${CMAKE_SHARED_LIBRARY_SUFFIX}" )
-
- configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
- set (WINPR_TOOLS_SRCS ${WINPR_TOOLS_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-endif()
-
-add_library(${MODULE_NAME} ${WINPR_TOOLS_SRCS})
-set_target_properties(${MODULE_NAME} PROPERTIES LINKER_LANGUAGE C)
-set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME ${MODULE_NAME}${WINPR_TOOLS_API_VERSION})
-if (WITH_LIBRARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES VERSION ${WINPR_TOOLS_VERSION} SOVERSION ${WINPR_TOOLS_API_VERSION})
-endif()
+AddTargetWithResourceFile(${MODULE_NAME} FALSE "${WINPR_VERSION}" WINPR_TOOLS_SRCS)
add_definitions(${WINPR_DEFINITIONS})
target_include_directories(${MODULE_NAME} INTERFACE $<INSTALL_INTERFACE:include/winpr${WINPR_VERSION_MAJOR}>)
@@ -118,10 +96,6 @@ install(TARGETS ${MODULE_NAME} COMPONENT libraries EXPORT WinPR-toolsTargets
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
-if (WITH_DEBUG_SYMBOLS AND MSVC AND BUILD_SHARED_LIBS)
- get_target_property(OUTPUT_FILENAME ${MODULE_NAME} OUTPUT_NAME)
- install(FILES ${CMAKE_PDB_BINARY_DIR}/${OUTPUT_FILENAME}.pdb DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT symbols)
-endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Tools")
# Add all command line utilities
diff --git a/winpr/tools/hash-cli/CMakeLists.txt b/winpr/tools/hash-cli/CMakeLists.txt
index 8f583d3..8eb9e66 100644
--- a/winpr/tools/hash-cli/CMakeLists.txt
+++ b/winpr/tools/hash-cli/CMakeLists.txt
@@ -21,39 +21,13 @@ set(MODULE_PREFIX "WINPR_TOOLS_HASH")
set(${MODULE_PREFIX}_SRCS
hash.c)
-# On windows create dll version information.
-# Vendor, product and year are already set in top level CMakeLists.txt
-if (WIN32)
- set(RC_VERSION_MAJOR ${WINPR_VERSION_MAJOR})
- set(RC_VERSION_MINOR ${WINPR_VERSION_MINOR})
- set(RC_VERSION_BUILD ${WINPR_VERSION_REVISION})
- set(RC_VERSION_FILE "${MODULE_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
-
- configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
- set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-endif()
-
-add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
+AddTargetWithResourceFile(${MODULE_NAME} TRUE "${WINPR_VERSION}" ${MODULE_PREFIX}_SRCS)
set(${MODULE_PREFIX}_LIBS winpr)
-set(MANPAGE_NAME "${MODULE_NAME}")
-if (WITH_BINARY_VERSIONING)
- set_target_properties(${MODULE_NAME} PROPERTIES OUTPUT_NAME "${MODULE_NAME}${WINPR_API_VERSION}")
- set(MANPAGE_NAME "${MODULE_NAME}${WINPR_API_VERSION}")
-endif()
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT tools EXPORT WinPRTargets)
-if (WITH_DEBUG_SYMBOLS AND MSVC)
- install(FILES ${PROJECT_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT symbols)
-endif()
-
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Tools")
-configure_file(winpr-hash.1.in ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE_NAME}.1)
-install_freerdp_man(${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE_NAME}.1 1)
+generate_and_install_freerdp_man_from_template(${MODULE_NAME} "1" "${WINPR_API_VERSION}")
diff --git a/winpr/tools/makecert-cli/CMakeLists.txt b/winpr/tools/makecert-cli/CMakeLists.txt
index e92d6f2..fe9c6f7 100644
--- a/winpr/tools/makecert-cli/CMakeLists.txt
+++ b/winpr/tools/makecert-cli/CMakeLists.txt
@@ -22,42 +22,14 @@ set(MODULE_PREFIX "WINPR_MAKECERT")
set(${MODULE_PREFIX}_SRCS
main.c)
-# On windows create dll version information.
-# Vendor, product and year are already set in top level CMakeLists.txt
-if (WIN32)
- set(RC_VERSION_MAJOR ${WINPR_VERSION_MAJOR})
- set(RC_VERSION_MINOR ${WINPR_VERSION_MINOR})
- set(RC_VERSION_BUILD ${WINPR_VERSION_REVISION})
- set(RC_VERSION_FILE "${MODULE_NAME}${CMAKE_EXECUTABLE_SUFFIX}")
-
- configure_file(
- ${PROJECT_SOURCE_DIR}/cmake/WindowsDLLVersion.rc.in
- ${CMAKE_CURRENT_BINARY_DIR}/version.rc
- @ONLY)
-
- set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc)
-endif()
-
-add_executable(${MODULE_NAME} ${${MODULE_PREFIX}_SRCS})
+AddTargetWithResourceFile(${MODULE_NAME} TRUE "${WINPR_VERSION}" ${MODULE_PREFIX}_SRCS)
set(${MODULE_PREFIX}_LIBS winpr-tools)
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS} winpr)
-set(MANPAGE_NAME ${MODULE_NAME})
-if (WITH_BINARY_VERSIONING)
- set_target_properties(${MODULE_NAME}
- PROPERTIES
- OUTPUT_NAME "${MODULE_NAME}${WINPR_API_VERSION}"
- )
- set(MANPAGE_NAME ${MODULE_NAME}${WINPR_API_VERSION})
-endif()
set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "WinPR/Tools")
install(TARGETS ${MODULE_NAME} DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT tools EXPORT WinPRTargets)
-if (WITH_DEBUG_SYMBOLS AND MSVC)
- install(FILES ${CMAKE_PDB_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT symbols)
-endif()
-configure_file(winpr-makecert.1.in ${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE_NAME}.1)
-install_freerdp_man(${CMAKE_CURRENT_BINARY_DIR}/${MANPAGE_NAME}.1 1)
+generate_and_install_freerdp_man_from_template(${MODULE_NAME} "1" "${WINPR_API_VERSION}")
diff --git a/winpr/tools/makecert/CMakeLists.txt b/winpr/tools/makecert/CMakeLists.txt
index a41cccd..de3ef92 100644
--- a/winpr/tools/makecert/CMakeLists.txt
+++ b/winpr/tools/makecert/CMakeLists.txt
@@ -32,13 +32,7 @@ endif()
winpr_tools_module_add(${${MODULE_PREFIX}_SRCS})
if(OPENSSL_FOUND)
- if(WIN32)
- list(APPEND ${MODULE_PREFIX}_LIBS ${OPENSSL_LIBRARIES})
- else()
- # if ${OPENSSL_LIBRARIES} libssl and libcrypto is linked
- # therefor explicitly link against libcrypto
- list(APPEND ${MODULE_PREFIX}_LIBS ${OPENSSL_CRYPTO_LIBRARIES})
- endif()
+ list(APPEND ${MODULE_PREFIX}_LIBS ${OPENSSL_LIBRARIES})
endif()
if(MBEDTLS_FOUND)