diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 01:25:12 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-04 01:25:12 +0000 |
commit | 827a4c3faa27e0c186452585b15094eee1119085 (patch) | |
tree | e6a08b0c767863d66f7d4a9de80db5edc7db29be | |
parent | Releasing progress-linux version 3.3.0+dfsg1-1~progress7.99u1. (diff) | |
download | freerdp3-827a4c3faa27e0c186452585b15094eee1119085.tar.xz freerdp3-827a4c3faa27e0c186452585b15094eee1119085.zip |
Merging upstream version 3.5.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
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() @@ -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. @@ -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><Right CTRL></term> + <listitem><para>releases keyboard and mouse grab</para></listitem> + </varlistentry> + <varlistentry> + <term><CTRL>+<ALT>+<Return></term> + <listitem><para>toggles fullscreen state of the application</para></listitem> + </varlistentry> + <varlistentry> + <term><CTRL>+<ALT>+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:<path>.</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, ¤t, limit, "[], ", "\r\n")) != NULL) - ; + do + { + cur = print_token(cur, start_offset + 1, ¤t, 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, ¤t, limit, " ", "\r\n")) != NULL) - ; + do + { + cur = print_token(cur, start_offset, ¤t, 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(®ion); + if (!rfx_process_message(context, Data, (UINT32)Size, 0, 0, dest, FORMAT, (UINT32)stride, + IMG_HEIGHT, ®ion)) + goto fail; + + region16_clear(®ion); + if (!rfx_process_message(context, Data, (UINT32)Size, 0, 0, dest, FORMAT, (UINT32)stride, + IMG_HEIGHT, ®ion)) + goto fail; + region16_print(®ion); + + rc = 0; +fail: + region16_uninit(®ion); + 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, ðernet) || !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) |