From 5a9772fdc85fecb7337184707f474e5788ebd87e Mon Sep 17 00:00:00 2001 From: Packit Service Date: Dec 09 2020 13:35:23 +0000 Subject: freerdp-2.1.1 base --- diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..33a6584 --- /dev/null +++ b/.clang-format @@ -0,0 +1,125 @@ +--- +AccessModifierOffset: -2 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: false +AlignConsecutiveDeclarations: false +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: true +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: false +AllowShortFunctionsOnASingleLine: None +AllowShortIfStatementsOnASingleLine: false +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: true +BinPackParameters: true +BraceWrapping: + AfterClass: true + AfterControlStatement: true + AfterEnum: true + AfterFunction: true + AfterNamespace: true + AfterObjCDeclaration: true + AfterStruct: true + AfterUnion: true + AfterExternBlock: true + BeforeCatch: true + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Allman +BreakBeforeInheritanceComma: false +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: false +BreakConstructorInitializers: BeforeColon +BreakStringLiterals: true +ColumnLimit: 100 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: false +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: false +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: false +IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: true +IndentPPDirectives: None +IndentWidth: 4 +IndentWrappedFunctionNames: false +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 60 +PointerAlignment: Left +ReflowComments: true +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: false +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: false +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +TabWidth: 4 +UseTab: ForIndentation +... +Language: Cpp +Standard: Auto +NamespaceIndentation: All +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +... +Language: ObjC +PointerBindsToType: false +ObjCSpaceAfterProperty: true +SortIncludes: false +ObjCBlockIndentWidth: 4 +ObjCSpaceAfterProperty: false +ObjCSpaceBeforeProtocolList: true +... +Language: Java +BreakAfterJavaFieldAnnotations: false +... +Language: JavaScript +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +... +Language: Proto +... +Language: TableGen +... +Language: TextProto +... diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 4d3c855..8ee9f39 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -30,7 +30,7 @@ A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. -** Application details +**Application details** * Version of FreeRDP * Command line used * output of `/buildconfig` diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index f76bc12..91a1cef 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -5,7 +5,8 @@ ## Preparations before creating a pull * Rebase your branch to current master, no merges allowed! * Try to clean up your commit history, group changes to commits -* Check your formatting! A _astyle_ script can be found at ```./scripts/format_code.sh``` +* Check your formatting! A _clang-format_ script can be found at ```.clang-format``` + * The cmake target ```clangformat``` reformats the whole codebase * Optional (but higly recommended) * Run a clang scanbuild before and after your changes to avoid introducing new bugs * Run your compiler at pedantic level to check for new warnings diff --git a/.gitignore b/.gitignore index b63a86e..c844922 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ +#ninja +.ninja_deps +.ninja_log +build.ninja +rules.ninja + # CMake CMakeFiles/ CMakeScripts/ @@ -80,6 +86,8 @@ RelWithDebInfo *.embed.manifest* *.intermediate.manifest* version.rc +*.VC.db +*.VC.opendb # Binaries *.a @@ -93,10 +101,10 @@ cunit/test_freerdp client/X11/xfreerdp client/Mac/xcode client/Sample/sfreerdp -client/DirectFB/dfreerdp client/Wayland/wlfreerdp server/Sample/sfreerdp-server server/X11/xfreerdp-server +server/proxy/freerdp-proxy xcode libfreerdp/codec/test/TestOpenH264ASM @@ -124,7 +132,7 @@ TAGS # generated packages *.zip *.exe -*.sh +#*.sh *.deb *.rpm *.dmg @@ -132,7 +140,7 @@ TAGS *.tar.gz # packaging related files -!packaging/scripts/prepare_deb_freerdp-nightly.sh +!packaging/**.sh packaging/deb/freerdp-nightly/freerdp-nightly packaging/deb/freerdp-nightly/freerdp-nightly-dev packaging/deb/freerdp-nightly/freerdp-nightly-dbg @@ -142,4 +150,5 @@ packaging/deb/freerdp-nightly/freerdp-nightly-dbg .idea # VisualStudio Code -.vscode \ No newline at end of file +.vscode +cache/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 0199269..1d685b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,10 @@ endif() include(CheckCmakeCompat) # Include cmake modules +if(WITH_CLANG_FORMAT) + include(ClangFormat) +endif() + include(CheckIncludeFiles) include(CheckLibraryExists) include(CheckSymbolExists) @@ -77,22 +81,22 @@ if ($ENV{BUILD_NUMBER}) endif() set(WITH_LIBRARY_VERSIONING "ON") -set(RAW_VERSTION_STRING "2.0.0-rc4") +set(RAW_VERSION_STRING "2.1.1") if(EXISTS "${CMAKE_SOURCE_DIR}/.source_tag") - file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSTION_STRING) + file(READ ${CMAKE_SOURCE_DIR}/.source_tag RAW_VERSION_STRING) elseif(USE_VERSION_FROM_GIT_TAG) git_get_exact_tag(_GIT_TAG --tags --always) if (NOT ${_GIT_TAG} STREQUAL "n/a") - set(RAW_VERSTION_STRING ${_GIT_TAG}) + set(RAW_VERSION_STRING ${_GIT_TAG}) endif() endif() -string(STRIP ${RAW_VERSTION_STRING} RAW_VERSTION_STRING) +string(STRIP ${RAW_VERSION_STRING} RAW_VERSION_STRING) set(VERSION_REGEX "^.?([0-9]+)\\.([0-9]+)\\.([0-9]+)-?(.*)") -string(REGEX REPLACE "${VERSION_REGEX}" "\\1" FREERDP_VERSION_MAJOR "${RAW_VERSTION_STRING}") -string(REGEX REPLACE "${VERSION_REGEX}" "\\2" FREERDP_VERSION_MINOR "${RAW_VERSTION_STRING}") -string(REGEX REPLACE "${VERSION_REGEX}" "\\3" FREERDP_VERSION_REVISION "${RAW_VERSTION_STRING}") -string(REGEX REPLACE "${VERSION_REGEX}" "\\4" FREERDP_VERSION_SUFFIX "${RAW_VERSTION_STRING}") +string(REGEX REPLACE "${VERSION_REGEX}" "\\1" FREERDP_VERSION_MAJOR "${RAW_VERSION_STRING}") +string(REGEX REPLACE "${VERSION_REGEX}" "\\2" FREERDP_VERSION_MINOR "${RAW_VERSION_STRING}") +string(REGEX REPLACE "${VERSION_REGEX}" "\\3" FREERDP_VERSION_REVISION "${RAW_VERSION_STRING}") +string(REGEX REPLACE "${VERSION_REGEX}" "\\4" FREERDP_VERSION_SUFFIX "${RAW_VERSION_STRING}") set(FREERDP_API_VERSION "${FREERDP_VERSION_MAJOR}") set(FREERDP_VERSION "${FREERDP_VERSION_MAJOR}.${FREERDP_VERSION_MINOR}.${FREERDP_VERSION_REVISION}") @@ -365,7 +369,7 @@ if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang" OR CMAKE_COMPILER_IS_GNUCC) endif(fsanitize-address-use-after-scope) else(fsanitize-address) - message(WARNING "Missing support for address sanitizer!") + message(WARNING "Missing support for address sanitizer!") endif(fsanitize-address) if(fno-omit-frame-pointer) @@ -397,7 +401,7 @@ if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang" OR CMAKE_COMPILER_IS_GNUCC) endif(fsanitize-memory-track-origins) else(fsanitize-memory) - message(WARNING "Missing support for memory sanitizer!") + message(WARNING "Missing support for memory sanitizer!") endif(fsanitize-memory) if(fno-omit-frame-pointer) @@ -416,7 +420,7 @@ if(${CMAKE_C_COMPILER_ID} STREQUAL "Clang" OR CMAKE_COMPILER_IS_GNUCC) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -fsanitize=thread") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fsanitize=thread") else(fsanitize-thread) - message(WARNING "Missing support for thread sanitizer!") + message(WARNING "Missing support for thread sanitizer!") endif(fsanitize-thread) if(fno-omit-frame-pointer) @@ -482,7 +486,7 @@ if(WIN32) add_definitions(-D_WINSOCK_DEPRECATED_NO_WARNINGS) set(CMAKE_USE_RELATIVE_PATH ON) - if (${CMAKE_GENERATOR} MATCHES "NMake Makefile*" OR ${CMAKE_GENERATOR} MATCHES "Ninja*") + if (${CMAKE_GENERATOR} MATCHES "NMake Makefile*" OR ${CMAKE_GENERATOR} MATCHES "Ninja*" OR ${CMAKE_GENERATOR} MATCHES "Unix Makefiles") set(CMAKE_PDB_BINARY_DIR ${CMAKE_BINARY_DIR}) elseif (${CMAKE_GENERATOR} MATCHES "Visual Studio*") set(CMAKE_PDB_BINARY_DIR "${CMAKE_BINARY_DIR}/\${CMAKE_INSTALL_CONFIG_NAME}") @@ -490,16 +494,10 @@ if(WIN32) message(FATAL_ERROR "Unknown generator ${CMAKE_GENERATOR}") endif() - # Set product and vendor for dll and exe version information. - set(RC_VERSION_VENDOR ${VENDOR}) - set(RC_VERSION_PRODUCT ${PRODUCT}) - set(RC_VERSION_PATCH ${BUILD_NUMBER}) - set(RC_VERSION_DESCRIPTION ${GIT_REVISION}) - string(TIMESTAMP RC_VERSION_YEAR "%Y") if(NOT DEFINED CMAKE_WINDOWS_VERSION) - set(CMAKE_WINDOWS_VERSION "WINXP") + set(CMAKE_WINDOWS_VERSION "WIN7") endif() if(CMAKE_WINDOWS_VERSION STREQUAL "WINXP") @@ -512,6 +510,12 @@ if(WIN32) add_definitions(-DWINVER=0x0A00 -D_WIN32_WINNT=0x0A00) endif() + # Set product and vendor for dll and exe version information. + set(RC_VERSION_VENDOR ${VENDOR}) + set(RC_VERSION_PRODUCT ${PRODUCT}) + set(RC_VERSION_PATCH ${BUILD_NUMBER}) + set(RC_VERSION_DESCRIPTION "${FREERDP_VERSION_FULL} ${GIT_REVISION} ${CMAKE_WINDOWS_VERSION} ${CMAKE_SYSTEM_PROCESSOR}") + if (FREERDP_EXTERNAL_SSL_PATH) set(OPENSSL_ROOT_DIR ${FREERDP_EXTERNAL_SSL_PATH}) endif() @@ -611,7 +615,7 @@ if(ANDROID) endif() endif() - list (APPEND CMAKE_INCLUDE_PATH ${FREERDP_EXTERNAL_PATH}/include) + list (APPEND CMAKE_INCLUDE_PATH ${FREERDP_EXTERNAL_PATH}/${ANDROID_ABI}/include) list (APPEND CMAKE_LIBRARY_PATH ${FREERDP_EXTERNAL_PATH}/${ANDROID_ABI}/ ) set( CMAKE_FIND_ROOT_PATH_MODE_LIBRARY BOTH ) set( CMAKE_FIND_ROOT_PATH_MODE_INCLUDE BOTH ) @@ -682,10 +686,6 @@ set(X11_FEATURE_DESCRIPTION "X11 client and server") set(WAYLAND_FEATURE_PURPOSE "Wayland") set(WAYLAND_FEATURE_DESCRIPTION "Wayland client") -set(DIRECTFB_FEATURE_TYPE "OPTIONAL") -set(DIRECTFB_FEATURE_PURPOSE "DirectFB") -set(DIRECTFB_FEATURE_DESCRIPTION "DirectFB client") - set(ZLIB_FEATURE_TYPE "REQUIRED") set(ZLIB_FEATURE_PURPOSE "compression") set(ZLIB_FEATURE_DESCRIPTION "data compression") @@ -710,15 +710,15 @@ set(ALSA_FEATURE_TYPE "RECOMMENDED") set(ALSA_FEATURE_PURPOSE "sound") set(ALSA_FEATURE_DESCRIPTION "audio input, audio output and multimedia redirection") -set(PULSE_FEATURE_TYPE "OPTIONAL") +set(PULSE_FEATURE_TYPE "RECOMMENDED") set(PULSE_FEATURE_PURPOSE "sound") set(PULSE_FEATURE_DESCRIPTION "audio input, audio output and multimedia redirection") -set(CUPS_FEATURE_TYPE "OPTIONAL") +set(CUPS_FEATURE_TYPE "RECOMMENDED") set(CUPS_FEATURE_PURPOSE "printing") set(CUPS_FEATURE_DESCRIPTION "printer device redirection") -set(PCSC_FEATURE_TYPE "OPTIONAL") +set(PCSC_FEATURE_TYPE "RECOMMENDED") set(PCSC_FEATURE_PURPOSE "smart card") set(PCSC_FEATURE_DESCRIPTION "smart card device redirection") @@ -730,14 +730,6 @@ set(VAAPI_FEATURE_TYPE "OPTIONAL") set(VAAPI_FEATURE_PURPOSE "multimedia") set(VAAPI_FEATURE_DESCRIPTION "VA-API hardware acceleration for video playback") -set(GSTREAMER_0_10_FEATURE_TYPE "OPTIONAL") -set(GSTREAMER_0_10_FEATURE_PURPOSE "multimedia") -set(GSTREAMER_0_10_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback, gstreamer 0.10 version") - -set(GSTREAMER_1_0_FEATURE_TYPE "RECOMMENDED") -set(GSTREAMER_1_0_FEATURE_PURPOSE "multimedia") -set(GSTREAMER_1_0_FEATURE_DESCRIPTION "multimedia redirection, audio and video playback") - set(IPP_FEATURE_TYPE "OPTIONAL") set(IPP_FEATURE_PURPOSE "performance") set(IPP_FEATURE_DESCRIPTION "Intel Integrated Performance Primitives library") @@ -754,6 +746,10 @@ set(OPENH264_FEATURE_TYPE "OPTIONAL") set(OPENH264_FEATURE_PURPOSE "codec") set(OPENH264_FEATURE_DESCRIPTION "use OpenH264 library") +set(OPENCL_FEATURE_TYPE "OPTIONAL") +set(OPENCL_FEATURE_PURPOSE "codec") +set(OPENCL_FEATURE_DESCRIPTION "use OpenCL library") + set(GSM_FEATURE_TYPE "OPTIONAL") set(GSM_FEATURE_PURPOSE "codec") set(GSM_FEATURE_DESCRIPTION "GSM audio codec library") @@ -782,7 +778,6 @@ if(WIN32) set(X11_FEATURE_TYPE "DISABLED") set(WAYLAND_FEATURE_TYPE "DISABLED") set(ZLIB_FEATURE_TYPE "DISABLED") - set(DIRECTFB_FEATURE_TYPE "DISABLED") set(OSS_FEATURE_TYPE "DISABLED") set(ALSA_FEATURE_TYPE "DISABLED") set(PULSE_FEATURE_TYPE "DISABLED") @@ -790,16 +785,12 @@ if(WIN32) set(PCSC_FEATURE_TYPE "DISABLED") set(FFMPEG_FEATURE_TYPE "DISABLED") set(VAAPI_FEATURE_TYPE "DISABLED") - set(GSTREAMER_1_0_FEATURE_TYPE "DISABLED") - set(GSTREAMER_0_10_FEATURE_TYPE "OPTIONAL") set(OPENSLES_FEATURE_TYPE "DISABLED") endif() if(APPLE) - set(DIRECTFB_FEATURE_TYPE "DISABLED") set(FFMPEG_FEATURE_TYPE "OPTIONAL") set(VAAPI_FEATURE_TYPE "DISABLED") - set(GSTREAMER_1_0_FEATURE_TYPE "OPTIONAL") set(X11_FEATURE_TYPE "OPTIONAL") set(WAYLAND_FEATURE_TYPE "DISABLED") set(OSS_FEATURE_TYPE "DISABLED") @@ -809,8 +800,6 @@ if(APPLE) set(PULSE_FEATURE_TYPE "DISABLED") set(CUPS_FEATURE_TYPE "DISABLED") set(PCSC_FEATURE_TYPE "DISABLED") - set(GSTREAMER_1_0_FEATURE_TYPE "DISABLED") - set(GSTREAMER_0_10_FEATURE_TYPE "DISABLED") endif() set(OPENSLES_FEATURE_TYPE "DISABLED") endif() @@ -833,7 +822,6 @@ endif(UNIX AND NOT ANDROID) if(ANDROID) set(X11_FEATURE_TYPE "DISABLED") set(WAYLAND_FEATURE_TYPE "DISABLED") - set(DIRECTFB_FEATURE_TYPE "DISABLED") set(OSS_FEATURE_TYPE "DISABLED") set(ALSA_FEATURE_TYPE "DISABLED") set(PULSE_FEATURE_TYPE "DISABLED") @@ -841,17 +829,11 @@ if(ANDROID) set(PCSC_FEATURE_TYPE "DISABLED") set(FFMPEG_FEATURE_TYPE "DISABLED") set(VAAPI_FEATURE_TYPE "DISABLED") - set(GSTREAMER_1_0_FEATURE_TYPE "DISABLED") - set(GSTREAMER_0_10_FEATURE_TYPE "DISABLED") set(OPENSLES_FEATURE_TYPE "REQUIRED") endif() find_feature(X11 ${X11_FEATURE_TYPE} ${X11_FEATURE_PURPOSE} ${X11_FEATURE_DESCRIPTION}) find_feature(Wayland ${WAYLAND_FEATURE_TYPE} ${WAYLAND_FEATURE_PURPOSE} ${WAYLAND_FEATURE_DESCRIPTION}) -find_feature(DirectFB ${DIRECTFB_FEATURE_TYPE} ${DIRECTFB_FEATURE_PURPOSE} ${DIRECTFB_FEATURE_DESCRIPTION}) -if (${WITH_DIRECTFB}) - message(WARNING "DIRECTFB is orphaned and not maintained see docs/README.directfb for details") -endif() find_feature(ZLIB ${ZLIB_FEATURE_TYPE} ${ZLIB_FEATURE_PURPOSE} ${ZLIB_FEATURE_DESCRIPTION}) find_feature(OpenSSL ${OPENSSL_FEATURE_TYPE} ${OPENSSL_FEATURE_PURPOSE} ${OPENSSL_FEATURE_DESCRIPTION}) @@ -867,12 +849,10 @@ find_feature(PCSC ${PCSC_FEATURE_TYPE} ${PCSC_FEATURE_PURPOSE} ${PCSC_FEATURE_DE find_feature(FFmpeg ${FFMPEG_FEATURE_TYPE} ${FFMPEG_FEATURE_PURPOSE} ${FFMPEG_FEATURE_DESCRIPTION}) -find_feature(GStreamer_0_10 ${GSTREAMER_0_10_FEATURE_TYPE} ${GSTREAMER_0_10_FEATURE_PURPOSE} ${GSTREAMER_0_10_FEATURE_DESCRIPTION}) -find_feature(GStreamer_1_0 ${GSTREAMER_1_0_FEATURE_TYPE} ${GSTREAMER_1_0_FEATURE_PURPOSE} ${GSTREAMER_1_0_FEATURE_DESCRIPTION}) - find_feature(JPEG ${JPEG_FEATURE_TYPE} ${JPEG_FEATURE_PURPOSE} ${JPEG_FEATURE_DESCRIPTION}) find_feature(x264 ${X264_FEATURE_TYPE} ${X264_FEATURE_PURPOSE} ${X264_FEATURE_DESCRIPTION}) find_feature(OpenH264 ${OPENH264_FEATURE_TYPE} ${OPENH264_FEATURE_PURPOSE} ${OPENH264_FEATURE_DESCRIPTION}) +find_feature(OpenCL ${OPENCL_FEATURE_TYPE} ${OPENCL_FEATURE_PURPOSE} ${OPENCL_FEATURE_DESCRIPTION}) find_feature(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRIPTION}) find_feature(LAME ${LAME_FEATURE_TYPE} ${LAME_FEATURE_PURPOSE} ${LAME_FEATURE_DESCRIPTION}) find_feature(FAAD2 ${FAAD2_FEATURE_TYPE} ${FAAD2_FEATURE_PURPOSE} ${FAAD2_FEATURE_DESCRIPTION}) @@ -881,6 +861,10 @@ find_feature(soxr ${SOXR_FEATURE_TYPE} ${SOXR_FEATURE_PURPOSE} ${SOXR_FEATURE_DE find_feature(GSSAPI ${GSSAPI_FEATURE_TYPE} ${GSSAPI_FEATURE_PURPOSE} ${GSSAPI_FEATURE_DESCRIPTION}) +if (WITH_OPENH264 AND NOT WITH_OPENH264_LOADING) + option(WITH_OPENH264_LOADING "Use LoadLibrary to load openh264 at runtime" OFF) +endif (WITH_OPENH264 AND NOT WITH_OPENH264_LOADING) + if ((WITH_FFMPEG OR WITH_DSP_FFMPEG) AND NOT FFMPEG_FOUND) message(FATAL_ERROR "FFMPEG support requested but not detected") endif() @@ -945,16 +929,13 @@ endif() if(OPENSSL_FOUND) add_definitions("-DWITH_OPENSSL") message(STATUS "Using OpenSSL Version: ${OPENSSL_VERSION}") + include_directories(${OPENSSL_INCLUDE_DIR}) endif() if(MBEDTLS_FOUND) add_definitions("-DWITH_MBEDTLS") endif() -if (TARGET_ARCH MATCHES "sparc") - set(HAVE_ALIGNED_REQUIRED 1) -endif() - if (WITH_X264 OR WITH_OPENH264 OR WITH_MEDIA_FOUNDATION OR WITH_FFMPEG) set(WITH_GFX_H264 ON) else() @@ -963,23 +944,34 @@ endif() # Android expects all libraries to be loadable # without paths. -if (ANDROID) - set(FREERDP_DATA_PATH "share") - set(FREERDP_INSTALL_PREFIX ".") - set(FREERDP_LIBRARY_PATH ".") - set(FREERDP_PLUGIN_PATH ".") - set(FREERDP_ADDIN_PATH ".") -else (ANDROID) +if (ANDROID OR WIN32 OR MAC_BUNDLE) + set(FREERDP_DATA_PATH "share") + if (NOT FREERDP_INSTALL_PREFIX) + set(FREERDP_INSTALL_PREFIX ".") + endif() + set(FREERDP_LIBRARY_PATH ".") + set(FREERDP_PLUGIN_PATH ".") +else() set(FREERDP_DATA_PATH "${CMAKE_INSTALL_PREFIX}/share/freerdp${FREERDP_VERSION_MAJOR}") - set(FREERDP_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + if (NOT FREERDP_INSTALL_PREFIX) + set(FREERDP_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + endif() set(FREERDP_LIBRARY_PATH "${CMAKE_INSTALL_LIBDIR}") set(FREERDP_PLUGIN_PATH "${CMAKE_INSTALL_LIBDIR}/freerdp${FREERDP_VERSION_MAJOR}") - set(FREERDP_ADDIN_PATH "${FREERDP_PLUGIN_PATH}") -endif(ANDROID) +endif() +set(FREERDP_ADDIN_PATH "${FREERDP_PLUGIN_PATH}") # Path to put extensions set(FREERDP_EXTENSION_PATH "${CMAKE_INSTALL_FULL_LIBDIR}/freerdp${FREERDP_VERSION_MAJOR}/extensions") +# Proxy plugins path +if(NOT DEFINED PROXY_PLUGINDIR) + message("using default plugins location") + set(FREERDP_PROXY_PLUGINDIR "${CMAKE_BINARY_DIR}/server/proxy/plugins") +else() + set(FREERDP_PROXY_PLUGINDIR "${PROXY_PLUGINDIR}") +endif() + # Include directories include_directories(${CMAKE_CURRENT_BINARY_DIR}) include_directories(${CMAKE_CURRENT_BINARY_DIR}/include) @@ -1062,7 +1054,7 @@ add_subdirectory(include) add_subdirectory(libfreerdp) if (IOS) - set(CMAKE_OSX_DEPLOYMENT_TARGET "") + set(CMAKE_OSX_DEPLOYMENT_TARGET "10.0") if (IOS_PLATFORM MATCHES "SIMULATOR") set(CMAKE_OSX_SYSROOT "iphonesimulator") else() diff --git a/ChangeLog b/ChangeLog index b7f6656..593cb89 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,83 @@ +# 2020-05-20 Version 2.1.1 + +Important notes: +* CVE: GHSL-2020-100 OOB Read in ntlm_read_ChallengeMessage +* CVE: GHSL-2020-101 OOB Read in security_fips_decrypt due to uninitialized value +* CVE: GHSL-2020-102 OOB Write in crypto_rsa_common +* Enforce synchronous legacy RDP encryption count (#6156) +* Fixed some leaks and crashes missed in 2.1.0 +* Removed dynamic channel listener limits +* Lots of resource cleanup fixes (clang sanitizers) +* A couple of performance improvements +* Various small annoyances eliminated (typos, prefilled username for windows client, ...) + + +For a complete and detailed change log since the last release candidate run: +git log 2.1.0..2.1.1 + + +# 2020-05-05 Version 2.1.0 + +Important notes: + +* fix multiple CVEs: CVE-2020-11039, CVE-2020-11038, CVE-2020-11043, CVE-2020-11040, CVE-2020-11041, + CVE-2020-11019, CVE-2020-11017, CVE-2020-11018 +* fix multiple leak and crash issues (#6129, #6128, #6127, #6110, #6081, #6077) + +Noteworthy features and improvements: +* Fixed sound issues (#6043) +* New expert command line options /tune and /tune-list to modify all client + settings in a generic way. +* Fixes for smartcard cache, this improves compatibility of smartcard devices + with newer smartcard channel. +* Shadow server can now be instructed to listen to multiple interfaces. +* Improved server certificate support (#6052) +* Various fixes for wayland client (fullscreen, mouse wheel, ...) +* Fixed large mouse pointer support, now mouse pointers > 96x96 pixel are visible. +* USB redirection command line improvements (filter options) +* Various translation improvements for android and ios clients + +For a complete and detailed change log since the last release candidate run: +git log 2.0.0..2.1.0 + + +# 2020-04-09 Version 2.0.0 + +Important notes: + +* fix multiple CVEs: CVE-2020-11521 CVE-2020-11522 CVE-2020-11523 CVE-2020-11524 CVE-2020-11525 CVE-2020-11526 +* fix multiple other security related issues (#6005, #6006, #6007, #6008, #6009, #6010, #6011, #6012, #6013) +* sha256 is now used instead of sha1 to fingerprint certificates. This will + invalidate all hosts in FreeRDP known_hosts2 file and causes a prompt if a + new connection is established after the update + +Noteworthy features and improvements: + +* First version of the RDP proxy was added (#5372) - thanks to @kubistika +* Smartcard received some refactoring. Missing functions were added and input + validation was improved (#5884) +* A new option /cert that unifies all certificate related options (#5880) + The old options (cert-ignore, cert-deny, cert-name, cert-tofu) are still + available but marked as deprecated +* Support for Remote Assistance Protocol Version 2 [MS-RA] +* The DirectFB client was removed because it was unmaintained +* Unified initialization of OrderSupport +* Fix for licensing against Windows Server 2003 +* Font smoothing is now enabled per default +* Flatpack support was added +* Smart scaling for Wayland using libcairo was added (#5215) +* Unified update->BeginPaint and update->EndPaint +* An image scaling API for software drawing was added +* Rail was updated to the latest spec version 28.0 +* Support for H.264 in the shadow server is now detected at runtime +* Add mask= option for /gfx and /gfx-h264 (#5771) +* Code reformatting (#5667) +* A new option /timeout was added to adjust the TCP ACK timeout (#5987) + +For a complete and detailed change log since the last release candidate run: +git log 2.0.0-rc4..2.0.0 + + # 2018-11-19 Version 2.0.0-rc4 FreeRDP 2.0.0-rc4 is the fifth release candidate for 2.0.0. Although it mainly diff --git a/README.md b/README.md new file mode 100644 index 0000000..70cf40d --- /dev/null +++ b/README.md @@ -0,0 +1,30 @@ +# FreeRDP: A Remote Desktop Protocol Implementation + +FreeRDP is a free implementation of the Remote Desktop Protocol (RDP), released under the Apache license. +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. + +## Resources + +Project website: https://www.freerdp.com/ +Issue tracker: https://github.com/FreeRDP/FreeRDP/issues +Sources: https://github.com/FreeRDP/FreeRDP/ +Downloads: https://pub.freerdp.com/releases/ +Wiki: https://github.com/FreeRDP/FreeRDP/wiki +API documentation: https://pub.freerdp.com/api/ + +IRC channel: #freerdp @ irc.freenode.net +Mailing list: https://lists.sourceforge.net/lists/listinfo/freerdp-devel + +## Microsoft Open Specifications + +Information regarding the Microsoft Open Specifications can be found at: +http://www.microsoft.com/openspecifications/ + +A list of reference documentation is maintained here: +https://github.com/FreeRDP/FreeRDP/wiki/Reference-Documentation + +## Compilation + +Instructions on how to get started compiling FreeRDP can be found on the wiki: +https://github.com/FreeRDP/FreeRDP/wiki/Compilation diff --git a/channels/CMakeLists.txt b/channels/CMakeLists.txt index 76a5716..882fef7 100644 --- a/channels/CMakeLists.txt +++ b/channels/CMakeLists.txt @@ -32,7 +32,8 @@ macro(define_channel_options) string(TOUPPER "CHANNEL_${CHANNEL_NAME}" CHANNEL_OPTION) string(TOUPPER "CHANNEL_${CHANNEL_NAME}_CLIENT" CHANNEL_CLIENT_OPTION) string(TOUPPER "CHANNEL_${CHANNEL_NAME}_SERVER" CHANNEL_SERVER_OPTION) - + string(TOUPPER "${CHANNEL_TYPE}" CHANNEL_TYPE) + if(${${CHANNEL_CLIENT_OPTION}}) set(OPTION_CLIENT_DEFAULT ${${CHANNEL_CLIENT_OPTION}}) endif() @@ -52,23 +53,30 @@ macro(define_channel_options) set(CHANNEL_DEFAULT ${OPTION_DEFAULT}) set(CHANNEL_OPTION_DOC "Build ${CHANNEL_NAME} ${CHANNEL_TYPE} channel") - option(${CHANNEL_OPTION} "${CHANNEL_OPTION_DOC}" ${CHANNEL_DEFAULT}) + + if ("${CHANNEL_TYPE}" STREQUAL "DYNAMIC") + CMAKE_DEPENDENT_OPTION(${CHANNEL_OPTION} "${CHANNEL_OPTION_DOC}" ${CHANNEL_DEFAULT} "CHANNEL_DRDYNVC" OFF) + else() + option(${CHANNEL_OPTION} "${CHANNEL_OPTION_DOC}" ${CHANNEL_DEFAULT}) + endif() endmacro(define_channel_options) macro(define_channel_client_options _channel_client_default) string(TOUPPER "CHANNEL_${CHANNEL_NAME}_CLIENT" CHANNEL_CLIENT_OPTION) + string(TOUPPER "CHANNEL_${CHANNEL_NAME}" CHANNEL_OPTION) set(CHANNEL_CLIENT_OPTION_DOC "Build ${CHANNEL_NAME} ${CHANNEL_TYPE} channel client") - option(${CHANNEL_CLIENT_OPTION} "${CHANNEL_CLIENT_OPTION_DOC}" ${_channel_client_default}) - cmake_dependent_option(${CHANNEL_CLIENT_OPTION} "${CHANNEL_CLIENT_OPTION_DOC}" + + CMAKE_DEPENDENT_OPTION(${CHANNEL_CLIENT_OPTION} "${CHANNEL_CLIENT_OPTION_DOC}" ${_channel_client_default} "${CHANNEL_OPTION}" OFF) endmacro(define_channel_client_options) macro(define_channel_server_options _channel_server_default) string(TOUPPER "CHANNEL_${CHANNEL_NAME}_SERVER" CHANNEL_SERVER_OPTION) + string(TOUPPER "CHANNEL_${CHANNEL_NAME}" CHANNEL_OPTION) set(CHANNEL_SERVER_OPTION_DOC "Build ${CHANNEL_NAME} ${CHANNEL_TYPE} channel server") - option(${CHANNEL_SERVER_OPTION} "${CHANNEL_SERVER_OPTION_DOC}" ${_channel_server_default}) - cmake_dependent_option(${CHANNEL_SERVER_OPTION} "${CHANNEL_SERVER_OPTION_DOC}" + + CMAKE_DEPENDENT_OPTION(${CHANNEL_SERVER_OPTION} "${CHANNEL_SERVER_OPTION_DOC}" ${_channel_server_default} "${CHANNEL_OPTION}" OFF) endmacro(define_channel_server_options) @@ -167,7 +175,12 @@ macro(client_channel_install _targets _destination) endmacro(client_channel_install) macro(add_channel_client_library _module_prefix _module_name _channel_name _dynamic _entry) - if(${_dynamic} AND (NOT BUILTIN_CHANNELS)) + set(_lnk_dir ${${_module_prefix}_LINK_DIRS}) + if (NOT "${_lnk_dir}" STREQUAL "") + link_directories(${_lnk_dir}) + endif() + + if(${_dynamic} AND (NOT BUILTIN_CHANNELS)) # On windows create dll version information. # Vendor, product and year are already set in top level CMakeLists.txt if (WIN32) @@ -185,22 +198,30 @@ macro(add_channel_client_library _module_prefix _module_name _channel_name _dyna set ( ${_module_prefix}_SRCS ${${_module_prefix}_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc) endif() - add_library(${_module_name} ${${_module_prefix}_SRCS}) - client_channel_install(${_module_name} ${FREERDP_ADDIN_PATH}) - else() - set(${_module_prefix}_STATIC ON PARENT_SCOPE) - set(${_module_prefix}_NAME ${_module_name} PARENT_SCOPE) - set(${_module_prefix}_CHANNEL ${_channel_name} PARENT_SCOPE) - set(${_module_prefix}_ENTRY ${_entry} PARENT_SCOPE) - add_library(${_module_name} STATIC ${${_module_prefix}_SRCS}) - if (${CMAKE_VERSION} VERSION_LESS 2.8.12 OR NOT BUILD_SHARED_LIBS) - client_channel_install(${_module_name} ${FREERDP_ADDIN_PATH}) - endif() - endif() + add_library(${_module_name} ${${_module_prefix}_SRCS}) + target_link_libraries(${_module_name} ${${_module_prefix}_LIBS}) + client_channel_install(${_module_name} ${FREERDP_ADDIN_PATH}) + else() + set(${_module_prefix}_STATIC ON PARENT_SCOPE) + set(${_module_prefix}_NAME ${_module_name} PARENT_SCOPE) + set(${_module_prefix}_CHANNEL ${_channel_name} PARENT_SCOPE) + set(${_module_prefix}_ENTRY ${_entry} PARENT_SCOPE) + add_library(${_module_name} STATIC ${${_module_prefix}_SRCS}) + target_link_libraries(${_module_name} ${${_module_prefix}_LIBS}) + + if (${CMAKE_VERSION} VERSION_LESS 2.8.12 OR NOT BUILD_SHARED_LIBS) + client_channel_install(${_module_name} ${FREERDP_ADDIN_PATH}) + endif() + endif() endmacro(add_channel_client_library) macro(add_channel_client_subsystem_library _module_prefix _module_name _channel_name _type _dynamic _entry) - if(${_dynamic} AND (NOT BUILTIN_CHANNELS)) + set(_lnk_dir ${${_module_prefix}_LINK_DIRS}) + if (NOT "${_lnk_dir}" STREQUAL "") + link_directories(${_lnk_dir}) + endif() + + if(${_dynamic} AND (NOT BUILTIN_CHANNELS)) # On windows create dll version information. # Vendor, product and year are already set in top level CMakeLists.txt if (WIN32) @@ -218,21 +239,29 @@ macro(add_channel_client_subsystem_library _module_prefix _module_name _channel_ set ( ${_module_prefix}_SRCS ${${_module_prefix}_SRCS} ${CMAKE_CURRENT_BINARY_DIR}/version.rc) endif() - add_library(${_module_name} ${${_module_prefix}_SRCS}) - client_channel_install(${_module_name} ${FREERDP_ADDIN_PATH}) - else() - set(${_module_prefix}_STATIC ON PARENT_SCOPE) - set(${_module_prefix}_NAME ${_module_name} PARENT_SCOPE) - set(${_module_prefix}_TYPE ${_type} PARENT_SCOPE) - add_library(${_module_name} STATIC ${${_module_prefix}_SRCS}) - if (${CMAKE_VERSION} VERSION_LESS 2.8.12 OR NOT BUILD_SHARED_LIBS) - client_channel_install(${_module_name} ${FREERDP_ADDIN_PATH}) - endif() - endif() + add_library(${_module_name} ${${_module_prefix}_SRCS}) + target_link_libraries(${_module_name} ${${_module_prefix}_LIBS}) + client_channel_install(${_module_name} ${FREERDP_ADDIN_PATH}) + else() + set(${_module_prefix}_STATIC ON PARENT_SCOPE) + set(${_module_prefix}_NAME ${_module_name} PARENT_SCOPE) + set(${_module_prefix}_TYPE ${_type} PARENT_SCOPE) + + add_library(${_module_name} STATIC ${${_module_prefix}_SRCS}) + target_link_libraries(${_module_name} ${${_module_prefix}_LIBS}) + if (${CMAKE_VERSION} VERSION_LESS 2.8.12 OR NOT BUILD_SHARED_LIBS) + client_channel_install(${_module_name} ${FREERDP_ADDIN_PATH}) + endif() + endif() endmacro(add_channel_client_subsystem_library) macro(add_channel_server_library _module_prefix _module_name _channel_name _dynamic _entry) - if(${_dynamic} AND (NOT BUILTIN_CHANNELS)) + set(_lnk_dir ${${_module_prefix}_LINK_DIRS}) + if (NOT "${_lnk_dir}" STREQUAL "") + link_directories(${_lnk_dir}) + endif() + + if(${_dynamic} AND (NOT BUILTIN_CHANNELS)) # On windows create dll version information. # Vendor, product and year are already set in top level CMakeLists.txt if (WIN32) @@ -266,6 +295,23 @@ endmacro(add_channel_server_library) set(FILENAME "ChannelOptions.cmake") file(GLOB FILEPATHS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} "*/${FILENAME}") +# We need special treatement for drdynvc: +# It needs to be the first entry so that every +# dynamic channel has the dependent options available. +set(DRDYNVC_MATCH "") + +foreach(FILEPATH ${FILEPATHS}) + if(${FILEPATH} MATCHES "^([^/]*)drdynvc/+${FILENAME}") + set(DRDYNVC_MATCH ${FILEPATH}) + endif() +endforeach() + +if (NOT "${DRDYNVC_MATCH}" STREQUAL "") + list(REMOVE_ITEM FILEPATHS ${DRDYNVC_MATCH}) + list(APPEND FILEPATHS ${DRDYNVC_MATCH}) + list(REVERSE FILEPATHS) # list PREPEND is not available on old CMake3 +endif() + foreach(FILEPATH ${FILEPATHS}) if(${FILEPATH} MATCHES "^([^/]*)/+${FILENAME}") string(REGEX REPLACE "^([^/]*)/+${FILENAME}" "\\1" DIR ${FILEPATH}) diff --git a/channels/audin/client/alsa/audin_alsa.c b/channels/audin/client/alsa/audin_alsa.c index 169422a..60e9fd8 100644 --- a/channels/audin/client/alsa/audin_alsa.c +++ b/channels/audin/client/alsa/audin_alsa.c @@ -87,34 +87,36 @@ static snd_pcm_format_t audin_alsa_format(UINT32 wFormatTag, UINT32 bitPerChanne } } -static BOOL audin_alsa_set_params(AudinALSADevice* alsa, - snd_pcm_t* capture_handle) +static BOOL audin_alsa_set_params(AudinALSADevice* alsa, snd_pcm_t* capture_handle) { int error; + SSIZE_T s; UINT32 channels = alsa->aformat.nChannels; snd_pcm_hw_params_t* hw_params; - snd_pcm_format_t format = audin_alsa_format(alsa->aformat.wFormatTag, alsa->aformat.wBitsPerSample); + snd_pcm_format_t format = + audin_alsa_format(alsa->aformat.wFormatTag, alsa->aformat.wBitsPerSample); if ((error = snd_pcm_hw_params_malloc(&hw_params)) < 0) { - WLog_Print(alsa->log, WLOG_ERROR, "snd_pcm_hw_params_malloc (%s)", - snd_strerror(error)); + WLog_Print(alsa->log, WLOG_ERROR, "snd_pcm_hw_params_malloc (%s)", snd_strerror(error)); return FALSE; } snd_pcm_hw_params_any(capture_handle, hw_params); - snd_pcm_hw_params_set_access(capture_handle, hw_params, - SND_PCM_ACCESS_RW_INTERLEAVED); + snd_pcm_hw_params_set_access(capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED); snd_pcm_hw_params_set_format(capture_handle, hw_params, format); - snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, - &alsa->aformat.nSamplesPerSec, NULL); - snd_pcm_hw_params_set_channels_near(capture_handle, hw_params, - &channels); + snd_pcm_hw_params_set_rate_near(capture_handle, hw_params, &alsa->aformat.nSamplesPerSec, NULL); + snd_pcm_hw_params_set_channels_near(capture_handle, hw_params, &channels); snd_pcm_hw_params(capture_handle, hw_params); snd_pcm_hw_params_free(hw_params); snd_pcm_prepare(capture_handle); - alsa->aformat.nChannels = channels; - alsa->bytes_per_frame = snd_pcm_format_size(format, 1) * channels; + if (channels > UINT16_MAX) + return FALSE; + s = snd_pcm_format_size(format, 1); + if ((s < 0) || (s > UINT16_MAX)) + return FALSE; + alsa->aformat.nChannels = (UINT16)channels; + alsa->bytes_per_frame = (size_t)s * channels; return TRUE; } @@ -123,12 +125,11 @@ static DWORD WINAPI audin_alsa_thread_func(LPVOID arg) long error; BYTE* buffer; snd_pcm_t* capture_handle = NULL; - AudinALSADevice* alsa = (AudinALSADevice*) arg; + AudinALSADevice* alsa = (AudinALSADevice*)arg; DWORD status; WLog_Print(alsa->log, WLOG_DEBUG, "in"); - if ((error = snd_pcm_open(&capture_handle, alsa->device_name, - SND_PCM_STREAM_CAPTURE, 0)) < 0) + if ((error = snd_pcm_open(&capture_handle, alsa->device_name, SND_PCM_STREAM_CAPTURE, 0)) < 0) { WLog_Print(alsa->log, WLOG_ERROR, "snd_pcm_open (%s)", snd_strerror(error)); error = CHANNEL_RC_INITIALIZATION_ERROR; @@ -141,7 +142,8 @@ static DWORD WINAPI audin_alsa_thread_func(LPVOID arg) goto out; } - buffer = (BYTE*) calloc(alsa->frames_per_packet + alsa->aformat.nBlockAlign, alsa->bytes_per_frame); + buffer = + (BYTE*)calloc(alsa->frames_per_packet + alsa->aformat.nBlockAlign, alsa->bytes_per_frame); if (!buffer) { @@ -181,12 +183,13 @@ static DWORD WINAPI audin_alsa_thread_func(LPVOID arg) break; } - error = alsa->receive(&alsa->aformat, - buffer, error * alsa->bytes_per_frame, alsa->user_data); + error = + alsa->receive(&alsa->aformat, buffer, error * alsa->bytes_per_frame, alsa->user_data); if (error) { - WLog_Print(alsa->log, WLOG_ERROR, "audin_alsa_thread_receive failed with error %ld", error); + WLog_Print(alsa->log, WLOG_ERROR, "audin_alsa_thread_receive failed with error %ld", + error); break; } } @@ -200,8 +203,7 @@ out: WLog_Print(alsa->log, WLOG_DEBUG, "out"); if (error && alsa->rdpcontext) - setChannelError(alsa->rdpcontext, error, - "audin_alsa_thread_func reported an error"); + setChannelError(alsa->rdpcontext, error, "audin_alsa_thread_func reported an error"); ExitThread(error); return error; @@ -214,7 +216,7 @@ out: */ static UINT audin_alsa_free(IAudinDevice* device) { - AudinALSADevice* alsa = (AudinALSADevice*) device; + AudinALSADevice* alsa = (AudinALSADevice*)device; if (alsa) free(alsa->device_name); @@ -223,8 +225,7 @@ static UINT audin_alsa_free(IAudinDevice* device) return CHANNEL_RC_OK; } -static BOOL audin_alsa_format_supported(IAudinDevice* device, - const AUDIO_FORMAT* format) +static BOOL audin_alsa_format_supported(IAudinDevice* device, const AUDIO_FORMAT* format) { if (!device || !format) return FALSE; @@ -232,8 +233,7 @@ static BOOL audin_alsa_format_supported(IAudinDevice* device, switch (format->wFormatTag) { case WAVE_FORMAT_PCM: - if (format->cbSize == 0 && - (format->nSamplesPerSec <= 48000) && + if (format->cbSize == 0 && (format->nSamplesPerSec <= 48000) && (format->wBitsPerSample == 8 || format->wBitsPerSample == 16) && (format->nChannels == 1 || format->nChannels == 2)) { @@ -261,7 +261,7 @@ static BOOL audin_alsa_format_supported(IAudinDevice* device, static UINT audin_alsa_set_format(IAudinDevice* device, const AUDIO_FORMAT* format, UINT32 FramesPerPacket) { - AudinALSADevice* alsa = (AudinALSADevice*) device; + AudinALSADevice* alsa = (AudinALSADevice*)device; if (!alsa || !format) return ERROR_INVALID_PARAMETER; @@ -280,10 +280,9 @@ static UINT audin_alsa_set_format(IAudinDevice* device, const AUDIO_FORMAT* form * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_alsa_open(IAudinDevice* device, AudinReceive receive, - void* user_data) +static UINT audin_alsa_open(IAudinDevice* device, AudinReceive receive, void* user_data) { - AudinALSADevice* alsa = (AudinALSADevice*) device; + AudinALSADevice* alsa = (AudinALSADevice*)device; if (!device || !receive || !user_data) return ERROR_INVALID_PARAMETER; @@ -297,8 +296,7 @@ static UINT audin_alsa_open(IAudinDevice* device, AudinReceive receive, goto error_out; } - if (!(alsa->thread = CreateThread(NULL, 0, - audin_alsa_thread_func, alsa, 0, NULL))) + if (!(alsa->thread = CreateThread(NULL, 0, audin_alsa_thread_func, alsa, 0, NULL))) { WLog_Print(alsa->log, WLOG_ERROR, "CreateThread failed!"); goto error_out; @@ -319,7 +317,7 @@ error_out: static UINT audin_alsa_close(IAudinDevice* device) { UINT error = CHANNEL_RC_OK; - AudinALSADevice* alsa = (AudinALSADevice*) device; + AudinALSADevice* alsa = (AudinALSADevice*)device; if (!alsa) return ERROR_INVALID_PARAMETER; @@ -331,7 +329,8 @@ static UINT audin_alsa_close(IAudinDevice* device) if (WaitForSingleObject(alsa->thread, INFINITE) == WAIT_FAILED) { error = GetLastError(); - WLog_Print(alsa->log, WLOG_ERROR, "WaitForSingleObject failed with error %"PRIu32"", error); + WLog_Print(alsa->log, WLOG_ERROR, "WaitForSingleObject failed with error %" PRIu32 "", + error); return error; } @@ -346,28 +345,24 @@ static UINT audin_alsa_close(IAudinDevice* device) return error; } -static COMMAND_LINE_ARGUMENT_A audin_alsa_args[] = -{ - { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "audio device name" }, - { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } -}; - /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, - ADDIN_ARGV* args) +static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, ADDIN_ARGV* args) { int status; DWORD flags; COMMAND_LINE_ARGUMENT_A* arg; - AudinALSADevice* alsa = (AudinALSADevice*) device; - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | - COMMAND_LINE_IGN_UNKNOWN_KEYWORD; - status = CommandLineParseArgumentsA(args->argc, args->argv, - audin_alsa_args, flags, alsa, NULL, NULL); + AudinALSADevice* alsa = (AudinALSADevice*)device; + COMMAND_LINE_ARGUMENT_A audin_alsa_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, "", + NULL, NULL, -1, NULL, "audio device name" }, + { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; + flags = + COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; + status = CommandLineParseArgumentsA(args->argc, args->argv, audin_alsa_args, flags, alsa, NULL, + NULL); if (status < 0) return ERROR_INVALID_PARAMETER; @@ -379,8 +374,7 @@ static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) continue; - CommandLineSwitchStart(arg) - CommandLineSwitchCase(arg, "dev") + CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "dev") { alsa->device_name = _strdup(arg->Value); @@ -391,16 +385,15 @@ static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, } } CommandLineSwitchEnd(arg) - } - while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); return CHANNEL_RC_OK; } #ifdef BUILTIN_CHANNELS -#define freerdp_audin_client_subsystem_entry alsa_freerdp_audin_client_subsystem_entry +#define freerdp_audin_client_subsystem_entry alsa_freerdp_audin_client_subsystem_entry #else -#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry +#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry #endif /** @@ -408,13 +401,12 @@ static UINT audin_alsa_parse_addin_args(AudinALSADevice* device, * * @return 0 on success, otherwise a Win32 error code */ -UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS - pEntryPoints) +UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) { ADDIN_ARGV* args; AudinALSADevice* alsa; UINT error; - alsa = (AudinALSADevice*) calloc(1, sizeof(AudinALSADevice)); + alsa = (AudinALSADevice*)calloc(1, sizeof(AudinALSADevice)); if (!alsa) { @@ -433,8 +425,8 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS if ((error = audin_alsa_parse_addin_args(alsa, args))) { - WLog_Print(alsa->log, WLOG_ERROR, "audin_alsa_parse_addin_args failed with errorcode %"PRIu32"!", - error); + WLog_Print(alsa->log, WLOG_ERROR, + "audin_alsa_parse_addin_args failed with errorcode %" PRIu32 "!", error); goto error_out; } @@ -456,10 +448,10 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS alsa->aformat.wFormatTag = WAVE_FORMAT_PCM; alsa->aformat.nSamplesPerSec = 44100; - if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, - (IAudinDevice*) alsa))) + if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*)alsa))) { - WLog_Print(alsa->log, WLOG_ERROR, "RegisterAudinDevice failed with error %"PRIu32"!", error); + WLog_Print(alsa->log, WLOG_ERROR, "RegisterAudinDevice failed with error %" PRIu32 "!", + error); goto error_out; } diff --git a/channels/audin/client/audin_main.c b/channels/audin/client/audin_main.c index b7ce330..26ac483 100644 --- a/channels/audin/client/audin_main.c +++ b/channels/audin/client/audin_main.c @@ -42,13 +42,13 @@ #include "audin_main.h" -#define MSG_SNDIN_VERSION 0x01 -#define MSG_SNDIN_FORMATS 0x02 -#define MSG_SNDIN_OPEN 0x03 -#define MSG_SNDIN_OPEN_REPLY 0x04 +#define MSG_SNDIN_VERSION 0x01 +#define MSG_SNDIN_FORMATS 0x02 +#define MSG_SNDIN_OPEN 0x03 +#define MSG_SNDIN_OPEN_REPLY 0x04 #define MSG_SNDIN_DATA_INCOMING 0x05 -#define MSG_SNDIN_DATA 0x06 -#define MSG_SNDIN_FORMATCHANGE 0x07 +#define MSG_SNDIN_DATA 0x06 +#define MSG_SNDIN_FORMATCHANGE 0x07 typedef struct _AUDIN_LISTENER_CALLBACK AUDIN_LISTENER_CALLBACK; struct _AUDIN_LISTENER_CALLBACK @@ -100,12 +100,14 @@ struct _AUDIN_PLUGIN FREERDP_DSP_CONTEXT* dsp_context; wLog* log; + + IWTSListener* listener; }; static BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args); static UINT audin_channel_write_and_free(AUDIN_CHANNEL_CALLBACK* callback, wStream* out, - BOOL freeStream) + BOOL freeStream) { UINT error; @@ -116,9 +118,8 @@ static UINT audin_channel_write_and_free(AUDIN_CHANNEL_CALLBACK* callback, wStre return ERROR_INTERNAL_ERROR; Stream_SealLength(out); - error = callback->channel->Write(callback->channel, - Stream_Length(out), - Stream_Buffer(out), NULL); + error = + callback->channel->Write(callback->channel, Stream_Length(out), Stream_Buffer(out), NULL); if (freeStream) Stream_Free(out, TRUE); @@ -126,7 +127,6 @@ static UINT audin_channel_write_and_free(AUDIN_CHANNEL_CALLBACK* callback, wStre return error; } - /** * Function description * @@ -142,15 +142,16 @@ static UINT audin_process_version(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* c return ERROR_INVALID_DATA; Stream_Read_UINT32(s, ServerVersion); - WLog_Print(audin->log, WLOG_DEBUG, "ServerVersion=%"PRIu32", ClientVersion=%"PRIu32, ServerVersion, - ClientVersion); + WLog_Print(audin->log, WLOG_DEBUG, "ServerVersion=%" PRIu32 ", ClientVersion=%" PRIu32, + ServerVersion, ClientVersion); /* Do not answer server packet, we do not support the channel version. */ if (ServerVersion != ClientVersion) { WLog_Print(audin->log, WLOG_WARN, - "Incompatible channel version server=%"PRIu32", client supports version=%"PRIu32, ServerVersion, - ClientVersion); + "Incompatible channel version server=%" PRIu32 + ", client supports version=%" PRIu32, + ServerVersion, ClientVersion); return CHANNEL_RC_OK; } @@ -199,11 +200,11 @@ static UINT audin_process_formats(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* c return ERROR_INVALID_DATA; Stream_Read_UINT32(s, NumFormats); - WLog_Print(audin->log, WLOG_DEBUG, "NumFormats %"PRIu32"", NumFormats); + WLog_Print(audin->log, WLOG_DEBUG, "NumFormats %" PRIu32 "", NumFormats); if ((NumFormats < 1) || (NumFormats > 1000)) { - WLog_Print(audin->log, WLOG_ERROR, "bad NumFormats %"PRIu32"", NumFormats); + WLog_Print(audin->log, WLOG_ERROR, "bad NumFormats %" PRIu32 "", NumFormats); return ERROR_INVALID_DATA; } @@ -271,11 +272,11 @@ static UINT audin_process_formats(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* c goto out; } - cbSizeFormatsPacket = (UINT32) Stream_GetPosition(out); + cbSizeFormatsPacket = (UINT32)Stream_GetPosition(out); Stream_SetPosition(out, 0); - Stream_Write_UINT8(out, MSG_SNDIN_FORMATS); /* Header (1 byte) */ + Stream_Write_UINT8(out, MSG_SNDIN_FORMATS); /* Header (1 byte) */ Stream_Write_UINT32(out, callback->formats_count); /* NumFormats (4 bytes) */ - Stream_Write_UINT32(out, cbSizeFormatsPacket); /* cbSizeFormatsPacket (4 bytes) */ + Stream_Write_UINT32(out, cbSizeFormatsPacket); /* cbSizeFormatsPacket (4 bytes) */ Stream_SetPosition(out, cbSizeFormatsPacket); error = audin_channel_write_and_free(callback, out, FALSE); out: @@ -296,7 +297,7 @@ out: * @return 0 on success, otherwise a Win32 error code */ static UINT audin_send_format_change_pdu(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callback, - UINT32 NewFormat) + UINT32 NewFormat) { wStream* out = Stream_New(NULL, 5); @@ -337,13 +338,13 @@ static UINT audin_send_open_reply_pdu(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBAC * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_receive_wave_data(const AUDIO_FORMAT* format, - const BYTE* data, size_t size, void* user_data) +static UINT audin_receive_wave_data(const AUDIO_FORMAT* format, const BYTE* data, size_t size, + void* user_data) { UINT error; BOOL compatible; AUDIN_PLUGIN* audin; - AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) user_data; + AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*)user_data; if (!callback) return CHANNEL_RC_BAD_CHANNEL_HANDLE; @@ -382,7 +383,7 @@ static UINT audin_receive_wave_data(const AUDIO_FORMAT* format, return CHANNEL_RC_OK; audio_format_print(audin->log, WLOG_TRACE, audin->format); - WLog_Print(audin->log, WLOG_TRACE, "[%"PRIdz"/%"PRIdz"]", size, + WLog_Print(audin->log, WLOG_TRACE, "[%" PRIdz "/%" PRIdz "]", size, Stream_GetPosition(audin->data) - 1); if ((error = audin_send_incoming_data_pdu(callback))) @@ -411,12 +412,7 @@ static BOOL audin_open_device(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callb if (!supported) { /* Default sample rates supported by most backends. */ - const UINT32 samplerates[] = { - 96000, - 48000, - 44100, - 22050 - }; + const UINT32 samplerates[] = { 96000, 48000, 44100, 22050 }; BOOL test = FALSE; format.wFormatTag = WAVE_FORMAT_PCM; @@ -425,7 +421,7 @@ static BOOL audin_open_device(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callb if (!test) { size_t x; - for (x=0; xdevice->FormatSupported, audin->device, &format); @@ -437,13 +433,11 @@ static BOOL audin_open_device(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callb return FALSE; } - IFCALLRET(audin->device->SetFormat, error, - audin->device, &format, - audin->FramesPerPacket); + IFCALLRET(audin->device->SetFormat, error, audin->device, &format, audin->FramesPerPacket); if (error != CHANNEL_RC_OK) { - WLog_ERR(TAG, "SetFormat failed with errorcode %"PRIu32"", error); + WLog_ERR(TAG, "SetFormat failed with errorcode %" PRIu32 "", error); return FALSE; } @@ -453,12 +447,11 @@ static BOOL audin_open_device(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* callb return FALSE; } - IFCALLRET(audin->device->Open, error, audin->device, - audin_receive_wave_data, callback); + IFCALLRET(audin->device->Open, error, audin->device, audin_receive_wave_data, callback); if (error != CHANNEL_RC_OK) { - WLog_ERR(TAG, "Open failed with errorcode %"PRIu32"", error); + WLog_ERR(TAG, "Open failed with errorcode %" PRIu32 "", error); return FALSE; } @@ -480,13 +473,13 @@ static UINT audin_process_open(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLBACK* call Stream_Read_UINT32(s, FramesPerPacket); Stream_Read_UINT32(s, initialFormat); - WLog_Print(audin->log, WLOG_DEBUG, "FramesPerPacket=%"PRIu32" initialFormat=%"PRIu32"", + WLog_Print(audin->log, WLOG_DEBUG, "FramesPerPacket=%" PRIu32 " initialFormat=%" PRIu32 "", FramesPerPacket, initialFormat); audin->FramesPerPacket = FramesPerPacket; if (initialFormat >= callback->formats_count) { - WLog_Print(audin->log, WLOG_ERROR, "invalid format index %"PRIu32" (total %d)", + WLog_Print(audin->log, WLOG_ERROR, "invalid format index %" PRIu32 " (total %d)", initialFormat, callback->formats_count); return ERROR_INVALID_DATA; } @@ -523,12 +516,12 @@ static UINT audin_process_format_change(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLB return ERROR_INVALID_DATA; Stream_Read_UINT32(s, NewFormat); - WLog_Print(audin->log, WLOG_DEBUG, "NewFormat=%"PRIu32"", NewFormat); + WLog_Print(audin->log, WLOG_DEBUG, "NewFormat=%" PRIu32 "", NewFormat); if (NewFormat >= callback->formats_count) { - WLog_Print(audin->log, WLOG_ERROR, "invalid format index %"PRIu32" (total %d)", - NewFormat, callback->formats_count); + WLog_Print(audin->log, WLOG_ERROR, "invalid format index %" PRIu32 " (total %d)", NewFormat, + callback->formats_count); return ERROR_INVALID_DATA; } @@ -540,7 +533,7 @@ static UINT audin_process_format_change(AUDIN_PLUGIN* audin, AUDIN_CHANNEL_CALLB if (error != CHANNEL_RC_OK) { - WLog_ERR(TAG, "Close failed with errorcode %"PRIu32"", error); + WLog_ERR(TAG, "Close failed with errorcode %" PRIu32 "", error); return error; } } @@ -564,12 +557,12 @@ static UINT audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, UINT error; BYTE MessageId; AUDIN_PLUGIN* audin; - AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; + AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*)pChannelCallback; if (!callback || !data) return ERROR_INVALID_PARAMETER; - audin = (AUDIN_PLUGIN*) callback->plugin; + audin = (AUDIN_PLUGIN*)callback->plugin; if (!audin) return ERROR_INTERNAL_ERROR; @@ -578,7 +571,7 @@ static UINT audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, return ERROR_NO_DATA; Stream_Read_UINT8(data, MessageId); - WLog_Print(audin->log, WLOG_DEBUG, "MessageId=0x%02"PRIx8"", MessageId); + WLog_Print(audin->log, WLOG_DEBUG, "MessageId=0x%02" PRIx8 "", MessageId); switch (MessageId) { @@ -599,7 +592,7 @@ static UINT audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, break; default: - WLog_Print(audin->log, WLOG_ERROR, "unknown MessageId=0x%02"PRIx8"", MessageId); + WLog_Print(audin->log, WLOG_ERROR, "unknown MessageId=0x%02" PRIx8 "", MessageId); error = ERROR_INVALID_DATA; break; } @@ -614,8 +607,8 @@ static UINT audin_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, */ static UINT audin_on_close(IWTSVirtualChannelCallback* pChannelCallback) { - AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*) pChannelCallback; - AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) callback->plugin; + AUDIN_CHANNEL_CALLBACK* callback = (AUDIN_CHANNEL_CALLBACK*)pChannelCallback; + AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*)callback->plugin; UINT error = CHANNEL_RC_OK; WLog_Print(audin->log, WLOG_TRACE, "..."); @@ -624,7 +617,7 @@ static UINT audin_on_close(IWTSVirtualChannelCallback* pChannelCallback) IFCALLRET(audin->device->Close, error, audin->device); if (error != CHANNEL_RC_OK) - WLog_Print(audin->log, WLOG_ERROR, "Close failed with errorcode %"PRIu32"", error); + WLog_Print(audin->log, WLOG_ERROR, "Close failed with errorcode %" PRIu32 "", error); } audin->format = NULL; @@ -639,19 +632,19 @@ static UINT audin_on_close(IWTSVirtualChannelCallback* pChannelCallback) * @return 0 on success, otherwise a Win32 error code */ static UINT audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, - IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept, - IWTSVirtualChannelCallback** ppCallback) + IWTSVirtualChannel* pChannel, BYTE* Data, + BOOL* pbAccept, IWTSVirtualChannelCallback** ppCallback) { AUDIN_CHANNEL_CALLBACK* callback; AUDIN_PLUGIN* audin; - AUDIN_LISTENER_CALLBACK* listener_callback = (AUDIN_LISTENER_CALLBACK*) pListenerCallback; + AUDIN_LISTENER_CALLBACK* listener_callback = (AUDIN_LISTENER_CALLBACK*)pListenerCallback; if (!listener_callback || !listener_callback->plugin) return ERROR_INTERNAL_ERROR; - audin = (AUDIN_PLUGIN*) listener_callback->plugin; + audin = (AUDIN_PLUGIN*)listener_callback->plugin; WLog_Print(audin->log, WLOG_TRACE, "..."); - callback = (AUDIN_CHANNEL_CALLBACK*) calloc(1, sizeof(AUDIN_CHANNEL_CALLBACK)); + callback = (AUDIN_CHANNEL_CALLBACK*)calloc(1, sizeof(AUDIN_CHANNEL_CALLBACK)); if (!callback) { @@ -664,7 +657,7 @@ static UINT audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallb callback->plugin = listener_callback->plugin; callback->channel_mgr = listener_callback->channel_mgr; callback->channel = pChannel; - *ppCallback = (IWTSVirtualChannelCallback*) callback; + *ppCallback = (IWTSVirtualChannelCallback*)callback; return CHANNEL_RC_OK; } @@ -675,7 +668,7 @@ static UINT audin_on_new_channel_connection(IWTSListenerCallback* pListenerCallb */ static UINT audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) { - AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; + AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*)pPlugin; if (!audin) return CHANNEL_RC_BAD_CHANNEL_HANDLE; @@ -684,7 +677,7 @@ static UINT audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag return ERROR_INVALID_PARAMETER; WLog_Print(audin->log, WLOG_TRACE, "..."); - audin->listener_callback = (AUDIN_LISTENER_CALLBACK*) calloc(1, sizeof(AUDIN_LISTENER_CALLBACK)); + audin->listener_callback = (AUDIN_LISTENER_CALLBACK*)calloc(1, sizeof(AUDIN_LISTENER_CALLBACK)); if (!audin->listener_callback) { @@ -696,7 +689,7 @@ static UINT audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag audin->listener_callback->plugin = pPlugin; audin->listener_callback->channel_mgr = pChannelMgr; return pChannelMgr->CreateListener(pChannelMgr, "AUDIO_INPUT", 0, - (IWTSListenerCallback*) audin->listener_callback, NULL); + &audin->listener_callback->iface, &audin->listener); } /** @@ -706,14 +699,21 @@ static UINT audin_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManag */ static UINT audin_plugin_terminated(IWTSPlugin* pPlugin) { - AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; + AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*)pPlugin; UINT error = CHANNEL_RC_OK; if (!audin) return CHANNEL_RC_BAD_CHANNEL_HANDLE; WLog_Print(audin->log, WLOG_TRACE, "..."); - audio_format_free(audin->fixed_format); + + if (audin->listener_callback) + { + IWTSVirtualChannelManager* mgr = audin->listener_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, audin->listener); + } + audio_formats_free(audin->fixed_format, 1); if (audin->device) { @@ -721,7 +721,7 @@ static UINT audin_plugin_terminated(IWTSPlugin* pPlugin) if (error != CHANNEL_RC_OK) { - WLog_Print(audin->log, WLOG_ERROR, "Free failed with errorcode %"PRIu32"", error); + WLog_Print(audin->log, WLOG_ERROR, "Free failed with errorcode %" PRIu32 "", error); // dont stop on error } @@ -739,7 +739,7 @@ static UINT audin_plugin_terminated(IWTSPlugin* pPlugin) static UINT audin_plugin_attached(IWTSPlugin* pPlugin) { - AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; + AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*)pPlugin; UINT error = CHANNEL_RC_OK; if (!audin) @@ -751,7 +751,7 @@ static UINT audin_plugin_attached(IWTSPlugin* pPlugin) static UINT audin_plugin_detached(IWTSPlugin* pPlugin) { - AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; + AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*)pPlugin; UINT error = CHANNEL_RC_OK; if (!audin) @@ -768,7 +768,7 @@ static UINT audin_plugin_detached(IWTSPlugin* pPlugin) */ static UINT audin_register_device_plugin(IWTSPlugin* pPlugin, IAudinDevice* device) { - AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*) pPlugin; + AUDIN_PLUGIN* audin = (AUDIN_PLUGIN*)pPlugin; if (audin->device) { @@ -791,8 +791,8 @@ static UINT audin_load_device_plugin(AUDIN_PLUGIN* audin, char* name, ADDIN_ARGV PFREERDP_AUDIN_DEVICE_ENTRY entry; FREERDP_AUDIN_DEVICE_ENTRY_POINTS entryPoints; UINT error; - entry = (PFREERDP_AUDIN_DEVICE_ENTRY) freerdp_load_channel_addin_entry("audin", (LPSTR) name, NULL, - 0); + entry = (PFREERDP_AUDIN_DEVICE_ENTRY)freerdp_load_channel_addin_entry("audin", (LPSTR)name, + NULL, 0); if (entry == NULL) { @@ -802,14 +802,14 @@ static UINT audin_load_device_plugin(AUDIN_PLUGIN* audin, char* name, ADDIN_ARGV return ERROR_INVALID_FUNCTION; } - entryPoints.plugin = (IWTSPlugin*) audin; + entryPoints.plugin = (IWTSPlugin*)audin; entryPoints.pRegisterAudinDevice = audin_register_device_plugin; entryPoints.args = args; entryPoints.rdpcontext = audin->rdpcontext; if ((error = entry(&entryPoints))) { - WLog_Print(audin->log, WLOG_ERROR, "%s entry returned error %"PRIu32".", name, error); + WLog_Print(audin->log, WLOG_ERROR, "%s entry returned error %" PRIu32 ".", name, error); return error; } @@ -855,29 +855,28 @@ static UINT audin_set_device_name(AUDIN_PLUGIN* audin, const char* device_name) return CHANNEL_RC_OK; } -static COMMAND_LINE_ARGUMENT_A audin_args[] = -{ - { "sys", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "subsystem" }, - { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "device" }, - { "format", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "format" }, - { "rate", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "rate" }, - { "channel", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "channel" }, - { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } -}; - BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args) { int status; DWORD flags; COMMAND_LINE_ARGUMENT_A* arg; UINT error; + COMMAND_LINE_ARGUMENT_A audin_args[] = { + { "sys", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "subsystem" }, + { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "device" }, + { "format", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "format" }, + { "rate", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "rate" }, + { "channel", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "channel" }, + { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } + }; if (!args || args->argc == 1) return TRUE; - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; - status = CommandLineParseArgumentsA(args->argc, args->argv, - audin_args, flags, audin, NULL, NULL); + flags = + COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; + status = + CommandLineParseArgumentsA(args->argc, args->argv, audin_args, flags, audin, NULL, NULL); if (status != 0) return FALSE; @@ -890,12 +889,12 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args) if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) continue; - CommandLineSwitchStart(arg) - CommandLineSwitchCase(arg, "sys") + CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "sys") { if ((error = audin_set_subsystem(audin, arg->Value))) { - WLog_Print(audin->log, WLOG_ERROR, "audin_set_subsystem failed with error %"PRIu32"!", error); + WLog_Print(audin->log, WLOG_ERROR, + "audin_set_subsystem failed with error %" PRIu32 "!", error); return FALSE; } } @@ -903,7 +902,8 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args) { if ((error = audin_set_device_name(audin, arg->Value))) { - WLog_Print(audin->log, WLOG_ERROR, "audin_set_device_name failed with error %"PRIu32"!", error); + WLog_Print(audin->log, WLOG_ERROR, + "audin_set_device_name failed with error %" PRIu32 "!", error); return FALSE; } } @@ -936,16 +936,15 @@ BOOL audin_process_addin_args(AUDIN_PLUGIN* audin, ADDIN_ARGV* args) { } CommandLineSwitchEnd(arg) - } - while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); return TRUE; } #ifdef BUILTIN_CHANNELS -#define DVCPluginEntry audin_DVCPluginEntry +#define DVCPluginEntry audin_DVCPluginEntry #else -#define DVCPluginEntry FREERDP_API DVCPluginEntry +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** @@ -966,34 +965,34 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) struct SubsystemEntry entries[] = { #if defined(WITH_PULSE) - {"pulse", ""}, + { "pulse", "" }, #endif #if defined(WITH_OSS) - {"oss", "default"}, + { "oss", "default" }, #endif #if defined(WITH_ALSA) - {"alsa", "default"}, + { "alsa", "default" }, #endif #if defined(WITH_OPENSLES) - {"opensles", "default"}, + { "opensles", "default" }, #endif #if defined(WITH_WINMM) - {"winmm", "default"}, + { "winmm", "default" }, #endif #if defined(WITH_MACAUDIO) - {"mac", "default"}, + { "mac", "default" }, #endif - {NULL, NULL} + { NULL, NULL } }; struct SubsystemEntry* entry = &entries[0]; assert(pEntryPoints); assert(pEntryPoints->GetPlugin); - audin = (AUDIN_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "audin"); + audin = (AUDIN_PLUGIN*)pEntryPoints->GetPlugin(pEntryPoints, "audin"); if (audin != NULL) return CHANNEL_RC_ALREADY_INITIALIZED; - audin = (AUDIN_PLUGIN*) calloc(1, sizeof(AUDIN_PLUGIN)); + audin = (AUDIN_PLUGIN*)calloc(1, sizeof(AUDIN_PLUGIN)); if (!audin) { @@ -1024,8 +1023,8 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) audin->iface.Attached = audin_plugin_attached; audin->iface.Detached = audin_plugin_detached; args = pEntryPoints->GetPluginData(pEntryPoints); - audin->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings( - pEntryPoints))->instance)->context; + audin->rdpcontext = + ((freerdp*)((rdpSettings*)pEntryPoints->GetRdpSettings(pEntryPoints))->instance)->context; if (args) { @@ -1037,8 +1036,10 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { if ((error = audin_load_device_plugin(audin, audin->subsystem, args))) { - WLog_Print(audin->log, WLOG_ERROR, "audin_load_device_plugin %s failed with error %"PRIu32"!", - audin->subsystem, error); + WLog_Print( + audin->log, WLOG_ERROR, + "Unable to load microphone redirection subsystem %s because of error %" PRIu32 "", + audin->subsystem, error); goto out; } } @@ -1048,17 +1049,20 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { if ((error = audin_set_subsystem(audin, entry->subsystem))) { - WLog_Print(audin->log, WLOG_ERROR, "audin_set_subsystem for %s failed with error %"PRIu32"!", + WLog_Print(audin->log, WLOG_ERROR, + "audin_set_subsystem for %s failed with error %" PRIu32 "!", entry->subsystem, error); } else if ((error = audin_set_device_name(audin, entry->device))) { - WLog_Print(audin->log, WLOG_ERROR, "audin_set_device_name for %s failed with error %"PRIu32"!", + WLog_Print(audin->log, WLOG_ERROR, + "audin_set_device_name for %s failed with error %" PRIu32 "!", entry->subsystem, error); } else if ((error = audin_load_device_plugin(audin, audin->subsystem, args))) { - WLog_Print(audin->log, WLOG_ERROR, "audin_load_device_plugin %s failed with error %"PRIu32"!", + WLog_Print(audin->log, WLOG_ERROR, + "audin_load_device_plugin %s failed with error %" PRIu32 "!", entry->subsystem, error); } @@ -1067,13 +1071,19 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) } if (audin->device == NULL) - WLog_Print(audin->log, WLOG_ERROR, "no sound device."); - - error = pEntryPoints->RegisterPlugin(pEntryPoints, "audin", (IWTSPlugin*) audin); -out: + { + /* If we have no audin device do not register plugin but still return OK or the client will + * just disconnect due to a missing microphone. */ + WLog_Print(audin->log, WLOG_ERROR, "No microphone device could be found."); + error = CHANNEL_RC_OK; + goto out; + } - if (error != CHANNEL_RC_OK) - audin_plugin_terminated((IWTSPlugin*)audin); + error = pEntryPoints->RegisterPlugin(pEntryPoints, "audin", (IWTSPlugin*)audin); + if (error == CHANNEL_RC_OK) + return error; +out: + audin_plugin_terminated((IWTSPlugin*)audin); return error; } diff --git a/channels/audin/client/audin_main.h b/channels/audin/client/audin_main.h index 83a75a4..760d3c8 100644 --- a/channels/audin/client/audin_main.h +++ b/channels/audin/client/audin_main.h @@ -33,4 +33,3 @@ #define TAG CHANNELS_TAG("audin.client") #endif /* FREERDP_CHANNEL_AUDIN_CLIENT_MAIN_H */ - diff --git a/channels/audin/client/mac/audin_mac.c b/channels/audin/client/mac/audin_mac.c index 40ba05d..e34b835 100644 --- a/channels/audin/client/mac/audin_mac.c +++ b/channels/audin/client/mac/audin_mac.c @@ -34,7 +34,11 @@ #include #define __COREFOUNDATION_CFPLUGINCOM__ 1 -#define IUNKNOWN_C_GUTS void *_reserved; void* QueryInterface; void* AddRef; void* Release +#define IUNKNOWN_C_GUTS \ + void* _reserved; \ + void* QueryInterface; \ + void* AddRef; \ + void* Release #include #include @@ -46,7 +50,7 @@ #include "audin_main.h" -#define MAC_AUDIO_QUEUE_NUM_BUFFERS 100 +#define MAC_AUDIO_QUEUE_NUM_BUFFERS 100 /* Fix for #4462: Provide type alias if not declared (Mac OS < 10.10) * https://developer.apple.com/documentation/coreaudio/audioformatid @@ -133,8 +137,8 @@ static UINT audin_mac_set_format(IAudinDevice* device, const AUDIO_FORMAT* forma mac->FramesPerPacket = FramesPerPacket; mac->format = *format; WLog_INFO(TAG, "Audio Format %s [channels=%d, samples=%d, bits=%d]", - audio_format_get_tag_string(format->wFormatTag), - format->nChannels, format->nSamplesPerSec, format->wBitsPerSample); + audio_format_get_tag_string(format->wFormatTag), format->nChannels, + format->nSamplesPerSec, format->wBitsPerSample); mac->audioFormat.mBitsPerChannel = format->wBitsPerSample; if (format->wBitsPerSample == 0) @@ -151,11 +155,8 @@ static UINT audin_mac_set_format(IAudinDevice* device, const AUDIO_FORMAT* forma return CHANNEL_RC_OK; } -static void mac_audio_queue_input_cb(void* aqData, - AudioQueueRef inAQ, - AudioQueueBufferRef inBuffer, - const AudioTimeStamp* inStartTime, - UInt32 inNumPackets, +static void mac_audio_queue_input_cb(void* aqData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, + const AudioTimeStamp* inStartTime, UInt32 inNumPackets, const AudioStreamPacketDescription* inPacketDesc) { AudinMacDevice* mac = (AudinMacDevice*)aqData; @@ -174,7 +175,7 @@ static void mac_audio_queue_input_cb(void* aqData, if (error) { - WLog_ERR(TAG, "mac->receive failed with error %"PRIu32"", error); + WLog_ERR(TAG, "mac->receive failed with error %" PRIu32 "", error); SetLastError(ERROR_INTERNAL_ERROR); } } @@ -196,7 +197,7 @@ static UINT audin_mac_close(IAudinDevice* device) if (devStat != 0) { errCode = GetLastError(); - WLog_ERR(TAG, "AudioQueueStop failed with %s [%"PRIu32"]", + WLog_ERR(TAG, "AudioQueueStop failed with %s [%" PRIu32 "]", winpr_strerror(errCode, errString, sizeof(errString)), errCode); } @@ -210,7 +211,7 @@ static UINT audin_mac_close(IAudinDevice* device) if (devStat != 0) { errCode = GetLastError(); - WLog_ERR(TAG, "AudioQueueDispose failed with %s [%"PRIu32"]", + WLog_ERR(TAG, "AudioQueueDispose failed with %s [%" PRIu32 "]", winpr_strerror(errCode, errString, sizeof(errString)), errCode); } @@ -231,13 +232,13 @@ static UINT audin_mac_open(IAudinDevice* device, AudinReceive receive, void* use size_t index; mac->receive = receive; mac->user_data = user_data; - devStat = AudioQueueNewInput(&(mac->audioFormat), mac_audio_queue_input_cb, - mac, NULL, kCFRunLoopCommonModes, 0, &(mac->audioQueue)); + devStat = AudioQueueNewInput(&(mac->audioFormat), mac_audio_queue_input_cb, mac, NULL, + kCFRunLoopCommonModes, 0, &(mac->audioQueue)); if (devStat != 0) { errCode = GetLastError(); - WLog_ERR(TAG, "AudioQueueNewInput failed with %s [%"PRIu32"]", + WLog_ERR(TAG, "AudioQueueNewInput failed with %s [%" PRIu32 "]", winpr_strerror(errCode, errString, sizeof(errString)), errCode); goto err_out; } @@ -251,20 +252,17 @@ static UINT audin_mac_open(IAudinDevice* device, AudinReceive receive, void* use if (devStat != 0) { errCode = GetLastError(); - WLog_ERR(TAG, "AudioQueueAllocateBuffer failed with %s [%"PRIu32"]", + WLog_ERR(TAG, "AudioQueueAllocateBuffer failed with %s [%" PRIu32 "]", winpr_strerror(errCode, errString, sizeof(errString)), errCode); goto err_out; } - devStat = AudioQueueEnqueueBuffer(mac->audioQueue, - mac->audioBuffers[index], - 0, - NULL); + devStat = AudioQueueEnqueueBuffer(mac->audioQueue, mac->audioBuffers[index], 0, NULL); if (devStat != 0) { errCode = GetLastError(); - WLog_ERR(TAG, "AudioQueueEnqueueBuffer failed with %s [%"PRIu32"]", + WLog_ERR(TAG, "AudioQueueEnqueueBuffer failed with %s [%" PRIu32 "]", winpr_strerror(errCode, errString, sizeof(errString)), errCode); goto err_out; } @@ -275,7 +273,7 @@ static UINT audin_mac_open(IAudinDevice* device, AudinReceive receive, void* use if (devStat != 0) { errCode = GetLastError(); - WLog_ERR(TAG, "AudioQueueStart failed with %s [%"PRIu32"]", + WLog_ERR(TAG, "AudioQueueStart failed with %s [%" PRIu32 "]", winpr_strerror(errCode, errString, sizeof(errString)), errCode); goto err_out; } @@ -304,28 +302,27 @@ static UINT audin_mac_free(IAudinDevice* device) return CHANNEL_RC_OK; } -static COMMAND_LINE_ARGUMENT_A audin_mac_args[] = -{ - { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "audio device name" }, - { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } -}; - static UINT audin_mac_parse_addin_args(AudinMacDevice* device, ADDIN_ARGV* args) { DWORD errCode; char errString[1024]; int status; - char* str_num, *eptr; + char *str_num, *eptr; DWORD flags; COMMAND_LINE_ARGUMENT_A* arg; + COMMAND_LINE_ARGUMENT_A audin_mac_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, "", + NULL, NULL, -1, NULL, "audio device name" }, + { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; + AudinMacDevice* mac = (AudinMacDevice*)device; if (args->argc == 1) return CHANNEL_RC_OK; - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; - status = CommandLineParseArgumentsA(args->argc, args->argv, audin_mac_args, flags, - mac, NULL, NULL); + flags = + COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; + status = + CommandLineParseArgumentsA(args->argc, args->argv, audin_mac_args, flags, mac, NULL, NULL); if (status < 0) return ERROR_INVALID_PARAMETER; @@ -337,8 +334,7 @@ static UINT audin_mac_parse_addin_args(AudinMacDevice* device, ADDIN_ARGV* args) if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) continue; - CommandLineSwitchStart(arg) - CommandLineSwitchCase(arg, "dev") + CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "dev") { str_num = _strdup(arg->Value); @@ -358,16 +354,15 @@ static UINT audin_mac_parse_addin_args(AudinMacDevice* device, ADDIN_ARGV* args) free(str_num); } CommandLineSwitchEnd(arg) - } - while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); return CHANNEL_RC_OK; } #ifdef BUILTIN_CHANNELS -#define freerdp_audin_client_subsystem_entry mac_freerdp_audin_client_subsystem_entry +#define freerdp_audin_client_subsystem_entry mac_freerdp_audin_client_subsystem_entry #else -#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry +#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry #endif UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) @@ -382,7 +377,7 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn if (!mac) { errCode = GetLastError(); - WLog_ERR(TAG, "calloc failed with %s [%"PRIu32"]", + WLog_ERR(TAG, "calloc failed with %s [%" PRIu32 "]", winpr_strerror(errCode, errString, sizeof(errString)), errCode); return CHANNEL_RC_NO_MEMORY; } @@ -398,13 +393,13 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn if ((error = audin_mac_parse_addin_args(mac, args))) { - WLog_ERR(TAG, "audin_mac_parse_addin_args failed with %"PRIu32"!", error); + WLog_ERR(TAG, "audin_mac_parse_addin_args failed with %" PRIu32 "!", error); goto error_out; } - if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) mac))) + if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*)mac))) { - WLog_ERR(TAG, "RegisterAudinDevice failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "RegisterAudinDevice failed with error %" PRIu32 "!", error); goto error_out; } diff --git a/channels/audin/client/opensles/audin_opensl_es.c b/channels/audin/client/opensles/audin_opensl_es.c index 549edd0..4e3efde 100644 --- a/channels/audin/client/opensles/audin_opensl_es.c +++ b/channels/audin/client/opensles/audin_opensl_es.c @@ -65,7 +65,7 @@ static UINT audin_opensles_close(IAudinDevice* device); static void audin_receive(void* context, const void* data, size_t size) { UINT error; - AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) context; + AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*)context; if (!opensles || !data) { @@ -86,39 +86,32 @@ static void audin_receive(void* context, const void* data, size_t size) */ static UINT audin_opensles_free(IAudinDevice* device) { - AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) device; + AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*)device; if (!opensles) return ERROR_INVALID_PARAMETER; - WLog_Print(opensles->log, WLOG_DEBUG, "device=%p", (void*) device); - - /* The function may have been called out of order, - * ignore duplicate requests. */ - if (!opensles) - return CHANNEL_RC_OK; + WLog_Print(opensles->log, WLOG_DEBUG, "device=%p", (void*)device); free(opensles->device_name); free(opensles); return CHANNEL_RC_OK; } -static BOOL audin_opensles_format_supported(IAudinDevice* device, - const AUDIO_FORMAT* format) +static BOOL audin_opensles_format_supported(IAudinDevice* device, const AUDIO_FORMAT* format) { - AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) device; + AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*)device; if (!opensles || !format) return FALSE; - WLog_Print(opensles->log, WLOG_DEBUG, "device=%p, format=%p", (void*) opensles, (void*) format); + WLog_Print(opensles->log, WLOG_DEBUG, "device=%p, format=%p", (void*)opensles, (void*)format); assert(format); switch (format->wFormatTag) { case WAVE_FORMAT_PCM: /* PCM */ - if (format->cbSize == 0 && - (format->nSamplesPerSec <= 48000) && + if (format->cbSize == 0 && (format->nSamplesPerSec <= 48000) && (format->wBitsPerSample == 8 || format->wBitsPerSample == 16) && (format->nChannels >= 1 && format->nChannels <= 2)) { @@ -128,9 +121,8 @@ static BOOL audin_opensles_format_supported(IAudinDevice* device, break; default: - WLog_Print(opensles->log, WLOG_DEBUG, "Encoding '%s' [0x%04X"PRIX16"] not supported", - audio_format_get_tag_string(format->wFormatTag), - format->wFormatTag); + WLog_Print(opensles->log, WLOG_DEBUG, "Encoding '%s' [0x%04X" PRIX16 "] not supported", + audio_format_get_tag_string(format->wFormatTag), format->wFormatTag); break; } @@ -142,23 +134,18 @@ static BOOL audin_opensles_format_supported(IAudinDevice* device, * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_opensles_set_format(IAudinDevice* device, - const AUDIO_FORMAT* format, UINT32 FramesPerPacket) +static UINT audin_opensles_set_format(IAudinDevice* device, const AUDIO_FORMAT* format, + UINT32 FramesPerPacket) { - AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) device; + AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*)device; if (!opensles || !format) return ERROR_INVALID_PARAMETER; - WLog_Print(opensles->log, WLOG_DEBUG, "device=%p, format=%p, FramesPerPacket=%"PRIu32"", - (void*) device, (void*) format, FramesPerPacket); + WLog_Print(opensles->log, WLOG_DEBUG, "device=%p, format=%p, FramesPerPacket=%" PRIu32 "", + (void*)device, (void*)format, FramesPerPacket); assert(format); - /* The function may have been called out of order, ignore - * requests before the device is available. */ - if (!opensles) - return CHANNEL_RC_OK; - opensles->format = *format; switch (format->wFormatTag) @@ -187,13 +174,13 @@ static UINT audin_opensles_set_format(IAudinDevice* device, break; default: - WLog_Print(opensles->log, WLOG_ERROR, "Encoding '%"PRIu16"' [%04"PRIX16"] not supported", - format->wFormatTag, + WLog_Print(opensles->log, WLOG_ERROR, + "Encoding '%" PRIu16 "' [%04" PRIX16 "] not supported", format->wFormatTag, format->wFormatTag); return ERROR_UNSUPPORTED_TYPE; } - WLog_Print(opensles->log, WLOG_DEBUG, "frames_per_packet=%"PRIu32, + WLog_Print(opensles->log, WLOG_DEBUG, "frames_per_packet=%" PRIu32, opensles->frames_per_packet); return CHANNEL_RC_OK; } @@ -203,27 +190,22 @@ static UINT audin_opensles_set_format(IAudinDevice* device, * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_opensles_open(IAudinDevice* device, AudinReceive receive, - void* user_data) +static UINT audin_opensles_open(IAudinDevice* device, AudinReceive receive, void* user_data) { - AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) device; + AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*)device; if (!opensles || !receive || !user_data) return ERROR_INVALID_PARAMETER; - WLog_Print(opensles->log, WLOG_DEBUG, "device=%p, receive=%p, user_data=%p", (void*) device, - (void*) receive, - (void*) user_data); + WLog_Print(opensles->log, WLOG_DEBUG, "device=%p, receive=%p, user_data=%p", (void*)device, + (void*)receive, (void*)user_data); if (opensles->stream) goto error_out; if (!(opensles->stream = android_OpenRecDevice( - opensles, audin_receive, - opensles->format.nSamplesPerSec, - opensles->format.nChannels, - opensles->frames_per_packet, - opensles->format.wBitsPerSample))) + opensles, audin_receive, opensles->format.nSamplesPerSec, opensles->format.nChannels, + opensles->frames_per_packet, opensles->format.wBitsPerSample))) { WLog_Print(opensles->log, WLOG_ERROR, "android_OpenRecDevice failed!"); goto error_out; @@ -244,12 +226,12 @@ error_out: */ UINT audin_opensles_close(IAudinDevice* device) { - AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) device; + AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*)device; if (!opensles) return ERROR_INVALID_PARAMETER; - WLog_Print(opensles->log, WLOG_DEBUG, "device=%p", (void*) device); + WLog_Print(opensles->log, WLOG_DEBUG, "device=%p", (void*)device); android_CloseRecDevice(opensles->stream); opensles->receive = NULL; opensles->user_data = NULL; @@ -257,31 +239,28 @@ UINT audin_opensles_close(IAudinDevice* device) return CHANNEL_RC_OK; } -static COMMAND_LINE_ARGUMENT_A audin_opensles_args[] = -{ - { - "dev", COMMAND_LINE_VALUE_REQUIRED, "", - NULL, NULL, -1, NULL, "audio device name" - }, - { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } -}; - /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_opensles_parse_addin_args(AudinOpenSLESDevice* device, - ADDIN_ARGV* args) +static UINT audin_opensles_parse_addin_args(AudinOpenSLESDevice* device, ADDIN_ARGV* args) { UINT status; DWORD flags; COMMAND_LINE_ARGUMENT_A* arg; - AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*) device; - WLog_Print(opensles->log, WLOG_DEBUG, "device=%p, args=%p", (void*) device, (void*) args); - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; - status = CommandLineParseArgumentsA(args->argc, args->argv, - audin_opensles_args, flags, opensles, NULL, NULL); + AudinOpenSLESDevice* opensles = (AudinOpenSLESDevice*)device; + COMMAND_LINE_ARGUMENT_A audin_opensles_args[] = { + { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, + "audio device name" }, + { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } + }; + + WLog_Print(opensles->log, WLOG_DEBUG, "device=%p, args=%p", (void*)device, (void*)args); + flags = + COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; + status = CommandLineParseArgumentsA(args->argc, args->argv, audin_opensles_args, flags, + opensles, NULL, NULL); if (status < 0) return status; @@ -293,8 +272,7 @@ static UINT audin_opensles_parse_addin_args(AudinOpenSLESDevice* device, if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) continue; - CommandLineSwitchStart(arg) - CommandLineSwitchCase(arg, "dev") + CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "dev") { opensles->device_name = _strdup(arg->Value); @@ -305,18 +283,15 @@ static UINT audin_opensles_parse_addin_args(AudinOpenSLESDevice* device, } } CommandLineSwitchEnd(arg) - } - while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); return CHANNEL_RC_OK; } #ifdef BUILTIN_CHANNELS -#define freerdp_audin_client_subsystem_entry \ - opensles_freerdp_audin_client_subsystem_entry +#define freerdp_audin_client_subsystem_entry opensles_freerdp_audin_client_subsystem_entry #else -#define freerdp_audin_client_subsystem_entry \ - FREERDP_API freerdp_audin_client_subsystem_entry +#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry #endif /** @@ -324,13 +299,12 @@ static UINT audin_opensles_parse_addin_args(AudinOpenSLESDevice* device, * * @return 0 on success, otherwise a Win32 error code */ -UINT freerdp_audin_client_subsystem_entry( - PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) +UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) { ADDIN_ARGV* args; AudinOpenSLESDevice* opensles; UINT error; - opensles = (AudinOpenSLESDevice*) calloc(1, sizeof(AudinOpenSLESDevice)); + opensles = (AudinOpenSLESDevice*)calloc(1, sizeof(AudinOpenSLESDevice)); if (!opensles) { @@ -350,13 +324,14 @@ UINT freerdp_audin_client_subsystem_entry( if ((error = audin_opensles_parse_addin_args(opensles, args))) { WLog_Print(opensles->log, WLOG_ERROR, - "audin_opensles_parse_addin_args failed with errorcode %"PRIu32"!", error); + "audin_opensles_parse_addin_args failed with errorcode %" PRIu32 "!", error); goto error_out; } - if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) opensles))) + if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*)opensles))) { - WLog_Print(opensles->log, WLOG_ERROR, "RegisterAudinDevice failed with error %"PRIu32"!", error); + WLog_Print(opensles->log, WLOG_ERROR, "RegisterAudinDevice failed with error %" PRIu32 "!", + error); goto error_out; } diff --git a/channels/audin/client/opensles/opensl_io.c b/channels/audin/client/opensles/opensl_io.c index 5e7fba6..be3e0b4 100644 --- a/channels/audin/client/opensles/opensl_io.c +++ b/channels/audin/client/opensles/opensl_io.c @@ -6,14 +6,14 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -32,7 +32,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "audin_main.h" #include "opensl_io.h" #define CONV16BIT 32768 -#define CONVMYFLT (1./32768.) +#define CONVMYFLT (1. / 32768.) typedef struct { @@ -66,7 +66,6 @@ struct opensl_stream opensl_receive_t receive; }; - static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void* context); // creates the OpenSL ES audio engine @@ -76,22 +75,24 @@ static SLresult openSLCreateEngine(OPENSL_STREAM* p) // create engine result = slCreateEngine(&(p->engineObject), 0, NULL, 0, NULL, NULL); - if (result != SL_RESULT_SUCCESS) goto engine_end; + if (result != SL_RESULT_SUCCESS) + goto engine_end; // realize the engine result = (*p->engineObject)->Realize(p->engineObject, SL_BOOLEAN_FALSE); - if (result != SL_RESULT_SUCCESS) goto engine_end; + if (result != SL_RESULT_SUCCESS) + goto engine_end; // get the engine interface, which is needed in order to create other objects - result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_ENGINE, - &(p->engineEngine)); + result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_ENGINE, &(p->engineEngine)); - if (result != SL_RESULT_SUCCESS) goto engine_end; + if (result != SL_RESULT_SUCCESS) + goto engine_end; // get the volume interface - important, this is optional! - result = (*p->engineObject)->GetInterface(p->engineObject, SL_IID_DEVICEVOLUME, - &(p->deviceVolume)); + result = + (*p->engineObject)->GetInterface(p->engineObject, SL_IID_DEVICEVOLUME, &(p->deviceVolume)); if (result != SL_RESULT_SUCCESS) { @@ -169,10 +170,9 @@ static SLresult openSLRecOpen(OPENSL_STREAM* p) } // configure audio source - SLDataLocator_IODevice loc_dev = {SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, - SL_DEFAULTDEVICEID_AUDIOINPUT, NULL - }; - SLDataSource audioSrc = {&loc_dev, NULL}; + SLDataLocator_IODevice loc_dev = { SL_DATALOCATOR_IODEVICE, SL_IODEVICE_AUDIOINPUT, + SL_DEFAULTDEVICEID_AUDIOINPUT, NULL }; + SLDataSource audioSrc = { &loc_dev, NULL }; // configure audio sink int speakers; @@ -181,7 +181,8 @@ static SLresult openSLRecOpen(OPENSL_STREAM* p) else speakers = SL_SPEAKER_FRONT_CENTER; - SLDataLocator_AndroidSimpleBufferQueue loc_bq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2}; + SLDataLocator_AndroidSimpleBufferQueue loc_bq = { SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, + 2 }; SLDataFormat_PCM format_pcm; format_pcm.formatType = SL_DATAFORMAT_PCM; format_pcm.numChannels = channels; @@ -202,41 +203,46 @@ static SLresult openSLRecOpen(OPENSL_STREAM* p) else assert(0); - SLDataSink audioSnk = {&loc_bq, &format_pcm}; + SLDataSink audioSnk = { &loc_bq, &format_pcm }; // create audio recorder // (requires the RECORD_AUDIO permission) - const SLInterfaceID id[] = {SL_IID_ANDROIDSIMPLEBUFFERQUEUE}; - const SLboolean req[] = {SL_BOOLEAN_TRUE}; - result = (*p->engineEngine)->CreateAudioRecorder(p->engineEngine, - &(p->recorderObject), &audioSrc, &audioSnk, 1, id, req); + const SLInterfaceID id[] = { SL_IID_ANDROIDSIMPLEBUFFERQUEUE }; + const SLboolean req[] = { SL_BOOLEAN_TRUE }; + result = (*p->engineEngine) + ->CreateAudioRecorder(p->engineEngine, &(p->recorderObject), &audioSrc, + &audioSnk, 1, id, req); assert(!result); - if (SL_RESULT_SUCCESS != result) goto end_recopen; + if (SL_RESULT_SUCCESS != result) + goto end_recopen; // realize the audio recorder result = (*p->recorderObject)->Realize(p->recorderObject, SL_BOOLEAN_FALSE); assert(!result); - if (SL_RESULT_SUCCESS != result) goto end_recopen; + if (SL_RESULT_SUCCESS != result) + goto end_recopen; // get the record interface - result = (*p->recorderObject)->GetInterface(p->recorderObject, - SL_IID_RECORD, &(p->recorderRecord)); + result = (*p->recorderObject) + ->GetInterface(p->recorderObject, SL_IID_RECORD, &(p->recorderRecord)); assert(!result); - if (SL_RESULT_SUCCESS != result) goto end_recopen; + if (SL_RESULT_SUCCESS != result) + goto end_recopen; // get the buffer queue interface - result = (*p->recorderObject)->GetInterface(p->recorderObject, - SL_IID_ANDROIDSIMPLEBUFFERQUEUE, - &(p->recorderBufferQueue)); + result = (*p->recorderObject) + ->GetInterface(p->recorderObject, SL_IID_ANDROIDSIMPLEBUFFERQUEUE, + &(p->recorderBufferQueue)); assert(!result); - if (SL_RESULT_SUCCESS != result) goto end_recopen; + if (SL_RESULT_SUCCESS != result) + goto end_recopen; // register callback on the buffer queue - result = (*p->recorderBufferQueue)->RegisterCallback(p->recorderBufferQueue, - bqRecorderCallback, p); + result = (*p->recorderBufferQueue) + ->RegisterCallback(p->recorderBufferQueue, bqRecorderCallback, p); assert(!result); if (SL_RESULT_SUCCESS != result) @@ -245,7 +251,8 @@ static SLresult openSLRecOpen(OPENSL_STREAM* p) end_recopen: return result; } - else return SL_RESULT_SUCCESS; + else + return SL_RESULT_SUCCESS; } // close the OpenSL IO and destroy the audio engine @@ -299,17 +306,15 @@ static void opensles_queue_element_free(void* obj) } // open the android audio device for input -OPENSL_STREAM* android_OpenRecDevice(void* context, opensl_receive_t receive, - int sr, - int inchannels, - int bufferframes, int bits_per_sample) +OPENSL_STREAM* android_OpenRecDevice(void* context, opensl_receive_t receive, int sr, + int inchannels, int bufferframes, int bits_per_sample) { OPENSL_STREAM* p; if (!context || !receive) return NULL; - p = (OPENSL_STREAM*) calloc(1, sizeof(OPENSL_STREAM)); + p = (OPENSL_STREAM*)calloc(1, sizeof(OPENSL_STREAM)); if (!p) return NULL; @@ -337,12 +342,9 @@ OPENSL_STREAM* android_OpenRecDevice(void* context, opensl_receive_t receive, if (!p->prep || !p->next) goto fail; - (*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue, - p->next->data, p->next->size); - (*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue, - p->prep->data, p->prep->size); - (*p->recorderRecord)->SetRecordState(p->recorderRecord, - SL_RECORDSTATE_RECORDING); + (*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue, p->next->data, p->next->size); + (*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue, p->prep->data, p->prep->size); + (*p->recorderRecord)->SetRecordState(p->recorderRecord, SL_RECORDSTATE_RECORDING); return p; fail: android_CloseRecDevice(p); @@ -364,7 +366,7 @@ void android_CloseRecDevice(OPENSL_STREAM* p) // this callback handler is called every time a buffer finishes recording static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void* context) { - OPENSL_STREAM* p = (OPENSL_STREAM*) context; + OPENSL_STREAM* p = (OPENSL_STREAM*)context; queue_element* e; if (!p) @@ -382,7 +384,5 @@ static void bqRecorderCallback(SLAndroidSimpleBufferQueueItf bq, void* context) p->next = p->prep; p->prep = e; - (*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue, - e->data, e->size); + (*p->recorderBufferQueue)->Enqueue(p->recorderBufferQueue, e->data, e->size); } - diff --git a/channels/audin/client/opensles/opensl_io.h b/channels/audin/client/opensles/opensl_io.h index 6a54b7c..e99522c 100644 --- a/channels/audin/client/opensles/opensl_io.h +++ b/channels/audin/client/opensles/opensl_io.h @@ -6,14 +6,14 @@ All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - * Neither the name of the nor the - names of its contributors may be used to endorse or promote products - derived from this software without specific prior written permission. + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of the nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED @@ -38,25 +38,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif -typedef struct opensl_stream OPENSL_STREAM; + typedef struct opensl_stream OPENSL_STREAM; -typedef void (*opensl_receive_t)(void* context, const void* data, size_t size); + typedef void (*opensl_receive_t)(void* context, const void* data, size_t size); -/* -Open the audio device with a given sampling rate (sr), input and output channels and IO buffer size -in frames. Returns a handle to the OpenSL stream -*/ -FREERDP_LOCAL OPENSL_STREAM* android_OpenRecDevice(void* context, - opensl_receive_t receive, int sr, - int inchannels, - int bufferframes, int bits_per_sample); -/* -Close the audio device -*/ -FREERDP_LOCAL void android_CloseRecDevice(OPENSL_STREAM* p); + /* + Open the audio device with a given sampling rate (sr), input and output channels and IO buffer + size in frames. Returns a handle to the OpenSL stream + */ + FREERDP_LOCAL OPENSL_STREAM* android_OpenRecDevice(void* context, opensl_receive_t receive, + int sr, int inchannels, int bufferframes, + int bits_per_sample); + /* + Close the audio device + */ + FREERDP_LOCAL void android_CloseRecDevice(OPENSL_STREAM* p); #ifdef __cplusplus }; diff --git a/channels/audin/client/oss/audin_oss.c b/channels/audin/client/oss/audin_oss.c index e1d73b2..97eb349 100644 --- a/channels/audin/client/oss/audin_oss.c +++ b/channels/audin/client/oss/audin_oss.c @@ -69,11 +69,10 @@ typedef struct _AudinOSSDevice } AudinOSSDevice; #define OSS_LOG_ERR(_text, _error) \ - if (_error != 0) \ + if (_error != 0) \ WLog_ERR(TAG, "%s: %i - %s\n", _text, _error, strerror(_error)); - -static int audin_oss_get_format(const AUDIO_FORMAT* format) +static UINT32 audin_oss_get_format(const AUDIO_FORMAT* format) { switch (format->wFormatTag) { @@ -99,8 +98,7 @@ static int audin_oss_get_format(const AUDIO_FORMAT* format) return 0; } -static BOOL audin_oss_format_supported(IAudinDevice* device, - const AUDIO_FORMAT* format) +static BOOL audin_oss_format_supported(IAudinDevice* device, const AUDIO_FORMAT* format) { if (device == NULL || format == NULL) return FALSE; @@ -108,8 +106,7 @@ static BOOL audin_oss_format_supported(IAudinDevice* device, switch (format->wFormatTag) { case WAVE_FORMAT_PCM: - if (format->cbSize != 0 || - format->nSamplesPerSec > 48000 || + if (format->cbSize != 0 || format->nSamplesPerSec > 48000 || (format->wBitsPerSample != 8 && format->wBitsPerSample != 16) || (format->nChannels != 1 && format->nChannels != 2)) return FALSE; @@ -151,7 +148,7 @@ static DWORD WINAPI audin_oss_thread_func(LPVOID arg) char mixer_name[PATH_MAX] = "/dev/mixer"; int pcm_handle = -1, mixer_handle; BYTE* buffer = NULL; - int tmp; + unsigned long tmp; size_t buffer_size; AudinOSSDevice* oss = (AudinOSSDevice*)arg; UINT error = 0; @@ -233,8 +230,7 @@ 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 = (oss->FramesPerPacket * oss->format.nChannels * (oss->format.wBitsPerSample / 8)); buffer = (BYTE*)calloc((buffer_size + sizeof(void*)), sizeof(BYTE)); if (NULL == buffer) @@ -246,42 +242,42 @@ static DWORD WINAPI audin_oss_thread_func(LPVOID arg) while (1) { + SSIZE_T stmp; status = WaitForSingleObject(oss->stopEvent, 0); if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error); goto err_out; } if (status == WAIT_OBJECT_0) break; - tmp = read(pcm_handle, buffer, buffer_size); + stmp = read(pcm_handle, buffer, buffer_size); /* Error happen. */ - if (tmp < 0) + if (stmp < 0) { OSS_LOG_ERR("read() error", errno); continue; } - if (tmp < buffer_size) /* Not enouth data. */ + if ((size_t)stmp < buffer_size) /* Not enouth data. */ continue; if ((error = oss->receive(&oss->format, buffer, buffer_size, oss->user_data))) { - WLog_ERR(TAG, "oss->receive failed with error %"PRIu32"", error); + WLog_ERR(TAG, "oss->receive failed with error %" PRIu32 "", error); break; } } err_out: - if (error && oss->rdpcontext) - setChannelError(oss->rdpcontext, error, - "audin_oss_thread_func reported an error"); + if (error && oss && oss->rdpcontext) + setChannelError(oss->rdpcontext, error, "audin_oss_thread_func reported an error"); if (pcm_handle != -1) { @@ -299,8 +295,7 @@ err_out: * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_oss_open(IAudinDevice* device, AudinReceive receive, - void* user_data) +static UINT audin_oss_open(IAudinDevice* device, AudinReceive receive, void* user_data) { AudinOSSDevice* oss = (AudinOSSDevice*)device; oss->receive = receive; @@ -343,7 +338,7 @@ static UINT audin_oss_close(IAudinDevice* device) if (WaitForSingleObject(oss->thread, INFINITE) == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error); return error; } @@ -366,7 +361,7 @@ static UINT audin_oss_close(IAudinDevice* device) static UINT audin_oss_free(IAudinDevice* device) { AudinOSSDevice* oss = (AudinOSSDevice*)device; - int error; + UINT error; if (device == NULL) return ERROR_INVALID_PARAMETER; @@ -380,12 +375,6 @@ static UINT audin_oss_free(IAudinDevice* device) return CHANNEL_RC_OK; } -static COMMAND_LINE_ARGUMENT_A audin_oss_args[] = -{ - { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "audio device name" }, - { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } -}; - /** * Function description * @@ -394,14 +383,18 @@ static COMMAND_LINE_ARGUMENT_A audin_oss_args[] = static UINT audin_oss_parse_addin_args(AudinOSSDevice* device, ADDIN_ARGV* args) { int status; - char* str_num, *eptr; + char *str_num, *eptr; DWORD flags; COMMAND_LINE_ARGUMENT_A* arg; AudinOSSDevice* oss = (AudinOSSDevice*)device; - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | - COMMAND_LINE_IGN_UNKNOWN_KEYWORD; - status = CommandLineParseArgumentsA(args->argc, args->argv, - audin_oss_args, flags, oss, NULL, NULL); + COMMAND_LINE_ARGUMENT_A audin_oss_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, "", + NULL, NULL, -1, NULL, "audio device name" }, + { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; + + flags = + COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; + status = + CommandLineParseArgumentsA(args->argc, args->argv, audin_oss_args, flags, oss, NULL, NULL); if (status < 0) return ERROR_INVALID_PARAMETER; @@ -414,8 +407,7 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice* device, ADDIN_ARGV* args) if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) continue; - CommandLineSwitchStart(arg) - CommandLineSwitchCase(arg, "dev") + CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "dev") { str_num = _strdup(arg->Value); @@ -434,7 +426,7 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice* device, ADDIN_ARGV* args) return CHANNEL_RC_NULL_DATA; } - oss->dev_unit = val; + oss->dev_unit = (INT32)val; } if (oss->dev_unit < 0 || *eptr != '\0') @@ -443,16 +435,15 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice* device, ADDIN_ARGV* args) free(str_num); } CommandLineSwitchEnd(arg) - } - while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); return CHANNEL_RC_OK; } #ifdef BUILTIN_CHANNELS -#define freerdp_audin_client_subsystem_entry oss_freerdp_audin_client_subsystem_entry +#define freerdp_audin_client_subsystem_entry oss_freerdp_audin_client_subsystem_entry #else -#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry +#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry #endif /** @@ -460,8 +451,7 @@ static UINT audin_oss_parse_addin_args(AudinOSSDevice* device, ADDIN_ARGV* args) * * @return 0 on success, otherwise a Win32 error code */ -UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS - pEntryPoints) +UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEntryPoints) { ADDIN_ARGV* args; AudinOSSDevice* oss; @@ -485,14 +475,13 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS if ((error = audin_oss_parse_addin_args(oss, args))) { - WLog_ERR(TAG, "audin_oss_parse_addin_args failed with errorcode %"PRIu32"!", error); + WLog_ERR(TAG, "audin_oss_parse_addin_args failed with errorcode %" PRIu32 "!", error); goto error_out; } - if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, - (IAudinDevice*) oss))) + if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*)oss))) { - WLog_ERR(TAG, "RegisterAudinDevice failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "RegisterAudinDevice failed with error %" PRIu32 "!", error); goto error_out; } diff --git a/channels/audin/client/pulse/audin_pulse.c b/channels/audin/client/pulse/audin_pulse.c index d22de87..8a5c3be 100644 --- a/channels/audin/client/pulse/audin_pulse.c +++ b/channels/audin/client/pulse/audin_pulse.c @@ -62,27 +62,67 @@ typedef struct _AudinPulseDevice wLog* log; } AudinPulseDevice; +static const char* pulse_context_state_string(pa_context_state_t state) +{ + switch (state) + { + case PA_CONTEXT_UNCONNECTED: + return "PA_CONTEXT_UNCONNECTED"; + case PA_CONTEXT_CONNECTING: + return "PA_CONTEXT_CONNECTING"; + case PA_CONTEXT_AUTHORIZING: + return "PA_CONTEXT_AUTHORIZING"; + case PA_CONTEXT_SETTING_NAME: + return "PA_CONTEXT_SETTING_NAME"; + case PA_CONTEXT_READY: + return "PA_CONTEXT_READY"; + case PA_CONTEXT_FAILED: + return "PA_CONTEXT_FAILED"; + case PA_CONTEXT_TERMINATED: + return "PA_CONTEXT_TERMINATED"; + default: + return "UNKNOWN"; + } +} + +static const char* pulse_stream_state_string(pa_stream_state_t state) +{ + switch (state) + { + case PA_STREAM_UNCONNECTED: + return "PA_STREAM_UNCONNECTED"; + case PA_STREAM_CREATING: + return "PA_STREAM_CREATING"; + case PA_STREAM_READY: + return "PA_STREAM_READY"; + case PA_STREAM_FAILED: + return "PA_STREAM_FAILED"; + case PA_STREAM_TERMINATED: + return "PA_STREAM_TERMINATED"; + default: + return "UNKNOWN"; + } +} + static void audin_pulse_context_state_callback(pa_context* context, void* userdata) { pa_context_state_t state; - AudinPulseDevice* pulse = (AudinPulseDevice*) userdata; + AudinPulseDevice* pulse = (AudinPulseDevice*)userdata; state = pa_context_get_state(context); + WLog_Print(pulse->log, WLOG_DEBUG, "context state %s", pulse_context_state_string(state)); switch (state) { case PA_CONTEXT_READY: - WLog_Print(pulse->log, WLOG_DEBUG, "PA_CONTEXT_READY"); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; case PA_CONTEXT_FAILED: case PA_CONTEXT_TERMINATED: - WLog_Print(pulse->log, WLOG_DEBUG, "state %d", state); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; default: - WLog_Print(pulse->log, WLOG_DEBUG, "state %d", state); break; } } @@ -95,7 +135,7 @@ static void audin_pulse_context_state_callback(pa_context* context, void* userda static UINT audin_pulse_connect(IAudinDevice* device) { pa_context_state_t state; - AudinPulseDevice* pulse = (AudinPulseDevice*) device; + AudinPulseDevice* pulse = (AudinPulseDevice*)device; if (!pulse->context) return ERROR_INVALID_PARAMETER; @@ -126,8 +166,8 @@ static UINT audin_pulse_connect(IAudinDevice* device) if (!PA_CONTEXT_IS_GOOD(state)) { - WLog_Print(pulse->log, WLOG_ERROR, "bad context state (%d)", - pa_context_errno(pulse->context)); + WLog_Print(pulse->log, WLOG_ERROR, "bad context state (%s: %d)", + pulse_context_state_string(state), pa_context_errno(pulse->context)); pa_context_disconnect(pulse->context); return ERROR_INVALID_STATE; } @@ -136,7 +176,7 @@ static UINT audin_pulse_connect(IAudinDevice* device) } pa_threaded_mainloop_unlock(pulse->mainloop); - WLog_Print(pulse->log, WLOG_DEBUG, "connected"); + WLog_Print(pulse->log, WLOG_DEBUG, "connected"); return CHANNEL_RC_OK; } @@ -147,7 +187,7 @@ static UINT audin_pulse_connect(IAudinDevice* device) */ static UINT audin_pulse_free(IAudinDevice* device) { - AudinPulseDevice* pulse = (AudinPulseDevice*) device; + AudinPulseDevice* pulse = (AudinPulseDevice*)device; if (!pulse) return ERROR_INVALID_PARAMETER; @@ -176,7 +216,7 @@ static UINT audin_pulse_free(IAudinDevice* device) static BOOL audin_pulse_format_supported(IAudinDevice* device, const AUDIO_FORMAT* format) { - AudinPulseDevice* pulse = (AudinPulseDevice*) device; + AudinPulseDevice* pulse = (AudinPulseDevice*)device; if (!pulse || !format) return FALSE; @@ -187,8 +227,7 @@ static BOOL audin_pulse_format_supported(IAudinDevice* device, const AUDIO_FORMA switch (format->wFormatTag) { case WAVE_FORMAT_PCM: - if (format->cbSize == 0 && - (format->nSamplesPerSec <= PA_RATE_MAX) && + if (format->cbSize == 0 && (format->nSamplesPerSec <= PA_RATE_MAX) && (format->wBitsPerSample == 8 || format->wBitsPerSample == 16) && (format->nChannels >= 1 && format->nChannels <= PA_CHANNELS_MAX)) { @@ -197,10 +236,9 @@ static BOOL audin_pulse_format_supported(IAudinDevice* device, const AUDIO_FORMA break; - case WAVE_FORMAT_ALAW: /* A-LAW */ + case WAVE_FORMAT_ALAW: /* A-LAW */ case WAVE_FORMAT_MULAW: /* U-LAW */ - if (format->cbSize == 0 && - (format->nSamplesPerSec <= PA_RATE_MAX) && + if (format->cbSize == 0 && (format->nSamplesPerSec <= PA_RATE_MAX) && (format->wBitsPerSample == 8) && (format->nChannels >= 1 && format->nChannels <= PA_CHANNELS_MAX)) { @@ -225,7 +263,7 @@ static UINT audin_pulse_set_format(IAudinDevice* device, const AUDIO_FORMAT* for UINT32 FramesPerPacket) { pa_sample_spec sample_spec = { 0 }; - AudinPulseDevice* pulse = (AudinPulseDevice*) device; + AudinPulseDevice* pulse = (AudinPulseDevice*)device; if (!pulse || !format) return ERROR_INVALID_PARAMETER; @@ -278,24 +316,22 @@ static UINT audin_pulse_set_format(IAudinDevice* device, const AUDIO_FORMAT* for static void audin_pulse_stream_state_callback(pa_stream* stream, void* userdata) { pa_stream_state_t state; - AudinPulseDevice* pulse = (AudinPulseDevice*) userdata; + AudinPulseDevice* pulse = (AudinPulseDevice*)userdata; state = pa_stream_get_state(stream); + WLog_Print(pulse->log, WLOG_DEBUG, "stream state %s", pulse_stream_state_string(state)); switch (state) { case PA_STREAM_READY: - WLog_Print(pulse->log, WLOG_DEBUG, "PA_STREAM_READY"); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; case PA_STREAM_FAILED: case PA_STREAM_TERMINATED: - WLog_Print(pulse->log, WLOG_DEBUG, "state %d", state); pa_threaded_mainloop_signal(pulse->mainloop, 0); break; default: - WLog_Print(pulse->log, WLOG_DEBUG, "state %d", state); break; } } @@ -303,17 +339,17 @@ static void audin_pulse_stream_state_callback(pa_stream* stream, void* userdata) static void audin_pulse_stream_request_callback(pa_stream* stream, size_t length, void* userdata) { const void* data; - AudinPulseDevice* pulse = (AudinPulseDevice*) userdata; + AudinPulseDevice* pulse = (AudinPulseDevice*)userdata; UINT error = CHANNEL_RC_OK; pa_stream_peek(stream, &data, &length); - error = IFCALLRESULT(CHANNEL_RC_OK, pulse->receive, &pulse->format, data, length, pulse->user_data); + error = + IFCALLRESULT(CHANNEL_RC_OK, pulse->receive, &pulse->format, data, length, pulse->user_data); pa_stream_drop(stream); if (error && pulse->rdpcontext) setChannelError(pulse->rdpcontext, error, "audin_pulse_thread_func reported an error"); } - /** * Function description * @@ -321,7 +357,7 @@ static void audin_pulse_stream_request_callback(pa_stream* stream, size_t length */ static UINT audin_pulse_close(IAudinDevice* device) { - AudinPulseDevice* pulse = (AudinPulseDevice*) device; + AudinPulseDevice* pulse = (AudinPulseDevice*)device; if (!pulse) return ERROR_INVALID_PARAMETER; @@ -349,7 +385,7 @@ static UINT audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u { pa_stream_state_t state; pa_buffer_attr buffer_attr = { 0 }; - AudinPulseDevice* pulse = (AudinPulseDevice*) device; + AudinPulseDevice* pulse = (AudinPulseDevice*)device; if (!pulse || !receive || !user_data) return ERROR_INVALID_PARAMETER; @@ -363,8 +399,7 @@ static UINT audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u pulse->receive = receive; pulse->user_data = user_data; pa_threaded_mainloop_lock(pulse->mainloop); - pulse->stream = pa_stream_new(pulse->context, "freerdp_audin", - &pulse->sample_spec, NULL); + pulse->stream = pa_stream_new(pulse->context, "freerdp_audin", &pulse->sample_spec, NULL); if (!pulse->stream) { @@ -375,24 +410,21 @@ static UINT audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u } pulse->bytes_per_frame = pa_frame_size(&pulse->sample_spec); - pa_stream_set_state_callback(pulse->stream, - audin_pulse_stream_state_callback, pulse); - pa_stream_set_read_callback(pulse->stream, - audin_pulse_stream_request_callback, pulse); - buffer_attr.maxlength = (UINT32) - 1; - buffer_attr.tlength = (UINT32) - 1; - buffer_attr.prebuf = (UINT32) - 1; - buffer_attr.minreq = (UINT32) - 1; + pa_stream_set_state_callback(pulse->stream, audin_pulse_stream_state_callback, pulse); + pa_stream_set_read_callback(pulse->stream, audin_pulse_stream_request_callback, pulse); + buffer_attr.maxlength = (UINT32)-1; + buffer_attr.tlength = (UINT32)-1; + buffer_attr.prebuf = (UINT32)-1; + buffer_attr.minreq = (UINT32)-1; /* 500ms latency */ buffer_attr.fragsize = pulse->bytes_per_frame * pulse->frames_per_packet; if (buffer_attr.fragsize % pulse->format.nBlockAlign) - buffer_attr.fragsize += pulse->format.nBlockAlign - buffer_attr.fragsize % - pulse->format.nBlockAlign; + buffer_attr.fragsize += + pulse->format.nBlockAlign - buffer_attr.fragsize % pulse->format.nBlockAlign; - if (pa_stream_connect_record(pulse->stream, - pulse->device_name, - &buffer_attr, PA_STREAM_ADJUST_LATENCY) < 0) + if (pa_stream_connect_record(pulse->stream, pulse->device_name, &buffer_attr, + PA_STREAM_ADJUST_LATENCY) < 0) { pa_threaded_mainloop_unlock(pulse->mainloop); WLog_Print(pulse->log, WLOG_ERROR, "pa_stream_connect_playback failed (%d)", @@ -410,8 +442,8 @@ static UINT audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u if (!PA_STREAM_IS_GOOD(state)) { audin_pulse_close(device); - WLog_Print(pulse->log, WLOG_ERROR, "bad stream state (%d)", - pa_context_errno(pulse->context)); + WLog_Print(pulse->log, WLOG_ERROR, "bad stream state (%s: %d)", + pulse_stream_state_string(state), pa_context_errno(pulse->context)); pa_threaded_mainloop_unlock(pulse->mainloop); return pa_context_errno(pulse->context); } @@ -425,12 +457,6 @@ static UINT audin_pulse_open(IAudinDevice* device, AudinReceive receive, void* u return CHANNEL_RC_OK; } -static COMMAND_LINE_ARGUMENT_A audin_pulse_args[] = -{ - { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "audio device name" }, - { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } -}; - /** * Function description * @@ -441,10 +467,15 @@ static UINT audin_pulse_parse_addin_args(AudinPulseDevice* device, ADDIN_ARGV* a int status; DWORD flags; COMMAND_LINE_ARGUMENT_A* arg; - AudinPulseDevice* pulse = (AudinPulseDevice*) device; - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; - status = CommandLineParseArgumentsA(args->argc, args->argv, audin_pulse_args, flags, - pulse, NULL, NULL); + AudinPulseDevice* pulse = (AudinPulseDevice*)device; + COMMAND_LINE_ARGUMENT_A audin_pulse_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, "", + NULL, NULL, -1, NULL, "audio device name" }, + { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; + + flags = + COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; + status = CommandLineParseArgumentsA(args->argc, args->argv, audin_pulse_args, flags, pulse, + NULL, NULL); if (status < 0) return ERROR_INVALID_PARAMETER; @@ -456,8 +487,7 @@ static UINT audin_pulse_parse_addin_args(AudinPulseDevice* device, ADDIN_ARGV* a if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) continue; - CommandLineSwitchStart(arg) - CommandLineSwitchCase(arg, "dev") + CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "dev") { pulse->device_name = _strdup(arg->Value); @@ -468,16 +498,15 @@ static UINT audin_pulse_parse_addin_args(AudinPulseDevice* device, ADDIN_ARGV* a } } CommandLineSwitchEnd(arg) - } - while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); return CHANNEL_RC_OK; } #ifdef BUILTIN_CHANNELS -#define freerdp_audin_client_subsystem_entry pulse_freerdp_audin_client_subsystem_entry +#define freerdp_audin_client_subsystem_entry pulse_freerdp_audin_client_subsystem_entry #else -#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry +#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry #endif /** @@ -490,7 +519,7 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn ADDIN_ARGV* args; AudinPulseDevice* pulse; UINT error; - pulse = (AudinPulseDevice*) calloc(1, sizeof(AudinPulseDevice)); + pulse = (AudinPulseDevice*)calloc(1, sizeof(AudinPulseDevice)); if (!pulse) { @@ -509,8 +538,8 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn if ((error = audin_pulse_parse_addin_args(pulse, args))) { - WLog_Print(pulse->log, WLOG_ERROR, "audin_pulse_parse_addin_args failed with error %"PRIu32"!", - error); + WLog_Print(pulse->log, WLOG_ERROR, + "audin_pulse_parse_addin_args failed with error %" PRIu32 "!", error); goto error_out; } @@ -534,21 +563,21 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn pa_context_set_state_callback(pulse->context, audin_pulse_context_state_callback, pulse); - if ((error = audin_pulse_connect((IAudinDevice*) pulse))) + if ((error = audin_pulse_connect(&pulse->iface))) { WLog_Print(pulse->log, WLOG_ERROR, "audin_pulse_connect failed"); goto error_out; } - if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) pulse))) + if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, &pulse->iface))) { - WLog_Print(pulse->log, WLOG_ERROR, "RegisterAudinDevice failed with error %"PRIu32"!", error); + WLog_Print(pulse->log, WLOG_ERROR, "RegisterAudinDevice failed with error %" PRIu32 "!", + error); goto error_out; } return CHANNEL_RC_OK; error_out: - audin_pulse_free((IAudinDevice*)pulse); + audin_pulse_free(&pulse->iface); return error; } - diff --git a/channels/audin/client/winmm/audin_winmm.c b/channels/audin/client/winmm/audin_winmm.c index 5e21005..bab9361 100644 --- a/channels/audin/client/winmm/audin_winmm.c +++ b/channels/audin/client/winmm/audin_winmm.c @@ -27,8 +27,8 @@ #include #include -#include -#include +#include +#include #include #include @@ -59,7 +59,7 @@ typedef struct _AudinWinmmDevice static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance, DWORD_PTR dwParam1, DWORD_PTR dwParam2) { - AudinWinmmDevice* winmm = (AudinWinmmDevice*) dwInstance; + AudinWinmmDevice* winmm = (AudinWinmmDevice*)dwInstance; PWAVEHDR pWaveHdr; UINT error = CHANNEL_RC_OK; MMRESULT mmResult; @@ -74,8 +74,8 @@ static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance if (WHDR_DONE == (WHDR_DONE & pWaveHdr->dwFlags)) { - if (pWaveHdr->dwBytesRecorded - && !(WaitForSingleObject(winmm->stopEvent, 0) == WAIT_OBJECT_0)) + if (pWaveHdr->dwBytesRecorded && + !(WaitForSingleObject(winmm->stopEvent, 0) == WAIT_OBJECT_0)) { AUDIO_FORMAT format; format.cbSize = winmm->pwfx_cur->cbSize; @@ -86,8 +86,8 @@ static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance format.wBitsPerSample = winmm->pwfx_cur->wBitsPerSample; format.wFormatTag = winmm->pwfx_cur->wFormatTag; - if ((error = winmm->receive(&format, pWaveHdr->lpData, pWaveHdr->dwBytesRecorded, - winmm->user_data))) + if ((error = winmm->receive(&format, pWaveHdr->lpData, + pWaveHdr->dwBytesRecorded, winmm->user_data))) break; mmResult = waveInAddBuffer(hWaveIn, pWaveHdr, sizeof(WAVEHDR)); @@ -112,7 +112,7 @@ static void CALLBACK waveInProc(HWAVEIN hWaveIn, UINT uMsg, DWORD_PTR dwInstance static DWORD WINAPI audin_winmm_thread_func(LPVOID arg) { - AudinWinmmDevice* winmm = (AudinWinmmDevice*) arg; + AudinWinmmDevice* winmm = (AudinWinmmDevice*)arg; char* buffer; int size, i; WAVEHDR waveHdr[4]; @@ -122,7 +122,8 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg) if (!winmm->hWaveIn) { if (MMSYSERR_NOERROR != waveInOpen(&winmm->hWaveIn, WAVE_MAPPER, winmm->pwfx_cur, - (DWORD_PTR)waveInProc, (DWORD_PTR)winmm, CALLBACK_FUNCTION)) + (DWORD_PTR)waveInProc, (DWORD_PTR)winmm, + CALLBACK_FUNCTION)) { if (winmm->rdpcontext) setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR, @@ -132,12 +133,14 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg) } } - size = (winmm->pwfx_cur->wBitsPerSample * winmm->pwfx_cur->nChannels * winmm->frames_per_packet + - 7) / 8; + size = + (winmm->pwfx_cur->wBitsPerSample * winmm->pwfx_cur->nChannels * winmm->frames_per_packet + + 7) / + 8; for (i = 0; i < 4; i++) { - buffer = (char*) malloc(size); + buffer = (char*)malloc(size); if (!buffer) return CHANNEL_RC_NO_MEMORY; @@ -149,7 +152,7 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg) if (MMSYSERR_NOERROR != rc) { - WLog_Print(winmm->log, WLOG_DEBUG, "waveInPrepareHeader failed. %"PRIu32"", rc); + WLog_Print(winmm->log, WLOG_DEBUG, "waveInPrepareHeader failed. %" PRIu32 "", rc); if (winmm->rdpcontext) setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR, @@ -160,7 +163,7 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg) if (MMSYSERR_NOERROR != rc) { - WLog_Print(winmm->log, WLOG_DEBUG, "waveInAddBuffer failed. %"PRIu32"", rc); + WLog_Print(winmm->log, WLOG_DEBUG, "waveInAddBuffer failed. %" PRIu32 "", rc); if (winmm->rdpcontext) setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR, @@ -172,7 +175,7 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg) if (MMSYSERR_NOERROR != rc) { - WLog_Print(winmm->log, WLOG_DEBUG, "waveInStart failed. %"PRIu32"", rc); + WLog_Print(winmm->log, WLOG_DEBUG, "waveInStart failed. %" PRIu32 "", rc); if (winmm->rdpcontext) setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR, @@ -194,7 +197,7 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg) if (MMSYSERR_NOERROR != rc) { - WLog_Print(winmm->log, WLOG_DEBUG, "waveInReset failed. %"PRIu32"", rc); + WLog_Print(winmm->log, WLOG_DEBUG, "waveInReset failed. %" PRIu32 "", rc); if (winmm->rdpcontext) setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR, @@ -207,7 +210,7 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg) if (MMSYSERR_NOERROR != rc) { - WLog_Print(winmm->log, WLOG_DEBUG, "waveInUnprepareHeader failed. %"PRIu32"", rc); + WLog_Print(winmm->log, WLOG_DEBUG, "waveInUnprepareHeader failed. %" PRIu32 "", rc); if (winmm->rdpcontext) setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR, @@ -221,7 +224,7 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg) if (MMSYSERR_NOERROR != rc) { - WLog_Print(winmm->log, WLOG_DEBUG, "waveInClose failed. %"PRIu32"", rc); + WLog_Print(winmm->log, WLOG_DEBUG, "waveInClose failed. %" PRIu32 "", rc); if (winmm->rdpcontext) setChannelError(winmm->rdpcontext, ERROR_INTERNAL_ERROR, @@ -240,7 +243,7 @@ static DWORD WINAPI audin_winmm_thread_func(LPVOID arg) static UINT audin_winmm_free(IAudinDevice* device) { UINT32 i; - AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; + AudinWinmmDevice* winmm = (AudinWinmmDevice*)device; if (!winmm) return ERROR_INVALID_PARAMETER; @@ -265,7 +268,7 @@ static UINT audin_winmm_close(IAudinDevice* device) { DWORD status; UINT error = CHANNEL_RC_OK; - AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; + AudinWinmmDevice* winmm = (AudinWinmmDevice*)device; if (!winmm) return ERROR_INVALID_PARAMETER; @@ -276,7 +279,8 @@ static UINT audin_winmm_close(IAudinDevice* device) if (status == WAIT_FAILED) { error = GetLastError(); - WLog_Print(winmm->log, WLOG_ERROR, "WaitForSingleObject failed with error %"PRIu32"!", error); + WLog_Print(winmm->log, WLOG_ERROR, "WaitForSingleObject failed with error %" PRIu32 "!", + error); return error; } @@ -298,7 +302,7 @@ static UINT audin_winmm_set_format(IAudinDevice* device, const AUDIO_FORMAT* for UINT32 FramesPerPacket) { UINT32 i; - AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; + AudinWinmmDevice* winmm = (AudinWinmmDevice*)device; if (!winmm || !format) return ERROR_INVALID_PARAMETER; @@ -307,9 +311,9 @@ static UINT audin_winmm_set_format(IAudinDevice* device, const AUDIO_FORMAT* for for (i = 0; i < winmm->cFormats; i++) { - if (winmm->ppwfx[i]->wFormatTag == format->wFormatTag - && winmm->ppwfx[i]->nChannels == format->nChannels - && winmm->ppwfx[i]->wBitsPerSample == format->wBitsPerSample) + if (winmm->ppwfx[i]->wFormatTag == format->wFormatTag && + winmm->ppwfx[i]->nChannels == format->nChannels && + winmm->ppwfx[i]->wBitsPerSample == format->wBitsPerSample) { winmm->pwfx_cur = winmm->ppwfx[i]; break; @@ -321,7 +325,7 @@ static UINT audin_winmm_set_format(IAudinDevice* device, const AUDIO_FORMAT* for static BOOL audin_winmm_format_supported(IAudinDevice* device, const AUDIO_FORMAT* format) { - AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; + AudinWinmmDevice* winmm = (AudinWinmmDevice*)device; PWAVEFORMATEX pwfx; BYTE* data; @@ -376,7 +380,7 @@ static BOOL audin_winmm_format_supported(IAudinDevice* device, const AUDIO_FORMA */ static UINT audin_winmm_open(IAudinDevice* device, AudinReceive receive, void* user_data) { - AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; + AudinWinmmDevice* winmm = (AudinWinmmDevice*)device; if (!winmm || !receive || !user_data) return ERROR_INVALID_PARAMETER; @@ -390,8 +394,7 @@ static UINT audin_winmm_open(IAudinDevice* device, AudinReceive receive, void* u return ERROR_INTERNAL_ERROR; } - if (!(winmm->thread = CreateThread(NULL, 0, - audin_winmm_thread_func, winmm, 0, NULL))) + if (!(winmm->thread = CreateThread(NULL, 0, audin_winmm_thread_func, winmm, 0, NULL))) { WLog_Print(winmm->log, WLOG_ERROR, "CreateThread failed!"); CloseHandle(winmm->stopEvent); @@ -402,12 +405,6 @@ static UINT audin_winmm_open(IAudinDevice* device, AudinReceive receive, void* u return CHANNEL_RC_OK; } -static COMMAND_LINE_ARGUMENT_A audin_winmm_args[] = -{ - { "dev", COMMAND_LINE_VALUE_REQUIRED, "", NULL, NULL, -1, NULL, "audio device name" }, - { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } -}; - /** * Function description * @@ -418,10 +415,15 @@ static UINT audin_winmm_parse_addin_args(AudinWinmmDevice* device, ADDIN_ARGV* a int status; DWORD flags; COMMAND_LINE_ARGUMENT_A* arg; - AudinWinmmDevice* winmm = (AudinWinmmDevice*) device; - flags = COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; - status = CommandLineParseArgumentsA(args->argc, args->argv, audin_winmm_args, flags, - winmm, NULL, NULL); + AudinWinmmDevice* winmm = (AudinWinmmDevice*)device; + COMMAND_LINE_ARGUMENT_A audin_winmm_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, "", + NULL, NULL, -1, NULL, "audio device name" }, + { NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } }; + + flags = + COMMAND_LINE_SIGIL_NONE | COMMAND_LINE_SEPARATOR_COLON | COMMAND_LINE_IGN_UNKNOWN_KEYWORD; + status = CommandLineParseArgumentsA(args->argc, args->argv, audin_winmm_args, flags, winmm, + NULL, NULL); arg = audin_winmm_args; do @@ -429,8 +431,7 @@ static UINT audin_winmm_parse_addin_args(AudinWinmmDevice* device, ADDIN_ARGV* a if (!(arg->Flags & COMMAND_LINE_VALUE_PRESENT)) continue; - CommandLineSwitchStart(arg) - CommandLineSwitchCase(arg, "dev") + CommandLineSwitchStart(arg) CommandLineSwitchCase(arg, "dev") { winmm->device_name = _strdup(arg->Value); @@ -441,16 +442,15 @@ static UINT audin_winmm_parse_addin_args(AudinWinmmDevice* device, ADDIN_ARGV* a } } CommandLineSwitchEnd(arg) - } - while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); + } while ((arg = CommandLineFindNextArgumentA(arg)) != NULL); return CHANNEL_RC_OK; } #ifdef BUILTIN_CHANNELS -#define freerdp_audin_client_subsystem_entry winmm_freerdp_audin_client_subsystem_entry +#define freerdp_audin_client_subsystem_entry winmm_freerdp_audin_client_subsystem_entry #else -#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry +#define freerdp_audin_client_subsystem_entry FREERDP_API freerdp_audin_client_subsystem_entry #endif /** @@ -463,7 +463,14 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn ADDIN_ARGV* args; AudinWinmmDevice* winmm; UINT error; - winmm = (AudinWinmmDevice*) calloc(1, sizeof(AudinWinmmDevice)); + + if (waveInGetNumDevs() == 0) + { + WLog_Print(WLog_Get(TAG), WLOG_ERROR, "No microphone available!"); + return ERROR_DEVICE_NOT_AVAILABLE; + } + + winmm = (AudinWinmmDevice*)calloc(1, sizeof(AudinWinmmDevice)); if (!winmm) { @@ -482,8 +489,8 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn if ((error = audin_winmm_parse_addin_args(winmm, args))) { - WLog_Print(winmm->log, WLOG_ERROR, "audin_winmm_parse_addin_args failed with error %"PRIu32"!", - error); + WLog_Print(winmm->log, WLOG_ERROR, + "audin_winmm_parse_addin_args failed with error %" PRIu32 "!", error); goto error_out; } @@ -509,9 +516,10 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn goto error_out; } - if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*) winmm))) + if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*)winmm))) { - WLog_Print(winmm->log, WLOG_ERROR, "RegisterAudinDevice failed with error %"PRIu32"!", error); + WLog_Print(winmm->log, WLOG_ERROR, "RegisterAudinDevice failed with error %" PRIu32 "!", + error); goto error_out; } diff --git a/channels/audin/server/audin.c b/channels/audin/server/audin.c index f521667..aa1979c 100644 --- a/channels/audin/server/audin.c +++ b/channels/audin/server/audin.c @@ -39,13 +39,13 @@ #include #define TAG CHANNELS_TAG("audin.server") -#define MSG_SNDIN_VERSION 0x01 -#define MSG_SNDIN_FORMATS 0x02 -#define MSG_SNDIN_OPEN 0x03 -#define MSG_SNDIN_OPEN_REPLY 0x04 -#define MSG_SNDIN_DATA_INCOMING 0x05 -#define MSG_SNDIN_DATA 0x06 -#define MSG_SNDIN_FORMATCHANGE 0x07 +#define MSG_SNDIN_VERSION 0x01 +#define MSG_SNDIN_FORMATS 0x02 +#define MSG_SNDIN_OPEN 0x03 +#define MSG_SNDIN_OPEN_REPLY 0x04 +#define MSG_SNDIN_DATA_INCOMING 0x05 +#define MSG_SNDIN_DATA 0x06 +#define MSG_SNDIN_FORMATCHANGE 0x07 typedef struct _audin_server { @@ -69,15 +69,13 @@ typedef struct _audin_server * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_server_select_format(audin_server_context* context, - size_t client_format_index) +static UINT audin_server_select_format(audin_server_context* context, size_t client_format_index) { - audin_server* audin = (audin_server*) context; + audin_server* audin = (audin_server*)context; if (client_format_index >= context->num_client_formats) { - WLog_ERR(TAG, - "error in protocol: client_format_index >= context->num_client_formats!"); + WLog_ERR(TAG, "error in protocol: client_format_index >= context->num_client_formats!"); return ERROR_INVALID_DATA; } @@ -109,7 +107,7 @@ static UINT audin_server_send_version(audin_server* audin, wStream* s) Stream_Write_UINT8(s, MSG_SNDIN_VERSION); Stream_Write_UINT32(s, 1); /* Version (4 bytes) */ - if (!WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), + if (!WTSVirtualChannelWrite(audin->audin_channel, (PCHAR)Stream_Buffer(s), Stream_GetPosition(s), &written)) { WLog_ERR(TAG, "WTSVirtualChannelWrite failed!"); @@ -124,14 +122,13 @@ static UINT audin_server_send_version(audin_server* audin, wStream* s) * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_server_recv_version(audin_server* audin, wStream* s, - UINT32 length) +static UINT audin_server_recv_version(audin_server* audin, wStream* s, UINT32 length) { UINT32 Version; if (length < 4) { - WLog_ERR(TAG, "error parsing version info: expected at least 4 bytes, got %"PRIu32"", + WLog_ERR(TAG, "error parsing version info: expected at least 4 bytes, got %" PRIu32 "", length); return ERROR_INVALID_DATA; } @@ -140,7 +137,7 @@ static UINT audin_server_recv_version(audin_server* audin, wStream* s, if (Version < 1) { - WLog_ERR(TAG, "expected Version > 0 but got %"PRIu32"", Version); + WLog_ERR(TAG, "expected Version > 0 but got %" PRIu32 "", Version); return ERROR_INVALID_DATA; } @@ -158,16 +155,15 @@ static UINT audin_server_send_formats(audin_server* audin, wStream* s) ULONG written; Stream_SetPosition(s, 0); Stream_Write_UINT8(s, MSG_SNDIN_FORMATS); - Stream_Write_UINT32(s, - audin->context.num_server_formats); /* NumFormats (4 bytes) */ - Stream_Write_UINT32(s, - 0); /* cbSizeFormatsPacket (4 bytes), client-to-server only */ + Stream_Write_UINT32(s, audin->context.num_server_formats); /* NumFormats (4 bytes) */ + Stream_Write_UINT32(s, 0); /* cbSizeFormatsPacket (4 bytes), client-to-server only */ for (i = 0; i < audin->context.num_server_formats; i++) { AUDIO_FORMAT format = audin->context.server_formats[i]; // TODO: Eliminate this - format.nAvgBytesPerSec = format.nSamplesPerSec * format.nChannels * format.wBitsPerSample / 8; + format.nAvgBytesPerSec = + format.nSamplesPerSec * format.nChannels * format.wBitsPerSample / 8; if (!audio_format_write(s, &format)) { @@ -176,8 +172,10 @@ static UINT audin_server_send_formats(audin_server* audin, wStream* s) } } - return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), - Stream_GetPosition(s), &written) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; + return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR)Stream_Buffer(s), + Stream_GetPosition(s), &written) + ? CHANNEL_RC_OK + : ERROR_INTERNAL_ERROR; } /** @@ -185,22 +183,20 @@ static UINT audin_server_send_formats(audin_server* audin, wStream* s) * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_server_recv_formats(audin_server* audin, wStream* s, - UINT32 length) +static UINT audin_server_recv_formats(audin_server* audin, wStream* s, UINT32 length) { size_t i; UINT success = CHANNEL_RC_OK; if (length < 8) { - WLog_ERR(TAG, "error parsing rec formats: expected at least 8 bytes, got %"PRIu32"", + WLog_ERR(TAG, "error parsing rec formats: expected at least 8 bytes, got %" PRIu32 "", length); return ERROR_INVALID_DATA; } - Stream_Read_UINT32(s, - audin->context.num_client_formats); /* NumFormats (4 bytes) */ - Stream_Seek_UINT32(s); /* cbSizeFormatsPacket (4 bytes) */ + Stream_Read_UINT32(s, audin->context.num_client_formats); /* NumFormats (4 bytes) */ + Stream_Seek_UINT32(s); /* cbSizeFormatsPacket (4 bytes) */ length -= 8; if (audin->context.num_client_formats <= 0) @@ -223,7 +219,7 @@ static UINT audin_server_recv_formats(audin_server* audin, wStream* s, { audio_formats_free(audin->context.client_formats, i); audin->context.client_formats = NULL; - WLog_ERR(TAG, "expected length at least 18, but got %"PRIu32"", length); + WLog_ERR(TAG, "expected length at least 18, but got %" PRIu32 "", length); return ERROR_INVALID_DATA; } @@ -233,7 +229,7 @@ static UINT audin_server_recv_formats(audin_server* audin, wStream* s, IFCALLRET(audin->context.Opening, success, &audin->context); if (success) - WLog_ERR(TAG, "context.Opening failed with error %"PRIu32"", success); + WLog_ERR(TAG, "context.Opening failed with error %" PRIu32 "", success); return success; } @@ -257,24 +253,24 @@ static UINT audin_server_send_open(audin_server* audin, wStream* s) audin->opened = TRUE; Stream_SetPosition(s, 0); Stream_Write_UINT8(s, MSG_SNDIN_OPEN); - Stream_Write_UINT32(s, - audin->context.frames_per_packet); /* FramesPerPacket (4 bytes) */ - Stream_Write_UINT32(s, - audin->context.selected_client_format); /* initialFormat (4 bytes) */ + Stream_Write_UINT32(s, audin->context.frames_per_packet); /* FramesPerPacket (4 bytes) */ + Stream_Write_UINT32(s, audin->context.selected_client_format); /* initialFormat (4 bytes) */ /* * [MS-RDPEAI] 3.2.5.1.6 * The second format specify the format that SHOULD be used to capture data from * the actual audio input device. */ - Stream_Write_UINT16(s, 1); /* wFormatTag = PCM */ - Stream_Write_UINT16(s, 2); /* nChannels */ - Stream_Write_UINT32(s, 44100); /* nSamplesPerSec */ + Stream_Write_UINT16(s, 1); /* wFormatTag = PCM */ + Stream_Write_UINT16(s, 2); /* nChannels */ + Stream_Write_UINT32(s, 44100); /* nSamplesPerSec */ Stream_Write_UINT32(s, 44100 * 2 * 2); /* nAvgBytesPerSec */ - Stream_Write_UINT16(s, 4); /* nBlockAlign */ - Stream_Write_UINT16(s, 16); /* wBitsPerSample */ - Stream_Write_UINT16(s, 0); /* cbSize */ - return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR) Stream_Buffer(s), - Stream_GetPosition(s), &written) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; + Stream_Write_UINT16(s, 4); /* nBlockAlign */ + Stream_Write_UINT16(s, 16); /* wBitsPerSample */ + Stream_Write_UINT16(s, 0); /* cbSize */ + return WTSVirtualChannelWrite(audin->audin_channel, (PCHAR)Stream_Buffer(s), + Stream_GetPosition(s), &written) + ? CHANNEL_RC_OK + : ERROR_INTERNAL_ERROR; } /** @@ -282,15 +278,14 @@ static UINT audin_server_send_open(audin_server* audin, wStream* s) * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_server_recv_open_reply(audin_server* audin, wStream* s, - UINT32 length) +static UINT audin_server_recv_open_reply(audin_server* audin, wStream* s, UINT32 length) { UINT32 Result; UINT success = CHANNEL_RC_OK; if (length < 4) { - WLog_ERR(TAG, "error parsing version info: expected at least 4 bytes, got %"PRIu32"", + WLog_ERR(TAG, "error parsing version info: expected at least 4 bytes, got %" PRIu32 "", length); return ERROR_INVALID_DATA; } @@ -299,7 +294,7 @@ static UINT audin_server_recv_open_reply(audin_server* audin, wStream* s, IFCALLRET(audin->context.OpenResult, success, &audin->context, Result); if (success) - WLog_ERR(TAG, "context.OpenResult failed with error %"PRIu32"", success); + WLog_ERR(TAG, "context.OpenResult failed with error %" PRIu32 "", success); return success; } @@ -309,8 +304,7 @@ static UINT audin_server_recv_open_reply(audin_server* audin, wStream* s, * * @return 0 on success, otherwise a Win32 error code */ -static UINT audin_server_recv_data(audin_server* audin, wStream* s, - UINT32 length) +static UINT audin_server_recv_data(audin_server* audin, wStream* s, UINT32 length) { AUDIO_FORMAT* format; int sbytes_per_sample; @@ -346,7 +340,7 @@ static UINT audin_server_recv_data(audin_server* audin, wStream* s, IFCALLRET(audin->context.ReceiveSamples, success, &audin->context, &dformat, out, frames); if (success) - WLog_ERR(TAG, "context.ReceiveSamples failed with error %"PRIu32"", success); + WLog_ERR(TAG, "context.ReceiveSamples failed with error %" PRIu32 "", success); } else WLog_ERR(TAG, "freerdp_dsp_decode failed!"); @@ -365,7 +359,7 @@ static DWORD WINAPI audin_server_thread_func(LPVOID arg) BOOL ready = FALSE; HANDLE ChannelEvent; DWORD BytesReturned = 0; - audin_server* audin = (audin_server*) arg; + audin_server* audin = (audin_server*)arg; UINT error = CHANNEL_RC_OK; DWORD status; buffer = NULL; @@ -395,26 +389,25 @@ static DWORD WINAPI audin_server_thread_func(LPVOID arg) while (1) { - if ((status = WaitForMultipleObjects(nCount, events, FALSE, - 100)) == WAIT_OBJECT_0) + if ((status = WaitForMultipleObjects(nCount, events, FALSE, 100)) == WAIT_OBJECT_0) goto out; if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForMultipleObjects failed with error %" PRIu32 "", error); goto out; } - if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, - &buffer, &BytesReturned) == FALSE) + if (WTSVirtualChannelQuery(audin->audin_channel, WTSVirtualChannelReady, &buffer, + &BytesReturned) == FALSE) { WLog_ERR(TAG, "WTSVirtualChannelQuery failed"); error = ERROR_INTERNAL_ERROR; goto out; } - ready = *((BOOL*) buffer); + ready = *((BOOL*)buffer); WTSFreeMemory(buffer); if (ready) @@ -434,21 +427,20 @@ static DWORD WINAPI audin_server_thread_func(LPVOID arg) { if ((error = audin_server_send_version(audin, s))) { - WLog_ERR(TAG, "audin_server_send_version failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "audin_server_send_version failed with error %" PRIu32 "!", error); goto out_capacity; } } while (ready) { - if ((status = WaitForMultipleObjects(nCount, events, FALSE, - INFINITE)) == WAIT_OBJECT_0) + if ((status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE)) == WAIT_OBJECT_0) break; if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForMultipleObjects failed with error %" PRIu32 "", error); goto out; } @@ -467,7 +459,7 @@ static DWORD WINAPI audin_server_thread_func(LPVOID arg) if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) break; - if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR) Stream_Buffer(s), + if (WTSVirtualChannelRead(audin->audin_channel, 0, (PCHAR)Stream_Buffer(s), Stream_Capacity(s), &BytesReturned) == FALSE) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); @@ -483,13 +475,15 @@ static DWORD WINAPI audin_server_thread_func(LPVOID arg) case MSG_SNDIN_VERSION: if ((error = audin_server_recv_version(audin, s, BytesReturned))) { - WLog_ERR(TAG, "audin_server_recv_version failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "audin_server_recv_version failed with error %" PRIu32 "!", + error); goto out_capacity; } if ((error = audin_server_send_formats(audin, s))) { - WLog_ERR(TAG, "audin_server_send_formats failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "audin_server_send_formats failed with error %" PRIu32 "!", + error); goto out_capacity; } @@ -498,13 +492,14 @@ static DWORD WINAPI audin_server_thread_func(LPVOID arg) case MSG_SNDIN_FORMATS: if ((error = audin_server_recv_formats(audin, s, BytesReturned))) { - WLog_ERR(TAG, "audin_server_recv_formats failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "audin_server_recv_formats failed with error %" PRIu32 "!", + error); goto out_capacity; } if ((error = audin_server_send_open(audin, s))) { - WLog_ERR(TAG, "audin_server_send_open failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "audin_server_send_open failed with error %" PRIu32 "!", error); goto out_capacity; } @@ -513,7 +508,8 @@ static DWORD WINAPI audin_server_thread_func(LPVOID arg) case MSG_SNDIN_OPEN_REPLY: if ((error = audin_server_recv_open_reply(audin, s, BytesReturned))) { - WLog_ERR(TAG, "audin_server_recv_open_reply failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "audin_server_recv_open_reply failed with error %" PRIu32 "!", + error); goto out_capacity; } @@ -525,7 +521,7 @@ static DWORD WINAPI audin_server_thread_func(LPVOID arg) case MSG_SNDIN_DATA: if ((error = audin_server_recv_data(audin, s, BytesReturned))) { - WLog_ERR(TAG, "audin_server_recv_data failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "audin_server_recv_data failed with error %" PRIu32 "!", error); goto out_capacity; }; @@ -535,7 +531,7 @@ static DWORD WINAPI audin_server_thread_func(LPVOID arg) break; default: - WLog_ERR(TAG, "audin_server_thread_func: unknown MessageId %"PRIu8"", MessageId); + WLog_ERR(TAG, "audin_server_thread_func: unknown MessageId %" PRIu8 "", MessageId); break; } } @@ -556,7 +552,7 @@ out: static BOOL audin_server_open(audin_server_context* context) { - audin_server* audin = (audin_server*) context; + audin_server* audin = (audin_server*)context; if (!audin->thread) { @@ -564,15 +560,15 @@ static BOOL audin_server_open(audin_server_context* context) DWORD BytesReturned = 0; audin->SessionId = WTS_CURRENT_SESSION; - if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, - WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned)) + if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId, + (LPSTR*)&pSessionId, &BytesReturned)) { - audin->SessionId = (DWORD) * pSessionId; + audin->SessionId = (DWORD)*pSessionId; WTSFreeMemory(pSessionId); } - audin->audin_channel = WTSVirtualChannelOpenEx(audin->SessionId, - "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC); + audin->audin_channel = + WTSVirtualChannelOpenEx(audin->SessionId, "AUDIO_INPUT", WTS_CHANNEL_OPTION_DYNAMIC); if (!audin->audin_channel) { @@ -586,7 +582,8 @@ static BOOL audin_server_open(audin_server_context* context) return FALSE; } - if (!(audin->thread = CreateThread(NULL, 0, audin_server_thread_func, (void*) audin, 0, NULL))) + if (!(audin->thread = + CreateThread(NULL, 0, audin_server_thread_func, (void*)audin, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); CloseHandle(audin->stopEvent); @@ -603,7 +600,7 @@ static BOOL audin_server_open(audin_server_context* context) static BOOL audin_server_is_open(audin_server_context* context) { - audin_server* audin = (audin_server*) context; + audin_server* audin = (audin_server*)context; if (!audin) return FALSE; @@ -613,7 +610,7 @@ static BOOL audin_server_is_open(audin_server_context* context) static BOOL audin_server_close(audin_server_context* context) { - audin_server* audin = (audin_server*) context; + audin_server* audin = (audin_server*)context; if (audin->thread) { @@ -621,7 +618,7 @@ static BOOL audin_server_close(audin_server_context* context) if (WaitForSingleObject(audin->thread, INFINITE) == WAIT_FAILED) { - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", GetLastError()); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", GetLastError()); return FALSE; } @@ -668,12 +665,12 @@ audin_server_context* audin_server_context_new(HANDLE vcm) return NULL; } - return (audin_server_context*) audin; + return (audin_server_context*)audin; } void audin_server_context_free(audin_server_context* context) { - audin_server* audin = (audin_server*) context; + audin_server* audin = (audin_server*)context; if (!audin) return; diff --git a/channels/client/CMakeLists.txt b/channels/client/CMakeLists.txt index 5f1fb31..eb0c80f 100644 --- a/channels/client/CMakeLists.txt +++ b/channels/client/CMakeLists.txt @@ -33,22 +33,28 @@ set(CLIENT_STATIC_TYPEDEFS "${CLIENT_STATIC_TYPEDEFS}typedef UINT (*static_addin foreach(STATIC_ENTRY ${CHANNEL_STATIC_CLIENT_ENTRIES}) foreach(STATIC_MODULE ${CHANNEL_STATIC_CLIENT_MODULES}) - if(${${STATIC_MODULE}_CLIENT_ENTRY} STREQUAL ${STATIC_ENTRY}) - set(STATIC_MODULE_NAME ${${STATIC_MODULE}_CLIENT_NAME}) - set(STATIC_MODULE_CHANNEL ${${STATIC_MODULE}_CLIENT_CHANNEL}) - set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${STATIC_MODULE_NAME}) + foreach(ENTRY ${${STATIC_MODULE}_CLIENT_ENTRY}) + if(${ENTRY} STREQUAL ${STATIC_ENTRY}) + set(STATIC_MODULE_NAME ${${STATIC_MODULE}_CLIENT_NAME}) + set(STATIC_MODULE_CHANNEL ${${STATIC_MODULE}_CLIENT_CHANNEL}) + set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${STATIC_MODULE_NAME}) - set(ENTRY_POINT_NAME "${STATIC_MODULE_CHANNEL}_${${STATIC_MODULE}_CLIENT_ENTRY}") - if(${${STATIC_MODULE}_CLIENT_ENTRY} STREQUAL "VirtualChannelEntry") - set(ENTRY_POINT_IMPORT "extern BOOL VCAPITYPE ${ENTRY_POINT_NAME}(PCHANNEL_ENTRY_POINTS);") - elseif(${${STATIC_MODULE}_CLIENT_ENTRY} STREQUAL "VirtualChannelEntryEx") - set(ENTRY_POINT_IMPORT "extern BOOL VCAPITYPE ${ENTRY_POINT_NAME}(PCHANNEL_ENTRY_POINTS,PVOID);") - else() - set(ENTRY_POINT_IMPORT "extern UINT ${ENTRY_POINT_NAME}(void);") + set(ENTRY_POINT_NAME "${STATIC_MODULE_CHANNEL}_${ENTRY}") + if(${ENTRY} STREQUAL "VirtualChannelEntry") + set(ENTRY_POINT_IMPORT "extern BOOL VCAPITYPE ${ENTRY_POINT_NAME}(PCHANNEL_ENTRY_POINTS);") + elseif(${ENTRY} STREQUAL "VirtualChannelEntryEx") + set(ENTRY_POINT_IMPORT "extern BOOL VCAPITYPE ${ENTRY_POINT_NAME}(PCHANNEL_ENTRY_POINTS,PVOID);") + elseif(${ENTRY} MATCHES "DVCPluginEntry$") + set(ENTRY_POINT_IMPORT "extern UINT ${ENTRY_POINT_NAME}(IDRDYNVC_ENTRY_POINTS* pEntryPoints);") + elseif(${ENTRY} MATCHES "DeviceServiceEntry$") + set(ENTRY_POINT_IMPORT "extern UINT ${ENTRY_POINT_NAME}(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints);") + else() + set(ENTRY_POINT_IMPORT "extern UINT ${ENTRY_POINT_NAME}(void);") + endif() + set(${STATIC_ENTRY}_IMPORTS "${${STATIC_ENTRY}_IMPORTS}\n${ENTRY_POINT_IMPORT}") + set(${STATIC_ENTRY}_TABLE "${${STATIC_ENTRY}_TABLE}\n\t{ \"${STATIC_MODULE_CHANNEL}\", (static_entry_fkt)${ENTRY_POINT_NAME} },") endif() - set(${STATIC_ENTRY}_IMPORTS "${${STATIC_ENTRY}_IMPORTS}\n${ENTRY_POINT_IMPORT}") - set(${STATIC_ENTRY}_TABLE "${${STATIC_ENTRY}_TABLE}\n\t{ \"${STATIC_MODULE_CHANNEL}\", (static_entry_fkt)${ENTRY_POINT_NAME} },") - endif() + endforeach() endforeach() endforeach() @@ -91,15 +97,17 @@ foreach(STATIC_MODULE ${CHANNEL_STATIC_CLIENT_MODULES}) set(STATIC_SUBSYSTEM_ENTRY "${STATIC_SUBSYSTEM_NAME}_freerdp_${STATIC_MODULE_CHANNEL}_client_subsystem_entry") endif() set(SUBSYSTEM_TABLE "${SUBSYSTEM_TABLE}\n\t{ \"${STATIC_SUBSYSTEM_NAME}\", \"${STATIC_SUBSYSTEM_TYPE}\", ${STATIC_SUBSYSTEM_ENTRY} },") - set(SUBSYSTEM_IMPORT "extern void ${STATIC_SUBSYSTEM_ENTRY}(void);") + set(SUBSYSTEM_IMPORT "extern UINT ${STATIC_SUBSYSTEM_ENTRY}(void*);") set(CLIENT_STATIC_SUBSYSTEM_IMPORTS "${CLIENT_STATIC_SUBSYSTEM_IMPORTS}\n${SUBSYSTEM_IMPORT}") endforeach() set(SUBSYSTEM_TABLE "${SUBSYSTEM_TABLE}\n\t{ NULL, NULL, NULL }\n};") set(CLIENT_STATIC_SUBSYSTEM_TABLES "${CLIENT_STATIC_SUBSYSTEM_TABLES}\n${SUBSYSTEM_TABLE}") - set(ENTRY_POINT_NAME "${STATIC_MODULE_CHANNEL}_${${STATIC_MODULE}_CLIENT_ENTRY}") - set(CLIENT_STATIC_ADDIN_TABLE "${CLIENT_STATIC_ADDIN_TABLE}\n\t{ \"${STATIC_MODULE_CHANNEL}\", (static_addin_fkt)${ENTRY_POINT_NAME}, ${SUBSYSTEM_TABLE_NAME} },") + foreach(ENTRY ${${STATIC_MODULE}_CLIENT_ENTRY}) + set (ENTRY_POINT_NAME ${STATIC_MODULE_CHANNEL}_${ENTRY}) + set(CLIENT_STATIC_ADDIN_TABLE "${CLIENT_STATIC_ADDIN_TABLE}\n\t{ \"${STATIC_MODULE_CHANNEL}\", \"${ENTRY}\", (static_addin_fkt)${ENTRY_POINT_NAME}, ${SUBSYSTEM_TABLE_NAME} },") + endforeach() endforeach() -set(CLIENT_STATIC_ADDIN_TABLE "${CLIENT_STATIC_ADDIN_TABLE}\n\t{ NULL, NULL, NULL }\n};") +set(CLIENT_STATIC_ADDIN_TABLE "${CLIENT_STATIC_ADDIN_TABLE}\n\t{ NULL, NULL, NULL, NULL }\n};") configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tables.c.in ${CMAKE_CURRENT_BINARY_DIR}/tables.c) diff --git a/channels/client/addin.c b/channels/client/addin.c index 86b9f43..cd6f90e 100644 --- a/channels/client/addin.c +++ b/channels/client/addin.c @@ -43,21 +43,21 @@ extern const STATIC_ENTRY_TABLE CLIENT_STATIC_ENTRY_TABLES[]; -void* freerdp_channels_find_static_entry_in_table(const STATIC_ENTRY_TABLE* table, - const char* identifier) +static void* freerdp_channels_find_static_entry_in_table(const STATIC_ENTRY_TABLE* table, + const char* identifier) { - int index = 0; + size_t index = 0; STATIC_ENTRY* pEntry; - pEntry = (STATIC_ENTRY*) &table->table[index++]; + pEntry = (STATIC_ENTRY*)&table->table[index++]; while (pEntry->entry != NULL) { if (strcmp(pEntry->name, identifier) == 0) { - return (void*) pEntry->entry; + return (void*)pEntry->entry; } - pEntry = (STATIC_ENTRY*) &table->table[index++]; + pEntry = (STATIC_ENTRY*)&table->table[index++]; } return NULL; @@ -65,9 +65,9 @@ void* freerdp_channels_find_static_entry_in_table(const STATIC_ENTRY_TABLE* tabl void* freerdp_channels_client_find_static_entry(const char* name, const char* identifier) { - int index = 0; + size_t index = 0; STATIC_ENTRY_TABLE* pEntry; - pEntry = (STATIC_ENTRY_TABLE*) &CLIENT_STATIC_ENTRY_TABLES[index++]; + pEntry = (STATIC_ENTRY_TABLE*)&CLIENT_STATIC_ENTRY_TABLES[index++]; while (pEntry->table != NULL) { @@ -76,7 +76,7 @@ void* freerdp_channels_client_find_static_entry(const char* name, const char* id return freerdp_channels_find_static_entry_in_table(pEntry, identifier); } - pEntry = (STATIC_ENTRY_TABLE*) &CLIENT_STATIC_ENTRY_TABLES[index++]; + pEntry = (STATIC_ENTRY_TABLE*)&CLIENT_STATIC_ENTRY_TABLES[index++]; } return NULL; @@ -84,15 +84,16 @@ void* freerdp_channels_client_find_static_entry(const char* name, const char* id extern const STATIC_ADDIN_TABLE CLIENT_STATIC_ADDIN_TABLE[]; -FREERDP_ADDIN** freerdp_channels_list_client_static_addins(LPSTR pszName, LPSTR pszSubsystem, - LPSTR pszType, DWORD dwFlags) +static FREERDP_ADDIN** freerdp_channels_list_client_static_addins(LPCSTR pszName, + LPCSTR pszSubsystem, + LPCSTR pszType, DWORD dwFlags) { size_t i, j; DWORD nAddins; FREERDP_ADDIN** ppAddins = NULL; STATIC_SUBSYSTEM_ENTRY* subsystems; nAddins = 0; - ppAddins = (FREERDP_ADDIN**) calloc(128, sizeof(FREERDP_ADDIN*)); + ppAddins = (FREERDP_ADDIN**)calloc(128, sizeof(FREERDP_ADDIN*)); if (!ppAddins) { @@ -104,7 +105,7 @@ FREERDP_ADDIN** freerdp_channels_list_client_static_addins(LPSTR pszName, LPSTR for (i = 0; CLIENT_STATIC_ADDIN_TABLE[i].name != NULL; i++) { - FREERDP_ADDIN* pAddin = (FREERDP_ADDIN*) calloc(1, sizeof(FREERDP_ADDIN)); + FREERDP_ADDIN* pAddin = (FREERDP_ADDIN*)calloc(1, sizeof(FREERDP_ADDIN)); if (!pAddin) { @@ -117,11 +118,11 @@ FREERDP_ADDIN** freerdp_channels_list_client_static_addins(LPSTR pszName, LPSTR pAddin->dwFlags |= FREERDP_ADDIN_STATIC; pAddin->dwFlags |= FREERDP_ADDIN_NAME; ppAddins[nAddins++] = pAddin; - subsystems = (STATIC_SUBSYSTEM_ENTRY*) CLIENT_STATIC_ADDIN_TABLE[i].table; + subsystems = (STATIC_SUBSYSTEM_ENTRY*)CLIENT_STATIC_ADDIN_TABLE[i].table; for (j = 0; subsystems[j].name != NULL; j++) { - pAddin = (FREERDP_ADDIN*) calloc(1, sizeof(FREERDP_ADDIN)); + pAddin = (FREERDP_ADDIN*)calloc(1, sizeof(FREERDP_ADDIN)); if (!pAddin) { @@ -129,7 +130,8 @@ FREERDP_ADDIN** freerdp_channels_list_client_static_addins(LPSTR pszName, LPSTR 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", + CLIENT_STATIC_ADDIN_TABLE[i].name); sprintf_s(pAddin->cSubsystem, ARRAYSIZE(pAddin->cSubsystem), "%s", subsystems[j].name); pAddin->dwFlags = FREERDP_ADDIN_CLIENT; pAddin->dwFlags |= FREERDP_ADDIN_STATIC; @@ -145,8 +147,8 @@ error_out: return NULL; } -FREERDP_ADDIN** freerdp_channels_list_dynamic_addins(LPSTR pszName, LPSTR pszSubsystem, - LPSTR pszType, DWORD dwFlags) +static FREERDP_ADDIN** freerdp_channels_list_dynamic_addins(LPCSTR pszName, LPCSTR pszSubsystem, + LPCSTR pszType, DWORD dwFlags) { int index; int nDashes; @@ -163,11 +165,11 @@ FREERDP_ADDIN** freerdp_channels_list_dynamic_addins(LPSTR pszName, LPSTR pszSub size_t cchInstallPrefix; FREERDP_ADDIN** ppAddins; WIN32_FIND_DATAA FindData; - cchAddinPath = strlen(pszAddinPath); - cchInstallPrefix = strlen(pszInstallPrefix); + cchAddinPath = strnlen(pszAddinPath, sizeof(FREERDP_ADDIN_PATH)); + cchInstallPrefix = strnlen(pszInstallPrefix, sizeof(FREERDP_INSTALL_PREFIX)); pszExtension = PathGetSharedLibraryExtensionA(0); - cchPattern = 128 + strlen(pszExtension) + 2; - pszPattern = (LPSTR) malloc(cchPattern + 1); + cchPattern = 128 + strnlen(pszExtension, MAX_PATH) + 2; + pszPattern = (LPSTR)malloc(cchPattern + 1); if (!pszPattern) { @@ -177,28 +179,28 @@ FREERDP_ADDIN** freerdp_channels_list_dynamic_addins(LPSTR pszName, LPSTR pszSub if (pszName && pszSubsystem && pszType) { - sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX"%s-client-%s-%s.%s", + sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX "%s-client-%s-%s.%s", pszName, pszSubsystem, pszType, pszExtension); } else if (pszName && pszType) { - sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX"%s-client-?-%s.%s", + sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX "%s-client-?-%s.%s", pszName, pszType, pszExtension); } else if (pszName) { - sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX"%s-client*.%s", - pszName, pszExtension); + sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX "%s-client*.%s", pszName, + pszExtension); } else { - sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX"?-client*.%s", + sprintf_s(pszPattern, cchPattern, FREERDP_SHARED_LIBRARY_PREFIX "?-client*.%s", pszExtension); } - cchPattern = strlen(pszPattern); + cchPattern = strnlen(pszPattern, cchPattern); cchSearchPath = cchInstallPrefix + cchAddinPath + cchPattern + 3; - pszSearchPath = (LPSTR) malloc(cchSearchPath + 1); + pszSearchPath = (LPSTR)malloc(cchSearchPath + 1); if (!pszSearchPath) { @@ -215,7 +217,7 @@ FREERDP_ADDIN** freerdp_channels_list_dynamic_addins(LPSTR pszName, LPSTR pszSub hFind = FindFirstFileA(pszSearchPath, &FindData); free(pszSearchPath); nAddins = 0; - ppAddins = (FREERDP_ADDIN**) calloc(128, sizeof(FREERDP_ADDIN*)); + ppAddins = (FREERDP_ADDIN**)calloc(128, sizeof(FREERDP_ADDIN*)); if (!ppAddins) { @@ -232,7 +234,7 @@ FREERDP_ADDIN** freerdp_channels_list_dynamic_addins(LPSTR pszName, LPSTR pszSub char* p[5]; FREERDP_ADDIN* pAddin; nDashes = 0; - pAddin = (FREERDP_ADDIN*) calloc(1, sizeof(FREERDP_ADDIN)); + pAddin = (FREERDP_ADDIN*)calloc(1, sizeof(FREERDP_ADDIN)); if (!pAddin) { @@ -291,8 +293,7 @@ FREERDP_ADDIN** freerdp_channels_list_dynamic_addins(LPSTR pszName, LPSTR pszSub { free(pAddin); } - } - while (FindNextFileA(hFind, &FindData)); + } while (FindNextFileA(hFind, &FindData)); FindClose(hFind); ppAddins[nAddins] = NULL; @@ -303,8 +304,8 @@ error_out: return NULL; } -FREERDP_ADDIN** freerdp_channels_list_addins(LPSTR pszName, LPSTR pszSubsystem, LPSTR pszType, - DWORD dwFlags) +FREERDP_ADDIN** freerdp_channels_list_addins(LPCSTR pszName, LPCSTR pszSubsystem, LPCSTR pszType, + DWORD dwFlags) { if (dwFlags & FREERDP_ADDIN_STATIC) return freerdp_channels_list_client_static_addins(pszName, pszSubsystem, pszType, dwFlags); @@ -316,7 +317,7 @@ FREERDP_ADDIN** freerdp_channels_list_addins(LPSTR pszName, LPSTR pszSubsystem, void freerdp_channels_addin_list_free(FREERDP_ADDIN** ppAddins) { - int index; + size_t index; if (!ppAddins) return; @@ -329,48 +330,68 @@ void freerdp_channels_addin_list_free(FREERDP_ADDIN** ppAddins) extern const STATIC_ENTRY CLIENT_VirtualChannelEntryEx_TABLE[]; -BOOL freerdp_channels_is_virtual_channel_entry_ex(LPCSTR pszName) +static BOOL freerdp_channels_is_virtual_channel_entry_ex(LPCSTR pszName) { - int i; - STATIC_ENTRY* entry; + size_t i; for (i = 0; CLIENT_VirtualChannelEntryEx_TABLE[i].name != NULL; i++) { - entry = (STATIC_ENTRY*) &CLIENT_VirtualChannelEntryEx_TABLE[i]; + const STATIC_ENTRY* entry = &CLIENT_VirtualChannelEntryEx_TABLE[i]; - if (!strcmp(entry->name, pszName)) + if (!strncmp(entry->name, pszName, MAX_PATH)) return TRUE; } return FALSE; } -PVIRTUALCHANNELENTRY freerdp_channels_load_static_addin_entry(LPCSTR pszName, LPSTR pszSubsystem, - LPSTR pszType, DWORD dwFlags) +PVIRTUALCHANNELENTRY freerdp_channels_load_static_addin_entry(LPCSTR pszName, LPCSTR pszSubsystem, + LPCSTR pszType, DWORD dwFlags) { - int i, j; - STATIC_SUBSYSTEM_ENTRY* subsystems; + const STATIC_ADDIN_TABLE* table = CLIENT_STATIC_ADDIN_TABLE; + const char* type = NULL; - for (i = 0; CLIENT_STATIC_ADDIN_TABLE[i].name != NULL; i++) + if (!pszName) + return NULL; + + if (dwFlags & FREERDP_ADDIN_CHANNEL_DYNAMIC) + type = "DVCPluginEntry"; + else if (dwFlags & FREERDP_ADDIN_CHANNEL_DEVICE) + type = "DeviceServiceEntry"; + else if (dwFlags & FREERDP_ADDIN_CHANNEL_STATIC) + { + if (dwFlags & FREERDP_ADDIN_CHANNEL_ENTRYEX) + type = "VirtualChannelEntryEx"; + else + type = "VirtualChannelEntry"; + } + + for (; table->name != NULL; table++) { - if (strcmp(CLIENT_STATIC_ADDIN_TABLE[i].name, pszName) == 0) + if (strncmp(table->name, pszName, MAX_PATH) == 0) { + if (type && strncmp(table->type, type, MAX_PATH)) + continue; + if (pszSubsystem != NULL) { - subsystems = (STATIC_SUBSYSTEM_ENTRY*) CLIENT_STATIC_ADDIN_TABLE[i].table; + const STATIC_SUBSYSTEM_ENTRY* subsystems = table->table; - for (j = 0; subsystems[j].name != NULL; j++) + for (; subsystems->name != NULL; subsystems++) { - if (strcmp(subsystems[j].name, pszSubsystem) == 0) + /* If the pszSubsystem is an empty string use the default backend. */ + if ((strnlen(pszSubsystem, 1) == + 0) || /* we only want to know if strnlen is > 0 */ + (strncmp(subsystems->name, pszSubsystem, MAX_PATH) == 0)) { if (pszType) { - if (strcmp(subsystems[j].type, pszType) == 0) - return (PVIRTUALCHANNELENTRY) subsystems[j].entry; + if (strncmp(subsystems->type, pszType, MAX_PATH) == 0) + return (PVIRTUALCHANNELENTRY)subsystems->entry; } else { - return (PVIRTUALCHANNELENTRY) subsystems[j].entry; + return (PVIRTUALCHANNELENTRY)subsystems->entry; } } } @@ -383,7 +404,7 @@ PVIRTUALCHANNELENTRY freerdp_channels_load_static_addin_entry(LPCSTR pszName, LP return NULL; } - return (PVIRTUALCHANNELENTRY) CLIENT_STATIC_ADDIN_TABLE[i].entry; + return (PVIRTUALCHANNELENTRY)table->entry; } } } diff --git a/channels/client/addin.h b/channels/client/addin.h index f3ad970..849b11f 100644 --- a/channels/client/addin.h +++ b/channels/client/addin.h @@ -16,5 +16,3 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - diff --git a/channels/client/tables.c.in b/channels/client/tables.c.in index cc789d8..aafc71d 100644 --- a/channels/client/tables.c.in +++ b/channels/client/tables.c.in @@ -19,6 +19,7 @@ * limitations under the License. */ +#include #include "tables.h" ${CLIENT_STATIC_TYPEDEFS} diff --git a/channels/client/tables.h b/channels/client/tables.h index c84298a..b6b3f9c 100644 --- a/channels/client/tables.h +++ b/channels/client/tables.h @@ -22,7 +22,7 @@ struct _STATIC_ENTRY { const char* name; - UINT(*entry)(); + UINT (*entry)(); }; typedef struct _STATIC_ENTRY STATIC_ENTRY; @@ -37,14 +37,15 @@ struct _STATIC_SUBSYSTEM_ENTRY { const char* name; const char* type; - void (*entry)(void); + UINT (*entry)(); }; typedef struct _STATIC_SUBSYSTEM_ENTRY STATIC_SUBSYSTEM_ENTRY; struct _STATIC_ADDIN_TABLE { const char* name; - UINT(*entry)(); + const char* type; + UINT (*entry)(); const STATIC_SUBSYSTEM_ENTRY* table; }; typedef struct _STATIC_ADDIN_TABLE STATIC_ADDIN_TABLE; diff --git a/channels/cliprdr/client/CMakeLists.txt b/channels/cliprdr/client/CMakeLists.txt index 6081bee..4511e08 100644 --- a/channels/cliprdr/client/CMakeLists.txt +++ b/channels/cliprdr/client/CMakeLists.txt @@ -21,7 +21,10 @@ set(${MODULE_PREFIX}_SRCS cliprdr_format.c cliprdr_format.h cliprdr_main.c - cliprdr_main.h) + cliprdr_main.h + ../cliprdr_common.h + ../cliprdr_common.c + ) add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntryEx") diff --git a/channels/cliprdr/client/cliprdr_format.c b/channels/cliprdr/client/cliprdr_format.c index a97a584..43b967e 100644 --- a/channels/cliprdr/client/cliprdr_format.c +++ b/channels/cliprdr/client/cliprdr_format.c @@ -33,22 +33,17 @@ #include "cliprdr_main.h" #include "cliprdr_format.h" +#include "../cliprdr_common.h" /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) +UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, + UINT16 msgFlags) { - UINT32 index; - size_t position; - BOOL asciiNames; - int formatNameLength; - char* szFormatName; - WCHAR* wszFormatName; - CLIPRDR_FORMAT* formats = NULL; - CLIPRDR_FORMAT_LIST formatList; + CLIPRDR_FORMAT_LIST formatList = { 0 }; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); UINT error = CHANNEL_RC_OK; @@ -58,185 +53,24 @@ UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 data return ERROR_INTERNAL_ERROR; } - asciiNames = (msgFlags & CB_ASCII_NAMES) ? TRUE : FALSE; - formatList.msgType = CB_FORMAT_LIST; formatList.msgFlags = msgFlags; formatList.dataLen = dataLen; - index = 0; - formatList.numFormats = 0; - position = Stream_GetPosition(s); - - if (!formatList.dataLen) - { - /* empty format list */ - formatList.formats = NULL; - formatList.numFormats = 0; - } - else if (!cliprdr->useLongFormatNames) - { - formatList.numFormats = (dataLen / 36); - - if ((formatList.numFormats * 36) != dataLen) - { - WLog_ERR(TAG, "Invalid short format list length: %"PRIu32"", dataLen); - return ERROR_INTERNAL_ERROR; - } - - if (formatList.numFormats) - formats = (CLIPRDR_FORMAT*) calloc(formatList.numFormats, sizeof(CLIPRDR_FORMAT)); - - if (!formats) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - formatList.formats = formats; - - while (dataLen) - { - Stream_Read_UINT32(s, formats[index].formatId); /* formatId (4 bytes) */ - dataLen -= 4; - - formats[index].formatName = NULL; - - /* According to MS-RDPECLIP 2.2.3.1.1.1 formatName is "a 32-byte block containing - * the *null-terminated* name assigned to the Clipboard Format: (32 ASCII 8 characters - * or 16 Unicode characters)" - * However, both Windows RDSH and mstsc violate this specs as seen in the following - * example of a transferred short format name string: [R.i.c.h. .T.e.x.t. .F.o.r.m.a.t.] - * These are 16 unicode charaters - *without* terminating null ! - */ - - if (asciiNames) - { - szFormatName = (char*) Stream_Pointer(s); - - if (szFormatName[0]) - { - /* ensure null termination */ - formats[index].formatName = (char*) malloc(32 + 1); - if (!formats[index].formatName) - { - WLog_ERR(TAG, "malloc failed!"); - error = CHANNEL_RC_NO_MEMORY; - goto error_out; - } - CopyMemory(formats[index].formatName, szFormatName, 32); - formats[index].formatName[32] = '\0'; - } - } - else - { - wszFormatName = (WCHAR*) Stream_Pointer(s); - - if (wszFormatName[0]) - { - /* ConvertFromUnicode always returns a null-terminated - * string on success, even if the source string isn't. - */ - if (ConvertFromUnicode(CP_UTF8, 0, wszFormatName, 16, - &(formats[index].formatName), 0, NULL, NULL) < 1) - { - WLog_ERR(TAG, "failed to convert short clipboard format name"); - error = ERROR_INTERNAL_ERROR; - goto error_out; - } - } - } - - Stream_Seek(s, 32); - dataLen -= 32; - index++; - } - } - else - { - while (dataLen) - { - Stream_Seek(s, 4); /* formatId (4 bytes) */ - dataLen -= 4; - - wszFormatName = (WCHAR*) Stream_Pointer(s); - - if (!wszFormatName[0]) - formatNameLength = 0; - else - formatNameLength = _wcslen(wszFormatName); - - Stream_Seek(s, (formatNameLength + 1) * 2); - dataLen -= ((formatNameLength + 1) * 2); - - formatList.numFormats++; - } - - dataLen = formatList.dataLen; - Stream_SetPosition(s, position); - - if (formatList.numFormats) - formats = (CLIPRDR_FORMAT*) calloc(formatList.numFormats, sizeof(CLIPRDR_FORMAT)); - - if (!formats) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - formatList.formats = formats; - - while (dataLen) - { - Stream_Read_UINT32(s, formats[index].formatId); /* formatId (4 bytes) */ - dataLen -= 4; - - formats[index].formatName = NULL; - - wszFormatName = (WCHAR*) Stream_Pointer(s); - - if (!wszFormatName[0]) - formatNameLength = 0; - else - formatNameLength = _wcslen(wszFormatName); + if ((error = cliprdr_read_format_list(s, &formatList, cliprdr->useLongFormatNames))) + goto error_out; - if (formatNameLength) - { - if (ConvertFromUnicode(CP_UTF8, 0, wszFormatName, -1, - &(formats[index].formatName), 0, NULL, NULL) < 1) - { - WLog_ERR(TAG, "failed to convert long clipboard format name"); - error = ERROR_INTERNAL_ERROR; - goto error_out; - } - } - - Stream_Seek(s, (formatNameLength + 1) * 2); - dataLen -= ((formatNameLength + 1) * 2); - - index++; - } - } - - WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatList: numFormats: %"PRIu32"", - formatList.numFormats); + WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerFormatList: numFormats: %" PRIu32 "", + formatList.numFormats); if (context->ServerFormatList) { if ((error = context->ServerFormatList(context, &formatList))) - WLog_ERR(TAG, "ServerFormatList failed with error %"PRIu32"", error); + WLog_ERR(TAG, "ServerFormatList failed with error %" PRIu32 "", error); } error_out: - if (formats) - { - for (index = 0; index < formatList.numFormats; index++) - { - free(formats[index].formatName); - } - - free(formats); - } + cliprdr_free_format_list(&formatList); return error; } @@ -245,9 +79,10 @@ error_out: * * @return 0 on success, otherwise a Win32 error code */ -UINT cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) +UINT cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, + UINT16 msgFlags) { - CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse; + CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse = { 0 }; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); UINT error = CHANNEL_RC_OK; @@ -265,7 +100,7 @@ UINT cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UI IFCALLRET(context->ServerFormatListResponse, error, context, &formatListResponse); if (error) - WLog_ERR(TAG, "ServerFormatListResponse failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ServerFormatListResponse failed with error %" PRIu32 "!", error); return error; } @@ -275,7 +110,8 @@ UINT cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UI * * @return 0 on success, otherwise a Win32 error code */ -UINT cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) +UINT cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, + UINT16 msgFlags) { CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); @@ -293,12 +129,13 @@ UINT cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UIN formatDataRequest.msgFlags = msgFlags; formatDataRequest.dataLen = dataLen; - Stream_Read_UINT32(s, formatDataRequest.requestedFormatId); /* requestedFormatId (4 bytes) */ - + if ((error = cliprdr_read_format_data_request(s, &formatDataRequest))) + return error; + context->lastRequestedFormatId = formatDataRequest.requestedFormatId; IFCALLRET(context->ServerFormatDataRequest, error, context, &formatDataRequest); if (error) - WLog_ERR(TAG, "ServerFormatDataRequest failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ServerFormatDataRequest failed with error %" PRIu32 "!", error); return error; } @@ -308,7 +145,8 @@ UINT cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UIN * * @return 0 on success, otherwise a Win32 error code */ -UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags) +UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, + UINT16 msgFlags) { CLIPRDR_FORMAT_DATA_RESPONSE formatDataResponse; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); @@ -325,14 +163,13 @@ UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UI formatDataResponse.msgType = CB_FORMAT_DATA_RESPONSE; formatDataResponse.msgFlags = msgFlags; formatDataResponse.dataLen = dataLen; - formatDataResponse.requestedFormatData = NULL; - if (dataLen) - formatDataResponse.requestedFormatData = (BYTE*) Stream_Pointer(s); + if ((error = cliprdr_read_format_data_response(s, &formatDataResponse))) + return error; IFCALLRET(context->ServerFormatDataResponse, error, context, &formatDataResponse); if (error) - WLog_ERR(TAG, "ServerFormatDataResponse failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ServerFormatDataResponse failed with error %" PRIu32 "!", error); return error; } @@ -340,17 +177,17 @@ UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UI static UINT64 filetime_to_uint64(FILETIME value) { UINT64 converted = 0; - converted |= (UINT32) value.dwHighDateTime; + converted |= (UINT32)value.dwHighDateTime; converted <<= 32; - converted |= (UINT32) value.dwLowDateTime; + converted |= (UINT32)value.dwLowDateTime; return converted; } static FILETIME uint64_to_filetime(UINT64 value) { FILETIME converted; - converted.dwLowDateTime = (UINT32) (value >> 0); - converted.dwHighDateTime = (UINT32) (value >> 32); + converted.dwLowDateTime = (UINT32)(value >> 0); + converted.dwHighDateTime = (UINT32)(value >> 32); return converted; } @@ -369,7 +206,7 @@ static FILETIME uint64_to_filetime(UINT64 value) * @returns 0 on success, otherwise a Win32 error code. */ UINT cliprdr_parse_file_list(const BYTE* format_data, UINT32 format_data_length, - FILEDESCRIPTOR** file_descriptor_array, UINT32* file_descriptor_count) + FILEDESCRIPTOR** file_descriptor_array, UINT32* file_descriptor_count) { UINT result = NO_ERROR; UINT32 i; @@ -379,7 +216,7 @@ UINT cliprdr_parse_file_list(const BYTE* format_data, UINT32 format_data_length, if (!format_data || !file_descriptor_array || !file_descriptor_count) return ERROR_BAD_ARGUMENTS; - s = Stream_New((BYTE*) format_data, format_data_length); + s = Stream_New((BYTE*)format_data, format_data_length); if (!s) return ERROR_NOT_ENOUGH_MEMORY; @@ -395,9 +232,8 @@ UINT cliprdr_parse_file_list(const BYTE* format_data, UINT32 format_data_length, if (Stream_GetRemainingLength(s) / CLIPRDR_FILEDESCRIPTOR_SIZE < count) { - WLog_ERR(TAG, "packed file list is too short: expected %"PRIuz", have %"PRIuz, - ((size_t) count) * CLIPRDR_FILEDESCRIPTOR_SIZE, - Stream_GetRemainingLength(s)); + WLog_ERR(TAG, "packed file list is too short: expected %" PRIuz ", have %" PRIuz, + ((size_t)count) * CLIPRDR_FILEDESCRIPTOR_SIZE, Stream_GetRemainingLength(s)); result = ERROR_INCORRECT_SIZE; goto out; @@ -417,21 +253,21 @@ UINT cliprdr_parse_file_list(const BYTE* format_data, UINT32 format_data_length, UINT64 lastWriteTime; FILEDESCRIPTOR* file = &((*file_descriptor_array)[i]); - Stream_Read_UINT32(s, file->dwFlags); /* flags (4 bytes) */ - Stream_Seek(s, 32); /* reserved1 (32 bytes) */ + Stream_Read_UINT32(s, file->dwFlags); /* flags (4 bytes) */ + Stream_Seek(s, 32); /* reserved1 (32 bytes) */ Stream_Read_UINT32(s, file->dwFileAttributes); /* fileAttributes (4 bytes) */ - Stream_Seek(s, 16); /* reserved2 (16 bytes) */ - Stream_Read_UINT64(s, lastWriteTime); /* lastWriteTime (8 bytes) */ + Stream_Seek(s, 16); /* reserved2 (16 bytes) */ + Stream_Read_UINT64(s, lastWriteTime); /* lastWriteTime (8 bytes) */ file->ftLastWriteTime = uint64_to_filetime(lastWriteTime); Stream_Read_UINT32(s, file->nFileSizeHigh); /* fileSizeHigh (4 bytes) */ - Stream_Read_UINT32(s, file->nFileSizeLow); /* fileSizeLow (4 bytes) */ - for (c = 0; c < 260; c++) /* cFileName (520 bytes) */ + Stream_Read_UINT32(s, file->nFileSizeLow); /* fileSizeLow (4 bytes) */ + for (c = 0; c < 260; c++) /* cFileName (520 bytes) */ Stream_Read_UINT16(s, file->cFileName[c]); } if (Stream_GetRemainingLength(s) > 0) - WLog_WARN(TAG, "packed file list has %"PRIuz" excess bytes", - Stream_GetRemainingLength(s)); + WLog_WARN(TAG, "packed file list has %" PRIuz " excess bytes", + Stream_GetRemainingLength(s)); out: Stream_Free(s, FALSE); @@ -453,7 +289,8 @@ out: * @returns 0 on success, otherwise a Win32 error code. */ UINT cliprdr_serialize_file_list(const FILEDESCRIPTOR* file_descriptor_array, - UINT32 file_descriptor_count, BYTE** format_data, UINT32* format_data_length) + UINT32 file_descriptor_count, BYTE** format_data, + UINT32* format_data_length) { UINT result = NO_ERROR; UINT32 i; @@ -488,15 +325,15 @@ UINT cliprdr_serialize_file_list(const FILEDESCRIPTOR* file_descriptor_array, goto error; } - Stream_Write_UINT32(s, file->dwFlags); /* flags (4 bytes) */ - Stream_Zero(s, 32); /* reserved1 (32 bytes) */ + Stream_Write_UINT32(s, file->dwFlags); /* flags (4 bytes) */ + Stream_Zero(s, 32); /* reserved1 (32 bytes) */ Stream_Write_UINT32(s, file->dwFileAttributes); /* fileAttributes (4 bytes) */ - Stream_Zero(s, 16); /* reserved2 (16 bytes) */ + Stream_Zero(s, 16); /* reserved2 (16 bytes) */ lastWriteTime = filetime_to_uint64(file->ftLastWriteTime); - Stream_Write_UINT64(s, lastWriteTime); /* lastWriteTime (8 bytes) */ + Stream_Write_UINT64(s, lastWriteTime); /* lastWriteTime (8 bytes) */ Stream_Write_UINT32(s, file->nFileSizeHigh); /* fileSizeHigh (4 bytes) */ - Stream_Write_UINT32(s, file->nFileSizeLow); /* fileSizeLow (4 bytes) */ - for (c = 0; c < 260; c++) /* cFileName (520 bytes) */ + Stream_Write_UINT32(s, file->nFileSizeLow); /* fileSizeLow (4 bytes) */ + for (c = 0; c < 260; c++) /* cFileName (520 bytes) */ Stream_Write_UINT16(s, file->cFileName[c]); } diff --git a/channels/cliprdr/client/cliprdr_format.h b/channels/cliprdr/client/cliprdr_format.h index dfe6965..a068d6f 100644 --- a/channels/cliprdr/client/cliprdr_format.h +++ b/channels/cliprdr/client/cliprdr_format.h @@ -23,9 +23,13 @@ #ifndef FREERDP_CHANNEL_CLIPRDR_CLIENT_FORMAT_H #define FREERDP_CHANNEL_CLIPRDR_CLIENT_FORMAT_H -UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags); -UINT cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags); -UINT cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags); -UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, UINT16 msgFlags); +UINT cliprdr_process_format_list(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, + UINT16 msgFlags); +UINT cliprdr_process_format_list_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, + UINT16 msgFlags); +UINT cliprdr_process_format_data_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, + UINT16 msgFlags); +UINT cliprdr_process_format_data_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 dataLen, + UINT16 msgFlags); #endif /* FREERDP_CHANNEL_CLIPRDR_CLIENT_FORMAT_H */ diff --git a/channels/cliprdr/client/cliprdr_main.c b/channels/cliprdr/client/cliprdr_main.c index 8ab0903..b5d119a 100644 --- a/channels/cliprdr/client/cliprdr_main.c +++ b/channels/cliprdr/client/cliprdr_main.c @@ -33,23 +33,21 @@ #include "cliprdr_main.h" #include "cliprdr_format.h" +#include "../cliprdr_common.h" #ifdef WITH_DEBUG_CLIPRDR -static const char* const CB_MSG_TYPE_STRINGS[] = -{ - "", - "CB_MONITOR_READY", - "CB_FORMAT_LIST", - "CB_FORMAT_LIST_RESPONSE", - "CB_FORMAT_DATA_REQUEST", - "CB_FORMAT_DATA_RESPONSE", - "CB_TEMP_DIRECTORY", - "CB_CLIP_CAPS", - "CB_FILECONTENTS_REQUEST", - "CB_FILECONTENTS_RESPONSE", - "CB_LOCK_CLIPDATA", - "CB_UNLOCK_CLIPDATA" -}; +static const char* const CB_MSG_TYPE_STRINGS[] = { "", + "CB_MONITOR_READY", + "CB_FORMAT_LIST", + "CB_FORMAT_LIST_RESPONSE", + "CB_FORMAT_DATA_REQUEST", + "CB_FORMAT_DATA_RESPONSE", + "CB_TEMP_DIRECTORY", + "CB_CLIP_CAPS", + "CB_FILECONTENTS_REQUEST", + "CB_FILECONTENTS_RESPONSE", + "CB_LOCK_CLIPDATA", + "CB_UNLOCK_CLIPDATA" }; #endif CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr) @@ -59,29 +57,10 @@ CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr) if (!cliprdr) return NULL; - pInterface = (CliprdrClientContext*) cliprdr->channelEntryPoints.pInterface; + pInterface = (CliprdrClientContext*)cliprdr->channelEntryPoints.pInterface; return pInterface; } -static wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, - UINT32 dataLen) -{ - wStream* s; - s = Stream_New(NULL, dataLen + 8); - - if (!s) - { - WLog_ERR(TAG, "Stream_New failed!"); - return NULL; - } - - Stream_Write_UINT16(s, msgType); - Stream_Write_UINT16(s, msgFlags); - /* Write actual length after the entire packet has been constructed. */ - Stream_Seek(s, 4); - return s; -} - /** * Function description * @@ -98,7 +77,7 @@ static UINT cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* s) Stream_Write_UINT32(s, dataLen); Stream_SetPosition(s, pos); #ifdef WITH_DEBUG_CLIPRDR - WLog_DBG(TAG, "Cliprdr Sending (%"PRIu32" bytes)", dataLen + 8); + WLog_DBG(TAG, "Cliprdr Sending (%" PRIu32 " bytes)", dataLen + 8); winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), dataLen + 8); #endif @@ -108,14 +87,17 @@ static UINT cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* s) } else { - status = cliprdr->channelEntryPoints.pVirtualChannelWriteEx(cliprdr->InitHandle, - cliprdr->OpenHandle, - Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s); + status = cliprdr->channelEntryPoints.pVirtualChannelWriteEx( + cliprdr->InitHandle, cliprdr->OpenHandle, Stream_Buffer(s), + (UINT32)Stream_GetPosition(s), s); } if (status != CHANNEL_RC_OK) - WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08"PRIX32"]", + { + Stream_Free(s, TRUE); + WLog_ERR(TAG, "VirtualChannelWrite failed with %s [%08" PRIX32 "]", WTSErrorToString(status), status); + } return status; } @@ -123,21 +105,21 @@ static UINT cliprdr_packet_send(cliprdrPlugin* cliprdr, wStream* s) #ifdef WITH_DEBUG_CLIPRDR static void cliprdr_print_general_capability_flags(UINT32 flags) { - WLog_INFO(TAG, "generalFlags (0x%08"PRIX32") {", flags); + WLog_INFO(TAG, "generalFlags (0x%08" PRIX32 ") {", flags); if (flags & CB_USE_LONG_FORMAT_NAMES) - WLog_INFO(TAG, "\tCB_USE_LONG_FORMAT_NAMES"); + WLog_INFO(TAG, "\tCB_USE_LONG_FORMAT_NAMES"); if (flags & CB_STREAM_FILECLIP_ENABLED) - WLog_INFO(TAG, "\tCB_STREAM_FILECLIP_ENABLED"); + WLog_INFO(TAG, "\tCB_STREAM_FILECLIP_ENABLED"); if (flags & CB_FILECLIP_NO_FILE_PATHS) - WLog_INFO(TAG, "\tCB_FILECLIP_NO_FILE_PATHS"); + WLog_INFO(TAG, "\tCB_FILECLIP_NO_FILE_PATHS"); if (flags & CB_CAN_LOCK_CLIPDATA) - WLog_INFO(TAG, "\tCB_CAN_LOCK_CLIPDATA"); + WLog_INFO(TAG, "\tCB_CAN_LOCK_CLIPDATA"); - WLog_INFO(TAG, "}"); + WLog_INFO(TAG, "}"); } #endif @@ -146,8 +128,7 @@ static void cliprdr_print_general_capability_flags(UINT32 flags) * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr, - wStream* s) +static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr, wStream* s) { UINT32 version; UINT32 generalFlags; @@ -165,28 +146,17 @@ static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr, if (Stream_GetRemainingLength(s) < 8) return ERROR_INVALID_DATA; - Stream_Read_UINT32(s, version); /* version (4 bytes) */ + Stream_Read_UINT32(s, version); /* version (4 bytes) */ Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */ - DEBUG_CLIPRDR("Version: %"PRIu32"", version); + DEBUG_CLIPRDR("Version: %" PRIu32 "", version); #ifdef WITH_DEBUG_CLIPRDR cliprdr_print_general_capability_flags(generalFlags); #endif - if (cliprdr->useLongFormatNames) - cliprdr->useLongFormatNames = (generalFlags & CB_USE_LONG_FORMAT_NAMES) ? TRUE : - FALSE; - - if (cliprdr->streamFileClipEnabled) - cliprdr->streamFileClipEnabled = (generalFlags & CB_STREAM_FILECLIP_ENABLED) ? - TRUE : FALSE; - - if (cliprdr->fileClipNoFilePaths) - cliprdr->fileClipNoFilePaths = (generalFlags & CB_FILECLIP_NO_FILE_PATHS) ? - TRUE : FALSE; - - if (cliprdr->canLockClipData) - cliprdr->canLockClipData = (generalFlags & CB_CAN_LOCK_CLIPDATA) ? TRUE : FALSE; - + cliprdr->useLongFormatNames = (generalFlags & CB_USE_LONG_FORMAT_NAMES); + cliprdr->streamFileClipEnabled = (generalFlags & CB_STREAM_FILECLIP_ENABLED); + cliprdr->fileClipNoFilePaths = (generalFlags & CB_FILECLIP_NO_FILE_PATHS); + cliprdr->canLockClipData = (generalFlags & CB_CAN_LOCK_CLIPDATA); cliprdr->capabilitiesReceived = TRUE; if (!context->custom) @@ -195,9 +165,9 @@ static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr, return ERROR_INTERNAL_ERROR; } + capabilities.msgType = CB_CLIP_CAPS; capabilities.cCapabilitiesSets = 1; - capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) & - (generalCapabilitySet); + capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*)&(generalCapabilitySet); generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL; generalCapabilitySet.capabilitySetLength = 12; generalCapabilitySet.version = version; @@ -205,7 +175,7 @@ static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr, IFCALLRET(context->ServerCapabilities, error, context, &capabilities); if (error) - WLog_ERR(TAG, "ServerCapabilities failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ServerCapabilities failed with error %" PRIu32 "!", error); return error; } @@ -215,8 +185,8 @@ static UINT cliprdr_process_general_capability(cliprdrPlugin* cliprdr, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, - UINT16 length, UINT16 flags) +static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, + UINT16 flags) { UINT16 index; UINT16 lengthCapability; @@ -228,7 +198,7 @@ static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, return ERROR_INVALID_DATA; Stream_Read_UINT16(s, cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */ - Stream_Seek_UINT16(s); /* pad1 (2 bytes) */ + Stream_Seek_UINT16(s); /* pad1 (2 bytes) */ WLog_Print(cliprdr->log, WLOG_DEBUG, "ServerCapabilities"); for (index = 0; index < cCapabilitiesSets; index++) @@ -237,9 +207,9 @@ static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, return ERROR_INVALID_DATA; Stream_Read_UINT16(s, capabilitySetType); /* capabilitySetType (2 bytes) */ - Stream_Read_UINT16(s, lengthCapability); /* lengthCapability (2 bytes) */ + Stream_Read_UINT16(s, lengthCapability); /* lengthCapability (2 bytes) */ - if (lengthCapability < 4 || Stream_GetRemainingLength(s) < lengthCapability - 4) + if ((lengthCapability < 4) || (Stream_GetRemainingLength(s) < (lengthCapability - 4U))) return ERROR_INVALID_DATA; switch (capabilitySetType) @@ -247,7 +217,8 @@ static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, case CB_CAPSTYPE_GENERAL: if ((error = cliprdr_process_general_capability(cliprdr, s))) { - WLog_ERR(TAG, "cliprdr_process_general_capability failed with error %"PRIu32"!", + WLog_ERR(TAG, + "cliprdr_process_general_capability failed with error %" PRIu32 "!", error); return error; } @@ -255,9 +226,8 @@ static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, break; default: - WLog_ERR(TAG, "unknown cliprdr capability set: %"PRIu16"", capabilitySetType); + WLog_ERR(TAG, "unknown cliprdr capability set: %" PRIu16 "", capabilitySetType); return CHANNEL_RC_BAD_PROC; - break; } } @@ -269,8 +239,8 @@ static UINT cliprdr_process_clip_caps(cliprdrPlugin* cliprdr, wStream* s, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, - UINT16 length, UINT16 flags) +static UINT cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, + UINT16 flags) { CLIPRDR_MONITOR_READY monitorReady; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); @@ -286,11 +256,11 @@ static UINT cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, if (!cliprdr->capabilitiesReceived) { /** - * The clipboard capabilities pdu from server to client is optional, - * but a server using it must send it before sending the monitor ready pdu. - * When the server capabilities pdu is not used, default capabilities - * corresponding to a generalFlags field set to zero are assumed. - */ + * The clipboard capabilities pdu from server to client is optional, + * but a server using it must send it before sending the monitor ready pdu. + * When the server capabilities pdu is not used, default capabilities + * corresponding to a generalFlags field set to zero are assumed. + */ cliprdr->useLongFormatNames = FALSE; cliprdr->streamFileClipEnabled = FALSE; cliprdr->fileClipNoFilePaths = TRUE; @@ -303,7 +273,7 @@ static UINT cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, IFCALLRET(context->MonitorReady, error, context, &monitorReady); if (error) - WLog_ERR(TAG, "MonitorReady failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "MonitorReady failed with error %" PRIu32 "!", error); return error; } @@ -313,8 +283,8 @@ static UINT cliprdr_process_monitor_ready(cliprdrPlugin* cliprdr, wStream* s, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_process_filecontents_request(cliprdrPlugin* cliprdr, - wStream* s, UINT32 length, UINT16 flags) +static UINT cliprdr_process_filecontents_request(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, + UINT16 flags) { CLIPRDR_FILE_CONTENTS_REQUEST request; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); @@ -327,33 +297,17 @@ static UINT cliprdr_process_filecontents_request(cliprdrPlugin* cliprdr, return ERROR_INTERNAL_ERROR; } - if (Stream_GetRemainingLength(s) < 24) - { - WLog_ERR(TAG, "not enough remaining data"); - return ERROR_INVALID_DATA; - } - request.msgType = CB_FILECONTENTS_REQUEST; request.msgFlags = flags; request.dataLen = length; - request.haveClipDataId = FALSE; - Stream_Read_UINT32(s, request.streamId); /* streamId (4 bytes) */ - Stream_Read_UINT32(s, request.listIndex); /* listIndex (4 bytes) */ - Stream_Read_UINT32(s, request.dwFlags); /* dwFlags (4 bytes) */ - Stream_Read_UINT32(s, request.nPositionLow); /* nPositionLow (4 bytes) */ - Stream_Read_UINT32(s, request.nPositionHigh); /* nPositionHigh (4 bytes) */ - Stream_Read_UINT32(s, request.cbRequested); /* cbRequested (4 bytes) */ - - if (Stream_GetRemainingLength(s) >= 4) - { - Stream_Read_UINT32(s, request.clipDataId); /* clipDataId (4 bytes) */ - request.haveClipDataId = TRUE; - } + + if ((error = cliprdr_read_file_contents_request(s, &request))) + return error; IFCALLRET(context->ServerFileContentsRequest, error, context, &request); if (error) - WLog_ERR(TAG, "ServerFileContentsRequest failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ServerFileContentsRequest failed with error %" PRIu32 "!", error); return error; } @@ -363,8 +317,8 @@ static UINT cliprdr_process_filecontents_request(cliprdrPlugin* cliprdr, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_process_filecontents_response(cliprdrPlugin* cliprdr, - wStream* s, UINT32 length, UINT16 flags) +static UINT cliprdr_process_filecontents_response(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, + UINT16 flags) { CLIPRDR_FILE_CONTENTS_RESPONSE response; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); @@ -377,22 +331,17 @@ static UINT cliprdr_process_filecontents_response(cliprdrPlugin* cliprdr, return ERROR_INTERNAL_ERROR; } - if (Stream_GetRemainingLength(s) < 4) - { - WLog_ERR(TAG, "not enough remaining data"); - return ERROR_INVALID_DATA; - } - response.msgType = CB_FILECONTENTS_RESPONSE; response.msgFlags = flags; response.dataLen = length; - Stream_Read_UINT32(s, response.streamId); /* streamId (4 bytes) */ - response.cbRequested = length - 4; - response.requestedData = Stream_Pointer(s); /* requestedFileContentsData */ + + if ((error = cliprdr_read_file_contents_response(s, &response))) + return error; + IFCALLRET(context->ServerFileContentsResponse, error, context, &response); if (error) - WLog_ERR(TAG, "ServerFileContentsResponse failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ServerFileContentsResponse failed with error %" PRIu32 "!", error); return error; } @@ -402,8 +351,8 @@ static UINT cliprdr_process_filecontents_response(cliprdrPlugin* cliprdr, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_process_lock_clipdata(cliprdrPlugin* cliprdr, wStream* s, - UINT32 length, UINT16 flags) +static UINT cliprdr_process_lock_clipdata(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, + UINT16 flags) { CLIPRDR_LOCK_CLIPBOARD_DATA lockClipboardData; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); @@ -429,7 +378,7 @@ static UINT cliprdr_process_lock_clipdata(cliprdrPlugin* cliprdr, wStream* s, IFCALLRET(context->ServerLockClipboardData, error, context, &lockClipboardData); if (error) - WLog_ERR(TAG, "ServerLockClipboardData failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ServerLockClipboardData failed with error %" PRIu32 "!", error); return error; } @@ -439,8 +388,8 @@ static UINT cliprdr_process_lock_clipdata(cliprdrPlugin* cliprdr, wStream* s, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s, - UINT32 length, UINT16 flags) +static UINT cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s, UINT32 length, + UINT16 flags) { CLIPRDR_UNLOCK_CLIPBOARD_DATA unlockClipboardData; CliprdrClientContext* context = cliprdr_get_client_interface(cliprdr); @@ -453,21 +402,17 @@ static UINT cliprdr_process_unlock_clipdata(cliprdrPlugin* cliprdr, wStream* s, return ERROR_INTERNAL_ERROR; } - if (Stream_GetRemainingLength(s) < 4) - { - WLog_ERR(TAG, "not enough remaining data"); - return ERROR_INVALID_DATA; - } + if ((error = cliprdr_read_unlock_clipdata(s, &unlockClipboardData))) + return error; unlockClipboardData.msgType = CB_UNLOCK_CLIPDATA; unlockClipboardData.msgFlags = flags; unlockClipboardData.dataLen = length; - Stream_Read_UINT32(s, unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */ - IFCALLRET(context->ServerUnlockClipboardData, error, context, - &unlockClipboardData); + + IFCALLRET(context->ServerUnlockClipboardData, error, context, &unlockClipboardData); if (error) - WLog_ERR(TAG, "ServerUnlockClipboardData failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ServerUnlockClipboardData failed with error %" PRIu32 "!", error); return error; } @@ -487,15 +432,15 @@ static UINT cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s) if (Stream_GetRemainingLength(s) < 8) return ERROR_INVALID_DATA; - Stream_Read_UINT16(s, msgType); /* msgType (2 bytes) */ + Stream_Read_UINT16(s, msgType); /* msgType (2 bytes) */ Stream_Read_UINT16(s, msgFlags); /* msgFlags (2 bytes) */ - Stream_Read_UINT32(s, dataLen); /* dataLen (4 bytes) */ + Stream_Read_UINT32(s, dataLen); /* dataLen (4 bytes) */ if (Stream_GetRemainingLength(s) < dataLen) return ERROR_INVALID_DATA; #ifdef WITH_DEBUG_CLIPRDR - WLog_DBG(TAG, "msgType: %s (%"PRIu16"), msgFlags: %"PRIu16" dataLen: %"PRIu32"", + WLog_DBG(TAG, "msgType: %s (%" PRIu16 "), msgFlags: %" PRIu16 " dataLen: %" PRIu32 "", CB_MSG_TYPE_STRINGS[msgType], msgType, msgFlags, dataLen); winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), dataLen + 8); #endif @@ -504,72 +449,76 @@ static UINT cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s) { case CB_CLIP_CAPS: if ((error = cliprdr_process_clip_caps(cliprdr, s, dataLen, msgFlags))) - WLog_ERR(TAG, "cliprdr_process_clip_caps failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "cliprdr_process_clip_caps failed with error %" PRIu32 "!", error); break; case CB_MONITOR_READY: if ((error = cliprdr_process_monitor_ready(cliprdr, s, dataLen, msgFlags))) - WLog_ERR(TAG, "cliprdr_process_monitor_ready failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "cliprdr_process_monitor_ready failed with error %" PRIu32 "!", + error); break; case CB_FORMAT_LIST: if ((error = cliprdr_process_format_list(cliprdr, s, dataLen, msgFlags))) - WLog_ERR(TAG, "cliprdr_process_format_list failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "cliprdr_process_format_list failed with error %" PRIu32 "!", error); break; case CB_FORMAT_LIST_RESPONSE: if ((error = cliprdr_process_format_list_response(cliprdr, s, dataLen, msgFlags))) - WLog_ERR(TAG, "cliprdr_process_format_list_response failed with error %"PRIu32"!", + WLog_ERR(TAG, "cliprdr_process_format_list_response failed with error %" PRIu32 "!", error); break; case CB_FORMAT_DATA_REQUEST: if ((error = cliprdr_process_format_data_request(cliprdr, s, dataLen, msgFlags))) - WLog_ERR(TAG, "cliprdr_process_format_data_request failed with error %"PRIu32"!", + WLog_ERR(TAG, "cliprdr_process_format_data_request failed with error %" PRIu32 "!", error); break; case CB_FORMAT_DATA_RESPONSE: if ((error = cliprdr_process_format_data_response(cliprdr, s, dataLen, msgFlags))) - WLog_ERR(TAG, "cliprdr_process_format_data_response failed with error %"PRIu32"!", + WLog_ERR(TAG, "cliprdr_process_format_data_response failed with error %" PRIu32 "!", error); break; case CB_FILECONTENTS_REQUEST: if ((error = cliprdr_process_filecontents_request(cliprdr, s, dataLen, msgFlags))) - WLog_ERR(TAG, "cliprdr_process_filecontents_request failed with error %"PRIu32"!", + WLog_ERR(TAG, "cliprdr_process_filecontents_request failed with error %" PRIu32 "!", error); break; case CB_FILECONTENTS_RESPONSE: if ((error = cliprdr_process_filecontents_response(cliprdr, s, dataLen, msgFlags))) - WLog_ERR(TAG, "cliprdr_process_filecontents_response failed with error %"PRIu32"!", + WLog_ERR(TAG, + "cliprdr_process_filecontents_response failed with error %" PRIu32 "!", error); break; case CB_LOCK_CLIPDATA: if ((error = cliprdr_process_lock_clipdata(cliprdr, s, dataLen, msgFlags))) - WLog_ERR(TAG, "cliprdr_process_lock_clipdata failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "cliprdr_process_lock_clipdata failed with error %" PRIu32 "!", + error); break; case CB_UNLOCK_CLIPDATA: if ((error = cliprdr_process_unlock_clipdata(cliprdr, s, dataLen, msgFlags))) - WLog_ERR(TAG, "cliprdr_process_lock_clipdata failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "cliprdr_process_lock_clipdata failed with error %" PRIu32 "!", + error); break; default: error = CHANNEL_RC_BAD_PROC; - WLog_ERR(TAG, "unknown msgType %"PRIu16"", msgType); + WLog_ERR(TAG, "unknown msgType %" PRIu16 "", msgType); break; } @@ -587,11 +536,13 @@ static UINT cliprdr_order_recv(cliprdrPlugin* cliprdr, wStream* s) * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_client_capabilities(CliprdrClientContext* context, - CLIPRDR_CAPABILITIES* capabilities) + const CLIPRDR_CAPABILITIES* capabilities) { wStream* s; - CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet; - cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; + UINT32 flags; + const CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet; + cliprdrPlugin* cliprdr = (cliprdrPlugin*)context->handle; + s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN); if (!s) @@ -602,11 +553,31 @@ static UINT cliprdr_client_capabilities(CliprdrClientContext* context, Stream_Write_UINT16(s, 1); /* cCapabilitiesSets */ Stream_Write_UINT16(s, 0); /* pad1 */ - generalCapabilitySet = (CLIPRDR_GENERAL_CAPABILITY_SET*)capabilities->capabilitySets; - Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetType); /* capabilitySetType */ + generalCapabilitySet = (const CLIPRDR_GENERAL_CAPABILITY_SET*)capabilities->capabilitySets; + Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetType); /* capabilitySetType */ Stream_Write_UINT16(s, generalCapabilitySet->capabilitySetLength); /* lengthCapability */ - Stream_Write_UINT32(s, generalCapabilitySet->version); /* version */ - Stream_Write_UINT32(s, generalCapabilitySet->generalFlags); /* generalFlags */ + Stream_Write_UINT32(s, generalCapabilitySet->version); /* version */ + flags = generalCapabilitySet->generalFlags; + + /* Client capabilities are sent in response to server capabilities. + * -> Do not request features the server does not support. + * -> Update clipboard context feature state to what was agreed upon. + */ + if (!cliprdr->useLongFormatNames) + flags &= ~CB_USE_LONG_FORMAT_NAMES; + if (!cliprdr->streamFileClipEnabled) + flags &= ~CB_STREAM_FILECLIP_ENABLED; + if (!cliprdr->fileClipNoFilePaths) + flags &= ~CB_FILECLIP_NO_FILE_PATHS; + if (!cliprdr->canLockClipData) + flags &= CB_CAN_LOCK_CLIPDATA; + + cliprdr->useLongFormatNames = flags & CB_USE_LONG_FORMAT_NAMES; + cliprdr->streamFileClipEnabled = flags & CB_STREAM_FILECLIP_ENABLED; + cliprdr->fileClipNoFilePaths = flags & CB_FILECLIP_NO_FILE_PATHS; + cliprdr->canLockClipData = flags & CB_CAN_LOCK_CLIPDATA; + + Stream_Write_UINT32(s, flags); /* generalFlags */ WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientCapabilities"); return cliprdr_packet_send(cliprdr, s); } @@ -617,13 +588,13 @@ static UINT cliprdr_client_capabilities(CliprdrClientContext* context, * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_temp_directory(CliprdrClientContext* context, - CLIPRDR_TEMP_DIRECTORY* tempDirectory) + const CLIPRDR_TEMP_DIRECTORY* tempDirectory) { int length; wStream* s; WCHAR* wszTempDir = NULL; - cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; - s = cliprdr_packet_new(CB_TEMP_DIRECTORY, 0, 520 * 2); + cliprdrPlugin* cliprdr = (cliprdrPlugin*)context->handle; + s = cliprdr_packet_new(CB_TEMP_DIRECTORY, 0, 260 * sizeof(WCHAR)); if (!s) { @@ -636,14 +607,15 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context, if (length < 0) return ERROR_INTERNAL_ERROR; - if (length > 520) - length = 520; + /* Path must be 260 UTF16 characters with '\0' termination. + * ensure this here */ + if (length >= 260) + length = 259; - Stream_Write(s, wszTempDir, length * 2); - Stream_Zero(s, (520 - length) * 2); + Stream_Write_UTF16_String(s, wszTempDir, length); + Stream_Zero(s, 520 - (length * sizeof(WCHAR))); free(wszTempDir); - WLog_Print(cliprdr->log, WLOG_DEBUG, "TempDirectory: %s", - tempDirectory->szTempDir); + WLog_Print(cliprdr->log, WLOG_DEBUG, "TempDirectory: %s", tempDirectory->szTempDir); return cliprdr_packet_send(cliprdr, s); } @@ -653,114 +625,19 @@ static UINT cliprdr_temp_directory(CliprdrClientContext* context, * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_client_format_list(CliprdrClientContext* context, - CLIPRDR_FORMAT_LIST* formatList) + const CLIPRDR_FORMAT_LIST* formatList) { wStream* s; - UINT32 index; - int length = 0; - int cchWideChar; - LPWSTR lpWideCharStr; - int formatNameSize; - int formatNameLength; - char* szFormatName; - WCHAR* wszFormatName; - BOOL asciiNames = FALSE; - CLIPRDR_FORMAT* format; - cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; - - if (!cliprdr->useLongFormatNames) - { - length = formatList->numFormats * 36; - s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length); + cliprdrPlugin* cliprdr = (cliprdrPlugin*)context->handle; - if (!s) - { - WLog_ERR(TAG, "cliprdr_packet_new failed!"); - return ERROR_INTERNAL_ERROR; - } - - for (index = 0; index < formatList->numFormats; index++) - { - format = (CLIPRDR_FORMAT*) & (formatList->formats[index]); - Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */ - formatNameSize = 0; - formatNameLength = 0; - szFormatName = format->formatName; - - if (asciiNames) - { - if (szFormatName) - formatNameLength = strlen(szFormatName); - - if (formatNameLength > 31) - formatNameLength = 31; - - Stream_Write(s, szFormatName, formatNameLength); - Stream_Zero(s, 32 - formatNameLength); - } - else - { - wszFormatName = NULL; - - if (szFormatName) - formatNameSize = ConvertToUnicode(CP_UTF8, 0, szFormatName, -1, &wszFormatName, - 0); - - if (formatNameSize > 15) - formatNameSize = 15; - - if (wszFormatName) - Stream_Write(s, wszFormatName, formatNameSize * 2); - - Stream_Zero(s, 32 - (formatNameSize * 2)); - free(wszFormatName); - } - } - } - else + s = cliprdr_packet_format_list_new(formatList, cliprdr->useLongFormatNames); + if (!s) { - for (index = 0; index < formatList->numFormats; index++) - { - format = (CLIPRDR_FORMAT*) & (formatList->formats[index]); - length += 4; - formatNameSize = 2; - - if (format->formatName) - formatNameSize = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, NULL, - 0) * 2; - - length += formatNameSize; - } - - s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length); - - if (!s) - { - WLog_ERR(TAG, "cliprdr_packet_new failed!"); - return ERROR_INTERNAL_ERROR; - } - - for (index = 0; index < formatList->numFormats; index++) - { - format = (CLIPRDR_FORMAT*) & (formatList->formats[index]); - Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */ - - if (format->formatName) - { - lpWideCharStr = (LPWSTR) Stream_Pointer(s); - cchWideChar = (Stream_Capacity(s) - Stream_GetPosition(s)) / 2; - formatNameSize = MultiByteToWideChar(CP_UTF8, 0, - format->formatName, -1, lpWideCharStr, cchWideChar) * 2; - Stream_Seek(s, formatNameSize); - } - else - { - Stream_Write_UINT16(s, 0); - } - } + WLog_ERR(TAG, "cliprdr_packet_format_list_new failed!"); + return ERROR_INTERNAL_ERROR; } - WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatList: numFormats: %"PRIu32"", + WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatList: numFormats: %" PRIu32 "", formatList->numFormats); return cliprdr_packet_send(cliprdr, s); } @@ -770,15 +647,13 @@ static UINT cliprdr_client_format_list(CliprdrClientContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_client_format_list_response(CliprdrClientContext* context, - CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse) +static UINT +cliprdr_client_format_list_response(CliprdrClientContext* context, + const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse) { wStream* s; - cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; - formatListResponse->msgType = CB_FORMAT_LIST_RESPONSE; - formatListResponse->dataLen = 0; - s = cliprdr_packet_new(formatListResponse->msgType, - formatListResponse->msgFlags, formatListResponse->dataLen); + cliprdrPlugin* cliprdr = (cliprdrPlugin*)context->handle; + s = cliprdr_packet_new(CB_FORMAT_LIST_RESPONSE, formatListResponse->msgFlags, 0); if (!s) { @@ -796,11 +671,11 @@ static UINT cliprdr_client_format_list_response(CliprdrClientContext* context, * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_client_lock_clipboard_data(CliprdrClientContext* context, - CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData) + const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData) { wStream* s; - cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; - s = cliprdr_packet_new(CB_LOCK_CLIPDATA, 0, 4); + cliprdrPlugin* cliprdr = (cliprdrPlugin*)context->handle; + s = cliprdr_packet_lock_clipdata_new(lockClipboardData); if (!s) { @@ -808,9 +683,7 @@ static UINT cliprdr_client_lock_clipboard_data(CliprdrClientContext* context, return ERROR_INTERNAL_ERROR; } - Stream_Write_UINT32(s, lockClipboardData->clipDataId); /* clipDataId (4 bytes) */ - WLog_Print(cliprdr->log, WLOG_DEBUG, - "ClientLockClipboardData: clipDataId: 0x%08"PRIX32"", + WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientLockClipboardData: clipDataId: 0x%08" PRIX32 "", lockClipboardData->clipDataId); return cliprdr_packet_send(cliprdr, s); } @@ -820,12 +693,13 @@ static UINT cliprdr_client_lock_clipboard_data(CliprdrClientContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context, - CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData) +static UINT +cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context, + const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData) { wStream* s; - cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; - s = cliprdr_packet_new(CB_UNLOCK_CLIPDATA, 0, 4); + cliprdrPlugin* cliprdr = (cliprdrPlugin*)context->handle; + s = cliprdr_packet_unlock_clipdata_new(unlockClipboardData); if (!s) { @@ -833,9 +707,7 @@ static UINT cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context, return ERROR_INTERNAL_ERROR; } - Stream_Write_UINT32(s, unlockClipboardData->clipDataId); /* clipDataId (4 bytes) */ - WLog_Print(cliprdr->log, WLOG_DEBUG, - "ClientUnlockClipboardData: clipDataId: 0x%08"PRIX32"", + WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientUnlockClipboardData: clipDataId: 0x%08" PRIX32 "", unlockClipboardData->clipDataId); return cliprdr_packet_send(cliprdr, s); } @@ -846,15 +718,12 @@ static UINT cliprdr_client_unlock_clipboard_data(CliprdrClientContext* context, * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_client_format_data_request(CliprdrClientContext* context, - CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) + const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) { wStream* s; - cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; - formatDataRequest->msgType = CB_FORMAT_DATA_REQUEST; - formatDataRequest->msgFlags = 0; - formatDataRequest->dataLen = 4; - s = cliprdr_packet_new(formatDataRequest->msgType, formatDataRequest->msgFlags, - formatDataRequest->dataLen); + cliprdrPlugin* cliprdr = (cliprdrPlugin*)context->handle; + + s = cliprdr_packet_new(CB_FORMAT_DATA_REQUEST, 0, 4); if (!s) { @@ -872,14 +741,15 @@ static UINT cliprdr_client_format_data_request(CliprdrClientContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_client_format_data_response(CliprdrClientContext* context, - CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse) +static UINT +cliprdr_client_format_data_response(CliprdrClientContext* context, + const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse) { wStream* s; - cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; - formatDataResponse->msgType = CB_FORMAT_DATA_RESPONSE; - s = cliprdr_packet_new(formatDataResponse->msgType, - formatDataResponse->msgFlags, formatDataResponse->dataLen); + cliprdrPlugin* cliprdr = (cliprdrPlugin*)context->handle; + + s = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE, formatDataResponse->msgFlags, + formatDataResponse->dataLen); if (!s) { @@ -887,8 +757,7 @@ static UINT cliprdr_client_format_data_response(CliprdrClientContext* context, return ERROR_INTERNAL_ERROR; } - Stream_Write(s, formatDataResponse->requestedFormatData, - formatDataResponse->dataLen); + Stream_Write(s, formatDataResponse->requestedFormatData, formatDataResponse->dataLen); WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFormatDataResponse"); return cliprdr_packet_send(cliprdr, s); } @@ -898,31 +767,22 @@ static UINT cliprdr_client_format_data_response(CliprdrClientContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_client_file_contents_request(CliprdrClientContext* context, - CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest) +static UINT +cliprdr_client_file_contents_request(CliprdrClientContext* context, + const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest) { wStream* s; - cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; - s = cliprdr_packet_new(CB_FILECONTENTS_REQUEST, 0, 28); + cliprdrPlugin* cliprdr = (cliprdrPlugin*)context->handle; + + s = cliprdr_packet_file_contents_request_new(fileContentsRequest); if (!s) { - WLog_ERR(TAG, "cliprdr_packet_new failed!"); + WLog_ERR(TAG, "cliprdr_packet_file_contents_request_new failed!"); return ERROR_INTERNAL_ERROR; } - Stream_Write_UINT32(s, fileContentsRequest->streamId); /* streamId (4 bytes) */ - Stream_Write_UINT32(s, fileContentsRequest->listIndex); /* listIndex (4 bytes) */ - Stream_Write_UINT32(s, fileContentsRequest->dwFlags); /* dwFlags (4 bytes) */ - Stream_Write_UINT32(s, fileContentsRequest->nPositionLow); /* nPositionLow (4 bytes) */ - Stream_Write_UINT32(s, fileContentsRequest->nPositionHigh); /* nPositionHigh (4 bytes) */ - Stream_Write_UINT32(s, fileContentsRequest->cbRequested); /* cbRequested (4 bytes) */ - - if (fileContentsRequest->haveClipDataId) - Stream_Write_UINT32(s, fileContentsRequest->clipDataId); /* clipDataId (4 bytes) */ - - WLog_Print(cliprdr->log, WLOG_DEBUG, - "ClientFileContentsRequest: streamId: 0x%08"PRIX32"", + WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFileContentsRequest: streamId: 0x%08" PRIX32 "", fileContentsRequest->streamId); return cliprdr_packet_send(cliprdr, s); } @@ -932,13 +792,13 @@ static UINT cliprdr_client_file_contents_request(CliprdrClientContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_client_file_contents_response(CliprdrClientContext* context, - CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse) +static UINT +cliprdr_client_file_contents_response(CliprdrClientContext* context, + const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse) { wStream* s; - cliprdrPlugin* cliprdr = (cliprdrPlugin*) context->handle; - s = cliprdr_packet_new(CB_FILECONTENTS_RESPONSE, fileContentsResponse->msgFlags, - 4 + fileContentsResponse->cbRequested); + cliprdrPlugin* cliprdr = (cliprdrPlugin*)context->handle; + s = cliprdr_packet_file_contents_response_new(fileContentsResponse); if (!s) { @@ -946,16 +806,7 @@ static UINT cliprdr_client_file_contents_response(CliprdrClientContext* context, return ERROR_INTERNAL_ERROR; } - Stream_Write_UINT32(s, fileContentsResponse->streamId); /* streamId (4 bytes) */ - /** - * requestedFileContentsData: - * FILECONTENTS_SIZE: file size as UINT64 - * FILECONTENTS_RANGE: file data from requested range - */ - Stream_Write(s, fileContentsResponse->requestedData, - fileContentsResponse->cbRequested); - WLog_Print(cliprdr->log, WLOG_DEBUG, - "ClientFileContentsResponse: streamId: 0x%08"PRIX32"", + WLog_Print(cliprdr->log, WLOG_DEBUG, "ClientFileContentsResponse: streamId: 0x%08" PRIX32 "", fileContentsResponse->streamId); return cliprdr_packet_send(cliprdr, s); } @@ -965,8 +816,9 @@ static UINT cliprdr_client_file_contents_response(CliprdrClientContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_virtual_channel_event_data_received(cliprdrPlugin* cliprdr, - void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) +static UINT cliprdr_virtual_channel_event_data_received(cliprdrPlugin* cliprdr, void* pData, + UINT32 dataLength, UINT32 totalLength, + UINT32 dataFlags) { wStream* data_in; @@ -989,7 +841,7 @@ static UINT cliprdr_virtual_channel_event_data_received(cliprdrPlugin* cliprdr, return CHANNEL_RC_NO_MEMORY; } - if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength)) + if (!Stream_EnsureRemainingCapacity(data_in, dataLength)) { Stream_Free(cliprdr->data_in, TRUE); cliprdr->data_in = NULL; @@ -1010,7 +862,7 @@ static UINT cliprdr_virtual_channel_event_data_received(cliprdrPlugin* cliprdr, Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); - if (!MessageQueue_Post(cliprdr->queue, NULL, 0, (void*) data_in, NULL)) + if (!MessageQueue_Post(cliprdr->queue, NULL, 0, (void*)data_in, NULL)) { WLog_ERR(TAG, "MessageQueue_Post failed!"); return ERROR_INTERNAL_ERROR; @@ -1021,35 +873,40 @@ static UINT cliprdr_virtual_channel_event_data_received(cliprdrPlugin* cliprdr, } static VOID VCAPITYPE cliprdr_virtual_channel_open_event_ex(LPVOID lpUserParam, DWORD openHandle, - UINT event, - LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) + UINT event, LPVOID pData, + UINT32 dataLength, UINT32 totalLength, + UINT32 dataFlags) { UINT error = CHANNEL_RC_OK; - cliprdrPlugin* cliprdr = (cliprdrPlugin*) lpUserParam; - - if (!cliprdr || (cliprdr->OpenHandle != openHandle)) - { - WLog_ERR(TAG, "error no match"); - return; - } + cliprdrPlugin* cliprdr = (cliprdrPlugin*)lpUserParam; switch (event) { case CHANNEL_EVENT_DATA_RECEIVED: + if (!cliprdr || (cliprdr->OpenHandle != openHandle)) + { + WLog_ERR(TAG, "error no match"); + return; + } if ((error = cliprdr_virtual_channel_event_data_received(cliprdr, pData, dataLength, - totalLength, dataFlags))) - WLog_ERR(TAG, "failed with error %"PRIu32"", error); + totalLength, dataFlags))) + WLog_ERR(TAG, "failed with error %" PRIu32 "", error); break; + case CHANNEL_EVENT_WRITE_CANCELLED: case CHANNEL_EVENT_WRITE_COMPLETE: - break; + { + wStream* s = (wStream*)pData; + Stream_Free(s, TRUE); + } + break; case CHANNEL_EVENT_USER: break; } - if (error && cliprdr->context->rdpcontext) + if (error && cliprdr && cliprdr->context->rdpcontext) setChannelError(cliprdr->context->rdpcontext, error, "cliprdr_virtual_channel_open_event_ex reported an error"); } @@ -1058,7 +915,7 @@ static DWORD WINAPI cliprdr_virtual_channel_client_thread(LPVOID arg) { wStream* data; wMessage message; - cliprdrPlugin* cliprdr = (cliprdrPlugin*) arg; + cliprdrPlugin* cliprdr = (cliprdrPlugin*)arg; UINT error = CHANNEL_RC_OK; while (1) @@ -1082,11 +939,11 @@ static DWORD WINAPI cliprdr_virtual_channel_client_thread(LPVOID arg) if (message.id == 0) { - data = (wStream*) message.wParam; + data = (wStream*)message.wParam; if ((error = cliprdr_order_recv(cliprdr, data))) { - WLog_ERR(TAG, "cliprdr_order_recv failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "cliprdr_order_recv failed with error %" PRIu32 "!", error); break; } } @@ -1100,27 +957,40 @@ static DWORD WINAPI cliprdr_virtual_channel_client_thread(LPVOID arg) return error; } +static void cliprdr_free_msg(void* obj) +{ + wMessage* msg = (wMessage*)obj; + + if (msg) + { + wStream* s = (wStream*)msg->wParam; + Stream_Free(s, TRUE); + } +} + /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_virtual_channel_event_connected(cliprdrPlugin* cliprdr, - LPVOID pData, UINT32 dataLength) +static UINT cliprdr_virtual_channel_event_connected(cliprdrPlugin* cliprdr, LPVOID pData, + UINT32 dataLength) { UINT32 status; - status = cliprdr->channelEntryPoints.pVirtualChannelOpenEx(cliprdr->InitHandle, - &cliprdr->OpenHandle, cliprdr->channelDef.name, - cliprdr_virtual_channel_open_event_ex); + wObject obj = { 0 }; + status = cliprdr->channelEntryPoints.pVirtualChannelOpenEx( + cliprdr->InitHandle, &cliprdr->OpenHandle, cliprdr->channelDef.name, + cliprdr_virtual_channel_open_event_ex); if (status != CHANNEL_RC_OK) { - WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08"PRIX32"]", + WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08" PRIX32 "]", WTSErrorToString(status), status); return status; } - cliprdr->queue = MessageQueue_New(NULL); + obj.fnObjectFree = cliprdr_free_msg; + cliprdr->queue = MessageQueue_New(&obj); if (!cliprdr->queue) { @@ -1129,8 +999,7 @@ static UINT cliprdr_virtual_channel_event_connected(cliprdrPlugin* cliprdr, } if (!(cliprdr->thread = CreateThread(NULL, 0, cliprdr_virtual_channel_client_thread, - (void*) cliprdr, - 0, NULL))) + (void*)cliprdr, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); MessageQueue_Free(cliprdr->queue); @@ -1153,22 +1022,23 @@ static UINT cliprdr_virtual_channel_event_disconnected(cliprdrPlugin* cliprdr) if (cliprdr->OpenHandle == 0) return CHANNEL_RC_OK; - if (MessageQueue_PostQuit(cliprdr->queue, 0) - && (WaitForSingleObject(cliprdr->thread, INFINITE) == WAIT_FAILED)) + if (MessageQueue_PostQuit(cliprdr->queue, 0) && + (WaitForSingleObject(cliprdr->thread, INFINITE) == WAIT_FAILED)) { rc = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", rc); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", rc); return rc; } MessageQueue_Free(cliprdr->queue); CloseHandle(cliprdr->thread); - rc = cliprdr->channelEntryPoints.pVirtualChannelCloseEx(cliprdr->InitHandle, cliprdr->OpenHandle); + rc = cliprdr->channelEntryPoints.pVirtualChannelCloseEx(cliprdr->InitHandle, + cliprdr->OpenHandle); if (CHANNEL_RC_OK != rc) { - WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08"PRIX32"]", - WTSErrorToString(rc), rc); + WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08" PRIX32 "]", WTSErrorToString(rc), + rc); return rc; } @@ -1197,10 +1067,11 @@ static UINT cliprdr_virtual_channel_event_terminated(cliprdrPlugin* cliprdr) } static VOID VCAPITYPE cliprdr_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle, - UINT event, LPVOID pData, UINT dataLength) + UINT event, LPVOID pData, + UINT dataLength) { UINT error = CHANNEL_RC_OK; - cliprdrPlugin* cliprdr = (cliprdrPlugin*) lpUserParam; + cliprdrPlugin* cliprdr = (cliprdrPlugin*)lpUserParam; if (!cliprdr || (cliprdr->InitHandle != pInitHandle)) { @@ -1212,7 +1083,8 @@ static VOID VCAPITYPE cliprdr_virtual_channel_init_event_ex(LPVOID lpUserParam, { case CHANNEL_EVENT_CONNECTED: if ((error = cliprdr_virtual_channel_event_connected(cliprdr, pData, dataLength))) - WLog_ERR(TAG, "cliprdr_virtual_channel_event_connected failed with error %"PRIu32"!", + WLog_ERR(TAG, + "cliprdr_virtual_channel_event_connected failed with error %" PRIu32 "!", error); break; @@ -1220,13 +1092,16 @@ static VOID VCAPITYPE cliprdr_virtual_channel_init_event_ex(LPVOID lpUserParam, case CHANNEL_EVENT_DISCONNECTED: if ((error = cliprdr_virtual_channel_event_disconnected(cliprdr))) WLog_ERR(TAG, - "cliprdr_virtual_channel_event_disconnected failed with error %"PRIu32"!", error); + "cliprdr_virtual_channel_event_disconnected failed with error %" PRIu32 + "!", + error); break; case CHANNEL_EVENT_TERMINATED: if ((error = cliprdr_virtual_channel_event_terminated(cliprdr))) - WLog_ERR(TAG, "cliprdr_virtual_channel_event_terminated failed with error %"PRIu32"!", + WLog_ERR(TAG, + "cliprdr_virtual_channel_event_terminated failed with error %" PRIu32 "!", error); break; @@ -1238,7 +1113,7 @@ static VOID VCAPITYPE cliprdr_virtual_channel_init_event_ex(LPVOID lpUserParam, } /* cliprdr is always built-in */ -#define VirtualChannelEntryEx cliprdr_VirtualChannelEntryEx +#define VirtualChannelEntryEx cliprdr_VirtualChannelEntryEx BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID pInitHandle) { @@ -1246,7 +1121,7 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p cliprdrPlugin* cliprdr; CliprdrClientContext* context = NULL; CHANNEL_ENTRY_POINTS_FREERDP_EX* pEntryPointsEx; - cliprdr = (cliprdrPlugin*) calloc(1, sizeof(cliprdrPlugin)); + cliprdr = (cliprdrPlugin*)calloc(1, sizeof(cliprdrPlugin)); if (!cliprdr) { @@ -1254,18 +1129,15 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p return FALSE; } - cliprdr->channelDef.options = - CHANNEL_OPTION_INITIALIZED | - CHANNEL_OPTION_ENCRYPT_RDP | - CHANNEL_OPTION_COMPRESS_RDP | - CHANNEL_OPTION_SHOW_PROTOCOL; + cliprdr->channelDef.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | + CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL; sprintf_s(cliprdr->channelDef.name, ARRAYSIZE(cliprdr->channelDef.name), "cliprdr"); - pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*) pEntryPoints; + pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*)pEntryPoints; if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)) && (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) { - context = (CliprdrClientContext*) calloc(1, sizeof(CliprdrClientContext)); + context = (CliprdrClientContext*)calloc(1, sizeof(CliprdrClientContext)); if (!context) { @@ -1274,7 +1146,7 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p return FALSE; } - context->handle = (void*) cliprdr; + context->handle = (void*)cliprdr; context->custom = NULL; context->ClientCapabilities = cliprdr_client_capabilities; context->TempDirectory = cliprdr_temp_directory; @@ -1291,22 +1163,18 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p } cliprdr->log = WLog_Get("com.freerdp.channels.cliprdr.client"); - cliprdr->useLongFormatNames = TRUE; - cliprdr->streamFileClipEnabled = FALSE; - cliprdr->fileClipNoFilePaths = TRUE; - cliprdr->canLockClipData = FALSE; WLog_Print(cliprdr->log, WLOG_DEBUG, "VirtualChannelEntryEx"); CopyMemory(&(cliprdr->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)); cliprdr->InitHandle = pInitHandle; - rc = cliprdr->channelEntryPoints.pVirtualChannelInitEx(cliprdr, context, pInitHandle, - &cliprdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, - cliprdr_virtual_channel_init_event_ex); + rc = cliprdr->channelEntryPoints.pVirtualChannelInitEx( + cliprdr, context, pInitHandle, &cliprdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, + cliprdr_virtual_channel_init_event_ex); if (CHANNEL_RC_OK != rc) { - WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08"PRIX32"]", - WTSErrorToString(rc), rc); + WLog_ERR(TAG, "pVirtualChannelInit failed with %s [%08" PRIX32 "]", WTSErrorToString(rc), + rc); free(cliprdr->context); free(cliprdr); return FALSE; diff --git a/channels/cliprdr/client/cliprdr_main.h b/channels/cliprdr/client/cliprdr_main.h index 25bad18..a233407 100644 --- a/channels/cliprdr/client/cliprdr_main.h +++ b/channels/cliprdr/client/cliprdr_main.h @@ -57,7 +57,10 @@ CliprdrClientContext* cliprdr_get_client_interface(cliprdrPlugin* cliprdr); #ifdef WITH_DEBUG_CLIPRDR #define DEBUG_CLIPRDR(...) WLog_DBG(TAG, __VA_ARGS__) #else -#define DEBUG_CLIPRDR(...) do { } while (0) +#define DEBUG_CLIPRDR(...) \ + do \ + { \ + } while (0) #endif #endif /* FREERDP_CHANNEL_CLIPRDR_CLIENT_MAIN_H */ diff --git a/channels/cliprdr/cliprdr_common.c b/channels/cliprdr/cliprdr_common.c new file mode 100644 index 0000000..c0fae6e --- /dev/null +++ b/channels/cliprdr/cliprdr_common.c @@ -0,0 +1,578 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Cliprdr common + * + * Copyright 2013 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2019 Kobi Mizrachi + * + * 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 +#include +#include + +#define TAG CHANNELS_TAG("cliprdr.common") + +#include "cliprdr_common.h" + +static BOOL cliprdr_validate_file_contents_request(const CLIPRDR_FILE_CONTENTS_REQUEST* request) +{ + /* + * [MS-RDPECLIP] 2.2.5.3 File Contents Request PDU (CLIPRDR_FILECONTENTS_REQUEST). + * + * A request for the size of the file identified by the lindex field. The size MUST be + * returned as a 64-bit, unsigned integer. The cbRequested field MUST be set to + * 0x00000008 and both the nPositionLow and nPositionHigh fields MUST be + * set to 0x00000000. + */ + + if (request->dwFlags & FILECONTENTS_SIZE) + { + if (request->cbRequested != sizeof(UINT64)) + { + WLog_ERR(TAG, "[%s]: cbRequested must be %" PRIu32 ", got %" PRIu32 "", __FUNCTION__, + sizeof(UINT64), request->cbRequested); + return FALSE; + } + + if (request->nPositionHigh != 0 || request->nPositionLow != 0) + { + WLog_ERR(TAG, "[%s]: nPositionHigh and nPositionLow must be set to 0", __FUNCTION__); + return FALSE; + } + } + + return TRUE; +} + +wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, UINT32 dataLen) +{ + wStream* s; + s = Stream_New(NULL, dataLen + 8); + + if (!s) + { + WLog_ERR(TAG, "Stream_New failed!"); + return NULL; + } + + Stream_Write_UINT16(s, msgType); + Stream_Write_UINT16(s, msgFlags); + /* Write actual length after the entire packet has been constructed. */ + Stream_Seek(s, 4); + return s; +} + +static void cliprdr_write_file_contents_request(wStream* s, + const CLIPRDR_FILE_CONTENTS_REQUEST* request) +{ + Stream_Write_UINT32(s, request->streamId); /* streamId (4 bytes) */ + Stream_Write_UINT32(s, request->listIndex); /* listIndex (4 bytes) */ + Stream_Write_UINT32(s, request->dwFlags); /* dwFlags (4 bytes) */ + Stream_Write_UINT32(s, request->nPositionLow); /* nPositionLow (4 bytes) */ + Stream_Write_UINT32(s, request->nPositionHigh); /* nPositionHigh (4 bytes) */ + Stream_Write_UINT32(s, request->cbRequested); /* cbRequested (4 bytes) */ + + if (request->haveClipDataId) + Stream_Write_UINT32(s, request->clipDataId); /* clipDataId (4 bytes) */ +} + +static INLINE void cliprdr_write_lock_unlock_clipdata(wStream* s, UINT32 clipDataId) +{ + Stream_Write_UINT32(s, clipDataId); +} + +static void cliprdr_write_lock_clipdata(wStream* s, + const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData) +{ + cliprdr_write_lock_unlock_clipdata(s, lockClipboardData->clipDataId); +} + +static void cliprdr_write_unlock_clipdata(wStream* s, + const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData) +{ + cliprdr_write_lock_unlock_clipdata(s, unlockClipboardData->clipDataId); +} + +static void cliprdr_write_file_contents_response(wStream* s, + const CLIPRDR_FILE_CONTENTS_RESPONSE* response) +{ + Stream_Write_UINT32(s, response->streamId); /* streamId (4 bytes) */ + Stream_Write(s, response->requestedData, response->cbRequested); +} + +wStream* cliprdr_packet_lock_clipdata_new(const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData) +{ + wStream* s; + + if (!lockClipboardData) + return NULL; + + s = cliprdr_packet_new(CB_LOCK_CLIPDATA, 0, 4); + + if (!s) + return NULL; + + cliprdr_write_lock_clipdata(s, lockClipboardData); + return s; +} + +wStream* +cliprdr_packet_unlock_clipdata_new(const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData) +{ + wStream* s; + + if (!unlockClipboardData) + return NULL; + + s = cliprdr_packet_new(CB_LOCK_CLIPDATA, 0, 4); + + if (!s) + return NULL; + + cliprdr_write_unlock_clipdata(s, unlockClipboardData); + return s; +} + +wStream* cliprdr_packet_file_contents_request_new(const CLIPRDR_FILE_CONTENTS_REQUEST* request) +{ + wStream* s; + + if (!request) + return NULL; + + s = cliprdr_packet_new(CB_FILECONTENTS_REQUEST, 0, 28); + + if (!s) + return NULL; + + cliprdr_write_file_contents_request(s, request); + return s; +} + +wStream* cliprdr_packet_file_contents_response_new(const CLIPRDR_FILE_CONTENTS_RESPONSE* response) +{ + wStream* s; + + if (!response) + return NULL; + + s = cliprdr_packet_new(CB_FILECONTENTS_RESPONSE, response->msgFlags, 4 + response->cbRequested); + + if (!s) + return NULL; + + cliprdr_write_file_contents_response(s, response); + return s; +} + +wStream* cliprdr_packet_format_list_new(const CLIPRDR_FORMAT_LIST* formatList, + BOOL useLongFormatNames) +{ + wStream* s; + UINT32 index; + int cchWideChar; + LPWSTR lpWideCharStr; + int formatNameSize; + char* szFormatName; + WCHAR* wszFormatName; + BOOL asciiNames = FALSE; + CLIPRDR_FORMAT* format; + + if (formatList->msgType != CB_FORMAT_LIST) + WLog_WARN(TAG, "[%s] called with invalid type %08" PRIx32, __FUNCTION__, + formatList->msgType); + + if (!useLongFormatNames) + { + UINT32 length = formatList->numFormats * 36; + s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length); + + if (!s) + { + WLog_ERR(TAG, "cliprdr_packet_new failed!"); + return NULL; + } + + for (index = 0; index < formatList->numFormats; index++) + { + size_t formatNameLength = 0; + format = (CLIPRDR_FORMAT*)&(formatList->formats[index]); + Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */ + formatNameSize = 0; + + szFormatName = format->formatName; + + if (asciiNames) + { + if (szFormatName) + formatNameLength = strnlen(szFormatName, 32); + + if (formatNameLength > 31) + formatNameLength = 31; + + Stream_Write(s, szFormatName, formatNameLength); + Stream_Zero(s, 32 - formatNameLength); + } + else + { + wszFormatName = NULL; + + if (szFormatName) + formatNameSize = + ConvertToUnicode(CP_UTF8, 0, szFormatName, -1, &wszFormatName, 0); + + if (formatNameSize < 0) + return NULL; + + if (formatNameSize > 15) + formatNameSize = 15; + + /* size in bytes instead of wchar */ + formatNameSize *= 2; + + if (wszFormatName) + Stream_Write(s, wszFormatName, (size_t)formatNameSize); + + Stream_Zero(s, (size_t)(32 - formatNameSize)); + free(wszFormatName); + } + } + } + else + { + UINT32 length = 0; + for (index = 0; index < formatList->numFormats; index++) + { + format = (CLIPRDR_FORMAT*)&(formatList->formats[index]); + length += 4; + formatNameSize = 2; + + if (format->formatName) + formatNameSize = + MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, NULL, 0) * 2; + + if (formatNameSize < 0) + return NULL; + + length += (UINT32)formatNameSize; + } + + s = cliprdr_packet_new(CB_FORMAT_LIST, 0, length); + + if (!s) + { + WLog_ERR(TAG, "cliprdr_packet_new failed!"); + return NULL; + } + + for (index = 0; index < formatList->numFormats; index++) + { + format = (CLIPRDR_FORMAT*)&(formatList->formats[index]); + Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */ + + if (format->formatName) + { + const size_t cap = Stream_Capacity(s); + const size_t pos = Stream_GetPosition(s); + const size_t rem = cap - pos; + if ((cap < pos) || ((rem / 2) > INT_MAX)) + return NULL; + + lpWideCharStr = (LPWSTR)Stream_Pointer(s); + cchWideChar = (int)(rem / 2); + formatNameSize = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, + lpWideCharStr, cchWideChar) * + 2; + if (formatNameSize < 0) + return NULL; + Stream_Seek(s, (size_t)formatNameSize); + } + else + { + Stream_Write_UINT16(s, 0); + } + } + } + + return s; +} +UINT cliprdr_read_unlock_clipdata(wStream* s, CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData) +{ + if (Stream_GetRemainingLength(s) < 4) + { + WLog_ERR(TAG, "not enough remaining data"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, unlockClipboardData->clipDataId); /* clipDataId (4 bytes) */ + return CHANNEL_RC_OK; +} + +UINT cliprdr_read_format_data_request(wStream* s, CLIPRDR_FORMAT_DATA_REQUEST* request) +{ + if (Stream_GetRemainingLength(s) < 4) + { + WLog_ERR(TAG, "not enough data in stream!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, request->requestedFormatId); /* requestedFormatId (4 bytes) */ + return CHANNEL_RC_OK; +} + +UINT cliprdr_read_format_data_response(wStream* s, CLIPRDR_FORMAT_DATA_RESPONSE* response) +{ + response->requestedFormatData = NULL; + + if (Stream_GetRemainingLength(s) < response->dataLen) + { + WLog_ERR(TAG, "not enough data in stream!"); + return ERROR_INVALID_DATA; + } + + if (response->dataLen) + response->requestedFormatData = Stream_Pointer(s); + + return CHANNEL_RC_OK; +} + +UINT cliprdr_read_file_contents_request(wStream* s, CLIPRDR_FILE_CONTENTS_REQUEST* request) +{ + if (Stream_GetRemainingLength(s) < 24) + { + WLog_ERR(TAG, "not enough remaining data"); + return ERROR_INVALID_DATA; + } + + request->haveClipDataId = FALSE; + Stream_Read_UINT32(s, request->streamId); /* streamId (4 bytes) */ + Stream_Read_UINT32(s, request->listIndex); /* listIndex (4 bytes) */ + Stream_Read_UINT32(s, request->dwFlags); /* dwFlags (4 bytes) */ + Stream_Read_UINT32(s, request->nPositionLow); /* nPositionLow (4 bytes) */ + Stream_Read_UINT32(s, request->nPositionHigh); /* nPositionHigh (4 bytes) */ + Stream_Read_UINT32(s, request->cbRequested); /* cbRequested (4 bytes) */ + + if (Stream_GetRemainingLength(s) >= 4) + { + Stream_Read_UINT32(s, request->clipDataId); /* clipDataId (4 bytes) */ + request->haveClipDataId = TRUE; + } + + if (!cliprdr_validate_file_contents_request(request)) + return ERROR_BAD_ARGUMENTS; + + return CHANNEL_RC_OK; +} + +UINT cliprdr_read_file_contents_response(wStream* s, CLIPRDR_FILE_CONTENTS_RESPONSE* response) +{ + if (Stream_GetRemainingLength(s) < 4) + { + WLog_ERR(TAG, "not enough remaining data"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, response->streamId); /* streamId (4 bytes) */ + response->requestedData = Stream_Pointer(s); /* requestedFileContentsData */ + response->cbRequested = response->dataLen - 4; + return CHANNEL_RC_OK; +} + +UINT cliprdr_read_format_list(wStream* s, CLIPRDR_FORMAT_LIST* formatList, BOOL useLongFormatNames) +{ + UINT32 index; + BOOL asciiNames; + int formatNameLength; + char* szFormatName; + WCHAR* wszFormatName; + wStream sub1, sub2; + CLIPRDR_FORMAT* formats = NULL; + UINT error = ERROR_INTERNAL_ERROR; + + asciiNames = (formatList->msgFlags & CB_ASCII_NAMES) ? TRUE : FALSE; + + index = 0; + /* empty format list */ + formatList->formats = NULL; + formatList->numFormats = 0; + + Stream_StaticInit(&sub1, Stream_Pointer(s), formatList->dataLen); + if (!Stream_SafeSeek(s, formatList->dataLen)) + return ERROR_INVALID_DATA; + + if (!formatList->dataLen) + { + } + else if (!useLongFormatNames) + { + const size_t cap = Stream_Capacity(&sub1); + formatList->numFormats = (cap / 36); + + if ((formatList->numFormats * 36) != cap) + { + WLog_ERR(TAG, "Invalid short format list length: %" PRIuz "", cap); + return ERROR_INTERNAL_ERROR; + } + + if (formatList->numFormats) + formats = (CLIPRDR_FORMAT*)calloc(formatList->numFormats, sizeof(CLIPRDR_FORMAT)); + + if (!formats) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + formatList->formats = formats; + + while (Stream_GetRemainingLength(&sub1) >= 4) + { + Stream_Read_UINT32(&sub1, formats[index].formatId); /* formatId (4 bytes) */ + + formats[index].formatName = NULL; + + /* According to MS-RDPECLIP 2.2.3.1.1.1 formatName is "a 32-byte block containing + * the *null-terminated* name assigned to the Clipboard Format: (32 ASCII 8 characters + * or 16 Unicode characters)" + * However, both Windows RDSH and mstsc violate this specs as seen in the following + * example of a transferred short format name string: [R.i.c.h. .T.e.x.t. .F.o.r.m.a.t.] + * These are 16 unicode charaters - *without* terminating null ! + */ + + szFormatName = (char*)Stream_Pointer(&sub1); + wszFormatName = (WCHAR*)Stream_Pointer(&sub1); + if (!Stream_SafeSeek(&sub1, 32)) + goto error_out; + if (asciiNames) + { + if (szFormatName[0]) + { + /* ensure null termination */ + formats[index].formatName = (char*)malloc(32 + 1); + if (!formats[index].formatName) + { + WLog_ERR(TAG, "malloc failed!"); + error = CHANNEL_RC_NO_MEMORY; + goto error_out; + } + CopyMemory(formats[index].formatName, szFormatName, 32); + formats[index].formatName[32] = '\0'; + } + } + else + { + if (wszFormatName[0]) + { + /* ConvertFromUnicode always returns a null-terminated + * string on success, even if the source string isn't. + */ + if (ConvertFromUnicode(CP_UTF8, 0, wszFormatName, 16, + &(formats[index].formatName), 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert short clipboard format name"); + error = ERROR_INTERNAL_ERROR; + goto error_out; + } + } + } + + index++; + } + } + else + { + sub2 = sub1; + while (Stream_GetRemainingLength(&sub1) > 0) + { + size_t rest; + if (!Stream_SafeSeek(&sub1, 4)) /* formatId (4 bytes) */ + goto error_out; + + wszFormatName = (WCHAR*)Stream_Pointer(&sub1); + rest = Stream_GetRemainingLength(&sub1); + formatNameLength = _wcsnlen(wszFormatName, rest / sizeof(WCHAR)); + + if (!Stream_SafeSeek(&sub1, (formatNameLength + 1) * sizeof(WCHAR))) + goto error_out; + formatList->numFormats++; + } + + if (formatList->numFormats) + formats = (CLIPRDR_FORMAT*)calloc(formatList->numFormats, sizeof(CLIPRDR_FORMAT)); + + if (!formats) + { + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + formatList->formats = formats; + + while (Stream_GetRemainingLength(&sub2) >= 4) + { + size_t rest; + Stream_Read_UINT32(&sub2, formats[index].formatId); /* formatId (4 bytes) */ + + formats[index].formatName = NULL; + + wszFormatName = (WCHAR*)Stream_Pointer(&sub2); + rest = Stream_GetRemainingLength(&sub2); + formatNameLength = _wcsnlen(wszFormatName, rest / sizeof(WCHAR)); + if (!Stream_SafeSeek(&sub2, (formatNameLength + 1) * sizeof(WCHAR))) + goto error_out; + + if (formatNameLength) + { + if (ConvertFromUnicode(CP_UTF8, 0, wszFormatName, formatNameLength, + &(formats[index].formatName), 0, NULL, NULL) < 1) + { + WLog_ERR(TAG, "failed to convert long clipboard format name"); + error = ERROR_INTERNAL_ERROR; + goto error_out; + } + } + + index++; + } + } + + return CHANNEL_RC_OK; + +error_out: + cliprdr_free_format_list(formatList); + return error; +} + +void cliprdr_free_format_list(CLIPRDR_FORMAT_LIST* formatList) +{ + UINT index = 0; + + if (formatList == NULL) + return; + + if (formatList->formats) + { + for (index = 0; index < formatList->numFormats; index++) + { + free(formatList->formats[index].formatName); + } + + free(formatList->formats); + formatList->formats = NULL; + formatList->numFormats = 0; + } +} diff --git a/channels/cliprdr/cliprdr_common.h b/channels/cliprdr/cliprdr_common.h new file mode 100644 index 0000000..b5d36b9 --- /dev/null +++ b/channels/cliprdr/cliprdr_common.h @@ -0,0 +1,61 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Cliprdr common + * + * Copyright 2013 Marc-Andre Moreau + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2019 Kobi Mizrachi + * + * 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_RDPECLIP_COMMON_H +#define FREERDP_CHANNEL_RDPECLIP_COMMON_H + +#include +#include + +#include +#include + +FREERDP_LOCAL wStream* cliprdr_packet_new(UINT16 msgType, UINT16 msgFlags, UINT32 dataLen); +FREERDP_LOCAL wStream* +cliprdr_packet_lock_clipdata_new(const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData); +FREERDP_LOCAL wStream* +cliprdr_packet_unlock_clipdata_new(const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData); +FREERDP_LOCAL wStream* +cliprdr_packet_file_contents_request_new(const CLIPRDR_FILE_CONTENTS_REQUEST* request); +FREERDP_LOCAL wStream* +cliprdr_packet_file_contents_response_new(const CLIPRDR_FILE_CONTENTS_RESPONSE* response); +FREERDP_LOCAL wStream* cliprdr_packet_format_list_new(const CLIPRDR_FORMAT_LIST* formatList, + BOOL useLongFormatNames); + +FREERDP_LOCAL UINT cliprdr_read_lock_clipdata(wStream* s, + CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData); +FREERDP_LOCAL UINT cliprdr_read_unlock_clipdata(wStream* s, + CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData); +FREERDP_LOCAL UINT cliprdr_read_format_data_request(wStream* s, + CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest); +FREERDP_LOCAL UINT cliprdr_read_format_data_response(wStream* s, + CLIPRDR_FORMAT_DATA_RESPONSE* response); +FREERDP_LOCAL UINT +cliprdr_read_file_contents_request(wStream* s, CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest); +FREERDP_LOCAL UINT cliprdr_read_file_contents_response(wStream* s, + CLIPRDR_FILE_CONTENTS_RESPONSE* response); +FREERDP_LOCAL UINT cliprdr_read_format_list(wStream* s, CLIPRDR_FORMAT_LIST* formatList, + BOOL useLongFormatNames); + +FREERDP_LOCAL void cliprdr_free_format_list(CLIPRDR_FORMAT_LIST* formatList); + +#endif /* FREERDP_CHANNEL_RDPECLIP_COMMON_H */ diff --git a/channels/cliprdr/server/CMakeLists.txt b/channels/cliprdr/server/CMakeLists.txt index 911c7a4..32ffbaa 100644 --- a/channels/cliprdr/server/CMakeLists.txt +++ b/channels/cliprdr/server/CMakeLists.txt @@ -19,7 +19,10 @@ define_channel_server("cliprdr") set(${MODULE_PREFIX}_SRCS cliprdr_main.c - cliprdr_main.h) + cliprdr_main.h + ../cliprdr_common.h + ../cliprdr_common.c + ) add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntry") diff --git a/channels/cliprdr/server/cliprdr_main.c b/channels/cliprdr/server/cliprdr_main.c index 118c2b0..da4ab0b 100644 --- a/channels/cliprdr/server/cliprdr_main.c +++ b/channels/cliprdr/server/cliprdr_main.c @@ -29,6 +29,7 @@ #include #include "cliprdr_main.h" +#include "../cliprdr_common.h" /** * Initialization Sequence\n @@ -50,60 +51,62 @@ * | |\n * |-------------------------------------------------------------------------|\n _ * |-------------------------------Format List PDU-------------------------->|\n | - * |<--------------------------Format List Response PDU----------------------|\n _| Copy Sequence + * |<--------------------------Format List Response PDU----------------------|\n _| Copy + * Sequence * |<---------------------Lock Clipboard Data PDU (Optional)-----------------|\n * |-------------------------------------------------------------------------|\n * |-------------------------------------------------------------------------|\n _ - * |<--------------------------Format Data Request PDU-----------------------|\n | Paste Sequence Palette, - * |---------------------------Format Data Response PDU--------------------->|\n _| Metafile, File List Data + * |<--------------------------Format Data Request PDU-----------------------|\n | Paste + * Sequence Palette, + * |---------------------------Format Data Response PDU--------------------->|\n _| Metafile, + * File List Data * |-------------------------------------------------------------------------|\n * |-------------------------------------------------------------------------|\n _ - * |<------------------------Format Contents Request PDU---------------------|\n | Paste Sequence - * |-------------------------Format Contents Response PDU------------------->|\n _| File Stream Data + * |<------------------------Format Contents Request PDU---------------------|\n | Paste + * Sequence + * |-------------------------Format Contents Response PDU------------------->|\n _| File + * Stream Data * |<---------------------Lock Clipboard Data PDU (Optional)-----------------|\n * |-------------------------------------------------------------------------|\n * */ -wStream* cliprdr_server_packet_new(UINT16 msgType, UINT16 msgFlags, - UINT32 dataLen) -{ - wStream* s; - s = Stream_New(NULL, dataLen + 8); - - if (!s) - { - WLog_ERR(TAG, "Stream_New failed!"); - return NULL; - } - - Stream_Write_UINT16(s, msgType); - Stream_Write_UINT16(s, msgFlags); - /* Write actual length after the entire packet has been constructed. */ - Stream_Seek(s, 4); - return s; -} - /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -UINT cliprdr_server_packet_send(CliprdrServerPrivate* cliprdr, wStream* s) +static UINT cliprdr_server_packet_send(CliprdrServerPrivate* cliprdr, wStream* s) { - size_t pos; + UINT rc; + size_t pos, size; BOOL status; UINT32 dataLen; UINT32 written; pos = Stream_GetPosition(s); - dataLen = pos - 8; + if ((pos < 8) || (pos > UINT32_MAX)) + { + rc = ERROR_NO_DATA; + goto fail; + } + + dataLen = (UINT32)(pos - 8); Stream_SetPosition(s, 4); Stream_Write_UINT32(s, dataLen); Stream_SetPosition(s, pos); - status = WTSVirtualChannelWrite(cliprdr->ChannelHandle, - (PCHAR) Stream_Buffer(s), Stream_Length(s), &written); + size = Stream_Length(s); + if (size > UINT32_MAX) + { + rc = ERROR_INVALID_DATA; + goto fail; + } + + status = WTSVirtualChannelWrite(cliprdr->ChannelHandle, (PCHAR)Stream_Buffer(s), (UINT32)size, + &written); + rc = status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; +fail: Stream_Free(s, TRUE); - return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; + return rc; } /** @@ -112,32 +115,66 @@ UINT cliprdr_server_packet_send(CliprdrServerPrivate* cliprdr, wStream* s) * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_server_capabilities(CliprdrServerContext* context, - CLIPRDR_CAPABILITIES* capabilities) + const CLIPRDR_CAPABILITIES* capabilities) { + size_t offset = 0; + UINT32 x; wStream* s; - CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet; - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; - capabilities->msgType = CB_CLIP_CAPS; - capabilities->msgFlags = 0; - s = cliprdr_server_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN); + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; + + if (capabilities->msgType != CB_CLIP_CAPS) + WLog_WARN(TAG, "[%s] called with invalid type %08" PRIx32, __FUNCTION__, + capabilities->msgType); + + if (capabilities->cCapabilitiesSets > UINT16_MAX) + { + WLog_ERR(TAG, "Invalid number of capability sets in clipboard caps"); + return ERROR_INVALID_PARAMETER; + } + + s = cliprdr_packet_new(CB_CLIP_CAPS, 0, 4 + CB_CAPSTYPE_GENERAL_LEN); if (!s) { - WLog_ERR(TAG, "cliprdr_server_packet_new failed!"); + WLog_ERR(TAG, "cliprdr_packet_new failed!"); return ERROR_INTERNAL_ERROR; } - Stream_Write_UINT16(s, 1); /* cCapabilitiesSets (2 bytes) */ - Stream_Write_UINT16(s, 0); /* pad1 (2 bytes) */ - generalCapabilitySet = (CLIPRDR_GENERAL_CAPABILITY_SET*) - capabilities->capabilitySets; - Stream_Write_UINT16(s, - generalCapabilitySet->capabilitySetType); /* capabilitySetType (2 bytes) */ Stream_Write_UINT16(s, - generalCapabilitySet->capabilitySetLength); /* lengthCapability (2 bytes) */ - Stream_Write_UINT32(s, generalCapabilitySet->version); /* version (4 bytes) */ - Stream_Write_UINT32(s, - generalCapabilitySet->generalFlags); /* generalFlags (4 bytes) */ + (UINT16)capabilities->cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */ + Stream_Write_UINT16(s, 0); /* pad1 (2 bytes) */ + for (x = 0; x < capabilities->cCapabilitiesSets; x++) + { + const CLIPRDR_CAPABILITY_SET* cap = + (const CLIPRDR_CAPABILITY_SET*)(((const BYTE*)capabilities->capabilitySets) + offset); + offset += cap->capabilitySetLength; + + switch (cap->capabilitySetType) + { + case CB_CAPSTYPE_GENERAL: + { + const CLIPRDR_GENERAL_CAPABILITY_SET* generalCapabilitySet = + (const CLIPRDR_GENERAL_CAPABILITY_SET*)cap; + Stream_Write_UINT16( + s, generalCapabilitySet->capabilitySetType); /* capabilitySetType (2 bytes) */ + Stream_Write_UINT16( + s, generalCapabilitySet->capabilitySetLength); /* lengthCapability (2 bytes) */ + Stream_Write_UINT32(s, generalCapabilitySet->version); /* version (4 bytes) */ + Stream_Write_UINT32( + s, generalCapabilitySet->generalFlags); /* generalFlags (4 bytes) */ + } + break; + + default: + WLog_WARN(TAG, "Unknown capability set type %08" PRIx16, cap->capabilitySetType); + if (!Stream_SafeSeek(s, cap->capabilitySetLength)) + { + WLog_ERR(TAG, "%s: short stream", __FUNCTION__); + return ERROR_NO_DATA; + } + break; + } + } WLog_DBG(TAG, "ServerCapabilities"); return cliprdr_server_packet_send(cliprdr, s); } @@ -148,19 +185,20 @@ static UINT cliprdr_server_capabilities(CliprdrServerContext* context, * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_server_monitor_ready(CliprdrServerContext* context, - CLIPRDR_MONITOR_READY* monitorReady) + const CLIPRDR_MONITOR_READY* monitorReady) { wStream* s; - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; - monitorReady->msgType = CB_MONITOR_READY; - monitorReady->msgFlags = 0; - monitorReady->dataLen = 0; - s = cliprdr_server_packet_new(monitorReady->msgType, - monitorReady->msgFlags, monitorReady->dataLen); + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; + + if (monitorReady->msgType != CB_MONITOR_READY) + WLog_WARN(TAG, "[%s] called with invalid type %08" PRIx32, __FUNCTION__, + monitorReady->msgType); + + s = cliprdr_packet_new(CB_MONITOR_READY, monitorReady->msgFlags, monitorReady->dataLen); if (!s) { - WLog_ERR(TAG, "cliprdr_server_packet_new failed!"); + WLog_ERR(TAG, "cliprdr_packet_new failed!"); return ERROR_INTERNAL_ERROR; } @@ -174,115 +212,19 @@ static UINT cliprdr_server_monitor_ready(CliprdrServerContext* context, * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_server_format_list(CliprdrServerContext* context, - CLIPRDR_FORMAT_LIST* formatList) + const CLIPRDR_FORMAT_LIST* formatList) { wStream* s; - UINT32 index; - int length = 0; - int cchWideChar; - LPWSTR lpWideCharStr; - int formatNameSize; - int formatNameLength; - char* szFormatName; - WCHAR* wszFormatName; - BOOL asciiNames = FALSE; - CLIPRDR_FORMAT* format; - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; - - if (!context->useLongFormatNames) - { - length = formatList->numFormats * 36; - s = cliprdr_server_packet_new(CB_FORMAT_LIST, 0, length); - - if (!s) - { - WLog_ERR(TAG, "cliprdr_server_packet_new failed!"); - return ERROR_INTERNAL_ERROR; - } - - for (index = 0; index < formatList->numFormats; index++) - { - format = (CLIPRDR_FORMAT*) & (formatList->formats[index]); - Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */ - formatNameSize = 0; - formatNameLength = 0; - szFormatName = format->formatName; - - if (asciiNames) - { - if (szFormatName) - formatNameLength = strlen(szFormatName); - - if (formatNameLength > 31) - formatNameLength = 31; - - Stream_Write(s, szFormatName, formatNameLength); - Stream_Zero(s, 32 - formatNameLength); - } - else - { - wszFormatName = NULL; - - if (szFormatName) - formatNameSize = ConvertToUnicode(CP_UTF8, 0, szFormatName, -1, &wszFormatName, - 0); - - if (formatNameSize > 15) - formatNameSize = 15; - - if (wszFormatName) - Stream_Write(s, wszFormatName, formatNameSize * 2); + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; - Stream_Zero(s, 32 - (formatNameSize * 2)); - free(wszFormatName); - } - } - } - else + s = cliprdr_packet_format_list_new(formatList, context->useLongFormatNames); + if (!s) { - for (index = 0; index < formatList->numFormats; index++) - { - format = (CLIPRDR_FORMAT*) & (formatList->formats[index]); - length += 4; - formatNameSize = 2; - - if (format->formatName) - formatNameSize = MultiByteToWideChar(CP_UTF8, 0, format->formatName, -1, NULL, - 0) * 2; - - length += formatNameSize; - } - - s = cliprdr_server_packet_new(CB_FORMAT_LIST, 0, length); - - if (!s) - { - WLog_ERR(TAG, "cliprdr_server_packet_new failed!"); - return ERROR_INTERNAL_ERROR; - } - - for (index = 0; index < formatList->numFormats; index++) - { - format = (CLIPRDR_FORMAT*) & (formatList->formats[index]); - Stream_Write_UINT32(s, format->formatId); /* formatId (4 bytes) */ - - if (format->formatName) - { - lpWideCharStr = (LPWSTR) Stream_Pointer(s); - cchWideChar = (Stream_Capacity(s) - Stream_GetPosition(s)) / 2; - formatNameSize = MultiByteToWideChar(CP_UTF8, 0, - format->formatName, -1, lpWideCharStr, cchWideChar) * 2; - Stream_Seek(s, formatNameSize); - } - else - { - Stream_Write_UINT16(s, 0); - } - } + WLog_ERR(TAG, "cliprdr_packet_format_list_new failed!"); + return ERROR_INTERNAL_ERROR; } - WLog_DBG(TAG, "ServerFormatList: numFormats: %"PRIu32"", - formatList->numFormats); + WLog_DBG(TAG, "ServerFormatList: numFormats: %" PRIu32 "", formatList->numFormats); return cliprdr_server_packet_send(cliprdr, s); } @@ -291,19 +233,22 @@ static UINT cliprdr_server_format_list(CliprdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_format_list_response(CliprdrServerContext* context, - CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse) +static UINT +cliprdr_server_format_list_response(CliprdrServerContext* context, + const CLIPRDR_FORMAT_LIST_RESPONSE* formatListResponse) { wStream* s; - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; - formatListResponse->msgType = CB_FORMAT_LIST_RESPONSE; - formatListResponse->dataLen = 0; - s = cliprdr_server_packet_new(formatListResponse->msgType, - formatListResponse->msgFlags, formatListResponse->dataLen); + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; + if (formatListResponse->msgType != CB_FORMAT_LIST_RESPONSE) + WLog_WARN(TAG, "[%s] called with invalid type %08" PRIx32, __FUNCTION__, + formatListResponse->msgType); + + s = cliprdr_packet_new(CB_FORMAT_LIST_RESPONSE, formatListResponse->msgFlags, + formatListResponse->dataLen); if (!s) { - WLog_ERR(TAG, "cliprdr_server_packet_new failed!"); + WLog_ERR(TAG, "cliprdr_packet_new failed!"); return ERROR_INTERNAL_ERROR; } @@ -317,21 +262,22 @@ static UINT cliprdr_server_format_list_response(CliprdrServerContext* context, * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_server_lock_clipboard_data(CliprdrServerContext* context, - CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData) + const CLIPRDR_LOCK_CLIPBOARD_DATA* lockClipboardData) { wStream* s; - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; - s = cliprdr_server_packet_new(CB_LOCK_CLIPDATA, 0, 4); + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; + if (lockClipboardData->msgType != CB_LOCK_CLIPDATA) + WLog_WARN(TAG, "[%s] called with invalid type %08" PRIx32, __FUNCTION__, + lockClipboardData->msgType); + s = cliprdr_packet_lock_clipdata_new(lockClipboardData); if (!s) { - WLog_ERR(TAG, "cliprdr_server_packet_new failed!"); + WLog_ERR(TAG, "cliprdr_packet_lock_clipdata_new failed!"); return ERROR_INTERNAL_ERROR; } - Stream_Write_UINT32(s, - lockClipboardData->clipDataId); /* clipDataId (4 bytes) */ - WLog_DBG(TAG, "ServerLockClipboardData: clipDataId: 0x%08"PRIX32"", + WLog_DBG(TAG, "ServerLockClipboardData: clipDataId: 0x%08" PRIX32 "", lockClipboardData->clipDataId); return cliprdr_server_packet_send(cliprdr, s); } @@ -341,22 +287,25 @@ static UINT cliprdr_server_lock_clipboard_data(CliprdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_unlock_clipboard_data(CliprdrServerContext* context, - CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData) +static UINT +cliprdr_server_unlock_clipboard_data(CliprdrServerContext* context, + const CLIPRDR_UNLOCK_CLIPBOARD_DATA* unlockClipboardData) { wStream* s; - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; - s = cliprdr_server_packet_new(CB_UNLOCK_CLIPDATA, 0, 4); + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; + if (unlockClipboardData->msgType != CB_UNLOCK_CLIPDATA) + WLog_WARN(TAG, "[%s] called with invalid type %08" PRIx32, __FUNCTION__, + unlockClipboardData->msgType); + + s = cliprdr_packet_unlock_clipdata_new(unlockClipboardData); if (!s) { - WLog_ERR(TAG, "cliprdr_server_packet_new failed!"); + WLog_ERR(TAG, "cliprdr_packet_unlock_clipdata_new failed!"); return ERROR_INTERNAL_ERROR; } - Stream_Write_UINT32(s, - unlockClipboardData->clipDataId); /* clipDataId (4 bytes) */ - WLog_DBG(TAG, "ServerUnlockClipboardData: clipDataId: 0x%08"PRIX32"", + WLog_DBG(TAG, "ServerUnlockClipboardData: clipDataId: 0x%08" PRIX32 "", unlockClipboardData->clipDataId); return cliprdr_server_packet_send(cliprdr, s); } @@ -367,24 +316,24 @@ static UINT cliprdr_server_unlock_clipboard_data(CliprdrServerContext* context, * @return 0 on success, otherwise a Win32 error code */ static UINT cliprdr_server_format_data_request(CliprdrServerContext* context, - CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) + const CLIPRDR_FORMAT_DATA_REQUEST* formatDataRequest) { wStream* s; - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; - formatDataRequest->msgType = CB_FORMAT_DATA_REQUEST; - formatDataRequest->msgFlags = 0; - formatDataRequest->dataLen = 4; - s = cliprdr_server_packet_new(formatDataRequest->msgType, - formatDataRequest->msgFlags, formatDataRequest->dataLen); + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; + if (formatDataRequest->msgType != CB_FORMAT_DATA_REQUEST) + WLog_WARN(TAG, "[%s] called with invalid type %08" PRIx32, __FUNCTION__, + formatDataRequest->msgType); + + s = cliprdr_packet_new(CB_FORMAT_DATA_REQUEST, formatDataRequest->msgFlags, + formatDataRequest->dataLen); if (!s) { - WLog_ERR(TAG, "cliprdr_server_packet_new failed!"); + WLog_ERR(TAG, "cliprdr_packet_new failed!"); return ERROR_INTERNAL_ERROR; } - Stream_Write_UINT32(s, - formatDataRequest->requestedFormatId); /* requestedFormatId (4 bytes) */ + Stream_Write_UINT32(s, formatDataRequest->requestedFormatId); /* requestedFormatId (4 bytes) */ WLog_DBG(TAG, "ClientFormatDataRequest"); return cliprdr_server_packet_send(cliprdr, s); } @@ -394,23 +343,27 @@ static UINT cliprdr_server_format_data_request(CliprdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_format_data_response(CliprdrServerContext* context, - CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse) +static UINT +cliprdr_server_format_data_response(CliprdrServerContext* context, + const CLIPRDR_FORMAT_DATA_RESPONSE* formatDataResponse) { wStream* s; - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; - formatDataResponse->msgType = CB_FORMAT_DATA_RESPONSE; - s = cliprdr_server_packet_new(formatDataResponse->msgType, - formatDataResponse->msgFlags, formatDataResponse->dataLen); + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; + + if (formatDataResponse->msgType != CB_FORMAT_DATA_RESPONSE) + WLog_WARN(TAG, "[%s] called with invalid type %08" PRIx32, __FUNCTION__, + formatDataResponse->msgType); + + s = cliprdr_packet_new(CB_FORMAT_DATA_RESPONSE, formatDataResponse->msgFlags, + formatDataResponse->dataLen); if (!s) { - WLog_ERR(TAG, "cliprdr_server_packet_new failed!"); + WLog_ERR(TAG, "cliprdr_packet_new failed!"); return ERROR_INTERNAL_ERROR; } - Stream_Write(s, formatDataResponse->requestedFormatData, - formatDataResponse->dataLen); + Stream_Write(s, formatDataResponse->requestedFormatData, formatDataResponse->dataLen); WLog_DBG(TAG, "ServerFormatDataResponse"); return cliprdr_server_packet_send(cliprdr, s); } @@ -420,32 +373,25 @@ static UINT cliprdr_server_format_data_response(CliprdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_file_contents_request(CliprdrServerContext* context, - CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest) +static UINT +cliprdr_server_file_contents_request(CliprdrServerContext* context, + const CLIPRDR_FILE_CONTENTS_REQUEST* fileContentsRequest) { wStream* s; - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; - s = cliprdr_server_packet_new(CB_FILECONTENTS_REQUEST, 0, 28); + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; + + if (fileContentsRequest->msgType != CB_FILECONTENTS_REQUEST) + WLog_WARN(TAG, "[%s] called with invalid type %08" PRIx32, __FUNCTION__, + fileContentsRequest->msgType); + s = cliprdr_packet_file_contents_request_new(fileContentsRequest); if (!s) { - WLog_ERR(TAG, "cliprdr_server_packet_new failed!"); + WLog_ERR(TAG, "cliprdr_packet_file_contents_request_new failed!"); return ERROR_INTERNAL_ERROR; } - Stream_Write_UINT32(s, fileContentsRequest->streamId); /* streamId (4 bytes) */ - Stream_Write_UINT32(s, - fileContentsRequest->listIndex); /* listIndex (4 bytes) */ - Stream_Write_UINT32(s, fileContentsRequest->dwFlags); /* dwFlags (4 bytes) */ - Stream_Write_UINT32(s, - fileContentsRequest->nPositionLow); /* nPositionLow (4 bytes) */ - Stream_Write_UINT32(s, - fileContentsRequest->nPositionHigh); /* nPositionHigh (4 bytes) */ - Stream_Write_UINT32(s, - fileContentsRequest->cbRequested); /* cbRequested (4 bytes) */ - Stream_Write_UINT32(s, - fileContentsRequest->clipDataId); /* clipDataId (4 bytes) */ - WLog_DBG(TAG, "ServerFileContentsRequest: streamId: 0x%08"PRIX32"", + WLog_DBG(TAG, "ServerFileContentsRequest: streamId: 0x%08" PRIX32 "", fileContentsRequest->streamId); return cliprdr_server_packet_send(cliprdr, s); } @@ -455,34 +401,25 @@ static UINT cliprdr_server_file_contents_request(CliprdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_file_contents_response(CliprdrServerContext* context, - CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse) +static UINT +cliprdr_server_file_contents_response(CliprdrServerContext* context, + const CLIPRDR_FILE_CONTENTS_RESPONSE* fileContentsResponse) { wStream* s; - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; - if (fileContentsResponse->dwFlags & FILECONTENTS_SIZE) - fileContentsResponse->cbRequested = sizeof(UINT64); - - s = cliprdr_server_packet_new(CB_FILECONTENTS_RESPONSE, - fileContentsResponse->msgFlags, - 4 + fileContentsResponse->cbRequested); + if (fileContentsResponse->msgType != CB_FILECONTENTS_RESPONSE) + WLog_WARN(TAG, "[%s] called with invalid type %08" PRIx32, __FUNCTION__, + fileContentsResponse->msgType); + s = cliprdr_packet_file_contents_response_new(fileContentsResponse); if (!s) { - WLog_ERR(TAG, "cliprdr_server_packet_new failed!"); + WLog_ERR(TAG, "cliprdr_packet_file_contents_response_new failed!"); return ERROR_INTERNAL_ERROR; } - Stream_Write_UINT32(s, fileContentsResponse->streamId); /* streamId (4 bytes) */ - /** - * requestedFileContentsData: - * FILECONTENTS_SIZE: file size as UINT64 - * FILECONTENTS_RANGE: file data from requested range - */ - Stream_Write(s, fileContentsResponse->requestedData, - fileContentsResponse->cbRequested); - WLog_DBG(TAG, "ServerFileContentsResponse: streamId: 0x%08"PRIX32"", + WLog_DBG(TAG, "ServerFileContentsResponse: streamId: 0x%08" PRIX32 "", fileContentsResponse->streamId); return cliprdr_server_packet_send(cliprdr, s); } @@ -492,28 +429,29 @@ static UINT cliprdr_server_file_contents_response(CliprdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_receive_general_capability(CliprdrServerContext* - context, wStream* s) +static UINT cliprdr_server_receive_general_capability(CliprdrServerContext* context, wStream* s, + CLIPRDR_GENERAL_CAPABILITY_SET* cap_set) { - UINT32 version; - UINT32 generalFlags; - Stream_Read_UINT32(s, version); /* version (4 bytes) */ - Stream_Read_UINT32(s, generalFlags); /* generalFlags (4 bytes) */ + if (Stream_GetRemainingLength(s) < 8) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, cap_set->version); /* version (4 bytes) */ + Stream_Read_UINT32(s, cap_set->generalFlags); /* generalFlags (4 bytes) */ if (context->useLongFormatNames) - context->useLongFormatNames = (generalFlags & CB_USE_LONG_FORMAT_NAMES) ? TRUE : - FALSE; + context->useLongFormatNames = + (cap_set->generalFlags & CB_USE_LONG_FORMAT_NAMES) ? TRUE : FALSE; if (context->streamFileClipEnabled) - context->streamFileClipEnabled = (generalFlags & CB_STREAM_FILECLIP_ENABLED) ? - TRUE : FALSE; + context->streamFileClipEnabled = + (cap_set->generalFlags & CB_STREAM_FILECLIP_ENABLED) ? TRUE : FALSE; if (context->fileClipNoFilePaths) - context->fileClipNoFilePaths = (generalFlags & CB_FILECLIP_NO_FILE_PATHS) ? - TRUE : FALSE; + context->fileClipNoFilePaths = + (cap_set->generalFlags & CB_FILECLIP_NO_FILE_PATHS) ? TRUE : FALSE; if (context->canLockClipData) - context->canLockClipData = (generalFlags & CB_CAN_LOCK_CLIPDATA) ? TRUE : FALSE; + context->canLockClipData = (cap_set->generalFlags & CB_CAN_LOCK_CLIPDATA) ? TRUE : FALSE; return CHANNEL_RC_OK; } @@ -523,43 +461,80 @@ static UINT cliprdr_server_receive_general_capability(CliprdrServerContext* * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_receive_capabilities(CliprdrServerContext* context, - wStream* s, CLIPRDR_HEADER* header) +static UINT cliprdr_server_receive_capabilities(CliprdrServerContext* context, wStream* s, + const CLIPRDR_HEADER* header) { UINT16 index; - UINT16 cCapabilitiesSets; UINT16 capabilitySetType; - UINT16 lengthCapability; - UINT error; + UINT16 capabilitySetLength; + UINT error = ERROR_INVALID_DATA; + size_t cap_sets_size = 0; + CLIPRDR_CAPABILITIES capabilities = { 0 }; + CLIPRDR_CAPABILITY_SET* capSet; + + WINPR_UNUSED(header); + + WLog_DBG(TAG, "CliprdrClientCapabilities"); - Stream_Read_UINT16(s, cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */ - Stream_Seek_UINT16(s); /* pad1 (2 bytes) */ + if (Stream_GetRemainingLength(s) < 4) + return ERROR_INVALID_DATA; - for (index = 0; index < cCapabilitiesSets; index++) + Stream_Read_UINT16(s, capabilities.cCapabilitiesSets); /* cCapabilitiesSets (2 bytes) */ + Stream_Seek_UINT16(s); /* pad1 (2 bytes) */ + + for (index = 0; index < capabilities.cCapabilitiesSets; index++) { - Stream_Read_UINT16(s, capabilitySetType); /* capabilitySetType (2 bytes) */ - Stream_Read_UINT16(s, lengthCapability); /* lengthCapability (2 bytes) */ + void* tmp = NULL; + if (Stream_GetRemainingLength(s) < 4) + goto out; + Stream_Read_UINT16(s, capabilitySetType); /* capabilitySetType (2 bytes) */ + Stream_Read_UINT16(s, capabilitySetLength); /* capabilitySetLength (2 bytes) */ + + cap_sets_size += capabilitySetLength; + + if (cap_sets_size > 0) + tmp = realloc(capabilities.capabilitySets, cap_sets_size); + if (tmp == NULL) + { + WLog_ERR(TAG, "capabilities.capabilitySets realloc failed!"); + free(capabilities.capabilitySets); + return CHANNEL_RC_NO_MEMORY; + } - switch (capabilitySetType) + capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*)tmp; + + capSet = &(capabilities.capabilitySets[index]); + + capSet->capabilitySetType = capabilitySetType; + capSet->capabilitySetLength = capabilitySetLength; + + switch (capSet->capabilitySetType) { case CB_CAPSTYPE_GENERAL: - if ((error = cliprdr_server_receive_general_capability(context, s))) + error = cliprdr_server_receive_general_capability( + context, s, (CLIPRDR_GENERAL_CAPABILITY_SET*)capSet); + if (error) { - WLog_ERR(TAG, "cliprdr_server_receive_general_capability failed with error %"PRIu32"", + WLog_ERR(TAG, + "cliprdr_server_receive_general_capability failed with error %" PRIu32 + "", error); - return error; + goto out; } - break; default: - WLog_ERR(TAG, "unknown cliprdr capability set: %"PRIu16"", capabilitySetType); - return ERROR_INVALID_DATA; - break; + WLog_ERR(TAG, "unknown cliprdr capability set: %" PRIu16 "", + capSet->capabilitySetType); + goto out; } } - return CHANNEL_RC_OK; + error = CHANNEL_RC_OK; + IFCALLRET(context->ClientCapabilities, error, context, &capabilities); +out: + free(capabilities.capabilitySets); + return error; } /** @@ -567,45 +542,46 @@ static UINT cliprdr_server_receive_capabilities(CliprdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_receive_temporary_directory(CliprdrServerContext* - context, wStream* s, CLIPRDR_HEADER* header) +static UINT cliprdr_server_receive_temporary_directory(CliprdrServerContext* context, wStream* s, + const CLIPRDR_HEADER* header) { - int length; + size_t length; WCHAR* wszTempDir; CLIPRDR_TEMP_DIRECTORY tempDirectory; - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; size_t slength; UINT error = CHANNEL_RC_OK; - if ((slength = Stream_GetRemainingLength(s)) < 520) + WINPR_UNUSED(header); + if ((slength = Stream_GetRemainingLength(s)) < 260 * sizeof(WCHAR)) { - WLog_ERR(TAG, - "Stream_GetRemainingLength returned %"PRIuz" but should at least be 520", slength); + WLog_ERR(TAG, "Stream_GetRemainingLength returned %" PRIuz " but should at least be 520", + slength); return CHANNEL_RC_NO_MEMORY; } - wszTempDir = (WCHAR*) Stream_Pointer(s); + wszTempDir = (WCHAR*)Stream_Pointer(s); - if (wszTempDir[260] != 0) + if (wszTempDir[259] != 0) { - WLog_ERR(TAG, "wszTempDir[260] was not 0"); + WLog_ERR(TAG, "wszTempDir[259] was not 0"); return ERROR_INVALID_DATA; } free(cliprdr->temporaryDirectory); cliprdr->temporaryDirectory = NULL; - if (ConvertFromUnicode(CP_UTF8, 0, wszTempDir, -1, - &(cliprdr->temporaryDirectory), 0, NULL, NULL) < 1) + if (ConvertFromUnicode(CP_UTF8, 0, wszTempDir, -1, &(cliprdr->temporaryDirectory), 0, NULL, + NULL) < 1) { WLog_ERR(TAG, "failed to convert temporary directory name"); return ERROR_INVALID_DATA; } - length = strlen(cliprdr->temporaryDirectory); + length = strnlen(cliprdr->temporaryDirectory, 260); - if (length > 519) - length = 519; + if (length >= 260) + length = 259; CopyMemory(tempDirectory.szTempDir, cliprdr->temporaryDirectory, length); tempDirectory.szTempDir[length] = '\0'; @@ -613,7 +589,7 @@ static UINT cliprdr_server_receive_temporary_directory(CliprdrServerContext* IFCALLRET(context->TempDirectory, error, context, &tempDirectory); if (error) - WLog_ERR(TAG, "TempDirectory failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "TempDirectory failed with error %" PRIu32 "!", error); return error; } @@ -623,183 +599,27 @@ static UINT cliprdr_server_receive_temporary_directory(CliprdrServerContext* * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_receive_format_list(CliprdrServerContext* context, - wStream* s, CLIPRDR_HEADER* header) +static UINT cliprdr_server_receive_format_list(CliprdrServerContext* context, wStream* s, + const CLIPRDR_HEADER* header) { - UINT32 index; - UINT32 dataLen; - size_t position; - BOOL asciiNames; - int formatNameLength; - char* szFormatName; - WCHAR* wszFormatName; - CLIPRDR_FORMAT* formats = NULL; CLIPRDR_FORMAT_LIST formatList; UINT error = CHANNEL_RC_OK; - dataLen = header->dataLen; - asciiNames = (header->msgFlags & CB_ASCII_NAMES) ? TRUE : FALSE; + formatList.msgType = CB_FORMAT_LIST; formatList.msgFlags = header->msgFlags; formatList.dataLen = header->dataLen; - index = 0; - formatList.numFormats = 0; - position = Stream_GetPosition(s); - if (!header->dataLen) - { - /* empty format list */ - formatList.formats = NULL; - formatList.numFormats = 0; - } - else if (!context->useLongFormatNames) - { - formatList.numFormats = (dataLen / 36); - - if ((formatList.numFormats * 36) != dataLen) - { - WLog_ERR(TAG, "Invalid short format list length: %"PRIu32"", dataLen); - return ERROR_INVALID_PARAMETER; - } - - if (formatList.numFormats) - formats = (CLIPRDR_FORMAT*) calloc(formatList.numFormats, - sizeof(CLIPRDR_FORMAT)); - - if (!formats) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - formatList.formats = formats; - - while (dataLen) - { - Stream_Read_UINT32(s, formats[index].formatId); /* formatId (4 bytes) */ - dataLen -= 4; - formats[index].formatName = NULL; - - /* According to MS-RDPECLIP 2.2.3.1.1.1 formatName is "a 32-byte block containing - * the *null-terminated* name assigned to the Clipboard Format: (32 ASCII 8 characters - * or 16 Unicode characters)" - * However, both Windows RDSH and mstsc violate this specs as seen in the following - * example of a transferred short format name string: [R.i.c.h. .T.e.x.t. .F.o.r.m.a.t.] - * These are 16 unicode charaters - *without* terminating null ! - */ - - if (asciiNames) - { - szFormatName = (char*) Stream_Pointer(s); - - if (szFormatName[0]) - { - /* ensure null termination */ - formats[index].formatName = (char*) malloc(32 + 1); - CopyMemory(formats[index].formatName, szFormatName, 32); - formats[index].formatName[32] = '\0'; - } - } - else - { - wszFormatName = (WCHAR*) Stream_Pointer(s); - - if (wszFormatName[0]) - { - /* ConvertFromUnicode always returns a null-terminated - * string on success, even if the source string isn't. - */ - if (ConvertFromUnicode(CP_UTF8, 0, wszFormatName, 16, - &(formats[index].formatName), 0, NULL, NULL) < 1) - { - WLog_ERR(TAG, "failed to convert short clipboard format name"); - error = ERROR_INVALID_DATA; - goto out; - } - } - } - - Stream_Seek(s, 32); - dataLen -= 32; - index++; - } - } - else - { - while (dataLen) - { - Stream_Seek(s, 4); /* formatId (4 bytes) */ - dataLen -= 4; - wszFormatName = (WCHAR*) Stream_Pointer(s); - - if (!wszFormatName[0]) - formatNameLength = 0; - else - formatNameLength = _wcslen(wszFormatName); - - Stream_Seek(s, (formatNameLength + 1) * 2); - dataLen -= ((formatNameLength + 1) * 2); - formatList.numFormats++; - } - - dataLen = formatList.dataLen; - Stream_SetPosition(s, position); - - if (formatList.numFormats) - formats = (CLIPRDR_FORMAT*) calloc(formatList.numFormats, - sizeof(CLIPRDR_FORMAT)); - - if (!formats) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - formatList.formats = formats; - - while (dataLen) - { - Stream_Read_UINT32(s, formats[index].formatId); /* formatId (4 bytes) */ - dataLen -= 4; - formats[index].formatName = NULL; - wszFormatName = (WCHAR*) Stream_Pointer(s); - - if (!wszFormatName[0]) - formatNameLength = 0; - else - formatNameLength = _wcslen(wszFormatName); - - if (formatNameLength) - { - if (ConvertFromUnicode(CP_UTF8, 0, wszFormatName, -1, - &(formats[index].formatName), 0, NULL, NULL) < 1) - { - WLog_ERR(TAG, "failed to convert long clipboard format name"); - error = ERROR_INVALID_DATA; - goto out; - } - } - - Stream_Seek(s, (formatNameLength + 1) * 2); - dataLen -= ((formatNameLength + 1) * 2); - index++; - } - } + if ((error = cliprdr_read_format_list(s, &formatList, context->useLongFormatNames))) + goto out; - WLog_DBG(TAG, "ClientFormatList: numFormats: %"PRIu32"", - formatList.numFormats); + WLog_DBG(TAG, "ClientFormatList: numFormats: %" PRIu32 "", formatList.numFormats); IFCALLRET(context->ClientFormatList, error, context, &formatList); if (error) - WLog_ERR(TAG, "ClientFormatList failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ClientFormatList failed with error %" PRIu32 "!", error); out: - - for (index = 0; index < formatList.numFormats; index++) - { - free(formatList.formats[index].formatName); - } - - free(formatList.formats); + cliprdr_free_format_list(&formatList); return error; } @@ -808,20 +628,21 @@ out: * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_receive_format_list_response( - CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header) +static UINT cliprdr_server_receive_format_list_response(CliprdrServerContext* context, wStream* s, + const CLIPRDR_HEADER* header) { CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse; UINT error = CHANNEL_RC_OK; + + WINPR_UNUSED(s); WLog_DBG(TAG, "CliprdrClientFormatListResponse"); formatListResponse.msgType = CB_FORMAT_LIST_RESPONSE; formatListResponse.msgFlags = header->msgFlags; formatListResponse.dataLen = header->dataLen; - IFCALLRET(context->ClientFormatListResponse, error, context, - &formatListResponse); + IFCALLRET(context->ClientFormatListResponse, error, context, &formatListResponse); if (error) - WLog_ERR(TAG, "ClientFormatListResponse failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ClientFormatListResponse failed with error %" PRIu32 "!", error); return error; } @@ -831,8 +652,8 @@ static UINT cliprdr_server_receive_format_list_response( * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_receive_lock_clipdata(CliprdrServerContext* context, - wStream* s, CLIPRDR_HEADER* header) +static UINT cliprdr_server_receive_lock_clipdata(CliprdrServerContext* context, wStream* s, + const CLIPRDR_HEADER* header) { CLIPRDR_LOCK_CLIPBOARD_DATA lockClipboardData; UINT error = CHANNEL_RC_OK; @@ -851,7 +672,7 @@ static UINT cliprdr_server_receive_lock_clipdata(CliprdrServerContext* context, IFCALLRET(context->ClientLockClipboardData, error, context, &lockClipboardData); if (error) - WLog_ERR(TAG, "ClientLockClipboardData failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ClientLockClipboardData failed with error %" PRIu32 "!", error); return error; } @@ -861,29 +682,24 @@ static UINT cliprdr_server_receive_lock_clipdata(CliprdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_receive_unlock_clipdata(CliprdrServerContext* - context, wStream* s, CLIPRDR_HEADER* header) +static UINT cliprdr_server_receive_unlock_clipdata(CliprdrServerContext* context, wStream* s, + const CLIPRDR_HEADER* header) { CLIPRDR_UNLOCK_CLIPBOARD_DATA unlockClipboardData; UINT error = CHANNEL_RC_OK; WLog_DBG(TAG, "CliprdrClientUnlockClipData"); + unlockClipboardData.msgType = CB_UNLOCK_CLIPDATA; unlockClipboardData.msgFlags = header->msgFlags; unlockClipboardData.dataLen = header->dataLen; - if (Stream_GetRemainingLength(s) < 4) - { - WLog_ERR(TAG, "not enough data in stream!"); - return ERROR_INVALID_DATA; - } + if ((error = cliprdr_read_unlock_clipdata(s, &unlockClipboardData))) + return error; - Stream_Read_UINT32(s, - unlockClipboardData.clipDataId); /* clipDataId (4 bytes) */ - IFCALLRET(context->ClientUnlockClipboardData, error, context, - &unlockClipboardData); + IFCALLRET(context->ClientUnlockClipboardData, error, context, &unlockClipboardData); if (error) - WLog_ERR(TAG, "ClientUnlockClipboardData failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ClientUnlockClipboardData failed with error %" PRIu32 "!", error); return error; } @@ -893,8 +709,8 @@ static UINT cliprdr_server_receive_unlock_clipdata(CliprdrServerContext* * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_receive_format_data_request(CliprdrServerContext* - context, wStream* s, CLIPRDR_HEADER* header) +static UINT cliprdr_server_receive_format_data_request(CliprdrServerContext* context, wStream* s, + const CLIPRDR_HEADER* header) { CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest; UINT error = CHANNEL_RC_OK; @@ -903,18 +719,14 @@ static UINT cliprdr_server_receive_format_data_request(CliprdrServerContext* formatDataRequest.msgFlags = header->msgFlags; formatDataRequest.dataLen = header->dataLen; - if (Stream_GetRemainingLength(s) < 4) - { - WLog_ERR(TAG, "not enough data in stream!"); - return ERROR_INVALID_DATA; - } + if ((error = cliprdr_read_format_data_request(s, &formatDataRequest))) + return error; - Stream_Read_UINT32(s, - formatDataRequest.requestedFormatId); /* requestedFormatId (4 bytes) */ + context->lastRequestedFormatId = formatDataRequest.requestedFormatId; IFCALLRET(context->ClientFormatDataRequest, error, context, &formatDataRequest); if (error) - WLog_ERR(TAG, "ClientFormatDataRequest failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ClientFormatDataRequest failed with error %" PRIu32 "!", error); return error; } @@ -924,36 +736,25 @@ static UINT cliprdr_server_receive_format_data_request(CliprdrServerContext* * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_receive_format_data_response( - CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header) +static UINT cliprdr_server_receive_format_data_response(CliprdrServerContext* context, wStream* s, + const CLIPRDR_HEADER* header) { CLIPRDR_FORMAT_DATA_RESPONSE formatDataResponse; UINT error = CHANNEL_RC_OK; + WLog_DBG(TAG, "CliprdrClientFormatDataResponse"); formatDataResponse.msgType = CB_FORMAT_DATA_RESPONSE; formatDataResponse.msgFlags = header->msgFlags; formatDataResponse.dataLen = header->dataLen; - formatDataResponse.requestedFormatData = NULL; - - if (Stream_GetRemainingLength(s) < header->dataLen) - { - WLog_ERR(TAG, "not enough data in stream!"); - return ERROR_INVALID_DATA; - } - if (header->dataLen) - { - formatDataResponse.requestedFormatData = (BYTE*) malloc(header->dataLen); - Stream_Read(s, formatDataResponse.requestedFormatData, header->dataLen); - } + if ((error = cliprdr_read_format_data_response(s, &formatDataResponse))) + return error; - IFCALLRET(context->ClientFormatDataResponse, error, context, - &formatDataResponse); + IFCALLRET(context->ClientFormatDataResponse, error, context, &formatDataResponse); if (error) - WLog_ERR(TAG, "ClientFormatDataResponse failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ClientFormatDataResponse failed with error %" PRIu32 "!", error); - free(formatDataResponse.requestedFormatData); return error; } @@ -962,8 +763,8 @@ static UINT cliprdr_server_receive_format_data_response( * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_receive_filecontents_request( - CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header) +static UINT cliprdr_server_receive_filecontents_request(CliprdrServerContext* context, wStream* s, + const CLIPRDR_HEADER* header) { CLIPRDR_FILE_CONTENTS_REQUEST request; UINT error = CHANNEL_RC_OK; @@ -972,28 +773,13 @@ static UINT cliprdr_server_receive_filecontents_request( request.msgFlags = header->msgFlags; request.dataLen = header->dataLen; - if (Stream_GetRemainingLength(s) < 24) - { - WLog_ERR(TAG, "not enough data in stream!"); - return ERROR_INVALID_DATA; - } - - Stream_Read_UINT32(s, request.streamId); /* streamId (4 bytes) */ - Stream_Read_UINT32(s, request.listIndex); /* listIndex (4 bytes) */ - Stream_Read_UINT32(s, request.dwFlags); /* dwFlags (4 bytes) */ - Stream_Read_UINT32(s, request.nPositionLow); /* nPositionLow (4 bytes) */ - Stream_Read_UINT32(s, request.nPositionHigh); /* nPositionHigh (4 bytes) */ - Stream_Read_UINT32(s, request.cbRequested); /* cbRequested (4 bytes) */ - - if (Stream_GetRemainingLength(s) < 4) /* clipDataId (4 bytes) optional */ - request.clipDataId = 0; - else - Stream_Read_UINT32(s, request.clipDataId); + if ((error = cliprdr_read_file_contents_request(s, &request))) + return error; IFCALLRET(context->ClientFileContentsRequest, error, context, &request); if (error) - WLog_ERR(TAG, "ClientFileContentsRequest failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ClientFileContentsRequest failed with error %" PRIu32 "!", error); return error; } @@ -1003,29 +789,24 @@ static UINT cliprdr_server_receive_filecontents_request( * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_receive_filecontents_response( - CliprdrServerContext* context, wStream* s, CLIPRDR_HEADER* header) +static UINT cliprdr_server_receive_filecontents_response(CliprdrServerContext* context, wStream* s, + const CLIPRDR_HEADER* header) { CLIPRDR_FILE_CONTENTS_RESPONSE response; UINT error = CHANNEL_RC_OK; WLog_DBG(TAG, "CliprdrClientFileContentsResponse"); + response.msgType = CB_FILECONTENTS_RESPONSE; response.msgFlags = header->msgFlags; response.dataLen = header->dataLen; - if (Stream_GetRemainingLength(s) < 4) - { - WLog_ERR(TAG, "not enough data in stream!"); - return ERROR_INVALID_DATA; - } + if ((error = cliprdr_read_file_contents_response(s, &response))) + return error; - Stream_Read_UINT32(s, response.streamId); /* streamId (4 bytes) */ - response.cbRequested = header->dataLen - 4; - response.requestedData = Stream_Pointer(s); /* requestedFileContentsData */ IFCALLRET(context->ClientFileContentsResponse, error, context, &response); if (error) - WLog_ERR(TAG, "ClientFileContentsResponse failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ClientFileContentsResponse failed with error %" PRIu32 "!", error); return error; } @@ -1035,19 +816,20 @@ static UINT cliprdr_server_receive_filecontents_response( * * @return 0 on success, otherwise a Win32 error code */ -static UINT cliprdr_server_receive_pdu(CliprdrServerContext* context, - wStream* s, CLIPRDR_HEADER* header) +static UINT cliprdr_server_receive_pdu(CliprdrServerContext* context, wStream* s, + const CLIPRDR_HEADER* header) { UINT error; WLog_DBG(TAG, - "CliprdrServerReceivePdu: msgType: %"PRIu16" msgFlags: 0x%04"PRIX16" dataLen: %"PRIu32"", + "CliprdrServerReceivePdu: msgType: %" PRIu16 " msgFlags: 0x%04" PRIX16 + " dataLen: %" PRIu32 "", header->msgType, header->msgFlags, header->dataLen); switch (header->msgType) { case CB_CLIP_CAPS: if ((error = cliprdr_server_receive_capabilities(context, s, header))) - WLog_ERR(TAG, "cliprdr_server_receive_capabilities failed with error %"PRIu32"!", + WLog_ERR(TAG, "cliprdr_server_receive_capabilities failed with error %" PRIu32 "!", error); break; @@ -1055,13 +837,15 @@ static UINT cliprdr_server_receive_pdu(CliprdrServerContext* context, case CB_TEMP_DIRECTORY: if ((error = cliprdr_server_receive_temporary_directory(context, s, header))) WLog_ERR(TAG, - "cliprdr_server_receive_temporary_directory failed with error %"PRIu32"!", error); + "cliprdr_server_receive_temporary_directory failed with error %" PRIu32 + "!", + error); break; case CB_FORMAT_LIST: if ((error = cliprdr_server_receive_format_list(context, s, header))) - WLog_ERR(TAG, "cliprdr_server_receive_format_list failed with error %"PRIu32"!", + WLog_ERR(TAG, "cliprdr_server_receive_format_list failed with error %" PRIu32 "!", error); break; @@ -1069,20 +853,23 @@ static UINT cliprdr_server_receive_pdu(CliprdrServerContext* context, case CB_FORMAT_LIST_RESPONSE: if ((error = cliprdr_server_receive_format_list_response(context, s, header))) WLog_ERR(TAG, - "cliprdr_server_receive_format_list_response failed with error %"PRIu32"!", error); + "cliprdr_server_receive_format_list_response failed with error %" PRIu32 + "!", + error); break; case CB_LOCK_CLIPDATA: if ((error = cliprdr_server_receive_lock_clipdata(context, s, header))) - WLog_ERR(TAG, "cliprdr_server_receive_lock_clipdata failed with error %"PRIu32"!", + WLog_ERR(TAG, "cliprdr_server_receive_lock_clipdata failed with error %" PRIu32 "!", error); break; case CB_UNLOCK_CLIPDATA: if ((error = cliprdr_server_receive_unlock_clipdata(context, s, header))) - WLog_ERR(TAG, "cliprdr_server_receive_unlock_clipdata failed with error %"PRIu32"!", + WLog_ERR(TAG, + "cliprdr_server_receive_unlock_clipdata failed with error %" PRIu32 "!", error); break; @@ -1090,34 +877,42 @@ static UINT cliprdr_server_receive_pdu(CliprdrServerContext* context, case CB_FORMAT_DATA_REQUEST: if ((error = cliprdr_server_receive_format_data_request(context, s, header))) WLog_ERR(TAG, - "cliprdr_server_receive_format_data_request failed with error %"PRIu32"!", error); + "cliprdr_server_receive_format_data_request failed with error %" PRIu32 + "!", + error); break; case CB_FORMAT_DATA_RESPONSE: if ((error = cliprdr_server_receive_format_data_response(context, s, header))) WLog_ERR(TAG, - "cliprdr_server_receive_format_data_response failed with error %"PRIu32"!", error); + "cliprdr_server_receive_format_data_response failed with error %" PRIu32 + "!", + error); break; case CB_FILECONTENTS_REQUEST: if ((error = cliprdr_server_receive_filecontents_request(context, s, header))) WLog_ERR(TAG, - "cliprdr_server_receive_filecontents_request failed with error %"PRIu32"!", error); + "cliprdr_server_receive_filecontents_request failed with error %" PRIu32 + "!", + error); break; case CB_FILECONTENTS_RESPONSE: if ((error = cliprdr_server_receive_filecontents_response(context, s, header))) WLog_ERR(TAG, - "cliprdr_server_receive_filecontents_response failed with error %"PRIu32"!", error); + "cliprdr_server_receive_filecontents_response failed with error %" PRIu32 + "!", + error); break; default: error = ERROR_INVALID_DATA; - WLog_DBG(TAG, "Unexpected clipboard PDU type: %"PRIu16"", header->msgType); + WLog_ERR(TAG, "Unexpected clipboard PDU type: %" PRIu16 "", header->msgType); break; } @@ -1132,13 +927,14 @@ static UINT cliprdr_server_receive_pdu(CliprdrServerContext* context, static UINT cliprdr_server_init(CliprdrServerContext* context) { UINT32 generalFlags; - CLIPRDR_CAPABILITIES capabilities; - CLIPRDR_MONITOR_READY monitorReady; CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet; UINT error; - ZeroMemory(&capabilities, sizeof(capabilities)); - ZeroMemory(&monitorReady, sizeof(monitorReady)); + CLIPRDR_MONITOR_READY monitorReady = { 0 }; + CLIPRDR_CAPABILITIES capabilities = { 0 }; + generalFlags = 0; + monitorReady.msgType = CB_MONITOR_READY; + capabilities.msgType = CB_CLIP_CAPS; if (context->useLongFormatNames) generalFlags |= CB_USE_LONG_FORMAT_NAMES; @@ -1156,7 +952,7 @@ static UINT cliprdr_server_init(CliprdrServerContext* context) capabilities.msgFlags = 0; capabilities.dataLen = 4 + CB_CAPSTYPE_GENERAL_LEN; capabilities.cCapabilitiesSets = 1; - capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*) &generalCapabilitySet; + capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET*)&generalCapabilitySet; generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL; generalCapabilitySet.capabilitySetLength = CB_CAPSTYPE_GENERAL_LEN; generalCapabilitySet.version = CB_CAPS_VERSION_2; @@ -1164,13 +960,13 @@ static UINT cliprdr_server_init(CliprdrServerContext* context) if ((error = context->ServerCapabilities(context, &capabilities))) { - WLog_ERR(TAG, "ServerCapabilities failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ServerCapabilities failed with error %" PRIu32 "!", error); return error; } if ((error = context->MonitorReady(context, &monitorReady))) { - WLog_ERR(TAG, "MonitorReady failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "MonitorReady failed with error %" PRIu32 "!", error); return error; } @@ -1182,14 +978,14 @@ static UINT cliprdr_server_init(CliprdrServerContext* context) * * @return 0 on success, otherwise a Win32 error code */ -UINT cliprdr_server_read(CliprdrServerContext* context) +static UINT cliprdr_server_read(CliprdrServerContext* context) { wStream* s; size_t position; DWORD BytesToRead; DWORD BytesReturned; CLIPRDR_HEADER header; - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; UINT error; DWORD status; s = cliprdr->s; @@ -1197,21 +993,21 @@ UINT cliprdr_server_read(CliprdrServerContext* context) if (Stream_GetPosition(s) < CLIPRDR_HEADER_LENGTH) { BytesReturned = 0; - BytesToRead = CLIPRDR_HEADER_LENGTH - Stream_GetPosition(s); + BytesToRead = (UINT32)(CLIPRDR_HEADER_LENGTH - Stream_GetPosition(s)); status = WaitForSingleObject(cliprdr->ChannelEvent, 0); if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error); return error; } if (status == WAIT_TIMEOUT) return CHANNEL_RC_OK; - if (!WTSVirtualChannelRead(cliprdr->ChannelHandle, 0, - (PCHAR) Stream_Pointer(s), BytesToRead, &BytesReturned)) + if (!WTSVirtualChannelRead(cliprdr->ChannelHandle, 0, (PCHAR)Stream_Pointer(s), BytesToRead, + &BytesReturned)) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); return ERROR_INTERNAL_ERROR; @@ -1224,9 +1020,9 @@ UINT cliprdr_server_read(CliprdrServerContext* context) { position = Stream_GetPosition(s); Stream_SetPosition(s, 0); - Stream_Read_UINT16(s, header.msgType); /* msgType (2 bytes) */ + Stream_Read_UINT16(s, header.msgType); /* msgType (2 bytes) */ Stream_Read_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */ - Stream_Read_UINT32(s, header.dataLen); /* dataLen (4 bytes) */ + Stream_Read_UINT32(s, header.dataLen); /* dataLen (4 bytes) */ if (!Stream_EnsureCapacity(s, (header.dataLen + CLIPRDR_HEADER_LENGTH))) { @@ -1239,21 +1035,22 @@ UINT cliprdr_server_read(CliprdrServerContext* context) if (Stream_GetPosition(s) < (header.dataLen + CLIPRDR_HEADER_LENGTH)) { BytesReturned = 0; - BytesToRead = (header.dataLen + CLIPRDR_HEADER_LENGTH) - Stream_GetPosition(s); + BytesToRead = + (UINT32)((header.dataLen + CLIPRDR_HEADER_LENGTH) - Stream_GetPosition(s)); status = WaitForSingleObject(cliprdr->ChannelEvent, 0); if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error); return error; } if (status == WAIT_TIMEOUT) return CHANNEL_RC_OK; - if (!WTSVirtualChannelRead(cliprdr->ChannelHandle, 0, - (PCHAR) Stream_Pointer(s), BytesToRead, &BytesReturned)) + if (!WTSVirtualChannelRead(cliprdr->ChannelHandle, 0, (PCHAR)Stream_Pointer(s), + BytesToRead, &BytesReturned)) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); return ERROR_INTERNAL_ERROR; @@ -1270,7 +1067,8 @@ UINT cliprdr_server_read(CliprdrServerContext* context) if ((error = cliprdr_server_receive_pdu(context, s, &header))) { - WLog_ERR(TAG, "cliprdr_server_receive_pdu failed with error code %"PRIu32"!", error); + WLog_ERR(TAG, "cliprdr_server_receive_pdu failed with error code %" PRIu32 "!", + error); return error; } @@ -1281,7 +1079,7 @@ UINT cliprdr_server_read(CliprdrServerContext* context) if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error); return error; } @@ -1291,8 +1089,8 @@ UINT cliprdr_server_read(CliprdrServerContext* context) BytesReturned = 0; BytesToRead = 4; - if (!WTSVirtualChannelRead(cliprdr->ChannelHandle, 0, - (PCHAR) Stream_Pointer(s), BytesToRead, &BytesReturned)) + if (!WTSVirtualChannelRead(cliprdr->ChannelHandle, 0, (PCHAR)Stream_Pointer(s), + BytesToRead, &BytesReturned)) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); return ERROR_INTERNAL_ERROR; @@ -1300,7 +1098,7 @@ UINT cliprdr_server_read(CliprdrServerContext* context) if (BytesReturned == 4) { - Stream_Read_UINT16(s, header.msgType); /* msgType (2 bytes) */ + Stream_Read_UINT16(s, header.msgType); /* msgType (2 bytes) */ Stream_Read_UINT16(s, header.msgFlags); /* msgFlags (2 bytes) */ if (!header.msgType) @@ -1325,19 +1123,22 @@ static DWORD WINAPI cliprdr_server_thread(LPVOID arg) DWORD nCount; HANDLE events[8]; HANDLE ChannelEvent; - CliprdrServerContext* context = (CliprdrServerContext*) arg; - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; - UINT error; + CliprdrServerContext* context = (CliprdrServerContext*)arg; + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; + UINT error = CHANNEL_RC_OK; ChannelEvent = context->GetEventHandle(context); nCount = 0; events[nCount++] = cliprdr->StopEvent; events[nCount++] = ChannelEvent; - if ((error = cliprdr_server_init(context))) + if (context->autoInitializationSequence) { - WLog_ERR(TAG, "cliprdr_server_init failed with error %"PRIu32"!", error); - goto out; + if ((error = cliprdr_server_init(context))) + { + WLog_ERR(TAG, "cliprdr_server_init failed with error %" PRIu32 "!", error); + goto out; + } } while (1) @@ -1347,7 +1148,7 @@ static DWORD WINAPI cliprdr_server_thread(LPVOID arg) if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForMultipleObjects failed with error %" PRIu32 "", error); goto out; } @@ -1356,7 +1157,7 @@ static DWORD WINAPI cliprdr_server_thread(LPVOID arg) if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error); goto out; } @@ -1368,7 +1169,7 @@ static DWORD WINAPI cliprdr_server_thread(LPVOID arg) if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error); goto out; } @@ -1376,7 +1177,7 @@ static DWORD WINAPI cliprdr_server_thread(LPVOID arg) { if ((error = context->CheckEventHandle(context))) { - WLog_ERR(TAG, "CheckEventHandle failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "CheckEventHandle failed with error %" PRIu32 "!", error); break; } } @@ -1385,8 +1186,7 @@ static DWORD WINAPI cliprdr_server_thread(LPVOID arg) out: if (error && context->rdpcontext) - setChannelError(context->rdpcontext, error, - "cliprdr_server_thread reported an error"); + setChannelError(context->rdpcontext, error, "cliprdr_server_thread reported an error"); ExitThread(error); return error; @@ -1401,9 +1201,8 @@ static UINT cliprdr_server_open(CliprdrServerContext* context) { void* buffer = NULL; DWORD BytesReturned = 0; - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; - cliprdr->ChannelHandle = WTSVirtualChannelOpen(cliprdr->vcm, - WTS_CURRENT_SESSION, "cliprdr"); + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; + cliprdr->ChannelHandle = WTSVirtualChannelOpen(cliprdr->vcm, WTS_CURRENT_SESSION, "cliprdr"); if (!cliprdr->ChannelHandle) { @@ -1413,8 +1212,8 @@ static UINT cliprdr_server_open(CliprdrServerContext* context) cliprdr->ChannelEvent = NULL; - if (WTSVirtualChannelQuery(cliprdr->ChannelHandle, WTSVirtualEventHandle, - &buffer, &BytesReturned)) + if (WTSVirtualChannelQuery(cliprdr->ChannelHandle, WTSVirtualEventHandle, &buffer, + &BytesReturned)) { if (BytesReturned != sizeof(HANDLE)) { @@ -1442,7 +1241,7 @@ static UINT cliprdr_server_open(CliprdrServerContext* context) */ static UINT cliprdr_server_close(CliprdrServerContext* context) { - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; if (cliprdr->ChannelHandle) { @@ -1460,7 +1259,7 @@ static UINT cliprdr_server_close(CliprdrServerContext* context) */ static UINT cliprdr_server_start(CliprdrServerContext* context) { - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; UINT error; if (!cliprdr->ChannelHandle) @@ -1478,7 +1277,7 @@ static UINT cliprdr_server_start(CliprdrServerContext* context) return ERROR_INTERNAL_ERROR; } - if (!(cliprdr->Thread = CreateThread(NULL, 0, cliprdr_server_thread, (void*) context, 0, NULL))) + if (!(cliprdr->Thread = CreateThread(NULL, 0, cliprdr_server_thread, (void*)context, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); CloseHandle(cliprdr->StopEvent); @@ -1497,7 +1296,7 @@ static UINT cliprdr_server_start(CliprdrServerContext* context) static UINT cliprdr_server_stop(CliprdrServerContext* context) { UINT error = CHANNEL_RC_OK; - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; if (cliprdr->StopEvent) { @@ -1506,7 +1305,7 @@ static UINT cliprdr_server_stop(CliprdrServerContext* context) if (WaitForSingleObject(cliprdr->Thread, INFINITE) == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error); return error; } @@ -1522,7 +1321,7 @@ static UINT cliprdr_server_stop(CliprdrServerContext* context) static HANDLE cliprdr_server_get_event_handle(CliprdrServerContext* context) { - CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*) context->handle; + CliprdrServerPrivate* cliprdr = (CliprdrServerPrivate*)context->handle; return cliprdr->ChannelEvent; } @@ -1540,10 +1339,11 @@ CliprdrServerContext* cliprdr_server_context_new(HANDLE vcm) { CliprdrServerContext* context; CliprdrServerPrivate* cliprdr; - context = (CliprdrServerContext*) calloc(1, sizeof(CliprdrServerContext)); + context = (CliprdrServerContext*)calloc(1, sizeof(CliprdrServerContext)); if (context) { + context->autoInitializationSequence = TRUE; context->Open = cliprdr_server_open; context->Close = cliprdr_server_close; context->Start = cliprdr_server_start; @@ -1560,8 +1360,7 @@ CliprdrServerContext* cliprdr_server_context_new(HANDLE vcm) context->ServerFormatDataResponse = cliprdr_server_format_data_response; context->ServerFileContentsRequest = cliprdr_server_file_contents_request; context->ServerFileContentsResponse = cliprdr_server_file_contents_response; - cliprdr = context->handle = (CliprdrServerPrivate*) calloc(1, - sizeof(CliprdrServerPrivate)); + cliprdr = context->handle = (CliprdrServerPrivate*)calloc(1, sizeof(CliprdrServerPrivate)); if (cliprdr) { @@ -1594,7 +1393,7 @@ void cliprdr_server_context_free(CliprdrServerContext* context) if (!context) return; - cliprdr = (CliprdrServerPrivate*) context->handle; + cliprdr = (CliprdrServerPrivate*)context->handle; if (cliprdr) { diff --git a/channels/cliprdr/server/cliprdr_main.h b/channels/cliprdr/server/cliprdr_main.h index 248f341..fce0ddb 100644 --- a/channels/cliprdr/server/cliprdr_main.h +++ b/channels/cliprdr/server/cliprdr_main.h @@ -30,7 +30,7 @@ #define TAG CHANNELS_TAG("cliprdr.server") -#define CLIPRDR_HEADER_LENGTH 8 +#define CLIPRDR_HEADER_LENGTH 8 struct _cliprdr_server_private { diff --git a/channels/disp/CMakeLists.txt b/channels/disp/CMakeLists.txt index 541892d..44afe99 100644 --- a/channels/disp/CMakeLists.txt +++ b/channels/disp/CMakeLists.txt @@ -20,3 +20,7 @@ define_channel("disp") 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/disp/client/CMakeLists.txt b/channels/disp/client/CMakeLists.txt index 1ec2c6f..6376f6e 100644 --- a/channels/disp/client/CMakeLists.txt +++ b/channels/disp/client/CMakeLists.txt @@ -19,7 +19,9 @@ define_channel_client("disp") set(${MODULE_PREFIX}_SRCS disp_main.c - disp_main.h) + disp_main.h + ../disp_common.c + ../disp_common.h) include_directories(..) diff --git a/channels/disp/client/disp_main.c b/channels/disp/client/disp_main.c index 0555317..fa92c25 100644 --- a/channels/disp/client/disp_main.c +++ b/channels/disp/client/disp_main.c @@ -40,6 +40,7 @@ #include #include "disp_main.h" +#include "../disp_common.h" struct _DISP_CHANNEL_CALLBACK { @@ -79,41 +80,42 @@ typedef struct _DISP_PLUGIN DISP_PLUGIN; * * @return 0 on success, otherwise a Win32 error code */ -UINT disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback, UINT32 NumMonitors, DISPLAY_CONTROL_MONITOR_LAYOUT* Monitors) +static UINT disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callback, + UINT32 NumMonitors, + DISPLAY_CONTROL_MONITOR_LAYOUT* Monitors) { UINT status; wStream* s; - UINT32 type; UINT32 index; - UINT32 length; DISP_PLUGIN* disp; UINT32 MonitorLayoutSize; + DISPLAY_CONTROL_HEADER header; + disp = (DISP_PLUGIN*)callback->plugin; + MonitorLayoutSize = DISPLAY_CONTROL_MONITOR_LAYOUT_SIZE; + header.length = 8 + 8 + (NumMonitors * MonitorLayoutSize); + header.type = DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT; - disp = (DISP_PLUGIN*) callback->plugin; + s = Stream_New(NULL, header.length); - MonitorLayoutSize = 40; - - length = 8 + 8 + (NumMonitors * MonitorLayoutSize); - - type = DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT; - - s = Stream_New(NULL, length); - if(!s) + if (!s) { WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } - Stream_Write_UINT32(s, type); /* Type (4 bytes) */ - Stream_Write_UINT32(s, length); /* Length (4 bytes) */ + if ((status = disp_write_header(s, &header))) + { + WLog_ERR(TAG, "Failed to write header with error %" PRIu32 "!", status); + goto out; + } if (NumMonitors > disp->MaxNumMonitors) NumMonitors = disp->MaxNumMonitors; Stream_Write_UINT32(s, MonitorLayoutSize); /* MonitorLayoutSize (4 bytes) */ - Stream_Write_UINT32(s, NumMonitors); /* NumMonitors (4 bytes) */ - - WLog_DBG(TAG, "disp_send_display_control_monitor_layout_pdu: NumMonitors=%"PRIu32"", NumMonitors); + Stream_Write_UINT32(s, NumMonitors); /* NumMonitors (4 bytes) */ + WLog_DBG(TAG, "disp_send_display_control_monitor_layout_pdu: NumMonitors=%" PRIu32 "", + NumMonitors); for (index = 0; index < NumMonitors; index++) { @@ -134,30 +136,34 @@ UINT disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callbac if (Monitors[index].Height > 8192) Monitors[index].Height = 8192; - Stream_Write_UINT32(s, Monitors[index].Flags); /* Flags (4 bytes) */ - Stream_Write_UINT32(s, Monitors[index].Left); /* Left (4 bytes) */ - Stream_Write_UINT32(s, Monitors[index].Top); /* Top (4 bytes) */ - Stream_Write_UINT32(s, Monitors[index].Width); /* Width (4 bytes) */ - Stream_Write_UINT32(s, Monitors[index].Height); /* Height (4 bytes) */ - Stream_Write_UINT32(s, Monitors[index].PhysicalWidth); /* PhysicalWidth (4 bytes) */ + Stream_Write_UINT32(s, Monitors[index].Flags); /* Flags (4 bytes) */ + Stream_Write_UINT32(s, Monitors[index].Left); /* Left (4 bytes) */ + Stream_Write_UINT32(s, Monitors[index].Top); /* Top (4 bytes) */ + Stream_Write_UINT32(s, Monitors[index].Width); /* Width (4 bytes) */ + Stream_Write_UINT32(s, Monitors[index].Height); /* Height (4 bytes) */ + Stream_Write_UINT32(s, Monitors[index].PhysicalWidth); /* PhysicalWidth (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].PhysicalHeight); /* PhysicalHeight (4 bytes) */ - Stream_Write_UINT32(s, Monitors[index].Orientation); /* Orientation (4 bytes) */ - Stream_Write_UINT32(s, Monitors[index].DesktopScaleFactor); /* DesktopScaleFactor (4 bytes) */ + Stream_Write_UINT32(s, Monitors[index].Orientation); /* Orientation (4 bytes) */ + Stream_Write_UINT32(s, + Monitors[index].DesktopScaleFactor); /* DesktopScaleFactor (4 bytes) */ Stream_Write_UINT32(s, Monitors[index].DeviceScaleFactor); /* DeviceScaleFactor (4 bytes) */ - - WLog_DBG(TAG, "\t%d : Flags: 0x%08"PRIX32" Left/Top: (%"PRId32",%"PRId32") W/H=%"PRIu32"x%"PRIu32")", index, - Monitors[index].Flags, Monitors[index].Left, Monitors[index].Top, Monitors[index].Width, - Monitors[index].Height); - WLog_DBG(TAG, "\t PhysicalWidth: %"PRIu32" PhysicalHeight: %"PRIu32" Orientation: %"PRIu32"", - Monitors[index].PhysicalWidth, Monitors[index].PhysicalHeight, Monitors[index].Orientation); + WLog_DBG(TAG, + "\t%d : Flags: 0x%08" PRIX32 " Left/Top: (%" PRId32 ",%" PRId32 ") W/H=%" PRIu32 + "x%" PRIu32 ")", + index, Monitors[index].Flags, Monitors[index].Left, Monitors[index].Top, + Monitors[index].Width, Monitors[index].Height); + WLog_DBG(TAG, + "\t PhysicalWidth: %" PRIu32 " PhysicalHeight: %" PRIu32 " Orientation: %" PRIu32 + "", + Monitors[index].PhysicalWidth, Monitors[index].PhysicalHeight, + Monitors[index].Orientation); } +out: Stream_SealLength(s); - - status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), Stream_Buffer(s), NULL); - + status = callback->channel->Write(callback->channel, (UINT32)Stream_Length(s), Stream_Buffer(s), + NULL); Stream_Free(s, TRUE); - return status; } @@ -166,14 +172,13 @@ UINT disp_send_display_control_monitor_layout_pdu(DISP_CHANNEL_CALLBACK* callbac * * @return 0 on success, otherwise a Win32 error code */ -UINT disp_recv_display_control_caps_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s) +static UINT disp_recv_display_control_caps_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s) { DISP_PLUGIN* disp; - DispClientContext *context; + DispClientContext* context; UINT ret = CHANNEL_RC_OK; - - disp = (DISP_PLUGIN*) callback->plugin; - context = (DispClientContext *)disp->iface.pInterface; + disp = (DISP_PLUGIN*)callback->plugin; + context = (DispClientContext*)disp->iface.pInterface; if (Stream_GetRemainingLength(s) < 12) { @@ -181,12 +186,13 @@ UINT disp_recv_display_control_caps_pdu(DISP_CHANNEL_CALLBACK* callback, wStream return ERROR_INVALID_DATA; } - Stream_Read_UINT32(s, disp->MaxNumMonitors); /* MaxNumMonitors (4 bytes) */ + Stream_Read_UINT32(s, disp->MaxNumMonitors); /* MaxNumMonitors (4 bytes) */ Stream_Read_UINT32(s, disp->MaxMonitorAreaFactorA); /* MaxMonitorAreaFactorA (4 bytes) */ Stream_Read_UINT32(s, disp->MaxMonitorAreaFactorB); /* MaxMonitorAreaFactorB (4 bytes) */ if (context->DisplayControlCaps) - ret = context->DisplayControlCaps(context, disp->MaxNumMonitors, disp->MaxMonitorAreaFactorA, disp->MaxMonitorAreaFactorB); + ret = context->DisplayControlCaps(context, disp->MaxNumMonitors, + disp->MaxMonitorAreaFactorA, disp->MaxMonitorAreaFactorB); return ret; } @@ -196,10 +202,10 @@ UINT disp_recv_display_control_caps_pdu(DISP_CHANNEL_CALLBACK* callback, wStream * * @return 0 on success, otherwise a Win32 error code */ -UINT disp_recv_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s) +static UINT disp_recv_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s) { - UINT32 type; - UINT32 length; + UINT32 error; + DISPLAY_CONTROL_HEADER header; if (Stream_GetRemainingLength(s) < 8) { @@ -207,18 +213,25 @@ UINT disp_recv_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s) return ERROR_INVALID_DATA; } - Stream_Read_UINT32(s, type); /* Type (4 bytes) */ - Stream_Read_UINT32(s, length); /* Length (4 bytes) */ + if ((error = disp_read_header(s, &header))) + { + WLog_ERR(TAG, "disp_read_header failed with error %" PRIu32 "!", error); + return error; + } - //WLog_ERR(TAG, "Type: %"PRIu32" Length: %"PRIu32"", type, length); + if (!Stream_EnsureRemainingCapacity(s, header.length)) + { + WLog_ERR(TAG, "not enough remaining data"); + return ERROR_INVALID_DATA; + } - switch (type) + switch (header.type) { case DISPLAY_CONTROL_PDU_TYPE_CAPS: return disp_recv_display_control_caps_pdu(callback, s); default: - WLog_ERR(TAG, "Type %"PRIu32" not recognized!", type); + WLog_ERR(TAG, "Type %" PRIu32 " not recognized!", header.type); return ERROR_INTERNAL_ERROR; } } @@ -228,10 +241,9 @@ UINT disp_recv_pdu(DISP_CHANNEL_CALLBACK* callback, wStream* s) * * @return 0 on success, otherwise a Win32 error code */ -static UINT disp_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) +static UINT disp_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data) { - DISP_CHANNEL_CALLBACK* callback = (DISP_CHANNEL_CALLBACK*) pChannelCallback; - + DISP_CHANNEL_CALLBACK* callback = (DISP_CHANNEL_CALLBACK*)pChannelCallback; return disp_recv_pdu(callback, data); } @@ -252,13 +264,12 @@ static UINT disp_on_close(IWTSVirtualChannelCallback* pChannelCallback) * @return 0 on success, otherwise a Win32 error code */ static UINT disp_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, - IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept, - IWTSVirtualChannelCallback** ppCallback) + IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept, + IWTSVirtualChannelCallback** ppCallback) { DISP_CHANNEL_CALLBACK* callback; - DISP_LISTENER_CALLBACK* listener_callback = (DISP_LISTENER_CALLBACK*) pListenerCallback; - - callback = (DISP_CHANNEL_CALLBACK*) calloc(1, sizeof(DISP_CHANNEL_CALLBACK)); + DISP_LISTENER_CALLBACK* listener_callback = (DISP_LISTENER_CALLBACK*)pListenerCallback; + callback = (DISP_CHANNEL_CALLBACK*)calloc(1, sizeof(DISP_CHANNEL_CALLBACK)); if (!callback) { @@ -272,9 +283,7 @@ static UINT disp_on_new_channel_connection(IWTSListenerCallback* pListenerCallba callback->channel_mgr = listener_callback->channel_mgr; callback->channel = pChannel; listener_callback->channel_callback = callback; - - *ppCallback = (IWTSVirtualChannelCallback*) callback; - + *ppCallback = (IWTSVirtualChannelCallback*)callback; return CHANNEL_RC_OK; } @@ -286,9 +295,8 @@ static UINT disp_on_new_channel_connection(IWTSListenerCallback* pListenerCallba static UINT disp_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) { UINT status; - DISP_PLUGIN* disp = (DISP_PLUGIN*) pPlugin; - - disp->listener_callback = (DISP_LISTENER_CALLBACK*) calloc(1, sizeof(DISP_LISTENER_CALLBACK)); + DISP_PLUGIN* disp = (DISP_PLUGIN*)pPlugin; + disp->listener_callback = (DISP_LISTENER_CALLBACK*)calloc(1, sizeof(DISP_LISTENER_CALLBACK)); if (!disp->listener_callback) { @@ -299,12 +307,9 @@ static UINT disp_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage disp->listener_callback->iface.OnNewChannelConnection = disp_on_new_channel_connection; disp->listener_callback->plugin = pPlugin; disp->listener_callback->channel_mgr = pChannelMgr; - status = pChannelMgr->CreateListener(pChannelMgr, DISP_DVC_CHANNEL_NAME, 0, - (IWTSListenerCallback*) disp->listener_callback, &(disp->listener)); - + &disp->listener_callback->iface, &(disp->listener)); disp->listener->pInterface = disp->iface.pInterface; - return status; } @@ -315,7 +320,15 @@ static UINT disp_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage */ static UINT disp_plugin_terminated(IWTSPlugin* pPlugin) { - DISP_PLUGIN* disp = (DISP_PLUGIN*) pPlugin; + DISP_PLUGIN* disp = (DISP_PLUGIN*)pPlugin; + + if (disp && disp->listener_callback) + { + IWTSVirtualChannelManager* mgr = disp->listener_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, disp->listener); + } + free(disp->listener_callback); free(disp->iface.pInterface); free(pPlugin); @@ -331,18 +344,18 @@ static UINT disp_plugin_terminated(IWTSPlugin* pPlugin) * * @return 0 on success, otherwise a Win32 error code */ -UINT disp_send_monitor_layout(DispClientContext* context, UINT32 NumMonitors, DISPLAY_CONTROL_MONITOR_LAYOUT* Monitors) +static UINT disp_send_monitor_layout(DispClientContext* context, UINT32 NumMonitors, + DISPLAY_CONTROL_MONITOR_LAYOUT* Monitors) { - DISP_PLUGIN* disp = (DISP_PLUGIN*) context->handle; + DISP_PLUGIN* disp = (DISP_PLUGIN*)context->handle; DISP_CHANNEL_CALLBACK* callback = disp->listener_callback->channel_callback; - return disp_send_display_control_monitor_layout_pdu(callback, NumMonitors, Monitors); } #ifdef BUILTIN_CHANNELS -#define DVCPluginEntry disp_DVCPluginEntry +#define DVCPluginEntry disp_DVCPluginEntry #else -#define DVCPluginEntry FREERDP_API DVCPluginEntry +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** @@ -355,11 +368,12 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) UINT error = CHANNEL_RC_OK; DISP_PLUGIN* disp; DispClientContext* context; + disp = (DISP_PLUGIN*)pEntryPoints->GetPlugin(pEntryPoints, "disp"); - disp = (DISP_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "disp"); if (!disp) { - disp = (DISP_PLUGIN*) calloc(1, sizeof(DISP_PLUGIN)); + disp = (DISP_PLUGIN*)calloc(1, sizeof(DISP_PLUGIN)); + if (!disp) { WLog_ERR(TAG, "calloc failed!"); @@ -373,8 +387,8 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) disp->MaxNumMonitors = 16; disp->MaxMonitorAreaFactorA = 8192; disp->MaxMonitorAreaFactorB = 8192; + context = (DispClientContext*)calloc(1, sizeof(DispClientContext)); - context = (DispClientContext*) calloc(1, sizeof(DispClientContext)); if (!context) { WLog_ERR(TAG, "calloc failed!"); @@ -382,12 +396,10 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) return CHANNEL_RC_NO_MEMORY; } - context->handle = (void*) disp; + context->handle = (void*)disp; context->SendMonitorLayout = disp_send_monitor_layout; - - disp->iface.pInterface = (void*) context; - - error = pEntryPoints->RegisterPlugin(pEntryPoints, "disp", (IWTSPlugin*) disp); + disp->iface.pInterface = (void*)context; + error = pEntryPoints->RegisterPlugin(pEntryPoints, "disp", (IWTSPlugin*)disp); } else { diff --git a/channels/disp/client/disp_main.h b/channels/disp/client/disp_main.h index c2aabae..45a4830 100644 --- a/channels/disp/client/disp_main.h +++ b/channels/disp/client/disp_main.h @@ -33,10 +33,6 @@ #include -#define DISPLAY_CONTROL_PDU_TYPE_CAPS 0x00000005 -#define DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT 0x00000002 - #define TAG CHANNELS_TAG("disp.client") #endif /* FREERDP_CHANNEL_DISP_CLIENT_MAIN_H */ - diff --git a/channels/disp/disp_common.c b/channels/disp/disp_common.c new file mode 100644 index 0000000..f4313d1 --- /dev/null +++ b/channels/disp/disp_common.c @@ -0,0 +1,60 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * RDPEDISP Virtual Channel Extension + * + * Copyright 2019 Kobi Mizrachi + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#define TAG CHANNELS_TAG("disp.common") + +#include "disp_common.h" + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +UINT disp_read_header(wStream* s, DISPLAY_CONTROL_HEADER* header) +{ + if (Stream_GetRemainingLength(s) < 8) + { + WLog_ERR(TAG, "header parsing failed: not enough data!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, header->type); + Stream_Read_UINT32(s, header->length); + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +UINT disp_write_header(wStream* s, const DISPLAY_CONTROL_HEADER* header) +{ + Stream_Write_UINT32(s, header->type); + Stream_Write_UINT32(s, header->length); + return CHANNEL_RC_OK; +} diff --git a/channels/disp/disp_common.h b/channels/disp/disp_common.h new file mode 100644 index 0000000..386b8b3 --- /dev/null +++ b/channels/disp/disp_common.h @@ -0,0 +1,32 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * RDPEDISP Virtual Channel Extension + * + * Copyright 2019 Kobi Mizrachi + * + * 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_DISP_COMMON_H +#define FREERDP_CHANNEL_DISP_COMMON_H + +#include +#include + +#include +#include + +FREERDP_LOCAL UINT disp_read_header(wStream* s, DISPLAY_CONTROL_HEADER* header); +FREERDP_LOCAL UINT disp_write_header(wStream* s, const DISPLAY_CONTROL_HEADER* header); + +#endif /* FREERDP_CHANNEL_DISP_COMMON_H */ diff --git a/channels/disp/server/CMakeLists.txt b/channels/disp/server/CMakeLists.txt new file mode 100644 index 0000000..dddc15b --- /dev/null +++ b/channels/disp/server/CMakeLists.txt @@ -0,0 +1,32 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2019 Kobi Mizrachi +# +# 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_server("disp") + +set(${MODULE_PREFIX}_SRCS + disp_main.c + disp_main.h + ../disp_common.c + ../disp_common.h + ) + +include_directories(..) + +add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "DVCPluginEntry") + +target_link_libraries(${MODULE_NAME} freerdp) +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server") diff --git a/channels/disp/server/disp_main.c b/channels/disp/server/disp_main.c new file mode 100644 index 0000000..5340165 --- /dev/null +++ b/channels/disp/server/disp_main.c @@ -0,0 +1,581 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * RDPEDISP Virtual Channel Extension + * + * Copyright 2019 Kobi Mizrachi + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "disp_main.h" +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "../disp_common.h" + +#define TAG CHANNELS_TAG("rdpedisp.server") + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ + +static wStream* disp_server_single_packet_new(UINT32 type, UINT32 length) +{ + UINT error; + DISPLAY_CONTROL_HEADER header; + wStream* s = Stream_New(NULL, DISPLAY_CONTROL_HEADER_LENGTH + length); + + if (!s) + { + WLog_ERR(TAG, "Stream_New failed!"); + goto error; + } + + header.type = type; + header.length = length; + + if ((error = disp_write_header(s, &header))) + { + WLog_ERR(TAG, "Failed to write header with error %" PRIu32 "!", error); + goto error; + } + + return s; +error: + Stream_Free(s, TRUE); + return NULL; +} + +static BOOL disp_server_is_monitor_layout_valid(DISPLAY_CONTROL_MONITOR_LAYOUT* monitor) +{ + if (monitor->Width < DISPLAY_CONTROL_MIN_MONITOR_WIDTH || + monitor->Width > DISPLAY_CONTROL_MAX_MONITOR_WIDTH) + { + WLog_WARN(TAG, "Received invalid value for monitor->Width: %" PRIu32 "", monitor->Width); + return FALSE; + } + + if (monitor->Height < DISPLAY_CONTROL_MIN_MONITOR_HEIGHT || + monitor->Height > DISPLAY_CONTROL_MAX_MONITOR_HEIGHT) + { + WLog_WARN(TAG, "Received invalid value for monitor->Height: %" PRIu32 "", monitor->Width); + return FALSE; + } + + if (monitor->PhysicalWidth < DISPLAY_CONTROL_MIN_PHYSICAL_MONITOR_WIDTH || + monitor->PhysicalWidth > DISPLAY_CONTROL_MAX_PHYSICAL_MONITOR_WIDTH) + { + WLog_WARN(TAG, "Received invalid value for monitor->PhysicalWidth: %" PRIu32 "", + monitor->PhysicalWidth); + return FALSE; + } + + if (monitor->PhysicalHeight < DISPLAY_CONTROL_MIN_PHYSICAL_MONITOR_HEIGHT || + monitor->PhysicalHeight > DISPLAY_CONTROL_MAX_PHYSICAL_MONITOR_HEIGHT) + { + WLog_WARN(TAG, "Received invalid value for monitor->Height: %" PRIu32 "", + monitor->PhysicalHeight); + return FALSE; + } + + switch (monitor->Orientation) + { + case ORIENTATION_LANDSCAPE: + case ORIENTATION_PORTRAIT: + case ORIENTATION_LANDSCAPE_FLIPPED: + case ORIENTATION_PORTRAIT_FLIPPED: + break; + + default: + WLog_WARN(TAG, "Received incorrect value for monitor->Orientation: %" PRIu32 "", + monitor->Orientation); + return FALSE; + } + + return TRUE; +} + +static UINT disp_recv_display_control_monitor_layout_pdu(wStream* s, DispServerContext* context) +{ + UINT32 error = CHANNEL_RC_OK; + UINT32 index; + DISPLAY_CONTROL_MONITOR_LAYOUT_PDU pdu; + DISPLAY_CONTROL_MONITOR_LAYOUT* monitor; + + if (Stream_GetRemainingLength(s) < 8) + { + WLog_ERR(TAG, "not enough data!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, pdu.MonitorLayoutSize); /* MonitorLayoutSize (4 bytes) */ + + if (pdu.MonitorLayoutSize != DISPLAY_CONTROL_MONITOR_LAYOUT_SIZE) + { + WLog_ERR(TAG, "MonitorLayoutSize is set to %" PRIu32 ". expected %" PRIu32 "", + pdu.MonitorLayoutSize, DISPLAY_CONTROL_MONITOR_LAYOUT_SIZE); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, pdu.NumMonitors); /* NumMonitors (4 bytes) */ + + if (pdu.NumMonitors > context->MaxNumMonitors) + { + WLog_ERR(TAG, "NumMonitors (%" PRIu32 ")> server MaxNumMonitors (%" PRIu32 ")", + pdu.NumMonitors, context->MaxNumMonitors); + return ERROR_INVALID_DATA; + } + + if (Stream_GetRemainingLength(s) < DISPLAY_CONTROL_MONITOR_LAYOUT_SIZE * pdu.NumMonitors) + { + WLog_ERR(TAG, "not enough data!"); + return ERROR_INVALID_DATA; + } + + pdu.Monitors = (DISPLAY_CONTROL_MONITOR_LAYOUT*)calloc(pdu.NumMonitors, + sizeof(DISPLAY_CONTROL_MONITOR_LAYOUT)); + + if (!pdu.Monitors) + { + WLog_ERR(TAG, "disp_recv_display_control_monitor_layout_pdu(): calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + WLog_DBG(TAG, "disp_recv_display_control_monitor_layout_pdu: NumMonitors=%" PRIu32 "", + pdu.NumMonitors); + + for (index = 0; index < pdu.NumMonitors; index++) + { + monitor = &(pdu.Monitors[index]); + Stream_Read_UINT32(s, monitor->Flags); /* Flags (4 bytes) */ + Stream_Read_UINT32(s, monitor->Left); /* Left (4 bytes) */ + Stream_Read_UINT32(s, monitor->Top); /* Top (4 bytes) */ + Stream_Read_UINT32(s, monitor->Width); /* Width (4 bytes) */ + Stream_Read_UINT32(s, monitor->Height); /* Height (4 bytes) */ + Stream_Read_UINT32(s, monitor->PhysicalWidth); /* PhysicalWidth (4 bytes) */ + Stream_Read_UINT32(s, monitor->PhysicalHeight); /* PhysicalHeight (4 bytes) */ + Stream_Read_UINT32(s, monitor->Orientation); /* Orientation (4 bytes) */ + Stream_Read_UINT32(s, monitor->DesktopScaleFactor); /* DesktopScaleFactor (4 bytes) */ + Stream_Read_UINT32(s, monitor->DeviceScaleFactor); /* DeviceScaleFactor (4 bytes) */ + WLog_DBG(TAG, + "\t%d : Flags: 0x%08" PRIX32 " Left/Top: (%" PRId32 ",%" PRId32 ") W/H=%" PRIu32 + "x%" PRIu32 ")", + index, monitor->Flags, monitor->Left, monitor->Top, monitor->Width, + monitor->Height); + WLog_DBG(TAG, + "\t PhysicalWidth: %" PRIu32 " PhysicalHeight: %" PRIu32 " Orientation: %" PRIu32 + "", + monitor->PhysicalWidth, monitor->PhysicalHeight, monitor->Orientation); + + if (!disp_server_is_monitor_layout_valid(monitor)) + { + error = ERROR_INVALID_DATA; + goto out; + } + } + + if (context) + IFCALLRET(context->DispMonitorLayout, error, context, &pdu); + +out: + free(pdu.Monitors); + return error; +} + +static UINT disp_server_receive_pdu(DispServerContext* context, wStream* s) +{ + UINT error = CHANNEL_RC_OK; + size_t beg, end; + DISPLAY_CONTROL_HEADER header; + beg = Stream_GetPosition(s); + + if ((error = disp_read_header(s, &header))) + { + WLog_ERR(TAG, "disp_read_header failed with error %" PRIu32 "!", error); + return error; + } + + switch (header.type) + { + case DISPLAY_CONTROL_PDU_TYPE_MONITOR_LAYOUT: + if ((error = disp_recv_display_control_monitor_layout_pdu(s, context))) + WLog_ERR(TAG, + "disp_recv_display_control_monitor_layout_pdu " + "failed with error %" PRIu32 "!", + error); + + break; + + default: + error = CHANNEL_RC_BAD_PROC; + WLog_WARN(TAG, "Received unknown PDU type: %" PRIu32 "", header.type); + break; + } + + end = Stream_GetPosition(s); + + if (end != (beg + header.length)) + { + WLog_ERR(TAG, "Unexpected DISP pdu end: Actual: %d, Expected: %" PRIu32 "", end, + (beg + header.length)); + Stream_SetPosition(s, (beg + header.length)); + } + + return error; +} + +static UINT disp_server_handle_messages(DispServerContext* context) +{ + DWORD BytesReturned; + void* buffer; + UINT ret = CHANNEL_RC_OK; + DispServerPrivate* priv = context->priv; + wStream* s = priv->input_stream; + + /* Check whether the dynamic channel is ready */ + if (!priv->isReady) + { + if (WTSVirtualChannelQuery(priv->disp_channel, WTSVirtualChannelReady, &buffer, + &BytesReturned) == FALSE) + { + if (GetLastError() == ERROR_NO_DATA) + return ERROR_NO_DATA; + + WLog_ERR(TAG, "WTSVirtualChannelQuery failed"); + return ERROR_INTERNAL_ERROR; + } + + priv->isReady = *((BOOL*)buffer); + WTSFreeMemory(buffer); + } + + /* Consume channel event only after the disp dynamic channel is ready */ + Stream_SetPosition(s, 0); + + if (!WTSVirtualChannelRead(priv->disp_channel, 0, NULL, 0, &BytesReturned)) + { + if (GetLastError() == ERROR_NO_DATA) + return ERROR_NO_DATA; + + WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); + return ERROR_INTERNAL_ERROR; + } + + if (BytesReturned < 1) + return CHANNEL_RC_OK; + + if (!Stream_EnsureRemainingCapacity(s, BytesReturned)) + { + WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + if (WTSVirtualChannelRead(priv->disp_channel, 0, (PCHAR)Stream_Buffer(s), Stream_Capacity(s), + &BytesReturned) == FALSE) + { + WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); + return ERROR_INTERNAL_ERROR; + } + + Stream_SetLength(s, BytesReturned); + Stream_SetPosition(s, 0); + + while (Stream_GetPosition(s) < Stream_Length(s)) + { + if ((ret = disp_server_receive_pdu(context, s))) + { + WLog_ERR(TAG, + "disp_server_receive_pdu " + "failed with error %" PRIu32 "!", + ret); + return ret; + } + } + + return ret; +} + +static DWORD WINAPI disp_server_thread_func(LPVOID arg) +{ + DispServerContext* context = (DispServerContext*)arg; + DispServerPrivate* priv = context->priv; + DWORD status; + DWORD nCount; + HANDLE events[8]; + UINT error = CHANNEL_RC_OK; + nCount = 0; + events[nCount++] = priv->stopEvent; + events[nCount++] = priv->channelEvent; + + /* Main virtual channel loop. RDPEDISP do not need version negotiation */ + while (TRUE) + { + status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); + + if (status == WAIT_FAILED) + { + error = GetLastError(); + WLog_ERR(TAG, "WaitForMultipleObjects failed with error %" PRIu32 "", error); + break; + } + + /* Stop Event */ + if (status == WAIT_OBJECT_0) + break; + + if ((error = disp_server_handle_messages(context))) + { + WLog_ERR(TAG, "disp_server_handle_messages failed with error %" PRIu32 "", error); + break; + } + } + + ExitThread(error); + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT disp_server_open(DispServerContext* context) +{ + UINT rc = ERROR_INTERNAL_ERROR; + DispServerPrivate* priv = context->priv; + DWORD BytesReturned = 0; + PULONG pSessionId = NULL; + void* buffer; + buffer = NULL; + priv->SessionId = WTS_CURRENT_SESSION; + + if (WTSQuerySessionInformationA(context->vcm, WTS_CURRENT_SESSION, WTSSessionId, + (LPSTR*)&pSessionId, &BytesReturned) == FALSE) + { + WLog_ERR(TAG, "WTSQuerySessionInformationA failed!"); + rc = ERROR_INTERNAL_ERROR; + goto out_close; + } + + priv->SessionId = (DWORD)*pSessionId; + WTSFreeMemory(pSessionId); + priv->disp_channel = (HANDLE)WTSVirtualChannelOpenEx(priv->SessionId, DISP_DVC_CHANNEL_NAME, + WTS_CHANNEL_OPTION_DYNAMIC); + + if (!priv->disp_channel) + { + WLog_ERR(TAG, "WTSVirtualChannelOpenEx failed!"); + rc = GetLastError(); + goto out_close; + } + + /* Query for channel event handle */ + if (!WTSVirtualChannelQuery(priv->disp_channel, WTSVirtualEventHandle, &buffer, + &BytesReturned) || + (BytesReturned != sizeof(HANDLE))) + { + WLog_ERR(TAG, + "WTSVirtualChannelQuery failed " + "or invalid returned size(%" PRIu32 ")", + BytesReturned); + + if (buffer) + WTSFreeMemory(buffer); + + rc = ERROR_INTERNAL_ERROR; + goto out_close; + } + + CopyMemory(&priv->channelEvent, buffer, sizeof(HANDLE)); + WTSFreeMemory(buffer); + + if (priv->thread == NULL) + { + if (!(priv->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) + { + WLog_ERR(TAG, "CreateEvent failed!"); + rc = ERROR_INTERNAL_ERROR; + } + + if (!(priv->thread = + CreateThread(NULL, 0, disp_server_thread_func, (void*)context, 0, NULL))) + { + WLog_ERR(TAG, "CreateEvent failed!"); + CloseHandle(priv->stopEvent); + priv->stopEvent = NULL; + rc = ERROR_INTERNAL_ERROR; + } + } + + return CHANNEL_RC_OK; +out_close: + WTSVirtualChannelClose(priv->disp_channel); + priv->disp_channel = NULL; + priv->channelEvent = NULL; + return rc; +} + +static UINT disp_server_packet_send(DispServerContext* context, wStream* s) +{ + UINT ret; + ULONG written; + + if (!WTSVirtualChannelWrite(context->priv->disp_channel, (PCHAR)Stream_Buffer(s), + Stream_GetPosition(s), &written)) + { + WLog_ERR(TAG, "WTSVirtualChannelWrite failed!"); + ret = ERROR_INTERNAL_ERROR; + goto out; + } + + if (written < Stream_GetPosition(s)) + { + WLog_WARN(TAG, "Unexpected bytes written: %" PRIu32 "/%" PRIuz "", written, + Stream_GetPosition(s)); + } + + ret = CHANNEL_RC_OK; +out: + Stream_Free(s, TRUE); + return ret; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT disp_server_send_caps_pdu(DispServerContext* context) +{ + wStream* s = disp_server_single_packet_new(DISPLAY_CONTROL_PDU_TYPE_CAPS, 12); + + if (!s) + { + WLog_ERR(TAG, "disp_server_single_packet_new failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + Stream_Write_UINT32(s, context->MaxNumMonitors); /* MaxNumMonitors (4 bytes) */ + Stream_Write_UINT32(s, context->MaxMonitorAreaFactorA); /* MaxMonitorAreaFactorA (4 bytes) */ + Stream_Write_UINT32(s, context->MaxMonitorAreaFactorB); /* MaxMonitorAreaFactorB (4 bytes) */ + return disp_server_packet_send(context, s); +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT disp_server_close(DispServerContext* context) +{ + UINT error = CHANNEL_RC_OK; + DispServerPrivate* priv = context->priv; + + if (priv->thread) + { + SetEvent(priv->stopEvent); + + if (WaitForSingleObject(priv->thread, INFINITE) == WAIT_FAILED) + { + error = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error); + return error; + } + + CloseHandle(priv->thread); + CloseHandle(priv->stopEvent); + priv->thread = NULL; + priv->stopEvent = NULL; + } + + if (priv->disp_channel) + { + WTSVirtualChannelClose(priv->disp_channel); + priv->disp_channel = NULL; + } + + return error; +} + +DispServerContext* disp_server_context_new(HANDLE vcm) +{ + DispServerContext* context; + DispServerPrivate* priv; + context = (DispServerContext*)calloc(1, sizeof(DispServerContext)); + + if (!context) + { + WLog_ERR(TAG, "disp_server_context_new(): calloc DispServerContext failed!"); + goto out_free; + } + + priv = context->priv = (DispServerPrivate*)calloc(1, sizeof(DispServerPrivate)); + + if (!context->priv) + { + WLog_ERR(TAG, "disp_server_context_new(): calloc DispServerPrivate failed!"); + goto out_free; + } + + priv->input_stream = Stream_New(NULL, 4); + + if (!priv->input_stream) + { + WLog_ERR(TAG, "Stream_New failed!"); + goto out_free_priv; + } + + context->vcm = vcm; + context->Open = disp_server_open; + context->Close = disp_server_close; + context->DisplayControlCaps = disp_server_send_caps_pdu; + priv->isReady = FALSE; + return context; +out_free_priv: + free(context->priv); +out_free: + free(context); + return NULL; +} + +void disp_server_context_free(DispServerContext* context) +{ + if (!context) + return; + + disp_server_close(context); + + if (context->priv) + { + Stream_Free(context->priv->input_stream, TRUE); + free(context->priv); + } + + free(context); +} diff --git a/channels/disp/server/disp_main.h b/channels/disp/server/disp_main.h new file mode 100644 index 0000000..c47462b --- /dev/null +++ b/channels/disp/server/disp_main.h @@ -0,0 +1,37 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * RDPEDISP Virtual Channel Extension + * + * Copyright 2019 Kobi Mizrachi + * + * 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_DISP_SERVER_MAIN_H +#define FREERDP_CHANNEL_DISP_SERVER_MAIN_H + +#include + +struct _disp_server_private +{ + BOOL isReady; + wStream* input_stream; + HANDLE channelEvent; + HANDLE thread; + HANDLE stopEvent; + DWORD SessionId; + + void* disp_channel; +}; + +#endif /* FREERDP_CHANNEL_DISP_SERVER_MAIN_H */ diff --git a/channels/drdynvc/client/drdynvc_main.c b/channels/drdynvc/client/drdynvc_main.c index f27381b..eb5b418 100644 --- a/channels/drdynvc/client/drdynvc_main.c +++ b/channels/drdynvc/client/drdynvc_main.c @@ -30,18 +30,28 @@ #define TAG CHANNELS_TAG("drdynvc.client") +static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr); static void dvcman_channel_free(void* channel); -static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, - const BYTE* data, UINT32 dataSize); +static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const BYTE* data, + UINT32 dataSize); +static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s); + +static void dvcman_wtslistener_free(DVCMAN_LISTENER* listener) +{ + if (listener) + free(listener->channel_name); + + free(listener); +} /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -static UINT dvcman_get_configuration(IWTSListener* pListener, - void** ppPropertyBag) +static UINT dvcman_get_configuration(IWTSListener* pListener, void** ppPropertyBag) { + WINPR_UNUSED(pListener); *ppPropertyBag = NULL; return ERROR_INTERNAL_ERROR; } @@ -53,48 +63,59 @@ static UINT dvcman_get_configuration(IWTSListener* pListener, */ static UINT dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr, const char* pszChannelName, ULONG ulFlags, - IWTSListenerCallback* pListenerCallback, IWTSListener** ppListener) + IWTSListenerCallback* pListenerCallback, + IWTSListener** ppListener) { - DVCMAN* dvcman = (DVCMAN*) pChannelMgr; + DVCMAN* dvcman = (DVCMAN*)pChannelMgr; DVCMAN_LISTENER* listener; - if (dvcman->num_listeners < MAX_PLUGINS) + WLog_DBG(TAG, "create_listener: %d.%s.", ArrayList_Count(dvcman->listeners) + 1, + pszChannelName); + listener = (DVCMAN_LISTENER*)calloc(1, sizeof(DVCMAN_LISTENER)); + + if (!listener) { - WLog_DBG(TAG, "create_listener: %d.%s.", dvcman->num_listeners, pszChannelName); - listener = (DVCMAN_LISTENER*) calloc(1, sizeof(DVCMAN_LISTENER)); + WLog_ERR(TAG, "calloc failed!"); + return CHANNEL_RC_NO_MEMORY; + } - if (!listener) - { - WLog_ERR(TAG, "calloc failed!"); - return CHANNEL_RC_NO_MEMORY; - } + listener->iface.GetConfiguration = dvcman_get_configuration; + listener->iface.pInterface = NULL; + listener->dvcman = dvcman; + listener->channel_name = _strdup(pszChannelName); - listener->iface.GetConfiguration = dvcman_get_configuration; - listener->iface.pInterface = NULL; - listener->dvcman = dvcman; - listener->channel_name = _strdup(pszChannelName); + if (!listener->channel_name) + { + WLog_ERR(TAG, "_strdup failed!"); + dvcman_wtslistener_free(listener); + return CHANNEL_RC_NO_MEMORY; + } - if (!listener->channel_name) - { - WLog_ERR(TAG, "_strdup failed!"); - free(listener); - return CHANNEL_RC_NO_MEMORY; - } + listener->flags = ulFlags; + listener->listener_callback = pListenerCallback; - listener->flags = ulFlags; - listener->listener_callback = pListenerCallback; + if (ppListener) + *ppListener = (IWTSListener*)listener; - if (ppListener) - *ppListener = (IWTSListener*) listener; + if (ArrayList_Add(dvcman->listeners, listener) < 0) + return ERROR_INTERNAL_ERROR; + return CHANNEL_RC_OK; +} - dvcman->listeners[dvcman->num_listeners++] = (IWTSListener*) listener; - return CHANNEL_RC_OK; - } - else +static UINT dvcman_destroy_listener(IWTSVirtualChannelManager* pChannelMgr, IWTSListener* pListener) +{ + DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)pListener; + + WINPR_UNUSED(pChannelMgr); + + if (listener) { - WLog_ERR(TAG, "create_listener: Maximum DVC listener number reached."); - return ERROR_INTERNAL_ERROR; + DVCMAN* dvcman = listener->dvcman; + if (dvcman) + ArrayList_Remove(dvcman->listeners, listener); } + + return CHANNEL_RC_OK; } /** @@ -102,122 +123,154 @@ static UINT dvcman_create_listener(IWTSVirtualChannelManager* pChannelMgr, * * @return 0 on success, otherwise a Win32 error code */ -static UINT dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, - const char* name, IWTSPlugin* pPlugin) +static UINT dvcman_register_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name, + IWTSPlugin* pPlugin) { - DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman; + DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*)pEntryPoints)->dvcman; - if (dvcman->num_plugins < MAX_PLUGINS) - { - dvcman->plugin_names[dvcman->num_plugins] = name; - dvcman->plugins[dvcman->num_plugins++] = pPlugin; - WLog_DBG(TAG, "register_plugin: num_plugins %d", dvcman->num_plugins); - return CHANNEL_RC_OK; - } - else - { - WLog_ERR(TAG, "register_plugin: Maximum DVC plugin number %u reached.", - MAX_PLUGINS); + if (ArrayList_Add(dvcman->plugin_names, _strdup(name)) < 0) return ERROR_INTERNAL_ERROR; - } + if (ArrayList_Add(dvcman->plugins, pPlugin) < 0) + return ERROR_INTERNAL_ERROR; + + WLog_DBG(TAG, "register_plugin: num_plugins %d", ArrayList_Count(dvcman->plugins)); + return CHANNEL_RC_OK; } -static IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, - const char* name) +static IWTSPlugin* dvcman_get_plugin(IDRDYNVC_ENTRY_POINTS* pEntryPoints, const char* name) { - int i; - DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->dvcman; + IWTSPlugin* plugin = NULL; + size_t i, nc, pc; + DVCMAN* dvcman = ((DVCMAN_ENTRY_POINTS*)pEntryPoints)->dvcman; + if (!dvcman || !pEntryPoints || !name) + return NULL; + + nc = ArrayList_Count(dvcman->plugin_names); + pc = ArrayList_Count(dvcman->plugins); + if (nc != pc) + return NULL; - for (i = 0; i < dvcman->num_plugins; i++) + ArrayList_Lock(dvcman->plugin_names); + ArrayList_Lock(dvcman->plugins); + for (i = 0; i < pc; i++) { - if (dvcman->plugin_names[i] == name || - strcmp(dvcman->plugin_names[i], name) == 0) + const char* cur = ArrayList_GetItem(dvcman->plugin_names, i); + if (strcmp(cur, name) == 0) { - return dvcman->plugins[i]; + plugin = ArrayList_GetItem(dvcman->plugins, i); + break; } } - - return NULL; + ArrayList_Unlock(dvcman->plugin_names); + ArrayList_Unlock(dvcman->plugins); + return plugin; } static ADDIN_ARGV* dvcman_get_plugin_data(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { - return ((DVCMAN_ENTRY_POINTS*) pEntryPoints)->args; + return ((DVCMAN_ENTRY_POINTS*)pEntryPoints)->args; } static void* dvcman_get_rdp_settings(IDRDYNVC_ENTRY_POINTS* pEntryPoints) { - return (void*)((DVCMAN_ENTRY_POINTS*) pEntryPoints)->settings; + return (void*)((DVCMAN_ENTRY_POINTS*)pEntryPoints)->settings; } static UINT32 dvcman_get_channel_id(IWTSVirtualChannel* channel) { - return ((DVCMAN_CHANNEL*) channel)->channel_id; + DVCMAN_CHANNEL* dvc = (DVCMAN_CHANNEL*)channel; + return dvc->channel_id; +} + +static const char* dvcman_get_channel_name(IWTSVirtualChannel* channel) +{ + DVCMAN_CHANNEL* dvc = (DVCMAN_CHANNEL*)channel; + return dvc->channel_name; } -static IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager* - pChannelMgr, - UINT32 ChannelId) +static IWTSVirtualChannel* dvcman_find_channel_by_id(IWTSVirtualChannelManager* pChannelMgr, + UINT32 ChannelId) { int index; - BOOL found = FALSE; - DVCMAN_CHANNEL* channel; - DVCMAN* dvcman = (DVCMAN*) pChannelMgr; + IWTSVirtualChannel* channel = NULL; + DVCMAN* dvcman = (DVCMAN*)pChannelMgr; ArrayList_Lock(dvcman->channels); - index = 0; - channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, index++); - - while (channel) + for (index = 0; index < ArrayList_Count(dvcman->channels); index++) { - if (channel->channel_id == ChannelId) + DVCMAN_CHANNEL* cur = (DVCMAN_CHANNEL*)ArrayList_GetItem(dvcman->channels, index); + if (cur->channel_id == ChannelId) { - found = TRUE; + channel = &cur->iface; break; } - - channel = (DVCMAN_CHANNEL*) ArrayList_GetItem(dvcman->channels, index++); } ArrayList_Unlock(dvcman->channels); - return (found) ? ((IWTSVirtualChannel*) channel) : NULL; + return channel; +} + +static void dvcman_plugin_terminate(void* plugin) +{ + IWTSPlugin* pPlugin = plugin; + + UINT error = IFCALLRESULT(CHANNEL_RC_OK, pPlugin->Terminated, pPlugin); + if (error != CHANNEL_RC_OK) + WLog_ERR(TAG, "Terminated failed with error %" PRIu32 "!", error); } +static void wts_listener_free(void* arg) +{ + DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)arg; + dvcman_wtslistener_free(listener); +} static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin) { + wObject* obj; DVCMAN* dvcman; - dvcman = (DVCMAN*) calloc(1, sizeof(DVCMAN)); + dvcman = (DVCMAN*)calloc(1, sizeof(DVCMAN)); if (!dvcman) - { - WLog_Print(plugin->log, WLOG_ERROR, "calloc failed!"); return NULL; - } dvcman->iface.CreateListener = dvcman_create_listener; + dvcman->iface.DestroyListener = dvcman_destroy_listener; dvcman->iface.FindChannelById = dvcman_find_channel_by_id; dvcman->iface.GetChannelId = dvcman_get_channel_id; + dvcman->iface.GetChannelName = dvcman_get_channel_name; dvcman->drdynvc = plugin; dvcman->channels = ArrayList_New(TRUE); if (!dvcman->channels) - { - WLog_Print(plugin->log, WLOG_ERROR, "ArrayList_New failed!"); - free(dvcman); - return NULL; - } + goto fail; - dvcman->channels->object.fnObjectFree = dvcman_channel_free; - dvcman->pool = StreamPool_New(TRUE, 10); + obj = ArrayList_Object(dvcman->channels); + obj->fnObjectFree = dvcman_channel_free; + dvcman->pool = StreamPool_New(TRUE, 10); if (!dvcman->pool) - { - WLog_Print(plugin->log, WLOG_ERROR, "StreamPool_New failed!"); - ArrayList_Free(dvcman->channels); - free(dvcman); - return NULL; - } - - return (IWTSVirtualChannelManager*) dvcman; + goto fail; + + dvcman->listeners = ArrayList_New(TRUE); + if (!dvcman->listeners) + goto fail; + obj = ArrayList_Object(dvcman->listeners); + obj->fnObjectFree = wts_listener_free; + + dvcman->plugin_names = ArrayList_New(TRUE); + if (!dvcman->plugin_names) + goto fail; + obj = ArrayList_Object(dvcman->plugin_names); + obj->fnObjectFree = free; + + dvcman->plugins = ArrayList_New(TRUE); + if (!dvcman->plugins) + goto fail; + obj = ArrayList_Object(dvcman->plugins); + obj->fnObjectFree = dvcman_plugin_terminate; + return &dvcman->iface; +fail: + dvcman_free(plugin, &dvcman->iface); + return NULL; } /** @@ -225,17 +278,14 @@ static IWTSVirtualChannelManager* dvcman_new(drdynvcPlugin* plugin) * * @return 0 on success, otherwise a Win32 error code */ -static UINT dvcman_load_addin(drdynvcPlugin* drdynvc, - IWTSVirtualChannelManager* pChannelMgr, - ADDIN_ARGV* args, - rdpSettings* settings) +static UINT dvcman_load_addin(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr, + ADDIN_ARGV* args, rdpSettings* settings) { DVCMAN_ENTRY_POINTS entryPoints; PDVC_PLUGIN_ENTRY pDVCPluginEntry = NULL; WLog_Print(drdynvc->log, WLOG_INFO, "Loading Dynamic Virtual Channel %s", args->argv[0]); - pDVCPluginEntry = (PDVC_PLUGIN_ENTRY) freerdp_load_channel_addin_entry( - args->argv[0], - NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC); + pDVCPluginEntry = (PDVC_PLUGIN_ENTRY)freerdp_load_channel_addin_entry( + args->argv[0], NULL, NULL, FREERDP_ADDIN_CHANNEL_DYNAMIC); if (pDVCPluginEntry) { @@ -243,75 +293,66 @@ static UINT dvcman_load_addin(drdynvcPlugin* drdynvc, entryPoints.iface.GetPlugin = dvcman_get_plugin; entryPoints.iface.GetPluginData = dvcman_get_plugin_data; entryPoints.iface.GetRdpSettings = dvcman_get_rdp_settings; - entryPoints.dvcman = (DVCMAN*) pChannelMgr; + entryPoints.dvcman = (DVCMAN*)pChannelMgr; entryPoints.args = args; entryPoints.settings = settings; - return pDVCPluginEntry((IDRDYNVC_ENTRY_POINTS*) &entryPoints); + return pDVCPluginEntry(&entryPoints.iface); } return ERROR_INVALID_FUNCTION; } static DVCMAN_CHANNEL* dvcman_channel_new(drdynvcPlugin* drdynvc, - IWTSVirtualChannelManager* pChannelMgr, - UINT32 ChannelId, const char* ChannelName) + IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, + const char* ChannelName) { DVCMAN_CHANNEL* channel; if (dvcman_find_channel_by_id(pChannelMgr, ChannelId)) { - WLog_Print(drdynvc->log, WLOG_ERROR, "Protocol error: Duplicated ChannelId %"PRIu32" (%s)!", - ChannelId, + WLog_Print(drdynvc->log, WLOG_ERROR, + "Protocol error: Duplicated ChannelId %" PRIu32 " (%s)!", ChannelId, ChannelName); return NULL; } - channel = (DVCMAN_CHANNEL*) calloc(1, sizeof(DVCMAN_CHANNEL)); + channel = (DVCMAN_CHANNEL*)calloc(1, sizeof(DVCMAN_CHANNEL)); if (!channel) - { - WLog_Print(drdynvc->log, WLOG_ERROR, "calloc failed!"); - return NULL; - } + goto fail; - channel->dvcman = (DVCMAN*) pChannelMgr; + channel->dvcman = (DVCMAN*)pChannelMgr; channel->channel_id = ChannelId; channel->channel_name = _strdup(ChannelName); if (!channel->channel_name) - { - WLog_Print(drdynvc->log, WLOG_ERROR, "_strdup failed!"); - free(channel); - return NULL; - } + goto fail; if (!InitializeCriticalSectionEx(&(channel->lock), 0, 0)) - { - WLog_Print(drdynvc->log, WLOG_ERROR, "InitializeCriticalSectionEx failed!"); - free(channel->channel_name); - free(channel); - return NULL; - } + goto fail; return channel; +fail: + dvcman_channel_free(channel); + return NULL; } static void dvcman_channel_free(void* arg) { - DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) arg; + DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*)arg; UINT error = CHANNEL_RC_OK; if (channel) { if (channel->channel_callback) { - IFCALL(channel->channel_callback->OnClose, - channel->channel_callback); + IFCALL(channel->channel_callback->OnClose, channel->channel_callback); + channel->channel_callback = NULL; } if (channel->status == CHANNEL_RC_OK) { - IWTSVirtualChannel* ichannel = (IWTSVirtualChannel*) channel; + IWTSVirtualChannel* ichannel = (IWTSVirtualChannel*)channel; if (channel->dvcman && channel->dvcman->drdynvc) { @@ -319,8 +360,7 @@ static void dvcman_channel_free(void* arg) if (context) { - IFCALLRET(context->OnChannelDisconnected, error, - context, channel->channel_name, + IFCALLRET(context->OnChannelDisconnected, error, context, channel->channel_name, channel->pInterface); } } @@ -328,7 +368,7 @@ static void dvcman_channel_free(void* arg) error = IFCALLRESULT(CHANNEL_RC_OK, ichannel->Close, ichannel); if (error != CHANNEL_RC_OK) - WLog_ERR(TAG, "Close failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "Close failed with error %" PRIu32 "!", error); } if (channel->dvc_data) @@ -341,34 +381,29 @@ static void dvcman_channel_free(void* arg) free(channel); } -static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr) +static void dvcman_clear(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr) { - int i; - IWTSPlugin* pPlugin; - DVCMAN_LISTENER* listener; - DVCMAN* dvcman = (DVCMAN*) pChannelMgr; - UINT error; - ArrayList_Free(dvcman->channels); + DVCMAN* dvcman = (DVCMAN*)pChannelMgr; - for (i = 0; i < dvcman->num_listeners; i++) - { - listener = (DVCMAN_LISTENER*) dvcman->listeners[i]; - free(listener->channel_name); - free(listener); - } + WINPR_UNUSED(drdynvc); + + ArrayList_Clear(dvcman->plugins); + ArrayList_Clear(dvcman->channels); + ArrayList_Clear(dvcman->plugin_names); + ArrayList_Clear(dvcman->listeners); +} - dvcman->num_listeners = 0; +static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr) +{ + DVCMAN* dvcman = (DVCMAN*)pChannelMgr; - for (i = 0; i < dvcman->num_plugins; i++) - { - pPlugin = dvcman->plugins[i]; + WINPR_UNUSED(drdynvc); - if (pPlugin->Terminated) - if ((error = pPlugin->Terminated(pPlugin))) - WLog_Print(drdynvc->log, WLOG_ERROR, "Terminated failed with error %"PRIu32"!", error); - } + ArrayList_Free(dvcman->plugins); + ArrayList_Free(dvcman->channels); + ArrayList_Free(dvcman->plugin_names); + ArrayList_Free(dvcman->listeners); - dvcman->num_plugins = 0; StreamPool_Free(dvcman->pool); free(dvcman); } @@ -380,24 +415,27 @@ static void dvcman_free(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChan */ static UINT dvcman_init(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr) { - int i; - IWTSPlugin* pPlugin; - DVCMAN* dvcman = (DVCMAN*) pChannelMgr; - UINT error; + size_t i; + DVCMAN* dvcman = (DVCMAN*)pChannelMgr; + UINT error = CHANNEL_RC_OK; - for (i = 0; i < dvcman->num_plugins; i++) + ArrayList_Lock(dvcman->plugins); + for (i = 0; i < ArrayList_Count(dvcman->plugins); i++) { - pPlugin = dvcman->plugins[i]; + IWTSPlugin* pPlugin = ArrayList_GetItem(dvcman->plugins, i); - if (pPlugin->Initialize) - if ((error = pPlugin->Initialize(pPlugin, pChannelMgr))) - { - WLog_Print(drdynvc->log, WLOG_ERROR, "Initialize failed with error %"PRIu32"!", error); - return error; - } + error = IFCALLRESULT(CHANNEL_RC_OK, pPlugin->Initialize, pPlugin, pChannelMgr); + if (error != CHANNEL_RC_OK) + { + WLog_Print(drdynvc->log, WLOG_ERROR, "Initialize failed with error %" PRIu32 "!", + error); + goto fail; + } } - return CHANNEL_RC_OK; +fail: + ArrayList_Unlock(dvcman->plugins); + return error; } /** @@ -405,18 +443,18 @@ static UINT dvcman_init(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChan * * @return 0 on success, otherwise a Win32 error code */ -static UINT dvcman_write_channel(IWTSVirtualChannel* pChannel, ULONG cbSize, - const BYTE* pBuffer, void* pReserved) +static UINT dvcman_write_channel(IWTSVirtualChannel* pChannel, ULONG cbSize, const BYTE* pBuffer, + void* pReserved) { UINT status; - DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel; + DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*)pChannel; + WINPR_UNUSED(pReserved); if (!channel || !channel->dvcman) return CHANNEL_RC_BAD_CHANNEL; EnterCriticalSection(&(channel->lock)); - status = drdynvc_write_data(channel->dvcman->drdynvc, - channel->channel_id, pBuffer, cbSize); + status = drdynvc_write_data(channel->dvcman->drdynvc, channel->channel_id, pBuffer, cbSize); LeaveCriticalSection(&(channel->lock)); return status; } @@ -428,12 +466,12 @@ static UINT dvcman_write_channel(IWTSVirtualChannel* pChannel, ULONG cbSize, */ static UINT dvcman_close_channel_iface(IWTSVirtualChannel* pChannel) { - DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*) pChannel; + DVCMAN_CHANNEL* channel = (DVCMAN_CHANNEL*)pChannel; if (!channel) return CHANNEL_RC_BAD_CHANNEL; - WLog_DBG(TAG, "close_channel_iface: id=%"PRIu32"", channel->channel_id); + WLog_DBG(TAG, "close_channel_iface: id=%" PRIu32 "", channel->channel_id); return CHANNEL_RC_OK; } @@ -442,17 +480,14 @@ static UINT dvcman_close_channel_iface(IWTSVirtualChannel* pChannel) * * @return 0 on success, otherwise a Win32 error code */ -static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, - IWTSVirtualChannelManager* pChannelMgr, +static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, const char* ChannelName) { - int i; + size_t i; BOOL bAccept; - DVCMAN_LISTENER* listener; DVCMAN_CHANNEL* channel; DrdynvcClientContext* context; - IWTSVirtualChannelCallback* pCallback; - DVCMAN* dvcman = (DVCMAN*) pChannelMgr; + DVCMAN* dvcman = (DVCMAN*)pChannelMgr; UINT error; if (!(channel = dvcman_channel_new(drdynvc, pChannelMgr, ChannelId, ChannelName))) @@ -462,25 +497,27 @@ static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, } channel->status = ERROR_NOT_CONNECTED; - ArrayList_Add(dvcman->channels, channel); + if (ArrayList_Add(dvcman->channels, channel) < 0) + return ERROR_INTERNAL_ERROR; - for (i = 0; i < dvcman->num_listeners; i++) + ArrayList_Lock(dvcman->listeners); + for (i = 0; i < ArrayList_Count(dvcman->listeners); i++) { - listener = (DVCMAN_LISTENER*) dvcman->listeners[i]; + DVCMAN_LISTENER* listener = (DVCMAN_LISTENER*)ArrayList_GetItem(dvcman->listeners, i); if (strcmp(listener->channel_name, ChannelName) == 0) { + IWTSVirtualChannelCallback* pCallback = NULL; channel->iface.Write = dvcman_write_channel; channel->iface.Close = dvcman_close_channel_iface; bAccept = TRUE; - pCallback = NULL; if ((error = listener->listener_callback->OnNewChannelConnection( - listener->listener_callback, - (IWTSVirtualChannel*) channel, NULL, &bAccept, &pCallback)) == CHANNEL_RC_OK - && bAccept) + listener->listener_callback, &channel->iface, NULL, &bAccept, &pCallback)) == + CHANNEL_RC_OK && + bAccept) { - WLog_Print(drdynvc->log, WLOG_DEBUG, "listener %s created new channel %"PRIu32"", + WLog_Print(drdynvc->log, WLOG_DEBUG, "listener %s created new channel %" PRIu32 "", listener->channel_name, channel->channel_id); channel->status = CHANNEL_RC_OK; channel->channel_callback = pCallback; @@ -490,28 +527,34 @@ static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, listener->iface.pInterface); if (error) - WLog_Print(drdynvc->log, WLOG_ERROR, "context.OnChannelConnected failed with error %"PRIu32"", - error); + WLog_Print(drdynvc->log, WLOG_ERROR, + "context.OnChannelConnected failed with error %" PRIu32 "", error); - return error; + goto fail; } else { if (error) { - WLog_Print(drdynvc->log, WLOG_ERROR, "OnNewChannelConnection failed with error %"PRIu32"!", error); - return error; + WLog_Print(drdynvc->log, WLOG_ERROR, + "OnNewChannelConnection failed with error %" PRIu32 "!", error); + goto fail; } else { - WLog_Print(drdynvc->log, WLOG_ERROR, "OnNewChannelConnection returned with bAccept FALSE!"); - return ERROR_INTERNAL_ERROR; + WLog_Print(drdynvc->log, WLOG_ERROR, + "OnNewChannelConnection returned with bAccept FALSE!"); + error = ERROR_INTERNAL_ERROR; + goto fail; } } } } + error = ERROR_INTERNAL_ERROR; +fail: + ArrayList_Unlock(dvcman->listeners); - return ERROR_INTERNAL_ERROR; + return error; } /** @@ -519,18 +562,17 @@ static UINT dvcman_create_channel(drdynvcPlugin* drdynvc, * * @return 0 on success, otherwise a Win32 error code */ -static UINT dvcman_open_channel(drdynvcPlugin* drdynvc, - IWTSVirtualChannelManager* pChannelMgr, +static UINT dvcman_open_channel(drdynvcPlugin* drdynvc, IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId) { DVCMAN_CHANNEL* channel; IWTSVirtualChannelCallback* pCallback; UINT error; - channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); + channel = (DVCMAN_CHANNEL*)dvcman_find_channel_by_id(pChannelMgr, ChannelId); if (!channel) { - WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %"PRIu32" not found!", ChannelId); + WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %" PRIu32 " not found!", ChannelId); return ERROR_INTERNAL_ERROR; } @@ -540,11 +582,11 @@ static UINT dvcman_open_channel(drdynvcPlugin* drdynvc, if ((pCallback->OnOpen) && (error = pCallback->OnOpen(pCallback))) { - WLog_Print(drdynvc->log, WLOG_ERROR, "OnOpen failed with error %"PRIu32"!", error); + WLog_Print(drdynvc->log, WLOG_ERROR, "OnOpen failed with error %" PRIu32 "!", error); return error; } - WLog_Print(drdynvc->log, WLOG_DEBUG, "open_channel: ChannelId %"PRIu32"", ChannelId); + WLog_Print(drdynvc->log, WLOG_DEBUG, "open_channel: ChannelId %" PRIu32 "", ChannelId); } return CHANNEL_RC_OK; @@ -555,24 +597,41 @@ static UINT dvcman_open_channel(drdynvcPlugin* drdynvc, * * @return 0 on success, otherwise a Win32 error code */ -static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, - UINT32 ChannelId) +static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, + BOOL bSendClosePDU) { DVCMAN_CHANNEL* channel; UINT error = CHANNEL_RC_OK; - DVCMAN* dvcman = (DVCMAN*) pChannelMgr; - channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); + DVCMAN* dvcman = (DVCMAN*)pChannelMgr; + drdynvcPlugin* drdynvc = dvcman->drdynvc; + channel = (DVCMAN_CHANNEL*)dvcman_find_channel_by_id(pChannelMgr, ChannelId); if (!channel) { - //WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %"PRIu32" not found!", ChannelId); + // WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %"PRIu32" not found!", ChannelId); /** - * Windows 8 / Windows Server 2012 send close requests for channels that failed to be created. - * Do not warn, simply return success here. + * Windows 8 / Windows Server 2012 send close requests for channels that failed to be + * created. Do not warn, simply return success here. */ return CHANNEL_RC_OK; } + if (drdynvc && bSendClosePDU) + { + wStream* s = StreamPool_Take(dvcman->pool, 5); + if (!s) + { + WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!"); + error = CHANNEL_RC_NO_MEMORY; + } + else + { + Stream_Write_UINT8(s, (CLOSE_REQUEST_PDU << 4) | 0x02); + Stream_Write_UINT32(s, ChannelId); + error = drdynvc_send(drdynvc, s); + } + } + ArrayList_Remove(dvcman->channels, channel); return error; } @@ -583,19 +642,20 @@ static UINT dvcman_close_channel(IWTSVirtualChannelManager* pChannelMgr, * @return 0 on success, otherwise a Win32 error code */ static UINT dvcman_receive_channel_data_first(drdynvcPlugin* drdynvc, - IWTSVirtualChannelManager* pChannelMgr, - UINT32 ChannelId, UINT32 length) + IWTSVirtualChannelManager* pChannelMgr, + UINT32 ChannelId, UINT32 length) { DVCMAN_CHANNEL* channel; - channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); + channel = (DVCMAN_CHANNEL*)dvcman_find_channel_by_id(pChannelMgr, ChannelId); if (!channel) { /** - * Windows Server 2012 R2 can send some messages over Microsoft::Windows::RDS::Geometry::v08.01 - * even if the dynamic virtual channel wasn't registered on our side. Ignoring it works. + * Windows Server 2012 R2 can send some messages over + * Microsoft::Windows::RDS::Geometry::v08.01 even if the dynamic virtual channel wasn't + * registered on our side. Ignoring it works. */ - WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %"PRIu32" not found!", ChannelId); + WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %" PRIu32 " not found!", ChannelId); return CHANNEL_RC_OK; } @@ -620,26 +680,26 @@ static UINT dvcman_receive_channel_data_first(drdynvcPlugin* drdynvc, * @return 0 on success, otherwise a Win32 error code */ static UINT dvcman_receive_channel_data(drdynvcPlugin* drdynvc, - IWTSVirtualChannelManager* pChannelMgr, - UINT32 ChannelId, wStream* data) + IWTSVirtualChannelManager* pChannelMgr, UINT32 ChannelId, + wStream* data) { UINT status = CHANNEL_RC_OK; DVCMAN_CHANNEL* channel; size_t dataSize = Stream_GetRemainingLength(data); - channel = (DVCMAN_CHANNEL*) dvcman_find_channel_by_id(pChannelMgr, ChannelId); + channel = (DVCMAN_CHANNEL*)dvcman_find_channel_by_id(pChannelMgr, ChannelId); if (!channel) { /* Windows 8.1 tries to open channels not created. - * Ignore cases like this. */ - WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %"PRIu32" not found!", ChannelId); + * Ignore cases like this. */ + WLog_Print(drdynvc->log, WLOG_ERROR, "ChannelId %" PRIu32 " not found!", ChannelId); return CHANNEL_RC_OK; } if (channel->dvc_data) { /* Fragmented data */ - if (Stream_GetPosition(channel->dvc_data) + dataSize > Stream_Capacity(channel->dvc_data)) + if (Stream_GetPosition(channel->dvc_data) + dataSize > channel->dvc_data_length) { WLog_Print(drdynvc->log, WLOG_ERROR, "data exceeding declared length!"); Stream_Release(channel->dvc_data); @@ -654,33 +714,32 @@ static UINT dvcman_receive_channel_data(drdynvcPlugin* drdynvc, Stream_SealLength(channel->dvc_data); Stream_SetPosition(channel->dvc_data, 0); status = channel->channel_callback->OnDataReceived(channel->channel_callback, - channel->dvc_data); + channel->dvc_data); Stream_Release(channel->dvc_data); channel->dvc_data = NULL; } } else { - status = channel->channel_callback->OnDataReceived(channel->channel_callback, - data); + status = channel->channel_callback->OnDataReceived(channel->channel_callback, data); } return status; } -static UINT drdynvc_write_variable_uint(wStream* s, UINT32 val) +static UINT8 drdynvc_write_variable_uint(wStream* s, UINT32 val) { - UINT cb; + UINT8 cb; if (val <= 0xFF) { cb = 0; - Stream_Write_UINT8(s, val); + Stream_Write_UINT8(s, (UINT8)val); } else if (val <= 0xFFFF) { cb = 1; - Stream_Write_UINT16(s, val); + Stream_Write_UINT16(s, (UINT16)val); } else { @@ -704,8 +763,9 @@ static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s) status = CHANNEL_RC_BAD_CHANNEL_HANDLE; else { - status = drdynvc->channelEntryPoints.pVirtualChannelWriteEx(drdynvc->InitHandle, - drdynvc->OpenHandle, Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s); + status = drdynvc->channelEntryPoints.pVirtualChannelWriteEx( + drdynvc->InitHandle, drdynvc->OpenHandle, Stream_Buffer(s), + (UINT32)Stream_GetPosition(s), s); } switch (status) @@ -714,19 +774,19 @@ static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s) return CHANNEL_RC_OK; case CHANNEL_RC_NOT_CONNECTED: - Stream_Free(s, TRUE); + Stream_Release(s); return CHANNEL_RC_OK; case CHANNEL_RC_BAD_CHANNEL_HANDLE: - Stream_Free(s, TRUE); + Stream_Release(s); WLog_ERR(TAG, "VirtualChannelWriteEx failed with CHANNEL_RC_BAD_CHANNEL_HANDLE"); return status; default: - Stream_Free(s, TRUE); - WLog_Print(drdynvc->log, WLOG_ERROR, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]", - WTSErrorToString(status), - status); + Stream_Release(s); + WLog_Print(drdynvc->log, WLOG_ERROR, + "VirtualChannelWriteEx failed with %s [%08" PRIX32 "]", + WTSErrorToString(status), status); return status; } } @@ -736,26 +796,29 @@ static UINT drdynvc_send(drdynvcPlugin* drdynvc, wStream* s) * * @return 0 on success, otherwise a Win32 error code */ -static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, - const BYTE* data, UINT32 dataSize) +static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, const BYTE* data, + UINT32 dataSize) { wStream* data_out; size_t pos; - UINT32 cbChId; - UINT32 cbLen; + UINT8 cbChId; + UINT8 cbLen; unsigned long chunkLength; - UINT status; + UINT status = CHANNEL_RC_BAD_INIT_HANDLE; + DVCMAN* dvcman; if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; - WLog_Print(drdynvc->log, WLOG_DEBUG, "write_data: ChannelId=%"PRIu32" size=%"PRIu32"", ChannelId, - dataSize); - data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH); + dvcman = (DVCMAN*)drdynvc->channel_mgr; + + WLog_Print(drdynvc->log, WLOG_DEBUG, "write_data: ChannelId=%" PRIu32 " size=%" PRIu32 "", + ChannelId, dataSize); + data_out = StreamPool_Take(dvcman->pool, CHANNEL_CHUNK_LENGTH); if (!data_out) { - WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -765,15 +828,13 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, if (dataSize == 0) { - Stream_SetPosition(data_out, 0); - Stream_Write_UINT8(data_out, 0x40 | cbChId); - Stream_SetPosition(data_out, pos); - status = drdynvc_send(drdynvc, data_out); + dvcman_close_channel(drdynvc->channel_mgr, ChannelId, TRUE); + Stream_Release(data_out); } else if (dataSize <= CHANNEL_CHUNK_LENGTH - pos) { Stream_SetPosition(data_out, 0); - Stream_Write_UINT8(data_out, 0x30 | cbChId); + Stream_Write_UINT8(data_out, (DATA_PDU << 4) | cbChId); Stream_SetPosition(data_out, pos); Stream_Write(data_out, data, dataSize); status = drdynvc_send(drdynvc, data_out); @@ -784,7 +845,7 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, cbLen = drdynvc_write_variable_uint(data_out, dataSize); pos = Stream_GetPosition(data_out); Stream_SetPosition(data_out, 0); - Stream_Write_UINT8(data_out, 0x20 | cbChId | (cbLen << 2)); + Stream_Write_UINT8(data_out, (DATA_FIRST_PDU << 4) | cbChId | (cbLen << 2)); Stream_SetPosition(data_out, pos); chunkLength = CHANNEL_CHUNK_LENGTH - pos; Stream_Write(data_out, data, chunkLength); @@ -794,11 +855,11 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, while (status == CHANNEL_RC_OK && dataSize > 0) { - data_out = Stream_New(NULL, CHANNEL_CHUNK_LENGTH); + data_out = StreamPool_Take(dvcman->pool, CHANNEL_CHUNK_LENGTH); if (!data_out) { - WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!"); return CHANNEL_RC_NO_MEMORY; } @@ -806,7 +867,7 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, cbChId = drdynvc_write_variable_uint(data_out, ChannelId); pos = Stream_GetPosition(data_out); Stream_SetPosition(data_out, 0); - Stream_Write_UINT8(data_out, 0x30 | cbChId); + Stream_Write_UINT8(data_out, (DATA_PDU << 4) | cbChId); Stream_SetPosition(data_out, pos); chunkLength = dataSize; @@ -822,7 +883,7 @@ static UINT drdynvc_write_data(drdynvcPlugin* drdynvc, UINT32 ChannelId, if (status != CHANNEL_RC_OK) { - WLog_Print(drdynvc->log, WLOG_ERROR, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]", + WLog_Print(drdynvc->log, WLOG_ERROR, "VirtualChannelWriteEx failed with %s [%08" PRIX32 "]", WTSErrorToString(status), status); return status; } @@ -839,12 +900,14 @@ static UINT drdynvc_send_capability_response(drdynvcPlugin* drdynvc) { UINT status; wStream* s; + DVCMAN* dvcman; if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; + dvcman = (DVCMAN*)drdynvc->channel_mgr; WLog_Print(drdynvc->log, WLOG_TRACE, "capability_response"); - s = Stream_New(NULL, 4); + s = StreamPool_Take(dvcman->pool, 4); if (!s) { @@ -852,14 +915,13 @@ static UINT drdynvc_send_capability_response(drdynvcPlugin* drdynvc) return CHANNEL_RC_NO_MEMORY; } - Stream_Write_UINT16(s, - 0x0050); /* Cmd+Sp+cbChId+Pad. Note: MSTSC sends 0x005c */ + Stream_Write_UINT16(s, 0x0050); /* Cmd+Sp+cbChId+Pad. Note: MSTSC sends 0x005c */ Stream_Write_UINT16(s, drdynvc->version); status = drdynvc_send(drdynvc, s); if (status != CHANNEL_RC_OK) { - WLog_Print(drdynvc->log, WLOG_ERROR, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]", + WLog_Print(drdynvc->log, WLOG_ERROR, "VirtualChannelWriteEx failed with %s [%08" PRIX32 "]", WTSErrorToString(status), status); } @@ -871,8 +933,8 @@ static UINT drdynvc_send_capability_response(drdynvcPlugin* drdynvc) * * @return 0 on success, otherwise a Win32 error code */ -static UINT drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, - int cbChId, wStream* s) +static UINT drdynvc_process_capability_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, + wStream* s) { UINT status; @@ -947,8 +1009,7 @@ static UINT32 drdynvc_read_variable_uint(wStream* s, int cbLen) * * @return 0 on success, otherwise a Win32 error code */ -static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, - int cbChId, wStream* s) +static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { size_t pos; UINT status; @@ -957,10 +1018,13 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, UINT channel_status; char* name; size_t length; + DVCMAN* dvcman; + WINPR_UNUSED(Sp); if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; + dvcman = (DVCMAN*)drdynvc->channel_mgr; if (drdynvc->state == DRDYNVC_STATE_CAPABILITIES) { /** @@ -990,18 +1054,18 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, if (strnlen(name, length) >= length) return ERROR_INVALID_DATA; - WLog_Print(drdynvc->log, WLOG_DEBUG, "process_create_request: ChannelId=%"PRIu32" ChannelName=%s", - ChannelId, name); + WLog_Print(drdynvc->log, WLOG_DEBUG, + "process_create_request: ChannelId=%" PRIu32 " ChannelName=%s", ChannelId, name); channel_status = dvcman_create_channel(drdynvc, drdynvc->channel_mgr, ChannelId, name); - data_out = Stream_New(NULL, pos + 4); + data_out = StreamPool_Take(dvcman->pool, pos + 4); if (!data_out) { - WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!"); return CHANNEL_RC_NO_MEMORY; } - Stream_Write_UINT8(data_out, 0x10 | cbChId); + Stream_Write_UINT8(data_out, (CREATE_REQUEST_PDU << 4) | cbChId); Stream_SetPosition(s, 1); Stream_Copy(s, data_out, pos - 1); @@ -1020,7 +1084,7 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, if (status != CHANNEL_RC_OK) { - WLog_Print(drdynvc->log, WLOG_ERROR, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]", + WLog_Print(drdynvc->log, WLOG_ERROR, "VirtualChannelWriteEx failed with %s [%08" PRIX32 "]", WTSErrorToString(status), status); return status; } @@ -1029,14 +1093,16 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, { if ((status = dvcman_open_channel(drdynvc, drdynvc->channel_mgr, ChannelId))) { - WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_open_channel failed with error %"PRIu32"!", status); + WLog_Print(drdynvc->log, WLOG_ERROR, + "dvcman_open_channel failed with error %" PRIu32 "!", status); return status; } } else { - if ((status = dvcman_close_channel(drdynvc->channel_mgr, ChannelId))) - WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_close_channel failed with error %"PRIu32"!", status); + if ((status = dvcman_close_channel(drdynvc->channel_mgr, ChannelId, FALSE))) + WLog_Print(drdynvc->log, WLOG_ERROR, + "dvcman_close_channel failed with error %" PRIu32 "!", status); } return status; @@ -1047,8 +1113,7 @@ static UINT drdynvc_process_create_request(drdynvcPlugin* drdynvc, int Sp, * * @return 0 on success, otherwise a Win32 error code */ -static UINT drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp, - int cbChId, wStream* s) +static UINT drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { UINT status; UINT32 Length; @@ -1060,15 +1125,17 @@ static UINT drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp, ChannelId = drdynvc_read_variable_uint(s, cbChId); Length = drdynvc_read_variable_uint(s, Sp); WLog_Print(drdynvc->log, WLOG_DEBUG, - "process_data_first: Sp=%d cbChId=%d, ChannelId=%"PRIu32" Length=%"PRIu32"", Sp, + "process_data_first: Sp=%d cbChId=%d, ChannelId=%" PRIu32 " Length=%" PRIu32 "", Sp, cbChId, ChannelId, Length); - status = dvcman_receive_channel_data_first(drdynvc, drdynvc->channel_mgr, ChannelId, - Length); + status = dvcman_receive_channel_data_first(drdynvc, drdynvc->channel_mgr, ChannelId, Length); - if (status) - return status; + if (status == CHANNEL_RC_OK) + status = dvcman_receive_channel_data(drdynvc, drdynvc->channel_mgr, ChannelId, s); - return dvcman_receive_channel_data(drdynvc, drdynvc->channel_mgr, ChannelId, s); + if (status != CHANNEL_RC_OK) + status = dvcman_close_channel(drdynvc->channel_mgr, ChannelId, TRUE); + + return status; } /** @@ -1076,19 +1143,23 @@ static UINT drdynvc_process_data_first(drdynvcPlugin* drdynvc, int Sp, * * @return 0 on success, otherwise a Win32 error code */ -static UINT drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, - wStream* s) +static UINT drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { UINT32 ChannelId; + UINT status; if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId)) return ERROR_INVALID_DATA; ChannelId = drdynvc_read_variable_uint(s, cbChId); - WLog_Print(drdynvc->log, WLOG_TRACE, "process_data: Sp=%d cbChId=%d, ChannelId=%"PRIu32"", Sp, - cbChId, - ChannelId); - return dvcman_receive_channel_data(drdynvc, drdynvc->channel_mgr, ChannelId, s); + WLog_Print(drdynvc->log, WLOG_TRACE, "process_data: Sp=%d cbChId=%d, ChannelId=%" PRIu32 "", Sp, + cbChId, ChannelId); + status = dvcman_receive_channel_data(drdynvc, drdynvc->channel_mgr, ChannelId, s); + + if (status != CHANNEL_RC_OK) + status = dvcman_close_channel(drdynvc->channel_mgr, ChannelId, TRUE); + + return status; } /** @@ -1096,44 +1167,22 @@ static UINT drdynvc_process_data(drdynvcPlugin* drdynvc, int Sp, int cbChId, * * @return 0 on success, otherwise a Win32 error code */ -static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, - int cbChId, wStream* s) +static UINT drdynvc_process_close_request(drdynvcPlugin* drdynvc, int Sp, int cbChId, wStream* s) { - int value; UINT error; UINT32 ChannelId; - wStream* data_out; if (Stream_GetRemainingLength(s) < drdynvc_cblen_to_bytes(cbChId)) return ERROR_INVALID_DATA; ChannelId = drdynvc_read_variable_uint(s, cbChId); - WLog_Print(drdynvc->log, WLOG_DEBUG, "process_close_request: Sp=%d cbChId=%d, ChannelId=%"PRIu32"", - Sp, - cbChId, ChannelId); - - if ((error = dvcman_close_channel(drdynvc->channel_mgr, ChannelId))) - { - WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_close_channel failed with error %"PRIu32"!", error); - return error; - } - - data_out = Stream_New(NULL, 4); - - if (!data_out) - { - WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - value = (CLOSE_REQUEST_PDU << 4) | (cbChId & 0x03); - Stream_Write_UINT8(data_out, value); - drdynvc_write_variable_uint(data_out, ChannelId); - error = drdynvc_send(drdynvc, data_out); + WLog_Print(drdynvc->log, WLOG_DEBUG, + "process_close_request: Sp=%d cbChId=%d, ChannelId=%" PRIu32 "", Sp, cbChId, + ChannelId); - if (error) - WLog_Print(drdynvc->log, WLOG_ERROR, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]", - WTSErrorToString(error), error); + if ((error = dvcman_close_channel(drdynvc->channel_mgr, ChannelId, TRUE))) + WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_close_channel failed with error %" PRIu32 "!", + error); return error; } @@ -1187,8 +1236,9 @@ static UINT drdynvc_order_recv(drdynvcPlugin* drdynvc, wStream* s) * * @return 0 on success, otherwise a Win32 error code */ -static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc, - void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) +static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc, void* pData, + UINT32 dataLength, UINT32 totalLength, + UINT32 dataFlags) { wStream* data_in; @@ -1199,22 +1249,23 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc, if (dataFlags & CHANNEL_FLAG_FIRST) { + DVCMAN* mgr = (DVCMAN*)drdynvc->channel_mgr; if (drdynvc->data_in) - Stream_Free(drdynvc->data_in, TRUE); + Stream_Release(drdynvc->data_in); - drdynvc->data_in = Stream_New(NULL, totalLength); + drdynvc->data_in = StreamPool_Take(mgr->pool, totalLength); } if (!(data_in = drdynvc->data_in)) { - WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_New failed!"); + WLog_Print(drdynvc->log, WLOG_ERROR, "StreamPool_Take failed!"); return CHANNEL_RC_NO_MEMORY; } if (!Stream_EnsureRemainingCapacity(data_in, dataLength)) { WLog_Print(drdynvc->log, WLOG_ERROR, "Stream_EnsureRemainingCapacity failed!"); - Stream_Free(drdynvc->data_in, TRUE); + Stream_Release(drdynvc->data_in); drdynvc->data_in = NULL; return ERROR_INTERNAL_ERROR; } @@ -1223,7 +1274,9 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc, if (dataFlags & CHANNEL_FLAG_LAST) { - if (Stream_Capacity(data_in) != Stream_GetPosition(data_in)) + const size_t cap = Stream_Capacity(data_in); + const size_t pos = Stream_GetPosition(data_in); + if (cap < pos) { WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_plugin_process_received: read error"); return ERROR_INVALID_DATA; @@ -1233,7 +1286,7 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc, Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); - if (!MessageQueue_Post(drdynvc->queue, NULL, 0, (void*) data_in, NULL)) + if (!MessageQueue_Post(drdynvc->queue, NULL, 0, (void*)data_in, NULL)) { WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_Post failed!"); return ERROR_INTERNAL_ERROR; @@ -1244,36 +1297,45 @@ static UINT drdynvc_virtual_channel_event_data_received(drdynvcPlugin* drdynvc, } static void VCAPITYPE drdynvc_virtual_channel_open_event_ex(LPVOID lpUserParam, DWORD openHandle, - UINT event, LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) + UINT event, LPVOID pData, + UINT32 dataLength, UINT32 totalLength, + UINT32 dataFlags) { UINT error = CHANNEL_RC_OK; - drdynvcPlugin* drdynvc = (drdynvcPlugin*) lpUserParam; - - if (!drdynvc || (drdynvc->OpenHandle != openHandle)) - { - WLog_ERR(TAG, "drdynvc_virtual_channel_open_event: error no match"); - return; - } + drdynvcPlugin* drdynvc = (drdynvcPlugin*)lpUserParam; switch (event) { case CHANNEL_EVENT_DATA_RECEIVED: - if ((error = drdynvc_virtual_channel_event_data_received(drdynvc, pData, dataLength, totalLength, - dataFlags))) + if (!drdynvc || (drdynvc->OpenHandle != openHandle)) + { + WLog_ERR(TAG, "drdynvc_virtual_channel_open_event: error no match"); + return; + } + if ((error = drdynvc_virtual_channel_event_data_received(drdynvc, pData, dataLength, + totalLength, dataFlags))) WLog_Print(drdynvc->log, WLOG_ERROR, - "drdynvc_virtual_channel_event_data_received failed with error %"PRIu32"", error); + "drdynvc_virtual_channel_event_data_received failed with error %" PRIu32 + "", + error); break; + case CHANNEL_EVENT_WRITE_CANCELLED: case CHANNEL_EVENT_WRITE_COMPLETE: - break; + { + wStream* s = (wStream*)pData; + Stream_Release(s); + } + break; case CHANNEL_EVENT_USER: break; } - if (error && drdynvc->rdpcontext) - setChannelError(drdynvc->rdpcontext, error, "drdynvc_virtual_channel_open_event reported an error"); + if (error && drdynvc && drdynvc->rdpcontext) + setChannelError(drdynvc->rdpcontext, error, + "drdynvc_virtual_channel_open_event reported an error"); } static DWORD WINAPI drdynvc_virtual_channel_client_thread(LPVOID arg) @@ -1281,11 +1343,11 @@ static DWORD WINAPI drdynvc_virtual_channel_client_thread(LPVOID arg) wStream* data; wMessage message; UINT error = CHANNEL_RC_OK; - drdynvcPlugin* drdynvc = (drdynvcPlugin*) arg; + drdynvcPlugin* drdynvc = (drdynvcPlugin*)arg; if (!drdynvc) { - ExitThread((DWORD) CHANNEL_RC_BAD_CHANNEL_HANDLE); + ExitThread((DWORD)CHANNEL_RC_BAD_CHANNEL_HANDLE); return CHANNEL_RC_BAD_CHANNEL_HANDLE; } @@ -1310,31 +1372,30 @@ static DWORD WINAPI drdynvc_virtual_channel_client_thread(LPVOID arg) if (message.id == 0) { - data = (wStream*) message.wParam; + data = (wStream*)message.wParam; if ((error = drdynvc_order_recv(drdynvc, data))) { - Stream_Free(data, TRUE); - WLog_Print(drdynvc->log, WLOG_ERROR, "drdynvc_order_recv failed with error %"PRIu32"!", error); - break; + WLog_Print(drdynvc->log, WLOG_WARN, + "drdynvc_order_recv failed with error %" PRIu32 "!", error); } - Stream_Free(data, TRUE); + Stream_Release(data); } } { /* Disconnect remaining dynamic channels that the server did not. - * This is required to properly shut down channels by calling the appropriate - * event handlers. */ + * This is required to properly shut down channels by calling the appropriate + * event handlers. */ DVCMAN* drdynvcMgr = (DVCMAN*)drdynvc->channel_mgr; while (ArrayList_Count(drdynvcMgr->channels) > 0) { - IWTSVirtualChannel* channel = (IWTSVirtualChannel*) - ArrayList_GetItem(drdynvcMgr->channels, 0); + IWTSVirtualChannel* channel = + (IWTSVirtualChannel*)ArrayList_GetItem(drdynvcMgr->channels, 0); const UINT32 ChannelId = drdynvc->channel_mgr->GetChannelId(channel); - dvcman_close_channel(drdynvc->channel_mgr, ChannelId); + dvcman_close_channel(drdynvc->channel_mgr, ChannelId, FALSE); } } @@ -1342,7 +1403,7 @@ static DWORD WINAPI drdynvc_virtual_channel_client_thread(LPVOID arg) setChannelError(drdynvc->rdpcontext, error, "drdynvc_virtual_channel_client_thread reported an error"); - ExitThread((DWORD) error); + ExitThread((DWORD)error); return error; } @@ -1357,35 +1418,18 @@ static void drdynvc_queue_object_free(void* obj) s = (wStream*)msg->wParam; if (s) - Stream_Free(s, TRUE); + Stream_Release(s); } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVOID pData, - UINT32 dataLength) +static UINT drdynvc_virtual_channel_event_initialized(drdynvcPlugin* drdynvc, LPVOID pData, + UINT32 dataLength) { - UINT error; - UINT32 status; - UINT32 index; - ADDIN_ARGV* args; - rdpSettings* settings; + UINT error = CHANNEL_RC_OK; + WINPR_UNUSED(pData); + WINPR_UNUSED(dataLength); if (!drdynvc) - return CHANNEL_RC_BAD_CHANNEL_HANDLE; - - status = drdynvc->channelEntryPoints.pVirtualChannelOpenEx(drdynvc->InitHandle, - &drdynvc->OpenHandle, drdynvc->channelDef.name, drdynvc_virtual_channel_open_event_ex); - - if (status != CHANNEL_RC_OK) - { - WLog_Print(drdynvc->log, WLOG_ERROR, "pVirtualChannelOpen failed with %s [%08"PRIX32"]", - WTSErrorToString(status), status); - return status; - } + goto error; drdynvc->queue = MessageQueue_New(NULL); @@ -1406,7 +1450,43 @@ static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO goto error; } - settings = (rdpSettings*) drdynvc->channelEntryPoints.pExtendedData; + return CHANNEL_RC_OK; +error: + return ERROR_INTERNAL_ERROR; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVOID pData, + UINT32 dataLength) +{ + UINT error; + UINT32 status; + UINT32 index; + ADDIN_ARGV* args; + rdpSettings* settings; + + WINPR_UNUSED(pData); + WINPR_UNUSED(dataLength); + + if (!drdynvc) + return CHANNEL_RC_BAD_CHANNEL_HANDLE; + + status = drdynvc->channelEntryPoints.pVirtualChannelOpenEx( + drdynvc->InitHandle, &drdynvc->OpenHandle, drdynvc->channelDef.name, + drdynvc_virtual_channel_open_event_ex); + + if (status != CHANNEL_RC_OK) + { + WLog_Print(drdynvc->log, WLOG_ERROR, "pVirtualChannelOpen failed with %s [%08" PRIX32 "]", + WTSErrorToString(status), status); + return status; + } + + settings = (rdpSettings*)drdynvc->channelEntryPoints.pExtendedData; for (index = 0; index < settings->DynamicChannelCount; index++) { @@ -1419,15 +1499,14 @@ static UINT drdynvc_virtual_channel_event_connected(drdynvcPlugin* drdynvc, LPVO if ((error = dvcman_init(drdynvc, drdynvc->channel_mgr))) { - WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_init failed with error %"PRIu32"!", error); + WLog_Print(drdynvc->log, WLOG_ERROR, "dvcman_init failed with error %" PRIu32 "!", error); goto error; } drdynvc->state = DRDYNVC_STATE_CAPABILITIES; if (!(drdynvc->thread = CreateThread(NULL, 0, drdynvc_virtual_channel_client_thread, - (void*) drdynvc, - 0, NULL))) + (void*)drdynvc, 0, NULL))) { error = ERROR_INTERNAL_ERROR; WLog_Print(drdynvc->log, WLOG_ERROR, "CreateThread failed!"); @@ -1447,53 +1526,50 @@ static UINT drdynvc_virtual_channel_event_disconnected(drdynvcPlugin* drdynvc) { UINT status; - if (drdynvc->OpenHandle == 0) - return CHANNEL_RC_OK; - if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; + if (drdynvc->OpenHandle == 0) + return CHANNEL_RC_OK; + if (!MessageQueue_PostQuit(drdynvc->queue, 0)) { status = GetLastError(); - WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_PostQuit failed with error %"PRIu32"", status); + WLog_Print(drdynvc->log, WLOG_ERROR, "MessageQueue_PostQuit failed with error %" PRIu32 "", + status); return status; } if (WaitForSingleObject(drdynvc->thread, INFINITE) != WAIT_OBJECT_0) { status = GetLastError(); - WLog_Print(drdynvc->log, WLOG_ERROR, "WaitForSingleObject failed with error %"PRIu32"", status); + WLog_Print(drdynvc->log, WLOG_ERROR, "WaitForSingleObject failed with error %" PRIu32 "", + status); return status; } - MessageQueue_Free(drdynvc->queue); CloseHandle(drdynvc->thread); - drdynvc->queue = NULL; drdynvc->thread = NULL; + status = drdynvc->channelEntryPoints.pVirtualChannelCloseEx(drdynvc->InitHandle, - drdynvc->OpenHandle); + drdynvc->OpenHandle); if (status != CHANNEL_RC_OK) { - WLog_Print(drdynvc->log, WLOG_ERROR, "pVirtualChannelClose failed with %s [%08"PRIX32"]", + WLog_Print(drdynvc->log, WLOG_ERROR, "pVirtualChannelClose failed with %s [%08" PRIX32 "]", WTSErrorToString(status), status); } + dvcman_clear(drdynvc, drdynvc->channel_mgr); + MessageQueue_Clear(drdynvc->queue); drdynvc->OpenHandle = 0; if (drdynvc->data_in) { - Stream_Free(drdynvc->data_in, TRUE); + Stream_Release(drdynvc->data_in); drdynvc->data_in = NULL; } - if (drdynvc->channel_mgr) - { - dvcman_free(drdynvc, drdynvc->channel_mgr); - drdynvc->channel_mgr = NULL; - } - return status; } @@ -1507,6 +1583,13 @@ static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc) if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; + if (drdynvc->channel_mgr) + { + dvcman_free(drdynvc, drdynvc->channel_mgr); + drdynvc->channel_mgr = NULL; + } + MessageQueue_Free(drdynvc->queue); + drdynvc->queue = NULL; drdynvc->InitHandle = 0; free(drdynvc->context); free(drdynvc); @@ -1515,67 +1598,75 @@ static UINT drdynvc_virtual_channel_event_terminated(drdynvcPlugin* drdynvc) static UINT drdynvc_virtual_channel_event_attached(drdynvcPlugin* drdynvc) { - int i; + UINT error = CHANNEL_RC_OK; + size_t i; DVCMAN* dvcman; if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; - dvcman = (DVCMAN*) drdynvc->channel_mgr; + dvcman = (DVCMAN*)drdynvc->channel_mgr; if (!dvcman) return CHANNEL_RC_BAD_CHANNEL_HANDLE; - for (i = 0; i < dvcman->num_plugins; i++) + ArrayList_Lock(dvcman->plugins); + for (i = 0; i < ArrayList_Count(dvcman->plugins); i++) { - UINT error; - IWTSPlugin* pPlugin = dvcman->plugins[i]; + IWTSPlugin* pPlugin = ArrayList_GetItem(dvcman->plugins, i); - if (pPlugin->Attached) - if ((error = pPlugin->Attached(pPlugin))) - { - WLog_Print(drdynvc->log, WLOG_ERROR, "Attach failed with error %"PRIu32"!", error); - return error; - } + error = IFCALLRESULT(CHANNEL_RC_OK, pPlugin->Attached, pPlugin); + if (error != CHANNEL_RC_OK) + { + WLog_Print(drdynvc->log, WLOG_ERROR, "Attach failed with error %" PRIu32 "!", error); + goto fail; + } } - return CHANNEL_RC_OK; +fail: + ArrayList_Unlock(dvcman->plugins); + return error; } static UINT drdynvc_virtual_channel_event_detached(drdynvcPlugin* drdynvc) { - int i; + UINT error = CHANNEL_RC_OK; + size_t i; DVCMAN* dvcman; if (!drdynvc) return CHANNEL_RC_BAD_CHANNEL_HANDLE; - dvcman = (DVCMAN*) drdynvc->channel_mgr; + dvcman = (DVCMAN*)drdynvc->channel_mgr; if (!dvcman) return CHANNEL_RC_BAD_CHANNEL_HANDLE; - for (i = 0; i < dvcman->num_plugins; i++) + ArrayList_Lock(dvcman->plugins); + for (i = 0; i < ArrayList_Count(dvcman->plugins); i++) { - UINT error; - IWTSPlugin* pPlugin = dvcman->plugins[i]; + IWTSPlugin* pPlugin = ArrayList_GetItem(dvcman->plugins, i); - if (pPlugin->Detached) - if ((error = pPlugin->Detached(pPlugin))) - { - WLog_Print(drdynvc->log, WLOG_ERROR, "Detach failed with error %"PRIu32"!", error); - return error; - } + error = IFCALLRESULT(CHANNEL_RC_OK, pPlugin->Detached, pPlugin); + if (error != CHANNEL_RC_OK) + { + WLog_Print(drdynvc->log, WLOG_ERROR, "Detach failed with error %" PRIu32 "!", error); + goto fail; + } } - return CHANNEL_RC_OK; +fail: + ArrayList_Unlock(dvcman->plugins); + + return error; } static VOID VCAPITYPE drdynvc_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle, - UINT event, LPVOID pData, UINT dataLength) + UINT event, LPVOID pData, + UINT dataLength) { UINT error = CHANNEL_RC_OK; - drdynvcPlugin* drdynvc = (drdynvcPlugin*) lpUserParam; + drdynvcPlugin* drdynvc = (drdynvcPlugin*)lpUserParam; if (!drdynvc || (drdynvc->InitHandle != pInitHandle)) { @@ -1585,38 +1676,47 @@ static VOID VCAPITYPE drdynvc_virtual_channel_init_event_ex(LPVOID lpUserParam, switch (event) { + case CHANNEL_EVENT_INITIALIZED: + error = drdynvc_virtual_channel_event_initialized(drdynvc, pData, dataLength); + break; case CHANNEL_EVENT_CONNECTED: if ((error = drdynvc_virtual_channel_event_connected(drdynvc, pData, dataLength))) WLog_Print(drdynvc->log, WLOG_ERROR, - "drdynvc_virtual_channel_event_connected failed with error %"PRIu32"", error); + "drdynvc_virtual_channel_event_connected failed with error %" PRIu32 "", + error); break; case CHANNEL_EVENT_DISCONNECTED: - if ((error = drdynvc_virtual_channel_event_disconnected(drdynvc))) + if ((error = drdynvc_virtual_channel_event_disconnected(drdynvc))) WLog_Print(drdynvc->log, WLOG_ERROR, - "drdynvc_virtual_channel_event_disconnected failed with error %"PRIu32"", error); + "drdynvc_virtual_channel_event_disconnected failed with error %" PRIu32 + "", + error); break; case CHANNEL_EVENT_TERMINATED: - if ((error = drdynvc_virtual_channel_event_terminated(drdynvc))) + if ((error = drdynvc_virtual_channel_event_terminated(drdynvc))) WLog_Print(drdynvc->log, WLOG_ERROR, - "drdynvc_virtual_channel_event_terminated failed with error %"PRIu32"", error); + "drdynvc_virtual_channel_event_terminated failed with error %" PRIu32 "", + error); break; case CHANNEL_EVENT_ATTACHED: - if ((error = drdynvc_virtual_channel_event_attached(drdynvc))) + if ((error = drdynvc_virtual_channel_event_attached(drdynvc))) WLog_Print(drdynvc->log, WLOG_ERROR, - "drdynvc_virtual_channel_event_attached failed with error %"PRIu32"", error); + "drdynvc_virtual_channel_event_attached failed with error %" PRIu32 "", + error); break; case CHANNEL_EVENT_DETACHED: - if ((error = drdynvc_virtual_channel_event_detached(drdynvc))) + if ((error = drdynvc_virtual_channel_event_detached(drdynvc))) WLog_Print(drdynvc->log, WLOG_ERROR, - "drdynvc_virtual_channel_event_detached failed with error %"PRIu32"", error); + "drdynvc_virtual_channel_event_detached failed with error %" PRIu32 "", + error); break; @@ -1635,12 +1735,12 @@ static VOID VCAPITYPE drdynvc_virtual_channel_init_event_ex(LPVOID lpUserParam, static int drdynvc_get_version(DrdynvcClientContext* context) { - drdynvcPlugin* drdynvc = (drdynvcPlugin*) context->handle; + drdynvcPlugin* drdynvc = (drdynvcPlugin*)context->handle; return drdynvc->version; } /* drdynvc is always built-in */ -#define VirtualChannelEntryEx drdynvc_VirtualChannelEntryEx +#define VirtualChannelEntryEx drdynvc_VirtualChannelEntryEx BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOID pInitHandle) { @@ -1648,7 +1748,7 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOI drdynvcPlugin* drdynvc; DrdynvcClientContext* context = NULL; CHANNEL_ENTRY_POINTS_FREERDP_EX* pEntryPointsEx; - drdynvc = (drdynvcPlugin*) calloc(1, sizeof(drdynvcPlugin)); + drdynvc = (drdynvcPlugin*)calloc(1, sizeof(drdynvcPlugin)); if (!drdynvc) { @@ -1657,17 +1757,15 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOI } drdynvc->channelDef.options = - CHANNEL_OPTION_INITIALIZED | - CHANNEL_OPTION_ENCRYPT_RDP | - CHANNEL_OPTION_COMPRESS_RDP; + CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP; sprintf_s(drdynvc->channelDef.name, ARRAYSIZE(drdynvc->channelDef.name), "drdynvc"); drdynvc->state = DRDYNVC_STATE_INITIAL; - pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*) pEntryPoints; + pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*)pEntryPoints; if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)) && (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) { - context = (DrdynvcClientContext*) calloc(1, sizeof(DrdynvcClientContext)); + context = (DrdynvcClientContext*)calloc(1, sizeof(DrdynvcClientContext)); if (!context) { @@ -1676,7 +1774,7 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOI return FALSE; } - context->handle = (void*) drdynvc; + context->handle = (void*)drdynvc; context->custom = NULL; drdynvc->context = context; context->GetVersion = drdynvc_get_version; @@ -1685,14 +1783,16 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOI drdynvc->log = WLog_Get(TAG); WLog_Print(drdynvc->log, WLOG_DEBUG, "VirtualChannelEntryEx"); - CopyMemory(&(drdynvc->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)); + CopyMemory(&(drdynvc->channelEntryPoints), pEntryPoints, + sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)); drdynvc->InitHandle = pInitHandle; - rc = drdynvc->channelEntryPoints.pVirtualChannelInitEx(drdynvc, context, pInitHandle, - &drdynvc->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, drdynvc_virtual_channel_init_event_ex); + rc = drdynvc->channelEntryPoints.pVirtualChannelInitEx( + drdynvc, context, pInitHandle, &drdynvc->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, + drdynvc_virtual_channel_init_event_ex); if (CHANNEL_RC_OK != rc) { - WLog_Print(drdynvc->log, WLOG_ERROR, "pVirtualChannelInit failed with %s [%08"PRIX32"]", + WLog_Print(drdynvc->log, WLOG_ERROR, "pVirtualChannelInit failed with %s [%08" PRIX32 "]", WTSErrorToString(rc), rc); free(drdynvc->context); free(drdynvc); @@ -1702,4 +1802,3 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOI drdynvc->channelEntryPoints.pInterface = context; return TRUE; } - diff --git a/channels/drdynvc/client/drdynvc_main.h b/channels/drdynvc/client/drdynvc_main.h index 1d83582..646c8fd 100644 --- a/channels/drdynvc/client/drdynvc_main.h +++ b/channels/drdynvc/client/drdynvc_main.h @@ -37,21 +37,16 @@ typedef struct drdynvc_plugin drdynvcPlugin; -#define MAX_PLUGINS 32 - struct _DVCMAN { IWTSVirtualChannelManager iface; drdynvcPlugin* drdynvc; - int num_plugins; - const char* plugin_names[MAX_PLUGINS]; - IWTSPlugin* plugins[MAX_PLUGINS]; - - int num_listeners; - IWTSListener* listeners[MAX_PLUGINS]; + wArrayList* plugin_names; + wArrayList* plugins; + wArrayList* listeners; wArrayList* channels; wStreamPool* pool; }; @@ -106,11 +101,11 @@ enum _DRDYNVC_STATE }; typedef enum _DRDYNVC_STATE DRDYNVC_STATE; -#define CREATE_REQUEST_PDU 0x01 -#define DATA_FIRST_PDU 0x02 -#define DATA_PDU 0x03 -#define CLOSE_REQUEST_PDU 0x04 -#define CAPABILITY_REQUEST_PDU 0x05 +#define CREATE_REQUEST_PDU 0x01 +#define DATA_FIRST_PDU 0x02 +#define DATA_PDU 0x03 +#define CLOSE_REQUEST_PDU 0x04 +#define CAPABILITY_REQUEST_PDU 0x05 struct drdynvc_plugin { @@ -127,7 +122,7 @@ struct drdynvc_plugin DRDYNVC_STATE state; DrdynvcClientContext* context; - int version; + UINT16 version; int PriorityCharge0; int PriorityCharge1; int PriorityCharge2; diff --git a/channels/drdynvc/server/drdynvc_main.c b/channels/drdynvc/server/drdynvc_main.c index b963970..66440b2 100644 --- a/channels/drdynvc/server/drdynvc_main.c +++ b/channels/drdynvc/server/drdynvc_main.c @@ -32,7 +32,6 @@ #define TAG CHANNELS_TAG("drdynvc.server") - static DWORD WINAPI drdynvc_server_thread(LPVOID arg) { #if 0 @@ -121,8 +120,8 @@ static DWORD WINAPI drdynvc_server_thread(LPVOID arg) */ static UINT drdynvc_server_start(DrdynvcServerContext* context) { - context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, - WTS_CURRENT_SESSION, "drdynvc"); + context->priv->ChannelHandle = + WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "drdynvc"); if (!context->priv->ChannelHandle) { @@ -136,7 +135,8 @@ static UINT drdynvc_server_start(DrdynvcServerContext* context) return ERROR_INTERNAL_ERROR; } - if (!(context->priv->Thread = CreateThread(NULL, 0, drdynvc_server_thread, (void*) context, 0, NULL))) + if (!(context->priv->Thread = + CreateThread(NULL, 0, drdynvc_server_thread, (void*)context, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); CloseHandle(context->priv->StopEvent); @@ -160,7 +160,7 @@ static UINT drdynvc_server_stop(DrdynvcServerContext* context) if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error); return error; } @@ -171,14 +171,14 @@ static UINT drdynvc_server_stop(DrdynvcServerContext* context) DrdynvcServerContext* drdynvc_server_context_new(HANDLE vcm) { DrdynvcServerContext* context; - context = (DrdynvcServerContext*) calloc(1, sizeof(DrdynvcServerContext)); + context = (DrdynvcServerContext*)calloc(1, sizeof(DrdynvcServerContext)); if (context) { context->vcm = vcm; context->Start = drdynvc_server_start; context->Stop = drdynvc_server_stop; - context->priv = (DrdynvcServerPrivate*) calloc(1, sizeof(DrdynvcServerPrivate)); + context->priv = (DrdynvcServerPrivate*)calloc(1, sizeof(DrdynvcServerPrivate)); if (!context->priv) { diff --git a/channels/drive/client/drive_file.c b/channels/drive/client/drive_file.c index f816695..3054385 100644 --- a/channels/drive/client/drive_file.c +++ b/channels/drive/client/drive_file.c @@ -46,16 +46,25 @@ #include "drive_file.h" #ifdef WITH_DEBUG_RDPDR -#define DEBUG_WSTR(msg, wstr) do { LPSTR lpstr; ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &lpstr, 0, NULL, NULL); WLog_DBG(TAG, msg, lpstr); free(lpstr); } while (0) +#define DEBUG_WSTR(msg, wstr) \ + do \ + { \ + LPSTR lpstr; \ + ConvertFromUnicode(CP_UTF8, 0, wstr, -1, &lpstr, 0, NULL, NULL); \ + WLog_DBG(TAG, msg, lpstr); \ + free(lpstr); \ + } while (0) #else -#define DEBUG_WSTR(msg, wstr) do { } while (0) +#define DEBUG_WSTR(msg, wstr) \ + do \ + { \ + } while (0) #endif static void drive_file_fix_path(WCHAR* path) { size_t i; - size_t length; - length = (int) _wcslen(path); + size_t length = _wcslen(path); for (i = 0; i < length; i++) { @@ -80,12 +89,12 @@ static void drive_file_fix_path(WCHAR* path) } static WCHAR* drive_file_combine_fullpath(const WCHAR* base_path, const WCHAR* path, - UINT32 PathLength) + size_t PathLength) { WCHAR* fullpath; - UINT32 base_path_length; + size_t base_path_length; - if (!base_path || !path) + if (!base_path || (!path && (PathLength > 0))) return NULL; base_path_length = _wcslen(base_path) * 2; @@ -98,7 +107,8 @@ static WCHAR* drive_file_combine_fullpath(const WCHAR* base_path, const WCHAR* p } CopyMemory(fullpath, base_path, base_path_length); - CopyMemory((char*)fullpath + base_path_length, path, PathLength); + if (path) + CopyMemory((char*)fullpath + base_path_length, path, PathLength); drive_file_fix_path(fullpath); return fullpath; } @@ -107,11 +117,10 @@ static BOOL drive_file_remove_dir(const WCHAR* path) { WIN32_FIND_DATAW findFileData; BOOL ret = TRUE; - INT len; HANDLE dir; WCHAR* fullpath; WCHAR* path_slash; - UINT32 base_path_length; + size_t base_path_length; if (!path) return FALSE; @@ -140,10 +149,10 @@ static BOOL drive_file_remove_dir(const WCHAR* path) do { - len = _wcslen(findFileData.cFileName); + size_t len = _wcslen(findFileData.cFileName); - if ((len == 1 && findFileData.cFileName[0] == L'.') || (len == 2 && - findFileData.cFileName[0] == L'.' && findFileData.cFileName[1] == L'.')) + if ((len == 1 && findFileData.cFileName[0] == L'.') || + (len == 2 && findFileData.cFileName[0] == L'.' && findFileData.cFileName[1] == L'.')) { continue; } @@ -164,8 +173,7 @@ static BOOL drive_file_remove_dir(const WCHAR* path) if (!ret) break; - } - while (ret && FindNextFileW(dir, &findFileData) != 0); + } while (ret && FindNextFileW(dir, &findFileData) != 0); FindClose(dir); @@ -240,7 +248,8 @@ static BOOL drive_file_init(DRIVE_FILE* file) if (file->is_dir) { /* Should only create the directory if the disposition allows for it */ - if ((file->CreateDisposition == FILE_OPEN_IF) || (file->CreateDisposition == FILE_CREATE)) + if ((file->CreateDisposition == FILE_OPEN_IF) || + (file->CreateDisposition == FILE_CREATE)) { if (CreateDirectoryW(file->fullpath, NULL) != 0) { @@ -257,27 +266,33 @@ static BOOL drive_file_init(DRIVE_FILE* file) { switch (file->CreateDisposition) { - case FILE_SUPERSEDE: /* If the file already exists, replace it with the given file. If it does not, create the given file. */ + case FILE_SUPERSEDE: /* If the file already exists, replace it with the given file. If + it does not, create the given file. */ CreateDisposition = CREATE_ALWAYS; break; - case FILE_OPEN: /* If the file already exists, open it instead of creating a new file. If it does not, fail the request and do not create a new file. */ + case FILE_OPEN: /* If the file already exists, open it instead of creating a new file. + If it does not, fail the request and do not create a new file. */ CreateDisposition = OPEN_EXISTING; break; - case FILE_CREATE: /* If the file already exists, fail the request and do not create or open the given file. If it does not, create the given file. */ + case FILE_CREATE: /* If the file already exists, fail the request and do not create or + open the given file. If it does not, create the given file. */ CreateDisposition = CREATE_NEW; break; - case FILE_OPEN_IF: /* If the file already exists, open it. If it does not, create the given file. */ + case FILE_OPEN_IF: /* If the file already exists, open it. If it does not, create the + given file. */ CreateDisposition = OPEN_ALWAYS; break; - case FILE_OVERWRITE: /* If the file already exists, open it and overwrite it. If it does not, fail the request. */ + case FILE_OVERWRITE: /* If the file already exists, open it and overwrite it. If it does + not, fail the request. */ CreateDisposition = TRUNCATE_EXISTING; break; - case FILE_OVERWRITE_IF: /* If the file already exists, open it and overwrite it. If it does not, create the given file. */ + case FILE_OVERWRITE_IF: /* If the file already exists, open it and overwrite it. If it + does not, create the given file. */ CreateDisposition = CREATE_ALWAYS; break; @@ -288,11 +303,11 @@ static BOOL drive_file_init(DRIVE_FILE* file) #ifndef WIN32 file->SharedAccess = 0; #endif - file->file_handle = CreateFileW(file->fullpath, file->DesiredAccess, - file->SharedAccess, NULL, CreateDisposition, - file->FileAttributes, NULL); + file->file_handle = CreateFileW(file->fullpath, file->DesiredAccess, file->SharedAccess, + NULL, CreateDisposition, file->FileAttributes, NULL); } +#ifdef WIN32 if (file->file_handle == INVALID_HANDLE_VALUE) { /* Get the error message, if any. */ @@ -300,31 +315,34 @@ static BOOL drive_file_init(DRIVE_FILE* file) if (errorMessageID != 0) { -#ifdef WIN32 LPSTR messageBuffer = NULL; - size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | - FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL); + size_t size = + FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&messageBuffer, 0, NULL); WLog_ERR(TAG, "Error in drive_file_init: %s %s", messageBuffer, file->fullpath); /* Free the buffer. */ LocalFree(messageBuffer); -#endif + /* restore original error code */ + SetLastError(errorMessageID); } } +#endif return file->file_handle != INVALID_HANDLE_VALUE; } DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathLength, UINT32 id, - UINT32 DesiredAccess, UINT32 CreateDisposition, - UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess) + UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions, + UINT32 FileAttributes, UINT32 SharedAccess) { DRIVE_FILE* file; - if (!base_path || !path) + if (!base_path || (!path && (PathLength > 0))) return NULL; - file = (DRIVE_FILE*) calloc(1, sizeof(DRIVE_FILE)); + file = (DRIVE_FILE*)calloc(1, sizeof(DRIVE_FILE)); if (!file) { @@ -335,7 +353,7 @@ DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 Pat file->file_handle = INVALID_HANDLE_VALUE; file->find_handle = INVALID_HANDLE_VALUE; file->id = id; - file->basepath = (WCHAR*) base_path; + file->basepath = base_path; file->FileAttributes = FileAttributes; file->DesiredAccess = DesiredAccess; file->CreateDisposition = CreateDisposition; @@ -345,7 +363,9 @@ DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 Pat if (!drive_file_init(file)) { + DWORD lastError = GetLastError(); drive_file_free(file); + SetLastError(lastError); return NULL; } @@ -397,7 +417,10 @@ BOOL drive_file_seek(DRIVE_FILE* file, UINT64 Offset) if (!file) return FALSE; - loffset.QuadPart = Offset; + if (Offset > INT64_MAX) + return FALSE; + + loffset.QuadPart = (LONGLONG)Offset; return SetFilePointerEx(file->file_handle, loffset, NULL, FILE_BEGIN); } @@ -460,15 +483,23 @@ BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, w goto out_fail; Stream_Write_UINT32(output, 36); /* Length */ - Stream_Write_UINT32(output, fileAttributes.ftCreationTime.dwLowDateTime); /* CreationTime */ - Stream_Write_UINT32(output, fileAttributes.ftCreationTime.dwHighDateTime); /* CreationTime */ - Stream_Write_UINT32(output, fileAttributes.ftLastAccessTime.dwLowDateTime); /* LastAccessTime */ - Stream_Write_UINT32(output, fileAttributes.ftLastAccessTime.dwHighDateTime); /* LastAccessTime */ - Stream_Write_UINT32(output, fileAttributes.ftLastWriteTime.dwLowDateTime); /* LastWriteTime */ - Stream_Write_UINT32(output, fileAttributes.ftLastWriteTime.dwHighDateTime); /* LastWriteTime */ - Stream_Write_UINT32(output, fileAttributes.ftLastWriteTime.dwLowDateTime); /* ChangeTime */ - Stream_Write_UINT32(output, fileAttributes.ftLastWriteTime.dwHighDateTime); /* ChangeTime */ - Stream_Write_UINT32(output, fileAttributes.dwFileAttributes); /* FileAttributes */ + Stream_Write_UINT32(output, + fileAttributes.ftCreationTime.dwLowDateTime); /* CreationTime */ + Stream_Write_UINT32(output, + fileAttributes.ftCreationTime.dwHighDateTime); /* CreationTime */ + Stream_Write_UINT32(output, + fileAttributes.ftLastAccessTime.dwLowDateTime); /* LastAccessTime */ + Stream_Write_UINT32( + output, fileAttributes.ftLastAccessTime.dwHighDateTime); /* LastAccessTime */ + Stream_Write_UINT32(output, + fileAttributes.ftLastWriteTime.dwLowDateTime); /* LastWriteTime */ + Stream_Write_UINT32(output, + fileAttributes.ftLastWriteTime.dwHighDateTime); /* LastWriteTime */ + Stream_Write_UINT32(output, + fileAttributes.ftLastWriteTime.dwLowDateTime); /* ChangeTime */ + Stream_Write_UINT32(output, + fileAttributes.ftLastWriteTime.dwHighDateTime); /* ChangeTime */ + Stream_Write_UINT32(output, fileAttributes.dwFileAttributes); /* FileAttributes */ /* Reserved(4), MUST NOT be added! */ break; @@ -478,15 +509,16 @@ BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, w if (!Stream_EnsureRemainingCapacity(output, 4 + 22)) goto out_fail; - Stream_Write_UINT32(output, 22); /* Length */ - Stream_Write_UINT32(output, fileAttributes.nFileSizeLow); /* AllocationSize */ + Stream_Write_UINT32(output, 22); /* Length */ + Stream_Write_UINT32(output, fileAttributes.nFileSizeLow); /* AllocationSize */ Stream_Write_UINT32(output, fileAttributes.nFileSizeHigh); /* AllocationSize */ - Stream_Write_UINT32(output, fileAttributes.nFileSizeLow); /* EndOfFile */ + Stream_Write_UINT32(output, fileAttributes.nFileSizeLow); /* EndOfFile */ Stream_Write_UINT32(output, fileAttributes.nFileSizeHigh); /* EndOfFile */ - Stream_Write_UINT32(output, 0); /* NumberOfLinks */ - Stream_Write_UINT8(output, file->delete_pending ? 1 : 0); /* DeletePending */ - Stream_Write_UINT8(output, fileAttributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ? TRUE : - FALSE); /* Directory */ + Stream_Write_UINT32(output, 0); /* NumberOfLinks */ + Stream_Write_UINT8(output, file->delete_pending ? 1 : 0); /* DeletePending */ + Stream_Write_UINT8(output, fileAttributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY + ? TRUE + : FALSE); /* Directory */ /* Reserved(2), MUST NOT be added! */ break; @@ -496,9 +528,9 @@ BOOL drive_file_query_information(DRIVE_FILE* file, UINT32 FsInformationClass, w if (!Stream_EnsureRemainingCapacity(output, 4 + 8)) goto out_fail; - Stream_Write_UINT32(output, 8); /* Length */ + Stream_Write_UINT32(output, 8); /* Length */ Stream_Write_UINT32(output, fileAttributes.dwFileAttributes); /* FileAttributes */ - Stream_Write_UINT32(output, 0); /* ReparseTag */ + Stream_Write_UINT32(output, 0); /* ReparseTag */ break; default: @@ -555,47 +587,49 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN if (file->file_handle == INVALID_HANDLE_VALUE) { - WLog_ERR(TAG, "Unable to set file time %s (%"PRId32")", file->fullpath, GetLastError()); + WLog_ERR(TAG, "Unable to set file time %s (%" PRId32 ")", file->fullpath, + GetLastError()); return FALSE; } if (liCreationTime.QuadPart != 0) { - ftCreationTime.dwHighDateTime = liCreationTime.HighPart; - ftCreationTime.dwLowDateTime = liCreationTime.LowPart; + ftCreationTime.dwHighDateTime = liCreationTime.u.HighPart; + ftCreationTime.dwLowDateTime = liCreationTime.u.LowPart; pftCreationTime = &ftCreationTime; } if (liLastAccessTime.QuadPart != 0) { - ftLastAccessTime.dwHighDateTime = liLastAccessTime.HighPart; - ftLastAccessTime.dwLowDateTime = liLastAccessTime.LowPart; + ftLastAccessTime.dwHighDateTime = liLastAccessTime.u.HighPart; + ftLastAccessTime.dwLowDateTime = liLastAccessTime.u.LowPart; pftLastAccessTime = &ftLastAccessTime; } if (liLastWriteTime.QuadPart != 0) { - ftLastWriteTime.dwHighDateTime = liLastWriteTime.HighPart; - ftLastWriteTime.dwLowDateTime = liLastWriteTime.LowPart; + ftLastWriteTime.dwHighDateTime = liLastWriteTime.u.HighPart; + ftLastWriteTime.dwLowDateTime = liLastWriteTime.u.LowPart; pftLastWriteTime = &ftLastWriteTime; } if (liChangeTime.QuadPart != 0 && liChangeTime.QuadPart > liLastWriteTime.QuadPart) { - ftLastWriteTime.dwHighDateTime = liChangeTime.HighPart; - ftLastWriteTime.dwLowDateTime = liChangeTime.LowPart; + ftLastWriteTime.dwHighDateTime = liChangeTime.u.HighPart; + ftLastWriteTime.dwLowDateTime = liChangeTime.u.LowPart; pftLastWriteTime = &ftLastWriteTime; } DEBUG_WSTR("SetFileTime %s", file->fullpath); - if (!SetFileTime(file->file_handle, pftCreationTime, pftLastAccessTime, pftLastWriteTime)) + SetFileAttributesW(file->fullpath, FileAttributes); + if (!SetFileTime(file->file_handle, pftCreationTime, pftLastAccessTime, + pftLastWriteTime)) { WLog_ERR(TAG, "Unable to set file time to %s", file->fullpath); return FALSE; } - SetFileAttributesW(file->fullpath, FileAttributes); break; case FileEndOfFileInformation: @@ -610,14 +644,17 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN if (file->file_handle == INVALID_HANDLE_VALUE) { - WLog_ERR(TAG, "Unable to truncate %s to %"PRId64" (%"PRId32")", file->fullpath, size, - GetLastError()); + WLog_ERR(TAG, "Unable to truncate %s to %" PRId64 " (%" PRId32 ")", file->fullpath, + size, GetLastError()); return FALSE; } + liSize.QuadPart = size; + if (!SetFilePointerEx(file->file_handle, liSize, NULL, FILE_BEGIN)) { - WLog_ERR(TAG, "Unable to truncate %s to %d (%"PRId32")", file->fullpath, size, GetLastError()); + WLog_ERR(TAG, "Unable to truncate %s to %d (%" PRId32 ")", file->fullpath, size, + GetLastError()); return FALSE; } @@ -625,7 +662,8 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN if (SetEndOfFile(file->file_handle) == 0) { - WLog_ERR(TAG, "Unable to truncate %s to %d (%"PRId32")", file->fullpath, size, GetLastError()); + WLog_ERR(TAG, "Unable to truncate %s to %d (%" PRId32 ")", file->fullpath, size, + GetLastError()); return FALSE; } @@ -696,7 +734,8 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN DEBUG_WSTR("MoveFileExW %s", file->fullpath); if (MoveFileExW(file->fullpath, fullpath, - MOVEFILE_COPY_ALLOWED | (ReplaceIfExists ? MOVEFILE_REPLACE_EXISTING : 0))) + MOVEFILE_COPY_ALLOWED | + (ReplaceIfExists ? MOVEFILE_REPLACE_EXISTING : 0))) { if (!drive_file_set_fullpath(file, fullpath)) return FALSE; @@ -755,23 +794,34 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT if (!Stream_EnsureRemainingCapacity(output, 4 + 64 + length)) goto out_fail; - Stream_Write_UINT32(output, 64 + length); /* Length */ - Stream_Write_UINT32(output, 0); /* NextEntryOffset */ - Stream_Write_UINT32(output, 0); /* FileIndex */ - Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwLowDateTime); /* CreationTime */ - Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwHighDateTime); /* CreationTime */ - Stream_Write_UINT32(output, file->find_data.ftLastAccessTime.dwLowDateTime); /* LastAccessTime */ - Stream_Write_UINT32(output, file->find_data.ftLastAccessTime.dwHighDateTime); /* LastAccessTime */ - Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); /* LastWriteTime */ - Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); /* LastWriteTime */ - Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); /* ChangeTime */ - Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); /* ChangeTime */ - Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* EndOfFile */ - Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* EndOfFile */ - Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* AllocationSize */ - Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* AllocationSize */ + if (length > UINT32_MAX - 64) + goto out_fail; + + Stream_Write_UINT32(output, (UINT32)(64 + length)); /* Length */ + Stream_Write_UINT32(output, 0); /* NextEntryOffset */ + Stream_Write_UINT32(output, 0); /* FileIndex */ + Stream_Write_UINT32(output, + file->find_data.ftCreationTime.dwLowDateTime); /* CreationTime */ + Stream_Write_UINT32(output, + file->find_data.ftCreationTime.dwHighDateTime); /* CreationTime */ + Stream_Write_UINT32( + output, file->find_data.ftLastAccessTime.dwLowDateTime); /* LastAccessTime */ + Stream_Write_UINT32( + output, file->find_data.ftLastAccessTime.dwHighDateTime); /* LastAccessTime */ + Stream_Write_UINT32(output, + file->find_data.ftLastWriteTime.dwLowDateTime); /* LastWriteTime */ + Stream_Write_UINT32(output, + file->find_data.ftLastWriteTime.dwHighDateTime); /* LastWriteTime */ + Stream_Write_UINT32(output, + file->find_data.ftLastWriteTime.dwLowDateTime); /* ChangeTime */ + Stream_Write_UINT32(output, + file->find_data.ftLastWriteTime.dwHighDateTime); /* ChangeTime */ + Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* EndOfFile */ + Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* EndOfFile */ + Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* AllocationSize */ + Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* AllocationSize */ Stream_Write_UINT32(output, file->find_data.dwFileAttributes); /* FileAttributes */ - Stream_Write_UINT32(output, length); /* FileNameLength */ + Stream_Write_UINT32(output, (UINT32)length); /* FileNameLength */ Stream_Write(output, file->find_data.cFileName, length); break; @@ -781,24 +831,35 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT if (!Stream_EnsureRemainingCapacity(output, 4 + 68 + length)) goto out_fail; - Stream_Write_UINT32(output, 68 + length); /* Length */ - Stream_Write_UINT32(output, 0); /* NextEntryOffset */ - Stream_Write_UINT32(output, 0); /* FileIndex */ - Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwHighDateTime); /* CreationTime */ - Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwLowDateTime); /* CreationTime */ - Stream_Write_UINT32(output, file->find_data.ftLastAccessTime.dwHighDateTime); /* LastAccessTime */ - Stream_Write_UINT32(output, file->find_data.ftLastAccessTime.dwLowDateTime); /* LastAccessTime */ - Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); /* LastWriteTime */ - Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); /* LastWriteTime */ - Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); /* ChangeTime */ - Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); /* ChangeTime */ - Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* EndOfFile */ - Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* EndOfFile */ - Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* AllocationSize */ - Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* AllocationSize */ + if (length > UINT32_MAX - 68) + goto out_fail; + + Stream_Write_UINT32(output, (UINT32)(68 + length)); /* Length */ + Stream_Write_UINT32(output, 0); /* NextEntryOffset */ + Stream_Write_UINT32(output, 0); /* FileIndex */ + Stream_Write_UINT32(output, + file->find_data.ftCreationTime.dwLowDateTime); /* CreationTime */ + Stream_Write_UINT32(output, + file->find_data.ftCreationTime.dwHighDateTime); /* CreationTime */ + Stream_Write_UINT32( + output, file->find_data.ftLastAccessTime.dwLowDateTime); /* LastAccessTime */ + Stream_Write_UINT32( + output, file->find_data.ftLastAccessTime.dwHighDateTime); /* LastAccessTime */ + Stream_Write_UINT32(output, + file->find_data.ftLastWriteTime.dwLowDateTime); /* LastWriteTime */ + Stream_Write_UINT32(output, + file->find_data.ftLastWriteTime.dwHighDateTime); /* LastWriteTime */ + Stream_Write_UINT32(output, + file->find_data.ftLastWriteTime.dwLowDateTime); /* ChangeTime */ + Stream_Write_UINT32(output, + file->find_data.ftLastWriteTime.dwHighDateTime); /* ChangeTime */ + Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* EndOfFile */ + Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* EndOfFile */ + Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* AllocationSize */ + Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* AllocationSize */ Stream_Write_UINT32(output, file->find_data.dwFileAttributes); /* FileAttributes */ - Stream_Write_UINT32(output, length); /* FileNameLength */ - Stream_Write_UINT32(output, 0); /* EaSize */ + Stream_Write_UINT32(output, (UINT32)length); /* FileNameLength */ + Stream_Write_UINT32(output, 0); /* EaSize */ Stream_Write(output, file->find_data.cFileName, length); break; @@ -808,25 +869,36 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT if (!Stream_EnsureRemainingCapacity(output, 4 + 93 + length)) goto out_fail; - Stream_Write_UINT32(output, 93 + length); /* Length */ - Stream_Write_UINT32(output, 0); /* NextEntryOffset */ - Stream_Write_UINT32(output, 0); /* FileIndex */ - Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwLowDateTime); /* CreationTime */ - Stream_Write_UINT32(output, file->find_data.ftCreationTime.dwHighDateTime); /* CreationTime */ - Stream_Write_UINT32(output, file->find_data.ftLastAccessTime.dwLowDateTime); /* LastAccessTime */ - Stream_Write_UINT32(output, file->find_data.ftLastAccessTime.dwHighDateTime); /* LastAccessTime */ - Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); /* LastWriteTime */ - Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); /* LastWriteTime */ - Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwLowDateTime); /* ChangeTime */ - Stream_Write_UINT32(output, file->find_data.ftLastWriteTime.dwHighDateTime); /* ChangeTime */ - Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* EndOfFile */ - Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* EndOfFile */ - Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* AllocationSize */ - Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* AllocationSize */ + if (length > UINT32_MAX - 93) + goto out_fail; + + Stream_Write_UINT32(output, (UINT32)(93 + length)); /* Length */ + Stream_Write_UINT32(output, 0); /* NextEntryOffset */ + Stream_Write_UINT32(output, 0); /* FileIndex */ + Stream_Write_UINT32(output, + file->find_data.ftCreationTime.dwLowDateTime); /* CreationTime */ + Stream_Write_UINT32(output, + file->find_data.ftCreationTime.dwHighDateTime); /* CreationTime */ + Stream_Write_UINT32( + output, file->find_data.ftLastAccessTime.dwLowDateTime); /* LastAccessTime */ + Stream_Write_UINT32( + output, file->find_data.ftLastAccessTime.dwHighDateTime); /* LastAccessTime */ + Stream_Write_UINT32(output, + file->find_data.ftLastWriteTime.dwLowDateTime); /* LastWriteTime */ + Stream_Write_UINT32(output, + file->find_data.ftLastWriteTime.dwHighDateTime); /* LastWriteTime */ + Stream_Write_UINT32(output, + file->find_data.ftLastWriteTime.dwLowDateTime); /* ChangeTime */ + Stream_Write_UINT32(output, + file->find_data.ftLastWriteTime.dwHighDateTime); /* ChangeTime */ + Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* EndOfFile */ + Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* EndOfFile */ + Stream_Write_UINT32(output, file->find_data.nFileSizeLow); /* AllocationSize */ + Stream_Write_UINT32(output, file->find_data.nFileSizeHigh); /* AllocationSize */ Stream_Write_UINT32(output, file->find_data.dwFileAttributes); /* FileAttributes */ - Stream_Write_UINT32(output, length); /* FileNameLength */ - Stream_Write_UINT32(output, 0); /* EaSize */ - Stream_Write_UINT8(output, 0); /* ShortNameLength */ + Stream_Write_UINT32(output, (UINT32)length); /* FileNameLength */ + Stream_Write_UINT32(output, 0); /* EaSize */ + Stream_Write_UINT8(output, 0); /* ShortNameLength */ /* Reserved(1), MUST NOT be added! */ Stream_Zero(output, 24); /* ShortName */ Stream_Write(output, file->find_data.cFileName, length); @@ -838,14 +910,18 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT if (!Stream_EnsureRemainingCapacity(output, 4 + 12 + length)) goto out_fail; - Stream_Write_UINT32(output, 12 + length); /* Length */ - Stream_Write_UINT32(output, 0); /* NextEntryOffset */ - Stream_Write_UINT32(output, 0); /* FileIndex */ - Stream_Write_UINT32(output, length); /* FileNameLength */ + if (length > UINT32_MAX - 12) + goto out_fail; + + Stream_Write_UINT32(output, (UINT32)(12 + length)); /* Length */ + Stream_Write_UINT32(output, 0); /* NextEntryOffset */ + Stream_Write_UINT32(output, 0); /* FileIndex */ + Stream_Write_UINT32(output, (UINT32)length); /* FileNameLength */ Stream_Write(output, file->find_data.cFileName, length); break; default: + WLog_ERR(TAG, "unhandled FsInformationClass %" PRIu32, FsInformationClass); /* Unhandled FsInformationClass */ goto out_fail; } @@ -853,6 +929,6 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT return TRUE; out_fail: Stream_Write_UINT32(output, 0); /* Length */ - Stream_Write_UINT8(output, 0); /* Padding */ + Stream_Write_UINT8(output, 0); /* Padding */ return FALSE; } diff --git a/channels/drive/client/drive_file.h b/channels/drive/client/drive_file.h index b928187..ed789d6 100644 --- a/channels/drive/client/drive_file.h +++ b/channels/drive/client/drive_file.h @@ -40,7 +40,7 @@ struct _DRIVE_FILE HANDLE file_handle; HANDLE find_handle; WIN32_FIND_DATAW find_data; - WCHAR* basepath; + const WCHAR* basepath; WCHAR* fullpath; WCHAR* filename; BOOL delete_pending; @@ -52,8 +52,8 @@ struct _DRIVE_FILE }; DRIVE_FILE* drive_file_new(const WCHAR* base_path, const WCHAR* path, UINT32 PathLength, UINT32 id, - UINT32 DesiredAccess, UINT32 CreateDisposition, - UINT32 CreateOptions, UINT32 FileAttributes, UINT32 SharedAccess); + UINT32 DesiredAccess, UINT32 CreateDisposition, UINT32 CreateOptions, + UINT32 FileAttributes, UINT32 SharedAccess); BOOL drive_file_free(DRIVE_FILE* file); BOOL drive_file_open(DRIVE_FILE* file); diff --git a/channels/drive/client/drive_main.c b/channels/drive/client/drive_main.c index df361c0..1b54225 100644 --- a/channels/drive/client/drive_main.c +++ b/channels/drive/client/drive_main.c @@ -102,7 +102,7 @@ static DWORD drive_map_windows_err(DWORD fs_errno) case ERROR_FILE_EXISTS: case ERROR_ALREADY_EXISTS: - rc = STATUS_OBJECT_NAME_COLLISION; + rc = STATUS_OBJECT_NAME_COLLISION; break; case ERROR_INVALID_NAME: @@ -127,7 +127,7 @@ static DWORD drive_map_windows_err(DWORD fs_errno) default: rc = STATUS_UNSUCCESSFUL; - WLog_ERR(TAG, "Error code not found: %"PRIu32"", fs_errno); + WLog_ERR(TAG, "Error code not found: %" PRIu32 "", fs_errno); break; } @@ -137,12 +137,12 @@ static DWORD drive_map_windows_err(DWORD fs_errno) static DRIVE_FILE* drive_get_file_by_id(DRIVE_DEVICE* drive, UINT32 id) { DRIVE_FILE* file = NULL; - void* key = (void*)(size_t) id; + void* key = (void*)(size_t)id; if (!drive) return NULL; - file = (DRIVE_FILE*) ListDictionary_GetItemValue(drive->files, key); + file = (DRIVE_FILE*)ListDictionary_GetItemValue(drive->files, key); return file; } @@ -182,7 +182,7 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp) if (Stream_GetRemainingLength(irp->input) < PathLength) return ERROR_INVALID_DATA; - path = (WCHAR*) Stream_Pointer(irp->input); + path = (const WCHAR*)Stream_Pointer(irp->input); FileId = irp->devman->id_sequence++; file = drive_file_new(drive->path, path, PathLength, FileId, DesiredAccess, CreateDisposition, CreateOptions, FileAttributes, SharedAccess); @@ -195,7 +195,7 @@ static UINT drive_process_irp_create(DRIVE_DEVICE* drive, IRP* irp) } else { - void* key = (void*)(size_t) file->id; + void* key = (void*)(size_t)file->id; if (!ListDictionary_Add(drive->files, key, file)) { @@ -245,7 +245,7 @@ static UINT drive_process_irp_close(DRIVE_DEVICE* drive, IRP* irp) return ERROR_INVALID_PARAMETER; file = drive_get_file_by_id(drive, irp->FileId); - key = (void*)(size_t) irp->FileId; + key = (void*)(size_t)irp->FileId; if (!file) irp->IoStatus = STATUS_UNSUCCESSFUL; @@ -331,6 +331,7 @@ static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp) DRIVE_FILE* file; UINT32 Length; UINT64 Offset; + void* ptr; if (!drive || !irp || !irp->input || !irp->output || !irp->Complete) return ERROR_INVALID_PARAMETER; @@ -341,6 +342,9 @@ static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp) Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); Stream_Seek(irp->input, 20); /* Padding */ + ptr = Stream_Pointer(irp->input); + if (!Stream_SafeSeek(irp->input, Length)) + return ERROR_INVALID_DATA; file = drive_get_file_by_id(drive, irp->FileId); if (!file) @@ -353,7 +357,7 @@ static UINT drive_process_irp_write(DRIVE_DEVICE* drive, IRP* irp) irp->IoStatus = drive_map_windows_err(GetLastError()); Length = 0; } - else if (!drive_file_write(file, Stream_Pointer(irp->input), Length)) + else if (!drive_file_write(file, ptr, Length)) { irp->IoStatus = drive_map_windows_err(GetLastError()); Length = 0; @@ -421,8 +425,7 @@ static UINT drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp) { irp->IoStatus = STATUS_UNSUCCESSFUL; } - else if (!drive_file_set_information(file, FsInformationClass, Length, - irp->input)) + else if (!drive_file_set_information(file, FsInformationClass, Length, irp->input)) { irp->IoStatus = drive_map_windows_err(GetLastError()); } @@ -434,19 +437,17 @@ static UINT drive_process_irp_set_information(DRIVE_DEVICE* drive, IRP* irp) return irp->Complete(irp); } - /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, - IRP* irp) +static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, IRP* irp) { UINT32 FsInformationClass; wStream* output = NULL; - char* volumeLabel = {"FREERDP"}; - char* diskType = {"FAT32"}; + char* volumeLabel = { "FREERDP" }; + char* diskType = { "FAT32" }; WCHAR* outStr = NULL; int length; DWORD lpSectorsPerCluster; @@ -489,10 +490,11 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, GetFileAttributesExW(drive->path, GetFileExInfoStandard, &wfad); Stream_Write_UINT32(output, wfad.ftCreationTime.dwLowDateTime); /* VolumeCreationTime */ - Stream_Write_UINT32(output, wfad.ftCreationTime.dwHighDateTime); /* VolumeCreationTime */ + Stream_Write_UINT32(output, + wfad.ftCreationTime.dwHighDateTime); /* VolumeCreationTime */ Stream_Write_UINT32(output, lpNumberOfFreeClusters & 0xffff); /* VolumeSerialNumber */ - Stream_Write_UINT32(output, length); /* VolumeLabelLength */ - Stream_Write_UINT8(output, 0); /* SupportsObjects */ + Stream_Write_UINT32(output, length); /* VolumeLabelLength */ + Stream_Write_UINT8(output, 0); /* SupportsObjects */ /* Reserved(1), MUST NOT be added! */ Stream_Write(output, outStr, length); /* VolumeLabel (Unicode) */ free(outStr); @@ -509,9 +511,9 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, } Stream_Write_UINT64(output, lpTotalNumberOfClusters); /* TotalAllocationUnits */ - Stream_Write_UINT64(output, lpNumberOfFreeClusters); /* AvailableAllocationUnits */ - Stream_Write_UINT32(output, lpSectorsPerCluster); /* SectorsPerAllocationUnit */ - Stream_Write_UINT32(output, lpBytesPerSector); /* BytesPerSector */ + Stream_Write_UINT64(output, lpNumberOfFreeClusters); /* AvailableAllocationUnits */ + Stream_Write_UINT32(output, lpSectorsPerCluster); /* SectorsPerAllocationUnit */ + Stream_Write_UINT32(output, lpBytesPerSector); /* BytesPerSector */ break; case FileFsAttributeInformation: @@ -532,13 +534,11 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, return CHANNEL_RC_NO_MEMORY; } - Stream_Write_UINT32(output, - FILE_CASE_SENSITIVE_SEARCH | - FILE_CASE_PRESERVED_NAMES | - FILE_UNICODE_ON_DISK); /* FileSystemAttributes */ - Stream_Write_UINT32(output, MAX_PATH); /* MaximumComponentNameLength */ - Stream_Write_UINT32(output, length); /* FileSystemNameLength */ - Stream_Write(output, outStr, length); /* FileSystemName (Unicode) */ + Stream_Write_UINT32(output, FILE_CASE_SENSITIVE_SEARCH | FILE_CASE_PRESERVED_NAMES | + FILE_UNICODE_ON_DISK); /* FileSystemAttributes */ + Stream_Write_UINT32(output, MAX_PATH); /* MaximumComponentNameLength */ + Stream_Write_UINT32(output, length); /* FileSystemNameLength */ + Stream_Write(output, outStr, length); /* FileSystemName (Unicode) */ free(outStr); break; @@ -553,10 +553,11 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, } Stream_Write_UINT64(output, lpTotalNumberOfClusters); /* TotalAllocationUnits */ - Stream_Write_UINT64(output, lpNumberOfFreeClusters); /* CallerAvailableAllocationUnits */ + Stream_Write_UINT64(output, + lpNumberOfFreeClusters); /* CallerAvailableAllocationUnits */ Stream_Write_UINT64(output, lpNumberOfFreeClusters); /* AvailableAllocationUnits */ - Stream_Write_UINT32(output, lpSectorsPerCluster); /* SectorsPerAllocationUnit */ - Stream_Write_UINT32(output, lpBytesPerSector); /* BytesPerSector */ + Stream_Write_UINT32(output, lpSectorsPerCluster); /* SectorsPerAllocationUnit */ + Stream_Write_UINT32(output, lpBytesPerSector); /* BytesPerSector */ break; case FileFsDeviceInformation: @@ -570,7 +571,7 @@ static UINT drive_process_irp_query_volume_information(DRIVE_DEVICE* drive, } Stream_Write_UINT32(output, FILE_DEVICE_DISK); /* DeviceType */ - Stream_Write_UINT32(output, 0); /* Characteristics */ + Stream_Write_UINT32(output, 0); /* Characteristics */ break; default: @@ -627,7 +628,7 @@ static UINT drive_process_irp_query_directory(DRIVE_DEVICE* drive, IRP* irp) Stream_Read_UINT8(irp->input, InitialQuery); Stream_Read_UINT32(irp->input, PathLength); Stream_Seek(irp->input, 23); /* Padding */ - path = (WCHAR*) Stream_Pointer(irp->input); + path = (WCHAR*)Stream_Pointer(irp->input); file = drive_get_file_by_id(drive, irp->FileId); if (file == NULL) @@ -754,7 +755,7 @@ static DWORD WINAPI drive_thread_func(LPVOID arg) { IRP* irp; wMessage message; - DRIVE_DEVICE* drive = (DRIVE_DEVICE*) arg; + DRIVE_DEVICE* drive = (DRIVE_DEVICE*)arg; UINT error = CHANNEL_RC_OK; if (!drive) @@ -782,13 +783,13 @@ static DWORD WINAPI drive_thread_func(LPVOID arg) if (message.id == WMQ_QUIT) break; - irp = (IRP*) message.wParam; + irp = (IRP*)message.wParam; if (irp) { if ((error = drive_process_irp(drive, irp))) { - WLog_ERR(TAG, "drive_process_irp failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "drive_process_irp failed with error %" PRIu32 "!", error); break; } } @@ -810,12 +811,12 @@ fail: */ static UINT drive_irp_request(DEVICE* device, IRP* irp) { - DRIVE_DEVICE* drive = (DRIVE_DEVICE*) device; + DRIVE_DEVICE* drive = (DRIVE_DEVICE*)device; if (!drive) return ERROR_INVALID_PARAMETER; - if (!MessageQueue_Post(drive->IrpQueue, NULL, 0, (void*) irp, NULL)) + if (!MessageQueue_Post(drive->IrpQueue, NULL, 0, (void*)irp, NULL)) { WLog_ERR(TAG, "MessageQueue_Post failed!"); return ERROR_INTERNAL_ERROR; @@ -847,17 +848,17 @@ static UINT drive_free_int(DRIVE_DEVICE* drive) */ static UINT drive_free(DEVICE* device) { - DRIVE_DEVICE* drive = (DRIVE_DEVICE*) device; + DRIVE_DEVICE* drive = (DRIVE_DEVICE*)device; UINT error = CHANNEL_RC_OK; if (!drive) return ERROR_INVALID_PARAMETER; - if (MessageQueue_PostQuit(drive->IrpQueue, 0) - && (WaitForSingleObject(drive->thread, INFINITE) == WAIT_FAILED)) + if (MessageQueue_PostQuit(drive->IrpQueue, 0) && + (WaitForSingleObject(drive->thread, INFINITE) == WAIT_FAILED)) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error); return error; } @@ -869,7 +870,7 @@ static UINT drive_free(DEVICE* device) */ static void drive_file_objfree(void* obj) { - drive_file_free((DRIVE_FILE*) obj); + drive_file_free((DRIVE_FILE*)obj); } /** @@ -877,17 +878,24 @@ static void drive_file_objfree(void* obj) * * @return 0 on success, otherwise a Win32 error code */ -static UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, - const char* name, const char* path, BOOL automount) +static UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, const char* name, + const char* path, BOOL automount) { size_t i, length; DRIVE_DEVICE* drive; - UINT error; + UINT error = ERROR_INTERNAL_ERROR; + + if (!pEntryPoints || !name || !path) + { + WLog_ERR(TAG, "[%s] Invalid parameters: pEntryPoints=%p, name=%p, path=%p", pEntryPoints, + name, path); + return ERROR_INVALID_PARAMETER; + } if (name[0] && path[0]) { size_t pathLength = strnlen(path, MAX_PATH); - drive = (DRIVE_DEVICE*) calloc(1, sizeof(DRIVE_DEVICE)); + drive = (DRIVE_DEVICE*)calloc(1, sizeof(DRIVE_DEVICE)); if (!drive) { @@ -896,7 +904,6 @@ static UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, } drive->device.type = RDPDR_DTYP_FILESYSTEM; - drive->device.name = name; drive->device.IRPRequest = drive_irp_request; drive->device.Free = drive_free; drive->rdpcontext = pEntryPoints->rdpcontext; @@ -911,11 +918,34 @@ static UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, goto out_error; } - for (i = 0; i <= length; i++) - Stream_Write_UINT8(drive->device.data, name[i] < 0 ? '_' : name[i]); + for (i = 0; i < length; i++) + { + /* Filter 2.2.1.3 Device Announce Header (DEVICE_ANNOUNCE) forbidden symbols */ + switch (name[i]) + { + case ':': + case '<': + case '>': + case '\"': + case '/': + case '\\': + case '|': + case ' ': + Stream_Write_UINT8(drive->device.data, '_'); + break; + default: + Stream_Write_UINT8(drive->device.data, (BYTE)name[i]); + break; + } + } + Stream_Write_UINT8(drive->device.data, '\0'); + + drive->device.name = (const char*)Stream_Buffer(drive->device.data); + if (!drive->device.name) + goto out_error; if ((pathLength > 1) && (path[pathLength - 1] == '/')) - pathLength --; + pathLength--; if (ConvertToUnicode(sys_code_page, 0, path, pathLength, &drive->path, 0) <= 0) { @@ -943,15 +973,14 @@ static UINT drive_register_drive_path(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, goto out_error; } - if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, - (DEVICE*) drive))) + if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)drive))) { - WLog_ERR(TAG, "RegisterDevice failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "RegisterDevice failed with error %" PRIu32 "!", error); goto out_error; } - if (!(drive->thread = CreateThread(NULL, 0, drive_thread_func, drive, - CREATE_SUSPENDED, NULL))) + if (!(drive->thread = + CreateThread(NULL, 0, drive_thread_func, drive, CREATE_SUSPENDED, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); goto out_error; @@ -967,9 +996,9 @@ out_error: } #ifdef BUILTIN_CHANNELS -#define DeviceServiceEntry drive_DeviceServiceEntry +#define DeviceServiceEntry drive_DeviceServiceEntry #else -#define DeviceServiceEntry FREERDP_API DeviceServiceEntry +#define DeviceServiceEntry FREERDP_API DeviceServiceEntry #endif /** @@ -988,7 +1017,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) char* bufdup; char* devdup; #endif - drive = (RDPDR_DRIVE*) pEntryPoints->device; + drive = (RDPDR_DRIVE*)pEntryPoints->device; #ifndef WIN32 sys_code_page = CP_UTF8; diff --git a/channels/echo/client/echo_main.c b/channels/echo/client/echo_main.c index a16089f..c8dc4d8 100644 --- a/channels/echo/client/echo_main.c +++ b/channels/echo/client/echo_main.c @@ -59,6 +59,7 @@ struct _ECHO_PLUGIN IWTSPlugin iface; ECHO_LISTENER_CALLBACK* listener_callback; + IWTSListener* listener; }; /** @@ -66,9 +67,9 @@ struct _ECHO_PLUGIN * * @return 0 on success, otherwise a Win32 error code */ -static UINT echo_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream *data) +static UINT echo_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data) { - ECHO_CHANNEL_CALLBACK* callback = (ECHO_CHANNEL_CALLBACK*) pChannelCallback; + ECHO_CHANNEL_CALLBACK* callback = (ECHO_CHANNEL_CALLBACK*)pChannelCallback; BYTE* pBuffer = Stream_Pointer(data); UINT32 cbSize = Stream_GetRemainingLength(data); @@ -83,7 +84,7 @@ static UINT echo_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, */ static UINT echo_on_close(IWTSVirtualChannelCallback* pChannelCallback) { - ECHO_CHANNEL_CALLBACK* callback = (ECHO_CHANNEL_CALLBACK*) pChannelCallback; + ECHO_CHANNEL_CALLBACK* callback = (ECHO_CHANNEL_CALLBACK*)pChannelCallback; free(callback); @@ -96,13 +97,13 @@ static UINT echo_on_close(IWTSVirtualChannelCallback* pChannelCallback) * @return 0 on success, otherwise a Win32 error code */ static UINT echo_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, - IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept, - IWTSVirtualChannelCallback** ppCallback) + IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept, + IWTSVirtualChannelCallback** ppCallback) { ECHO_CHANNEL_CALLBACK* callback; - ECHO_LISTENER_CALLBACK* listener_callback = (ECHO_LISTENER_CALLBACK*) pListenerCallback; + ECHO_LISTENER_CALLBACK* listener_callback = (ECHO_LISTENER_CALLBACK*)pListenerCallback; - callback = (ECHO_CHANNEL_CALLBACK*) calloc(1, sizeof(ECHO_CHANNEL_CALLBACK)); + callback = (ECHO_CHANNEL_CALLBACK*)calloc(1, sizeof(ECHO_CHANNEL_CALLBACK)); if (!callback) { @@ -116,7 +117,7 @@ static UINT echo_on_new_channel_connection(IWTSListenerCallback* pListenerCallba callback->channel_mgr = listener_callback->channel_mgr; callback->channel = pChannel; - *ppCallback = (IWTSVirtualChannelCallback*) callback; + *ppCallback = (IWTSVirtualChannelCallback*)callback; return CHANNEL_RC_OK; } @@ -128,9 +129,9 @@ static UINT echo_on_new_channel_connection(IWTSListenerCallback* pListenerCallba */ static UINT echo_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) { - ECHO_PLUGIN* echo = (ECHO_PLUGIN*) pPlugin; + ECHO_PLUGIN* echo = (ECHO_PLUGIN*)pPlugin; - echo->listener_callback = (ECHO_LISTENER_CALLBACK*) calloc(1, sizeof(ECHO_LISTENER_CALLBACK)); + echo->listener_callback = (ECHO_LISTENER_CALLBACK*)calloc(1, sizeof(ECHO_LISTENER_CALLBACK)); if (!echo->listener_callback) { @@ -142,8 +143,8 @@ static UINT echo_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage echo->listener_callback->plugin = pPlugin; echo->listener_callback->channel_mgr = pChannelMgr; - return pChannelMgr->CreateListener(pChannelMgr, "ECHO", 0, - (IWTSListenerCallback*) echo->listener_callback, NULL); + return pChannelMgr->CreateListener(pChannelMgr, "ECHO", 0, &echo->listener_callback->iface, + &echo->listener); } /** @@ -153,17 +154,22 @@ static UINT echo_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManage */ static UINT echo_plugin_terminated(IWTSPlugin* pPlugin) { - ECHO_PLUGIN* echo = (ECHO_PLUGIN*) pPlugin; - + ECHO_PLUGIN* echo = (ECHO_PLUGIN*)pPlugin; + if (echo && echo->listener_callback) + { + IWTSVirtualChannelManager* mgr = echo->listener_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, echo->listener); + } free(echo); return CHANNEL_RC_OK; } #ifdef BUILTIN_CHANNELS -#define DVCPluginEntry echo_DVCPluginEntry +#define DVCPluginEntry echo_DVCPluginEntry #else -#define DVCPluginEntry FREERDP_API DVCPluginEntry +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** @@ -176,11 +182,11 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) UINT status = CHANNEL_RC_OK; ECHO_PLUGIN* echo; - echo = (ECHO_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "echo"); + echo = (ECHO_PLUGIN*)pEntryPoints->GetPlugin(pEntryPoints, "echo"); if (!echo) { - echo = (ECHO_PLUGIN*) calloc(1, sizeof(ECHO_PLUGIN)); + echo = (ECHO_PLUGIN*)calloc(1, sizeof(ECHO_PLUGIN)); if (!echo) { @@ -193,7 +199,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) echo->iface.Disconnected = NULL; echo->iface.Terminated = echo_plugin_terminated; - status = pEntryPoints->RegisterPlugin(pEntryPoints, "echo", (IWTSPlugin*) echo); + status = pEntryPoints->RegisterPlugin(pEntryPoints, "echo", (IWTSPlugin*)echo); } return status; diff --git a/channels/echo/client/echo_main.h b/channels/echo/client/echo_main.h index 04cda41..06262b1 100644 --- a/channels/echo/client/echo_main.h +++ b/channels/echo/client/echo_main.h @@ -33,8 +33,10 @@ #ifdef WITH_DEBUG_DVC #define DEBUG_DVC(...) WLog_DBG(DVC_TAG, __VA_ARGS__) #else -#define DEBUG_DVC(...) do { } while (0) +#define DEBUG_DVC(...) \ + do \ + { \ + } while (0) #endif #endif /* FREERDP_CHANNEL_ECHO_CLIENT_MAIN_H */ - diff --git a/channels/echo/server/echo_main.c b/channels/echo/server/echo_main.c index b3f8eb0..55e2fa2 100644 --- a/channels/echo/server/echo_main.c +++ b/channels/echo/server/echo_main.c @@ -66,14 +66,14 @@ static UINT echo_server_open_channel(echo_server* echo) DWORD BytesReturned = 0; PULONG pSessionId = NULL; - if (WTSQuerySessionInformationA(echo->context.vcm, WTS_CURRENT_SESSION, - WTSSessionId, (LPSTR*) &pSessionId, &BytesReturned) == FALSE) + if (WTSQuerySessionInformationA(echo->context.vcm, WTS_CURRENT_SESSION, WTSSessionId, + (LPSTR*)&pSessionId, &BytesReturned) == FALSE) { WLog_ERR(TAG, "WTSQuerySessionInformationA failed!"); return ERROR_INTERNAL_ERROR; } - echo->SessionId = (DWORD) * pSessionId; + echo->SessionId = (DWORD)*pSessionId; WTSFreeMemory(pSessionId); hEvent = WTSVirtualChannelManagerGetEventHandle(echo->context.vcm); StartTick = GetTickCount(); @@ -83,12 +83,12 @@ static UINT echo_server_open_channel(echo_server* echo) if (WaitForSingleObject(hEvent, 1000) == WAIT_FAILED) { Error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", Error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", Error); return Error; } - echo->echo_channel = WTSVirtualChannelOpenEx(echo->SessionId, - "ECHO", WTS_CHANNEL_OPTION_DYNAMIC); + echo->echo_channel = + WTSVirtualChannelOpenEx(echo->SessionId, "ECHO", WTS_CHANNEL_OPTION_DYNAMIC); if (echo->echo_channel) break; @@ -114,19 +114,19 @@ static DWORD WINAPI echo_server_thread_func(LPVOID arg) BOOL ready = FALSE; HANDLE ChannelEvent; DWORD BytesReturned = 0; - echo_server* echo = (echo_server*) arg; + echo_server* echo = (echo_server*)arg; UINT error; DWORD status; if ((error = echo_server_open_channel(echo))) { UINT error2 = 0; - WLog_ERR(TAG, "echo_server_open_channel failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "echo_server_open_channel failed with error %" PRIu32 "!", error); IFCALLRET(echo->context.OpenResult, error2, &echo->context, ECHO_SERVER_OPEN_RESULT_NOTSUPPORTED); if (error2) - WLog_ERR(TAG, "echo server's OpenResult callback failed with error %"PRIu32"", + WLog_ERR(TAG, "echo server's OpenResult callback failed with error %" PRIu32 "", error2); goto out; @@ -158,7 +158,7 @@ static DWORD WINAPI echo_server_thread_func(LPVOID arg) if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForMultipleObjects failed with error %" PRIu32 "", error); break; } @@ -168,7 +168,7 @@ static DWORD WINAPI echo_server_thread_func(LPVOID arg) ECHO_SERVER_OPEN_RESULT_CLOSED); if (error) - WLog_ERR(TAG, "OpenResult failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "OpenResult failed with error %" PRIu32 "!", error); break; } @@ -180,21 +180,20 @@ static DWORD WINAPI echo_server_thread_func(LPVOID arg) ECHO_SERVER_OPEN_RESULT_ERROR); if (error) - WLog_ERR(TAG, "OpenResult failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "OpenResult failed with error %" PRIu32 "!", error); break; } - ready = *((BOOL*) buffer); + ready = *((BOOL*)buffer); WTSFreeMemory(buffer); if (ready) { - IFCALLRET(echo->context.OpenResult, error, &echo->context, - ECHO_SERVER_OPEN_RESULT_OK); + IFCALLRET(echo->context.OpenResult, error, &echo->context, ECHO_SERVER_OPEN_RESULT_OK); if (error) - WLog_ERR(TAG, "OpenResult failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "OpenResult failed with error %" PRIu32 "!", error); break; } @@ -217,7 +216,7 @@ static DWORD WINAPI echo_server_thread_func(LPVOID arg) if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForMultipleObjects failed with error %" PRIu32 "", error); break; } @@ -237,20 +236,20 @@ static DWORD WINAPI echo_server_thread_func(LPVOID arg) break; } - if (WTSVirtualChannelRead(echo->echo_channel, 0, (PCHAR) Stream_Buffer(s), - (ULONG) Stream_Capacity(s), &BytesReturned) == FALSE) + if (WTSVirtualChannelRead(echo->echo_channel, 0, (PCHAR)Stream_Buffer(s), + (ULONG)Stream_Capacity(s), &BytesReturned) == FALSE) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); error = ERROR_INTERNAL_ERROR; break; } - IFCALLRET(echo->context.Response, error, &echo->context, - (BYTE*) Stream_Buffer(s), BytesReturned); + IFCALLRET(echo->context.Response, error, &echo->context, (BYTE*)Stream_Buffer(s), + BytesReturned); if (error) { - WLog_ERR(TAG, "Response failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "Response failed with error %" PRIu32 "!", error); break; } } @@ -275,7 +274,7 @@ out: */ static UINT echo_server_open(echo_server_context* context) { - echo_server* echo = (echo_server*) context; + echo_server* echo = (echo_server*)context; if (echo->thread == NULL) { @@ -285,7 +284,7 @@ static UINT echo_server_open(echo_server_context* context) return ERROR_INTERNAL_ERROR; } - if (!(echo->thread = CreateThread(NULL, 0, echo_server_thread_func, (void*) echo, 0, NULL))) + if (!(echo->thread = CreateThread(NULL, 0, echo_server_thread_func, (void*)echo, 0, NULL))) { WLog_ERR(TAG, "CreateEvent failed!"); CloseHandle(echo->stopEvent); @@ -305,7 +304,7 @@ static UINT echo_server_open(echo_server_context* context) static UINT echo_server_close(echo_server_context* context) { UINT error = CHANNEL_RC_OK; - echo_server* echo = (echo_server*) context; + echo_server* echo = (echo_server*)context; if (echo->thread) { @@ -314,7 +313,7 @@ static UINT echo_server_close(echo_server_context* context) if (WaitForSingleObject(echo->thread, INFINITE) == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error); return error; } @@ -327,17 +326,16 @@ static UINT echo_server_close(echo_server_context* context) return error; } -static BOOL echo_server_request(echo_server_context* context, - const BYTE* buffer, UINT32 length) +static BOOL echo_server_request(echo_server_context* context, const BYTE* buffer, UINT32 length) { - echo_server* echo = (echo_server*) context; - return WTSVirtualChannelWrite(echo->echo_channel, (PCHAR) buffer, length, NULL); + echo_server* echo = (echo_server*)context; + return WTSVirtualChannelWrite(echo->echo_channel, (PCHAR)buffer, length, NULL); } echo_server_context* echo_server_context_new(HANDLE vcm) { echo_server* echo; - echo = (echo_server*) calloc(1, sizeof(echo_server)); + echo = (echo_server*)calloc(1, sizeof(echo_server)); if (echo) { @@ -349,12 +347,12 @@ echo_server_context* echo_server_context_new(HANDLE vcm) else WLog_ERR(TAG, "calloc failed!"); - return (echo_server_context*) echo; + return (echo_server_context*)echo; } void echo_server_context_free(echo_server_context* context) { - echo_server* echo = (echo_server*) context; + echo_server* echo = (echo_server*)context; echo_server_close(context); free(echo); } diff --git a/channels/encomsp/client/encomsp_main.c b/channels/encomsp/client/encomsp_main.c index d595fef..dc21720 100644 --- a/channels/encomsp/client/encomsp_main.c +++ b/channels/encomsp/client/encomsp_main.c @@ -31,6 +31,21 @@ #include "encomsp_main.h" +struct encomsp_plugin +{ + CHANNEL_DEF channelDef; + CHANNEL_ENTRY_POINTS_FREERDP_EX channelEntryPoints; + + EncomspClientContext* context; + + HANDLE thread; + wStream* data_in; + void* InitHandle; + DWORD OpenHandle; + wMessageQueue* queue; + rdpContext* rdpcontext; +}; + /** * Function description * @@ -44,7 +59,7 @@ static UINT encomsp_read_header(wStream* s, ENCOMSP_ORDER_HEADER* header) return ERROR_INVALID_DATA; } - Stream_Read_UINT16(s, header->Type); /* Type (2 bytes) */ + Stream_Read_UINT16(s, header->Type); /* Type (2 bytes) */ Stream_Read_UINT16(s, header->Length); /* Length (2 bytes) */ return CHANNEL_RC_OK; } @@ -54,9 +69,9 @@ static UINT encomsp_read_header(wStream* s, ENCOMSP_ORDER_HEADER* header) * * @return 0 on success, otherwise a Win32 error code */ -static UINT encomsp_write_header(wStream* s, ENCOMSP_ORDER_HEADER* header) +static UINT encomsp_write_header(wStream* s, const ENCOMSP_ORDER_HEADER* header) { - Stream_Write_UINT16(s, header->Type); /* Type (2 bytes) */ + Stream_Write_UINT16(s, header->Type); /* Type (2 bytes) */ Stream_Write_UINT16(s, header->Length); /* Length (2 bytes) */ return CHANNEL_RC_OK; } @@ -80,7 +95,7 @@ static UINT encomsp_read_unicode_string(wStream* s, ENCOMSP_UNICODE_STRING* str) if (str->cchString > 1024) { - WLog_ERR(TAG, "cchString was %"PRIu16" but has to be < 1025!", str->cchString); + WLog_ERR(TAG, "cchString was %" PRIu16 " but has to be < 1025!", str->cchString); return ERROR_INVALID_DATA; } @@ -94,11 +109,10 @@ static UINT encomsp_read_unicode_string(wStream* s, ENCOMSP_UNICODE_STRING* str) return CHANNEL_RC_OK; } -static EncomspClientContext* encomsp_get_client_interface( - encomspPlugin* encomsp) +static EncomspClientContext* encomsp_get_client_interface(encomspPlugin* encomsp) { EncomspClientContext* pInterface; - pInterface = (EncomspClientContext*) encomsp->channelEntryPoints.pInterface; + pInterface = (EncomspClientContext*)encomsp->channelEntryPoints.pInterface; return pInterface; } @@ -112,20 +126,24 @@ static UINT encomsp_virtual_channel_write(encomspPlugin* encomsp, wStream* s) UINT status; if (!encomsp) + { + Stream_Free(s, TRUE); return ERROR_INVALID_HANDLE; + } #if 0 WLog_INFO(TAG, "EncomspWrite (%"PRIuz")", Stream_Length(s)); winpr_HexDump(Stream_Buffer(s), Stream_Length(s)); #endif - status = encomsp->channelEntryPoints.pVirtualChannelWriteEx(encomsp->InitHandle, - encomsp->OpenHandle, - Stream_Buffer(s), (UINT32) Stream_Length(s), s); + status = encomsp->channelEntryPoints.pVirtualChannelWriteEx( + encomsp->InitHandle, encomsp->OpenHandle, Stream_Buffer(s), (UINT32)Stream_Length(s), s); if (status != CHANNEL_RC_OK) - WLog_ERR(TAG, "VirtualChannelWriteEx failed with %s [%08"PRIX32"]", + { + Stream_Free(s, TRUE); + WLog_ERR(TAG, "VirtualChannelWriteEx failed with %s [%08" PRIX32 "]", WTSErrorToString(status), status); - + } return status; } @@ -135,9 +153,9 @@ static UINT encomsp_virtual_channel_write(encomspPlugin* encomsp, wStream* s) * @return 0 on success, otherwise a Win32 error code */ static UINT encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp, wStream* s, - ENCOMSP_ORDER_HEADER* header) + const ENCOMSP_ORDER_HEADER* header) { - int beg, end; + size_t beg, end, pos; EncomspClientContext* context; ENCOMSP_FILTER_UPDATED_PDU pdu; UINT error = CHANNEL_RC_OK; @@ -146,7 +164,10 @@ static UINT encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp, wStream* s, if (!context) return ERROR_INVALID_HANDLE; - beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; + pos = Stream_GetPosition(s); + if (pos < ENCOMSP_ORDER_HEADER_SIZE) + return ERROR_INVALID_DATA; + beg = pos - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 1) @@ -156,7 +177,7 @@ static UINT encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp, wStream* s, } Stream_Read_UINT8(s, pdu.Flags); /* Flags (1 byte) */ - end = (int) Stream_GetPosition(s); + end = Stream_GetPosition(s); if ((beg + header->Length) < end) { @@ -178,7 +199,7 @@ static UINT encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp, wStream* s, IFCALLRET(context->FilterUpdated, error, context, &pdu); if (error) - WLog_ERR(TAG, "context->FilterUpdated failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context->FilterUpdated failed with error %" PRIu32 "", error); return error; } @@ -188,10 +209,10 @@ static UINT encomsp_recv_filter_updated_pdu(encomspPlugin* encomsp, wStream* s, * * @return 0 on success, otherwise a Win32 error code */ -static UINT encomsp_recv_application_created_pdu(encomspPlugin* encomsp, - wStream* s, ENCOMSP_ORDER_HEADER* header) +static UINT encomsp_recv_application_created_pdu(encomspPlugin* encomsp, wStream* s, + const ENCOMSP_ORDER_HEADER* header) { - int beg, end; + size_t beg, end, pos; EncomspClientContext* context; ENCOMSP_APPLICATION_CREATED_PDU pdu; UINT error; @@ -200,25 +221,28 @@ static UINT encomsp_recv_application_created_pdu(encomspPlugin* encomsp, if (!context) return ERROR_INVALID_HANDLE; - beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; - CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); - if (Stream_GetRemainingLength(s) < 6) { WLog_ERR(TAG, "Not enough data!"); return ERROR_INVALID_DATA; } + pos = Stream_GetPosition(s); + if (pos < ENCOMSP_ORDER_HEADER_SIZE) + return ERROR_INVALID_DATA; + beg = pos - ENCOMSP_ORDER_HEADER_SIZE; + CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); + Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */ Stream_Read_UINT32(s, pdu.AppId); /* AppId (4 bytes) */ if ((error = encomsp_read_unicode_string(s, &(pdu.Name)))) { - WLog_ERR(TAG, "encomsp_read_unicode_string failed with error %"PRIu32"", error); + WLog_ERR(TAG, "encomsp_read_unicode_string failed with error %" PRIu32 "", error); return error; } - end = (int) Stream_GetPosition(s); + end = Stream_GetPosition(s); if ((beg + header->Length) < end) { @@ -240,7 +264,7 @@ static UINT encomsp_recv_application_created_pdu(encomspPlugin* encomsp, IFCALLRET(context->ApplicationCreated, error, context, &pdu); if (error) - WLog_ERR(TAG, "context->ApplicationCreated failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context->ApplicationCreated failed with error %" PRIu32 "", error); return error; } @@ -250,10 +274,10 @@ static UINT encomsp_recv_application_created_pdu(encomspPlugin* encomsp, * * @return 0 on success, otherwise a Win32 error code */ -static UINT encomsp_recv_application_removed_pdu(encomspPlugin* encomsp, - wStream* s, ENCOMSP_ORDER_HEADER* header) +static UINT encomsp_recv_application_removed_pdu(encomspPlugin* encomsp, wStream* s, + const ENCOMSP_ORDER_HEADER* header) { - int beg, end; + size_t beg, end, pos; EncomspClientContext* context; ENCOMSP_APPLICATION_REMOVED_PDU pdu; UINT error = CHANNEL_RC_OK; @@ -262,7 +286,10 @@ static UINT encomsp_recv_application_removed_pdu(encomspPlugin* encomsp, if (!context) return ERROR_INVALID_HANDLE; - beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; + pos = Stream_GetPosition(s); + if (pos < ENCOMSP_ORDER_HEADER_SIZE) + return ERROR_INVALID_DATA; + beg = pos - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 4) @@ -272,7 +299,7 @@ static UINT encomsp_recv_application_removed_pdu(encomspPlugin* encomsp, } Stream_Read_UINT32(s, pdu.AppId); /* AppId (4 bytes) */ - end = (int) Stream_GetPosition(s); + end = Stream_GetPosition(s); if ((beg + header->Length) < end) { @@ -294,7 +321,7 @@ static UINT encomsp_recv_application_removed_pdu(encomspPlugin* encomsp, IFCALLRET(context->ApplicationRemoved, error, context, &pdu); if (error) - WLog_ERR(TAG, "context->ApplicationRemoved failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context->ApplicationRemoved failed with error %" PRIu32 "", error); return error; } @@ -305,9 +332,9 @@ static UINT encomsp_recv_application_removed_pdu(encomspPlugin* encomsp, * @return 0 on success, otherwise a Win32 error code */ static UINT encomsp_recv_window_created_pdu(encomspPlugin* encomsp, wStream* s, - ENCOMSP_ORDER_HEADER* header) + const ENCOMSP_ORDER_HEADER* header) { - int beg, end; + size_t beg, end, pos; EncomspClientContext* context; ENCOMSP_WINDOW_CREATED_PDU pdu; UINT error; @@ -316,7 +343,10 @@ static UINT encomsp_recv_window_created_pdu(encomspPlugin* encomsp, wStream* s, if (!context) return ERROR_INVALID_HANDLE; - beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; + pos = Stream_GetPosition(s); + if (pos < ENCOMSP_ORDER_HEADER_SIZE) + return ERROR_INVALID_DATA; + beg = pos - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 10) @@ -331,11 +361,11 @@ static UINT encomsp_recv_window_created_pdu(encomspPlugin* encomsp, wStream* s, if ((error = encomsp_read_unicode_string(s, &(pdu.Name)))) { - WLog_ERR(TAG, "encomsp_read_unicode_string failed with error %"PRIu32"", error); + WLog_ERR(TAG, "encomsp_read_unicode_string failed with error %" PRIu32 "", error); return error; } - end = (int) Stream_GetPosition(s); + end = Stream_GetPosition(s); if ((beg + header->Length) < end) { @@ -357,7 +387,7 @@ static UINT encomsp_recv_window_created_pdu(encomspPlugin* encomsp, wStream* s, IFCALLRET(context->WindowCreated, error, context, &pdu); if (error) - WLog_ERR(TAG, "context->WindowCreated failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context->WindowCreated failed with error %" PRIu32 "", error); return error; } @@ -368,9 +398,9 @@ static UINT encomsp_recv_window_created_pdu(encomspPlugin* encomsp, wStream* s, * @return 0 on success, otherwise a Win32 error code */ static UINT encomsp_recv_window_removed_pdu(encomspPlugin* encomsp, wStream* s, - ENCOMSP_ORDER_HEADER* header) + const ENCOMSP_ORDER_HEADER* header) { - int beg, end; + size_t beg, end, pos; EncomspClientContext* context; ENCOMSP_WINDOW_REMOVED_PDU pdu; UINT error = CHANNEL_RC_OK; @@ -379,7 +409,10 @@ static UINT encomsp_recv_window_removed_pdu(encomspPlugin* encomsp, wStream* s, if (!context) return ERROR_INVALID_HANDLE; - beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; + pos = Stream_GetPosition(s); + if (pos < ENCOMSP_ORDER_HEADER_SIZE) + return ERROR_INVALID_DATA; + beg = pos - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 4) @@ -389,7 +422,7 @@ static UINT encomsp_recv_window_removed_pdu(encomspPlugin* encomsp, wStream* s, } Stream_Read_UINT32(s, pdu.WndId); /* WndId (4 bytes) */ - end = (int) Stream_GetPosition(s); + end = Stream_GetPosition(s); if ((beg + header->Length) < end) { @@ -411,7 +444,7 @@ static UINT encomsp_recv_window_removed_pdu(encomspPlugin* encomsp, wStream* s, IFCALLRET(context->WindowRemoved, error, context, &pdu); if (error) - WLog_ERR(TAG, "context->WindowRemoved failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context->WindowRemoved failed with error %" PRIu32 "", error); return error; } @@ -422,9 +455,9 @@ static UINT encomsp_recv_window_removed_pdu(encomspPlugin* encomsp, wStream* s, * @return 0 on success, otherwise a Win32 error code */ static UINT encomsp_recv_show_window_pdu(encomspPlugin* encomsp, wStream* s, - ENCOMSP_ORDER_HEADER* header) + const ENCOMSP_ORDER_HEADER* header) { - int beg, end; + size_t beg, end, pos; EncomspClientContext* context; ENCOMSP_SHOW_WINDOW_PDU pdu; UINT error = CHANNEL_RC_OK; @@ -433,7 +466,10 @@ static UINT encomsp_recv_show_window_pdu(encomspPlugin* encomsp, wStream* s, if (!context) return ERROR_INVALID_HANDLE; - beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; + pos = Stream_GetPosition(s); + if (pos < ENCOMSP_ORDER_HEADER_SIZE) + return ERROR_INVALID_DATA; + beg = pos - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 4) @@ -443,7 +479,7 @@ static UINT encomsp_recv_show_window_pdu(encomspPlugin* encomsp, wStream* s, } Stream_Read_UINT32(s, pdu.WndId); /* WndId (4 bytes) */ - end = (int) Stream_GetPosition(s); + end = Stream_GetPosition(s); if ((beg + header->Length) < end) { @@ -465,7 +501,7 @@ static UINT encomsp_recv_show_window_pdu(encomspPlugin* encomsp, wStream* s, IFCALLRET(context->ShowWindow, error, context, &pdu); if (error) - WLog_ERR(TAG, "context->ShowWindow failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context->ShowWindow failed with error %" PRIu32 "", error); return error; } @@ -475,10 +511,10 @@ static UINT encomsp_recv_show_window_pdu(encomspPlugin* encomsp, wStream* s, * * @return 0 on success, otherwise a Win32 error code */ -static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp, - wStream* s, ENCOMSP_ORDER_HEADER* header) +static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp, wStream* s, + const ENCOMSP_ORDER_HEADER* header) { - int beg, end; + size_t beg, end, pos; EncomspClientContext* context; ENCOMSP_PARTICIPANT_CREATED_PDU pdu; UINT error; @@ -487,7 +523,10 @@ static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp, if (!context) return ERROR_INVALID_HANDLE; - beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; + pos = Stream_GetPosition(s); + if (pos < ENCOMSP_ORDER_HEADER_SIZE) + return ERROR_INVALID_DATA; + beg = pos - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 10) @@ -497,16 +536,16 @@ static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp, } Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */ - Stream_Read_UINT32(s, pdu.GroupId); /* GroupId (4 bytes) */ - Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */ + Stream_Read_UINT32(s, pdu.GroupId); /* GroupId (4 bytes) */ + Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */ if ((error = encomsp_read_unicode_string(s, &(pdu.FriendlyName)))) { - WLog_ERR(TAG, "encomsp_read_unicode_string failed with error %"PRIu32"", error); + WLog_ERR(TAG, "encomsp_read_unicode_string failed with error %" PRIu32 "", error); return error; } - end = (int) Stream_GetPosition(s); + end = Stream_GetPosition(s); if ((beg + header->Length) < end) { @@ -528,7 +567,7 @@ static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp, IFCALLRET(context->ParticipantCreated, error, context, &pdu); if (error) - WLog_ERR(TAG, "context->ParticipantCreated failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context->ParticipantCreated failed with error %" PRIu32 "", error); return error; } @@ -538,10 +577,10 @@ static UINT encomsp_recv_participant_created_pdu(encomspPlugin* encomsp, * * @return 0 on success, otherwise a Win32 error code */ -static UINT encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp, - wStream* s, ENCOMSP_ORDER_HEADER* header) +static UINT encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp, wStream* s, + const ENCOMSP_ORDER_HEADER* header) { - int beg, end; + size_t beg, end; EncomspClientContext* context; ENCOMSP_PARTICIPANT_REMOVED_PDU pdu; UINT error = CHANNEL_RC_OK; @@ -550,19 +589,19 @@ static UINT encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp, if (!context) return ERROR_INVALID_HANDLE; - beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; - CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); - if (Stream_GetRemainingLength(s) < 12) { WLog_ERR(TAG, "Not enough data!"); return ERROR_INVALID_DATA; } + beg = (Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; + CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); + Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */ - Stream_Read_UINT32(s, pdu.DiscType); /* DiscType (4 bytes) */ - Stream_Read_UINT32(s, pdu.DiscCode); /* DiscCode (4 bytes) */ - end = (int) Stream_GetPosition(s); + Stream_Read_UINT32(s, pdu.DiscType); /* DiscType (4 bytes) */ + Stream_Read_UINT32(s, pdu.DiscCode); /* DiscCode (4 bytes) */ + end = Stream_GetPosition(s); if ((beg + header->Length) < end) { @@ -584,7 +623,7 @@ static UINT encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp, IFCALLRET(context->ParticipantRemoved, error, context, &pdu); if (error) - WLog_ERR(TAG, "context->ParticipantRemoved failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context->ParticipantRemoved failed with error %" PRIu32 "", error); return error; } @@ -594,10 +633,10 @@ static UINT encomsp_recv_participant_removed_pdu(encomspPlugin* encomsp, * * @return 0 on success, otherwise a Win32 error code */ -static UINT encomsp_recv_change_participant_control_level_pdu( - encomspPlugin* encomsp, wStream* s, ENCOMSP_ORDER_HEADER* header) +static UINT encomsp_recv_change_participant_control_level_pdu(encomspPlugin* encomsp, wStream* s, + const ENCOMSP_ORDER_HEADER* header) { - int beg, end; + size_t beg, end, pos; EncomspClientContext* context; ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU pdu; UINT error = CHANNEL_RC_OK; @@ -606,7 +645,10 @@ static UINT encomsp_recv_change_participant_control_level_pdu( if (!context) return ERROR_INVALID_HANDLE; - beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; + pos = Stream_GetPosition(s); + if (pos < ENCOMSP_ORDER_HEADER_SIZE) + return ERROR_INVALID_DATA; + beg = pos - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 6) @@ -615,9 +657,9 @@ static UINT encomsp_recv_change_participant_control_level_pdu( return ERROR_INVALID_DATA; } - Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */ + Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */ Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */ - end = (int) Stream_GetPosition(s); + end = Stream_GetPosition(s); if ((beg + header->Length) < end) { @@ -639,7 +681,7 @@ static UINT encomsp_recv_change_participant_control_level_pdu( IFCALLRET(context->ChangeParticipantControlLevel, error, context, &pdu); if (error) - WLog_ERR(TAG, "context->ChangeParticipantControlLevel failed with error %"PRIu32"", + WLog_ERR(TAG, "context->ChangeParticipantControlLevel failed with error %" PRIu32 "", error); return error; @@ -651,16 +693,17 @@ static UINT encomsp_recv_change_participant_control_level_pdu( * @return 0 on success, otherwise a Win32 error code */ static UINT encomsp_send_change_participant_control_level_pdu( - EncomspClientContext* context, - ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU* pdu) + EncomspClientContext* context, const ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU* pdu) { wStream* s; encomspPlugin* encomsp; UINT error; - encomsp = (encomspPlugin*) context->handle; - pdu->Type = ODTYPE_PARTICIPANT_CTRL_CHANGED; - pdu->Length = ENCOMSP_ORDER_HEADER_SIZE + 6; - s = Stream_New(NULL, pdu->Length); + ENCOMSP_ORDER_HEADER header; + + encomsp = (encomspPlugin*)context->handle; + header.Type = ODTYPE_PARTICIPANT_CTRL_CHANGED; + header.Length = ENCOMSP_ORDER_HEADER_SIZE + 6; + s = Stream_New(NULL, header.Length); if (!s) { @@ -668,13 +711,13 @@ static UINT encomsp_send_change_participant_control_level_pdu( return CHANNEL_RC_NO_MEMORY; } - if ((error = encomsp_write_header(s, (ENCOMSP_ORDER_HEADER*) pdu))) + if ((error = encomsp_write_header(s, &header))) { - WLog_ERR(TAG, "encomsp_write_header failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "encomsp_write_header failed with error %" PRIu32 "!", error); return error; } - Stream_Write_UINT16(s, pdu->Flags); /* Flags (2 bytes) */ + Stream_Write_UINT16(s, pdu->Flags); /* Flags (2 bytes) */ Stream_Write_UINT32(s, pdu->ParticipantId); /* ParticipantId (4 bytes) */ Stream_SealLength(s); return encomsp_virtual_channel_write(encomsp, s); @@ -685,10 +728,10 @@ static UINT encomsp_send_change_participant_control_level_pdu( * * @return 0 on success, otherwise a Win32 error code */ -static UINT encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp, - wStream* s, ENCOMSP_ORDER_HEADER* header) +static UINT encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp, wStream* s, + const ENCOMSP_ORDER_HEADER* header) { - int beg, end; + size_t beg, end, pos; EncomspClientContext* context; ENCOMSP_GRAPHICS_STREAM_PAUSED_PDU pdu; UINT error = CHANNEL_RC_OK; @@ -697,9 +740,12 @@ static UINT encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp, if (!context) return ERROR_INVALID_HANDLE; - beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; + pos = Stream_GetPosition(s); + if (pos < ENCOMSP_ORDER_HEADER_SIZE) + return ERROR_INVALID_DATA; + beg = pos - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); - end = (int) Stream_GetPosition(s); + end = Stream_GetPosition(s); if ((beg + header->Length) < end) { @@ -721,7 +767,7 @@ static UINT encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp, IFCALLRET(context->GraphicsStreamPaused, error, context, &pdu); if (error) - WLog_ERR(TAG, "context->GraphicsStreamPaused failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context->GraphicsStreamPaused failed with error %" PRIu32 "", error); return error; } @@ -731,10 +777,10 @@ static UINT encomsp_recv_graphics_stream_paused_pdu(encomspPlugin* encomsp, * * @return 0 on success, otherwise a Win32 error code */ -static UINT encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp, - wStream* s, ENCOMSP_ORDER_HEADER* header) +static UINT encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp, wStream* s, + const ENCOMSP_ORDER_HEADER* header) { - int beg, end; + size_t beg, end, pos; EncomspClientContext* context; ENCOMSP_GRAPHICS_STREAM_RESUMED_PDU pdu; UINT error = CHANNEL_RC_OK; @@ -743,9 +789,12 @@ static UINT encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp, if (!context) return ERROR_INVALID_HANDLE; - beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; + pos = Stream_GetPosition(s); + if (pos < ENCOMSP_ORDER_HEADER_SIZE) + return ERROR_INVALID_DATA; + beg = pos - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); - end = (int) Stream_GetPosition(s); + end = Stream_GetPosition(s); if ((beg + header->Length) < end) { @@ -767,7 +816,7 @@ static UINT encomsp_recv_graphics_stream_resumed_pdu(encomspPlugin* encomsp, IFCALLRET(context->GraphicsStreamResumed, error, context, &pdu); if (error) - WLog_ERR(TAG, "context->GraphicsStreamResumed failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context->GraphicsStreamResumed failed with error %" PRIu32 "", error); return error; } @@ -786,18 +835,20 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s) { if ((error = encomsp_read_header(s, &header))) { - WLog_ERR(TAG, "encomsp_read_header failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "encomsp_read_header failed with error %" PRIu32 "!", error); return error; } - //WLog_DBG(TAG, "EncomspReceive: Type: %"PRIu16" Length: %"PRIu16"", header.Type, header.Length); + // WLog_DBG(TAG, "EncomspReceive: Type: %"PRIu16" Length: %"PRIu16"", header.Type, + // header.Length); switch (header.Type) { case ODTYPE_FILTER_STATE_UPDATED: if ((error = encomsp_recv_filter_updated_pdu(encomsp, s, &header))) { - WLog_ERR(TAG, "encomsp_recv_filter_updated_pdu failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "encomsp_recv_filter_updated_pdu failed with error %" PRIu32 "!", + error); return error; } @@ -806,7 +857,8 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s) case ODTYPE_APP_REMOVED: if ((error = encomsp_recv_application_removed_pdu(encomsp, s, &header))) { - WLog_ERR(TAG, "encomsp_recv_application_removed_pdu failed with error %"PRIu32"!", + WLog_ERR(TAG, + "encomsp_recv_application_removed_pdu failed with error %" PRIu32 "!", error); return error; } @@ -816,7 +868,8 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s) case ODTYPE_APP_CREATED: if ((error = encomsp_recv_application_created_pdu(encomsp, s, &header))) { - WLog_ERR(TAG, "encomsp_recv_application_removed_pdu failed with error %"PRIu32"!", + WLog_ERR(TAG, + "encomsp_recv_application_removed_pdu failed with error %" PRIu32 "!", error); return error; } @@ -826,7 +879,8 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s) case ODTYPE_WND_REMOVED: if ((error = encomsp_recv_window_removed_pdu(encomsp, s, &header))) { - WLog_ERR(TAG, "encomsp_recv_window_removed_pdu failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "encomsp_recv_window_removed_pdu failed with error %" PRIu32 "!", + error); return error; } @@ -835,7 +889,8 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s) case ODTYPE_WND_CREATED: if ((error = encomsp_recv_window_created_pdu(encomsp, s, &header))) { - WLog_ERR(TAG, "encomsp_recv_window_created_pdu failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "encomsp_recv_window_created_pdu failed with error %" PRIu32 "!", + error); return error; } @@ -844,7 +899,8 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s) case ODTYPE_WND_SHOW: if ((error = encomsp_recv_show_window_pdu(encomsp, s, &header))) { - WLog_ERR(TAG, "encomsp_recv_show_window_pdu failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "encomsp_recv_show_window_pdu failed with error %" PRIu32 "!", + error); return error; } @@ -853,7 +909,8 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s) case ODTYPE_PARTICIPANT_REMOVED: if ((error = encomsp_recv_participant_removed_pdu(encomsp, s, &header))) { - WLog_ERR(TAG, "encomsp_recv_participant_removed_pdu failed with error %"PRIu32"!", + WLog_ERR(TAG, + "encomsp_recv_participant_removed_pdu failed with error %" PRIu32 "!", error); return error; } @@ -863,7 +920,8 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s) case ODTYPE_PARTICIPANT_CREATED: if ((error = encomsp_recv_participant_created_pdu(encomsp, s, &header))) { - WLog_ERR(TAG, "encomsp_recv_participant_created_pdu failed with error %"PRIu32"!", + WLog_ERR(TAG, + "encomsp_recv_participant_created_pdu failed with error %" PRIu32 "!", error); return error; } @@ -871,11 +929,12 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s) break; case ODTYPE_PARTICIPANT_CTRL_CHANGED: - if ((error = encomsp_recv_change_participant_control_level_pdu(encomsp, s, - &header))) + if ((error = + encomsp_recv_change_participant_control_level_pdu(encomsp, s, &header))) { WLog_ERR(TAG, - "encomsp_recv_change_participant_control_level_pdu failed with error %"PRIu32"!", + "encomsp_recv_change_participant_control_level_pdu failed with error " + "%" PRIu32 "!", error); return error; } @@ -885,7 +944,9 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s) case ODTYPE_GRAPHICS_STREAM_PAUSED: if ((error = encomsp_recv_graphics_stream_paused_pdu(encomsp, s, &header))) { - WLog_ERR(TAG, "encomsp_recv_graphics_stream_paused_pdu failed with error %"PRIu32"!", + WLog_ERR(TAG, + "encomsp_recv_graphics_stream_paused_pdu failed with error %" PRIu32 + "!", error); return error; } @@ -895,7 +956,9 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s) case ODTYPE_GRAPHICS_STREAM_RESUMED: if ((error = encomsp_recv_graphics_stream_resumed_pdu(encomsp, s, &header))) { - WLog_ERR(TAG, "encomsp_recv_graphics_stream_resumed_pdu failed with error %"PRIu32"!", + WLog_ERR(TAG, + "encomsp_recv_graphics_stream_resumed_pdu failed with error %" PRIu32 + "!", error); return error; } @@ -903,9 +966,8 @@ static UINT encomsp_process_receive(encomspPlugin* encomsp, wStream* s) break; default: - WLog_ERR(TAG, "header.Type %"PRIu16" not found", header.Type); + WLog_ERR(TAG, "header.Type %" PRIu16 " not found", header.Type); return ERROR_INVALID_DATA; - break; } } @@ -921,8 +983,9 @@ static void encomsp_process_connect(encomspPlugin* encomsp) * * @return 0 on success, otherwise a Win32 error code */ -static UINT encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp, - void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) +static UINT encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp, const void* pData, + UINT32 dataLength, UINT32 totalLength, + UINT32 dataFlags) { wStream* data_in; @@ -945,7 +1008,7 @@ static UINT encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp, data_in = encomsp->data_in; - if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength)) + if (!Stream_EnsureRemainingCapacity(data_in, dataLength)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); return ERROR_INTERNAL_ERROR; @@ -957,7 +1020,7 @@ static UINT encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp, { if (Stream_Capacity(data_in) != Stream_GetPosition(data_in)) { - WLog_ERR(TAG, "encomsp_plugin_process_received: read error"); + WLog_ERR(TAG, "encomsp_plugin_process_received: read error"); return ERROR_INVALID_DATA; } @@ -965,7 +1028,7 @@ static UINT encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp, Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); - if (!MessageQueue_Post(encomsp->queue, NULL, 0, (void*) data_in, NULL)) + if (!MessageQueue_Post(encomsp->queue, NULL, 0, (void*)data_in, NULL)) { WLog_ERR(TAG, "MessageQueue_Post failed!"); return ERROR_INTERNAL_ERROR; @@ -976,36 +1039,45 @@ static UINT encomsp_virtual_channel_event_data_received(encomspPlugin* encomsp, } static VOID VCAPITYPE encomsp_virtual_channel_open_event_ex(LPVOID lpUserParam, DWORD openHandle, - UINT event, - LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) + UINT event, LPVOID pData, + UINT32 dataLength, UINT32 totalLength, + UINT32 dataFlags) { UINT error = CHANNEL_RC_OK; - encomspPlugin* encomsp = (encomspPlugin*) lpUserParam; - - if (!encomsp || (encomsp->OpenHandle != openHandle)) - { - WLog_ERR(TAG, "error no match"); - return; - } + encomspPlugin* encomsp = (encomspPlugin*)lpUserParam; switch (event) { case CHANNEL_EVENT_DATA_RECEIVED: - if ((error = encomsp_virtual_channel_event_data_received(encomsp, pData, - dataLength, totalLength, dataFlags))) - WLog_ERR(TAG, "encomsp_virtual_channel_event_data_received failed with error %"PRIu32"", error); + if (!encomsp || (encomsp->OpenHandle != openHandle)) + { + WLog_ERR(TAG, "error no match"); + return; + } + if ((error = encomsp_virtual_channel_event_data_received(encomsp, pData, dataLength, + totalLength, dataFlags))) + WLog_ERR(TAG, + "encomsp_virtual_channel_event_data_received failed with error %" PRIu32 + "", + error); break; + case CHANNEL_EVENT_WRITE_CANCELLED: case CHANNEL_EVENT_WRITE_COMPLETE: - break; + { + wStream* s = (wStream*)pData; + Stream_Free(s, TRUE); + } + break; case CHANNEL_EVENT_USER: break; } - if (error && encomsp->rdpcontext) - setChannelError(encomsp->rdpcontext, error, "encomsp_virtual_channel_open_event reported an error"); + if (error && encomsp && encomsp->rdpcontext) + setChannelError(encomsp->rdpcontext, error, + "encomsp_virtual_channel_open_event reported an error"); return; } @@ -1014,7 +1086,7 @@ static DWORD WINAPI encomsp_virtual_channel_client_thread(LPVOID arg) { wStream* data; wMessage message; - encomspPlugin* encomsp = (encomspPlugin*) arg; + encomspPlugin* encomsp = (encomspPlugin*)arg; UINT error = CHANNEL_RC_OK; encomsp_process_connect(encomsp); @@ -1039,11 +1111,11 @@ static DWORD WINAPI encomsp_virtual_channel_client_thread(LPVOID arg) if (message.id == 0) { - data = (wStream*) message.wParam; + data = (wStream*)message.wParam; if ((error = encomsp_process_receive(encomsp, data))) { - WLog_ERR(TAG, "encomsp_process_receive failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "encomsp_process_receive failed with error %" PRIu32 "!", error); break; } } @@ -1062,17 +1134,17 @@ static DWORD WINAPI encomsp_virtual_channel_client_thread(LPVOID arg) * * @return 0 on success, otherwise a Win32 error code */ -static UINT encomsp_virtual_channel_event_connected(encomspPlugin* encomsp, - LPVOID pData, UINT32 dataLength) +static UINT encomsp_virtual_channel_event_connected(encomspPlugin* encomsp, LPVOID pData, + UINT32 dataLength) { UINT32 status; - status = encomsp->channelEntryPoints.pVirtualChannelOpenEx(encomsp->InitHandle, - &encomsp->OpenHandle, encomsp->channelDef.name, - encomsp_virtual_channel_open_event_ex); + status = encomsp->channelEntryPoints.pVirtualChannelOpenEx( + encomsp->InitHandle, &encomsp->OpenHandle, encomsp->channelDef.name, + encomsp_virtual_channel_open_event_ex); if (status != CHANNEL_RC_OK) { - WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08"PRIX32"]", + WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08" PRIX32 "]", WTSErrorToString(status), status); return status; } @@ -1085,9 +1157,8 @@ static UINT encomsp_virtual_channel_event_connected(encomspPlugin* encomsp, return CHANNEL_RC_NO_MEMORY; } - if (!(encomsp->thread = CreateThread(NULL, 0, - encomsp_virtual_channel_client_thread, (void*) encomsp, - 0, NULL))) + if (!(encomsp->thread = CreateThread(NULL, 0, encomsp_virtual_channel_client_thread, + (void*)encomsp, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); MessageQueue_Free(encomsp->queue); @@ -1109,11 +1180,11 @@ static UINT encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp) if (encomsp->OpenHandle == 0) return CHANNEL_RC_OK; - if (MessageQueue_PostQuit(encomsp->queue, 0) - && (WaitForSingleObject(encomsp->thread, INFINITE) == WAIT_FAILED)) + if (MessageQueue_PostQuit(encomsp->queue, 0) && + (WaitForSingleObject(encomsp->thread, INFINITE) == WAIT_FAILED)) { rc = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", rc); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", rc); return rc; } @@ -1121,12 +1192,13 @@ static UINT encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp) CloseHandle(encomsp->thread); encomsp->queue = NULL; encomsp->thread = NULL; - rc = encomsp->channelEntryPoints.pVirtualChannelCloseEx(encomsp->InitHandle, encomsp->OpenHandle); + rc = encomsp->channelEntryPoints.pVirtualChannelCloseEx(encomsp->InitHandle, + encomsp->OpenHandle); if (CHANNEL_RC_OK != rc) { - WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08"PRIX32"]", - WTSErrorToString(rc), rc); + WLog_ERR(TAG, "pVirtualChannelClose failed with %s [%08" PRIX32 "]", WTSErrorToString(rc), + rc); return rc; } @@ -1141,7 +1213,6 @@ static UINT encomsp_virtual_channel_event_disconnected(encomspPlugin* encomsp) return CHANNEL_RC_OK; } - /** * Function description * @@ -1156,23 +1227,24 @@ static UINT encomsp_virtual_channel_event_terminated(encomspPlugin* encomsp) } static VOID VCAPITYPE encomsp_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle, - UINT event, LPVOID pData, UINT dataLength) + UINT event, LPVOID pData, + UINT dataLength) { UINT error = CHANNEL_RC_OK; - encomspPlugin* encomsp = (encomspPlugin*) lpUserParam; + encomspPlugin* encomsp = (encomspPlugin*)lpUserParam; if (!encomsp || (encomsp->InitHandle != pInitHandle)) { - WLog_ERR(TAG, "error no match"); + WLog_ERR(TAG, "error no match"); return; } switch (event) { case CHANNEL_EVENT_CONNECTED: - if ((error = encomsp_virtual_channel_event_connected(encomsp, pData, - dataLength))) - WLog_ERR(TAG, "encomsp_virtual_channel_event_connected failed with error %"PRIu32"", + if ((error = encomsp_virtual_channel_event_connected(encomsp, pData, dataLength))) + WLog_ERR(TAG, + "encomsp_virtual_channel_event_connected failed with error %" PRIu32 "", error); break; @@ -1180,7 +1252,8 @@ static VOID VCAPITYPE encomsp_virtual_channel_init_event_ex(LPVOID lpUserParam, case CHANNEL_EVENT_DISCONNECTED: if ((error = encomsp_virtual_channel_event_disconnected(encomsp))) WLog_ERR(TAG, - "encomsp_virtual_channel_event_disconnected failed with error %"PRIu32"", error); + "encomsp_virtual_channel_event_disconnected failed with error %" PRIu32 "", + error); break; @@ -1189,15 +1262,16 @@ static VOID VCAPITYPE encomsp_virtual_channel_init_event_ex(LPVOID lpUserParam, break; default: - WLog_ERR(TAG, "Unhandled event type %"PRIu32"", event); + break; } if (error && encomsp->rdpcontext) - setChannelError(encomsp->rdpcontext, error, "encomsp_virtual_channel_init_event reported an error"); + setChannelError(encomsp->rdpcontext, error, + "encomsp_virtual_channel_init_event reported an error"); } /* encomsp is always built-in */ -#define VirtualChannelEntryEx encomsp_VirtualChannelEntryEx +#define VirtualChannelEntryEx encomsp_VirtualChannelEntryEx BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOID pInitHandle) { @@ -1206,7 +1280,7 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOI EncomspClientContext* context = NULL; CHANNEL_ENTRY_POINTS_FREERDP_EX* pEntryPointsEx; BOOL isFreerdp = FALSE; - encomsp = (encomspPlugin*) calloc(1, sizeof(encomspPlugin)); + encomsp = (encomspPlugin*)calloc(1, sizeof(encomspPlugin)); if (!encomsp) { @@ -1214,18 +1288,15 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOI return FALSE; } - encomsp->channelDef.options = - CHANNEL_OPTION_INITIALIZED | - CHANNEL_OPTION_ENCRYPT_RDP | - CHANNEL_OPTION_COMPRESS_RDP | - CHANNEL_OPTION_SHOW_PROTOCOL; + encomsp->channelDef.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | + CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL; sprintf_s(encomsp->channelDef.name, ARRAYSIZE(encomsp->channelDef.name), "encomsp"); - pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*) pEntryPoints; + pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*)pEntryPoints; if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)) && (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) { - context = (EncomspClientContext*) calloc(1, sizeof(EncomspClientContext)); + context = (EncomspClientContext*)calloc(1, sizeof(EncomspClientContext)); if (!context) { @@ -1233,7 +1304,7 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOI goto error_out; } - context->handle = (void*) encomsp; + context->handle = (void*)encomsp; context->FilterUpdated = NULL; context->ApplicationCreated = NULL; context->ApplicationRemoved = NULL; @@ -1242,8 +1313,7 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOI context->ShowWindow = NULL; context->ParticipantCreated = NULL; context->ParticipantRemoved = NULL; - context->ChangeParticipantControlLevel = - encomsp_send_change_participant_control_level_pdu; + context->ChangeParticipantControlLevel = encomsp_send_change_participant_control_level_pdu; context->GraphicsStreamPaused = NULL; context->GraphicsStreamResumed = NULL; encomsp->context = context; @@ -1254,14 +1324,13 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS_EX pEntryPoints, PVOI CopyMemory(&(encomsp->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)); encomsp->InitHandle = pInitHandle; - rc = encomsp->channelEntryPoints.pVirtualChannelInitEx(encomsp, context, pInitHandle, - &encomsp->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, - encomsp_virtual_channel_init_event_ex); + rc = encomsp->channelEntryPoints.pVirtualChannelInitEx( + encomsp, context, pInitHandle, &encomsp->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, + encomsp_virtual_channel_init_event_ex); if (CHANNEL_RC_OK != rc) { - WLog_ERR(TAG, "failed with %s [%08"PRIX32"]", - WTSErrorToString(rc), rc); + WLog_ERR(TAG, "failed with %s [%08" PRIX32 "]", WTSErrorToString(rc), rc); goto error_out; } diff --git a/channels/encomsp/client/encomsp_main.h b/channels/encomsp/client/encomsp_main.h index 7b23ed1..ad43cea 100644 --- a/channels/encomsp/client/encomsp_main.h +++ b/channels/encomsp/client/encomsp_main.h @@ -37,20 +37,6 @@ #define TAG CHANNELS_TAG("encomsp.client") -struct encomsp_plugin -{ - CHANNEL_DEF channelDef; - CHANNEL_ENTRY_POINTS_FREERDP_EX channelEntryPoints; - - EncomspClientContext* context; - - HANDLE thread; - wStream* data_in; - void* InitHandle; - DWORD OpenHandle; - wMessageQueue* queue; - rdpContext* rdpcontext; -}; typedef struct encomsp_plugin encomspPlugin; #endif /* FREERDP_CHANNEL_ENCOMSP_CLIENT_MAIN_H */ diff --git a/channels/encomsp/server/encomsp_main.c b/channels/encomsp/server/encomsp_main.c index e1b2248..9b1693b 100644 --- a/channels/encomsp/server/encomsp_main.c +++ b/channels/encomsp/server/encomsp_main.c @@ -43,7 +43,7 @@ static UINT encomsp_read_header(wStream* s, ENCOMSP_ORDER_HEADER* header) if (Stream_GetRemainingLength(s) < ENCOMSP_ORDER_HEADER_SIZE) return ERROR_INVALID_DATA; - Stream_Read_UINT16(s, header->Type); /* Type (2 bytes) */ + Stream_Read_UINT16(s, header->Type); /* Type (2 bytes) */ Stream_Read_UINT16(s, header->Length); /* Length (2 bytes) */ return CHANNEL_RC_OK; } @@ -83,13 +83,14 @@ static int encomsp_read_unicode_string(wStream* s, ENCOMSP_UNICODE_STRING* str) * * @return 0 on success, otherwise a Win32 error code */ -static UINT encomsp_recv_change_participant_control_level_pdu( - EncomspServerContext* context, wStream* s, ENCOMSP_ORDER_HEADER* header) +static UINT encomsp_recv_change_participant_control_level_pdu(EncomspServerContext* context, + wStream* s, + ENCOMSP_ORDER_HEADER* header) { int beg, end; ENCOMSP_CHANGE_PARTICIPANT_CONTROL_LEVEL_PDU pdu; UINT error = CHANNEL_RC_OK; - beg = ((int) Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; + beg = ((int)Stream_GetPosition(s)) - ENCOMSP_ORDER_HEADER_SIZE; CopyMemory(&pdu, header, sizeof(ENCOMSP_ORDER_HEADER)); if (Stream_GetRemainingLength(s) < 6) @@ -98,9 +99,9 @@ static UINT encomsp_recv_change_participant_control_level_pdu( return ERROR_INVALID_DATA; } - Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */ + Stream_Read_UINT16(s, pdu.Flags); /* Flags (2 bytes) */ Stream_Read_UINT32(s, pdu.ParticipantId); /* ParticipantId (4 bytes) */ - end = (int) Stream_GetPosition(s); + end = (int)Stream_GetPosition(s); if ((beg + header->Length) < end) { @@ -110,7 +111,7 @@ static UINT encomsp_recv_change_participant_control_level_pdu( if ((beg + header->Length) > end) { - if (Stream_GetRemainingLength(s) < ((beg + header->Length) - end)) + if (Stream_GetRemainingLength(s) < (size_t)((beg + header->Length) - end)) { WLog_ERR(TAG, "Not enough data!"); return ERROR_INVALID_DATA; @@ -122,7 +123,7 @@ static UINT encomsp_recv_change_participant_control_level_pdu( IFCALLRET(context->ChangeParticipantControlLevel, error, context, &pdu); if (error) - WLog_ERR(TAG, "context->ChangeParticipantControlLevel failed with error %"PRIu32"", + WLog_ERR(TAG, "context->ChangeParticipantControlLevel failed with error %" PRIu32 "", error); return error; @@ -133,8 +134,7 @@ static UINT encomsp_recv_change_participant_control_level_pdu( * * @return 0 on success, otherwise a Win32 error code */ -static UINT encomsp_server_receive_pdu(EncomspServerContext* context, - wStream* s) +static UINT encomsp_server_receive_pdu(EncomspServerContext* context, wStream* s) { UINT error = CHANNEL_RC_OK; ENCOMSP_ORDER_HEADER header; @@ -143,21 +143,22 @@ static UINT encomsp_server_receive_pdu(EncomspServerContext* context, { if ((error = encomsp_read_header(s, &header))) { - WLog_ERR(TAG, "encomsp_read_header failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "encomsp_read_header failed with error %" PRIu32 "!", error); return error; } - WLog_INFO(TAG, "EncomspReceive: Type: %"PRIu16" Length: %"PRIu16"", header.Type, + WLog_INFO(TAG, "EncomspReceive: Type: %" PRIu16 " Length: %" PRIu16 "", header.Type, header.Length); switch (header.Type) { case ODTYPE_PARTICIPANT_CTRL_CHANGED: - if ((error = encomsp_recv_change_participant_control_level_pdu(context, s, - &header))) + if ((error = + encomsp_recv_change_participant_control_level_pdu(context, s, &header))) { WLog_ERR(TAG, - "encomsp_recv_change_participant_control_level_pdu failed with error %"PRIu32"!", + "encomsp_recv_change_participant_control_level_pdu failed with error " + "%" PRIu32 "!", error); return error; } @@ -165,7 +166,7 @@ static UINT encomsp_server_receive_pdu(EncomspServerContext* context, break; default: - WLog_ERR(TAG, "header.Type unknown %"PRIu16"!", header.Type); + WLog_ERR(TAG, "header.Type unknown %" PRIu16 "!", header.Type); return ERROR_INVALID_DATA; break; } @@ -186,7 +187,7 @@ static DWORD WINAPI encomsp_server_thread(LPVOID arg) EncomspServerContext* context; UINT error = CHANNEL_RC_OK; DWORD status; - context = (EncomspServerContext*) arg; + context = (EncomspServerContext*)arg; buffer = NULL; BytesReturned = 0; @@ -200,8 +201,8 @@ static DWORD WINAPI encomsp_server_thread(LPVOID arg) goto out; } - if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, - &buffer, &BytesReturned) == TRUE) + if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, + &BytesReturned) == TRUE) { if (BytesReturned == sizeof(HANDLE)) CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); @@ -220,7 +221,7 @@ static DWORD WINAPI encomsp_server_thread(LPVOID arg) if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForMultipleObjects failed with error %" PRIu32 "", error); break; } @@ -229,7 +230,7 @@ static DWORD WINAPI encomsp_server_thread(LPVOID arg) if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error); break; } @@ -250,8 +251,8 @@ static DWORD WINAPI encomsp_server_thread(LPVOID arg) break; } - if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, - (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) + if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR)Stream_Buffer(s), + Stream_Capacity(s), &BytesReturned)) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); error = ERROR_INTERNAL_ERROR; @@ -260,7 +261,7 @@ static DWORD WINAPI encomsp_server_thread(LPVOID arg) if (Stream_GetPosition(s) >= ENCOMSP_ORDER_HEADER_SIZE) { - header = (ENCOMSP_ORDER_HEADER*) Stream_Buffer(s); + header = (ENCOMSP_ORDER_HEADER*)Stream_Buffer(s); if (header->Length >= Stream_GetPosition(s)) { @@ -269,7 +270,8 @@ static DWORD WINAPI encomsp_server_thread(LPVOID arg) if ((error = encomsp_server_receive_pdu(context, s))) { - WLog_ERR(TAG, "encomsp_server_receive_pdu failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "encomsp_server_receive_pdu failed with error %" PRIu32 "!", + error); break; } @@ -282,8 +284,7 @@ static DWORD WINAPI encomsp_server_thread(LPVOID arg) out: if (error && context->rdpcontext) - setChannelError(context->rdpcontext, error, - "encomsp_server_thread reported an error"); + setChannelError(context->rdpcontext, error, "encomsp_server_thread reported an error"); ExitThread(error); return error; @@ -296,8 +297,8 @@ out: */ static UINT encomsp_server_start(EncomspServerContext* context) { - context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, - WTS_CURRENT_SESSION, "encomsp"); + context->priv->ChannelHandle = + WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "encomsp"); if (!context->priv->ChannelHandle) return CHANNEL_RC_BAD_CHANNEL; @@ -308,8 +309,8 @@ static UINT encomsp_server_start(EncomspServerContext* context) return ERROR_INTERNAL_ERROR; } - if (!(context->priv->Thread = CreateThread(NULL, 0, - encomsp_server_thread, (void*) context, 0, NULL))) + if (!(context->priv->Thread = + CreateThread(NULL, 0, encomsp_server_thread, (void*)context, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); CloseHandle(context->priv->StopEvent); @@ -333,7 +334,7 @@ static UINT encomsp_server_stop(EncomspServerContext* context) if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", error); return error; } @@ -345,14 +346,14 @@ static UINT encomsp_server_stop(EncomspServerContext* context) EncomspServerContext* encomsp_server_context_new(HANDLE vcm) { EncomspServerContext* context; - context = (EncomspServerContext*) calloc(1, sizeof(EncomspServerContext)); + context = (EncomspServerContext*)calloc(1, sizeof(EncomspServerContext)); if (context) { context->vcm = vcm; context->Start = encomsp_server_start; context->Stop = encomsp_server_stop; - context->priv = (EncomspServerPrivate*) calloc(1, sizeof(EncomspServerPrivate)); + context->priv = (EncomspServerPrivate*)calloc(1, sizeof(EncomspServerPrivate)); if (!context->priv) { @@ -371,7 +372,7 @@ void encomsp_server_context_free(EncomspServerContext* context) { if (context->priv->ChannelHandle != INVALID_HANDLE_VALUE) WTSVirtualChannelClose(context->priv->ChannelHandle); - + free(context->priv); free(context); } diff --git a/channels/geometry/client/geometry_main.c b/channels/geometry/client/geometry_main.c index 5ef7def..eb65b2c 100644 --- a/channels/geometry/client/geometry_main.c +++ b/channels/geometry/client/geometry_main.c @@ -72,23 +72,22 @@ struct _GEOMETRY_PLUGIN }; typedef struct _GEOMETRY_PLUGIN GEOMETRY_PLUGIN; - -static UINT32 mappedGeometryHash(UINT64 *g) +static UINT32 mappedGeometryHash(UINT64* g) { return (UINT32)((*g >> 32) + (*g & 0xffffffff)); } -static BOOL mappedGeometryKeyCompare(UINT64 *g1, UINT64 *g2) +static BOOL mappedGeometryKeyCompare(UINT64* g1, UINT64* g2) { return *g1 == *g2; } -void mappedGeometryRef(MAPPED_GEOMETRY *g) +void mappedGeometryRef(MAPPED_GEOMETRY* g) { InterlockedIncrement(&g->refCounter); } -void mappedGeometryUnref(MAPPED_GEOMETRY *g) +void mappedGeometryUnref(MAPPED_GEOMETRY* g) { if (InterlockedDecrement(&g->refCounter)) return; @@ -100,16 +99,16 @@ void mappedGeometryUnref(MAPPED_GEOMETRY *g) free(g); } - -void freerdp_rgndata_reset(FREERDP_RGNDATA *data) +static void freerdp_rgndata_reset(FREERDP_RGNDATA* data) { data->nRectCount = 0; } -static UINT32 geometry_read_RGNDATA(wStream *s, UINT32 len, FREERDP_RGNDATA *rgndata) +static UINT32 geometry_read_RGNDATA(wStream* s, UINT32 len, FREERDP_RGNDATA* rgndata) { UINT32 dwSize, iType; INT32 right, bottom; + INT32 x, y, w, h; if (len < 32) { @@ -129,18 +128,26 @@ static UINT32 geometry_read_RGNDATA(wStream *s, UINT32 len, FREERDP_RGNDATA *rgn if (iType != RDH_RECTANGLE) { - WLog_ERR(TAG, "iType %"PRIu32" for RGNDATA is not supported", iType); + WLog_ERR(TAG, "iType %" PRIu32 " for RGNDATA is not supported", iType); return ERROR_UNSUPPORTED_TYPE; } Stream_Read_UINT32(s, rgndata->nRectCount); Stream_Seek_UINT32(s); /* nRgnSize IGNORED */ - Stream_Read_INT32(s, rgndata->boundingRect.x); - Stream_Read_INT32(s, rgndata->boundingRect.y); + Stream_Read_INT32(s, x); + Stream_Read_INT32(s, y); Stream_Read_INT32(s, right); Stream_Read_INT32(s, bottom); - rgndata->boundingRect.width = right - rgndata->boundingRect.x; - rgndata->boundingRect.height = bottom - rgndata->boundingRect.y; + if ((abs(x) > INT16_MAX) || (abs(y) > INT16_MAX)) + return ERROR_INVALID_DATA; + w = right - x; + h = bottom - y; + if ((abs(w) > INT16_MAX) || (abs(h) > INT16_MAX)) + return ERROR_INVALID_DATA; + rgndata->boundingRect.x = (INT16)x; + rgndata->boundingRect.y = (INT16)y; + rgndata->boundingRect.width = (INT16)w; + rgndata->boundingRect.height = (INT16)h; len -= 32; if (len / (4 * 4) < rgndata->nRectCount) @@ -150,24 +157,32 @@ static UINT32 geometry_read_RGNDATA(wStream *s, UINT32 len, FREERDP_RGNDATA *rgn if (rgndata->nRectCount) { - int i; - RDP_RECT *tmp = realloc(rgndata->rects, rgndata->nRectCount * sizeof(RDP_RECT)); + UINT32 i; + RDP_RECT* tmp = realloc(rgndata->rects, rgndata->nRectCount * sizeof(RDP_RECT)); if (!tmp) { - WLog_ERR(TAG, "unable to allocate memory for %"PRIu32" RECTs", rgndata->nRectCount); + WLog_ERR(TAG, "unable to allocate memory for %" PRIu32 " RECTs", rgndata->nRectCount); return CHANNEL_RC_NO_MEMORY; } rgndata->rects = tmp; for (i = 0; i < rgndata->nRectCount; i++) { - Stream_Read_INT32(s, rgndata->rects[i].x); - Stream_Read_INT32(s, rgndata->rects[i].y); + Stream_Read_INT32(s, x); + Stream_Read_INT32(s, y); Stream_Read_INT32(s, right); Stream_Read_INT32(s, bottom); - rgndata->rects[i].width = right - rgndata->rects[i].x; - rgndata->rects[i].height = bottom - rgndata->rects[i].y; + if ((abs(x) > INT16_MAX) || (abs(y) > INT16_MAX)) + return ERROR_INVALID_DATA; + w = right - x; + h = bottom - y; + if ((abs(w) > INT16_MAX) || (abs(h) > INT16_MAX)) + return ERROR_INVALID_DATA; + rgndata->rects[i].x = (INT16)x; + rgndata->rects[i].y = (INT16)y; + rgndata->rects[i].width = (INT16)w; + rgndata->rects[i].height = (INT16)h; } } @@ -182,14 +197,14 @@ static UINT32 geometry_read_RGNDATA(wStream *s, UINT32 len, FREERDP_RGNDATA *rgn static UINT geometry_recv_pdu(GEOMETRY_CHANNEL_CALLBACK* callback, wStream* s) { UINT32 length, cbGeometryBuffer; - MAPPED_GEOMETRY *mappedGeometry; + MAPPED_GEOMETRY* mappedGeometry; GEOMETRY_PLUGIN* geometry; - GeometryClientContext *context; + GeometryClientContext* context; UINT ret = CHANNEL_RC_OK; UINT32 version, updateType, geometryType; UINT64 id; - geometry = (GEOMETRY_PLUGIN*) callback->plugin; + geometry = (GEOMETRY_PLUGIN*)callback->plugin; context = (GeometryClientContext*)geometry->iface.pInterface; if (Stream_GetRemainingLength(s) < 4) @@ -213,17 +228,18 @@ static UINT geometry_recv_pdu(GEOMETRY_CHANNEL_CALLBACK* callback, wStream* s) mappedGeometry = HashTable_GetItemValue(context->geometries, &id); - if (updateType == GEOMETRY_CLEAR ) + if (updateType == GEOMETRY_CLEAR) { if (!mappedGeometry) { - WLog_ERR(TAG, "geometry 0x%"PRIx64" not found here, ignoring clear command", id); + WLog_ERR(TAG, "geometry 0x%" PRIx64 " not found here, ignoring clear command", id); return CHANNEL_RC_OK; } - WLog_DBG(TAG, "clearing geometry 0x%"PRIx64"", id); + WLog_DBG(TAG, "clearing geometry 0x%" PRIx64 "", id); - if (mappedGeometry->MappedGeometryClear && !mappedGeometry->MappedGeometryClear(mappedGeometry)) + if (mappedGeometry->MappedGeometryClear && + !mappedGeometry->MappedGeometryClear(mappedGeometry)) return ERROR_INTERNAL_ERROR; if (!HashTable_Remove(context->geometries, &id)) @@ -236,7 +252,7 @@ static UINT geometry_recv_pdu(GEOMETRY_CHANNEL_CALLBACK* callback, wStream* s) if (!mappedGeometry) { newOne = TRUE; - WLog_DBG(TAG, "creating geometry 0x%"PRIx64"", id); + WLog_DBG(TAG, "creating geometry 0x%" PRIx64 "", id); mappedGeometry = calloc(1, sizeof(MAPPED_GEOMETRY)); if (!mappedGeometry) return CHANNEL_RC_NO_MEMORY; @@ -244,16 +260,17 @@ static UINT geometry_recv_pdu(GEOMETRY_CHANNEL_CALLBACK* callback, wStream* s) mappedGeometry->refCounter = 1; mappedGeometry->mappingId = id; - if (HashTable_Add(context->geometries, &(mappedGeometry->mappingId), mappedGeometry) < 0) + if (HashTable_Add(context->geometries, &(mappedGeometry->mappingId), mappedGeometry) < + 0) { - WLog_ERR(TAG, "unable to register geometry 0x%"PRIx64" in the table", id); + WLog_ERR(TAG, "unable to register geometry 0x%" PRIx64 " in the table", id); free(mappedGeometry); return CHANNEL_RC_NO_MEMORY; } } else { - WLog_DBG(TAG, "updating geometry 0x%"PRIx64"", id); + WLog_DBG(TAG, "updating geometry 0x%" PRIx64 "", id); } Stream_Read_UINT64(s, mappedGeometry->topLevelId); @@ -290,7 +307,8 @@ static UINT geometry_recv_pdu(GEOMETRY_CHANNEL_CALLBACK* callback, wStream* s) if (newOne) { - if (context->MappedGeometryAdded && !context->MappedGeometryAdded(context, mappedGeometry)) + if (context->MappedGeometryAdded && + !context->MappedGeometryAdded(context, mappedGeometry)) { WLog_ERR(TAG, "geometry added callback failed"); ret = ERROR_INTERNAL_ERROR; @@ -298,7 +316,8 @@ static UINT geometry_recv_pdu(GEOMETRY_CHANNEL_CALLBACK* callback, wStream* s) } else { - if (mappedGeometry->MappedGeometryUpdate && !mappedGeometry->MappedGeometryUpdate(mappedGeometry)) + if (mappedGeometry->MappedGeometryUpdate && + !mappedGeometry->MappedGeometryUpdate(mappedGeometry)) { WLog_ERR(TAG, "geometry update callback failed"); ret = ERROR_INTERNAL_ERROR; @@ -307,11 +326,10 @@ static UINT geometry_recv_pdu(GEOMETRY_CHANNEL_CALLBACK* callback, wStream* s) } else { - WLog_ERR(TAG, "unknown updateType=%"PRIu32"", updateType); + WLog_ERR(TAG, "unknown updateType=%" PRIu32 "", updateType); ret = CHANNEL_RC_OK; } - return ret; } @@ -322,7 +340,7 @@ static UINT geometry_recv_pdu(GEOMETRY_CHANNEL_CALLBACK* callback, wStream* s) */ static UINT geometry_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data) { - GEOMETRY_CHANNEL_CALLBACK* callback = (GEOMETRY_CHANNEL_CALLBACK*) pChannelCallback; + GEOMETRY_CHANNEL_CALLBACK* callback = (GEOMETRY_CHANNEL_CALLBACK*)pChannelCallback; return geometry_recv_pdu(callback, data); } @@ -343,12 +361,17 @@ static UINT geometry_on_close(IWTSVirtualChannelCallback* pChannelCallback) * @return 0 on success, otherwise a Win32 error code */ static UINT geometry_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, - IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept, - IWTSVirtualChannelCallback** ppCallback) + IWTSVirtualChannel* pChannel, BYTE* Data, + BOOL* pbAccept, + IWTSVirtualChannelCallback** ppCallback) { GEOMETRY_CHANNEL_CALLBACK* callback; - GEOMETRY_LISTENER_CALLBACK* listener_callback = (GEOMETRY_LISTENER_CALLBACK*) pListenerCallback; - callback = (GEOMETRY_CHANNEL_CALLBACK*) calloc(1, sizeof(GEOMETRY_CHANNEL_CALLBACK)); + GEOMETRY_LISTENER_CALLBACK* listener_callback = (GEOMETRY_LISTENER_CALLBACK*)pListenerCallback; + + WINPR_UNUSED(Data); + WINPR_UNUSED(pbAccept); + + callback = (GEOMETRY_CHANNEL_CALLBACK*)calloc(1, sizeof(GEOMETRY_CHANNEL_CALLBACK)); if (!callback) { @@ -362,7 +385,7 @@ static UINT geometry_on_new_channel_connection(IWTSListenerCallback* pListenerCa callback->channel_mgr = listener_callback->channel_mgr; callback->channel = pChannel; listener_callback->channel_callback = callback; - *ppCallback = (IWTSVirtualChannelCallback*) callback; + *ppCallback = (IWTSVirtualChannelCallback*)callback; return CHANNEL_RC_OK; } @@ -374,9 +397,9 @@ static UINT geometry_on_new_channel_connection(IWTSListenerCallback* pListenerCa static UINT geometry_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) { UINT status; - GEOMETRY_PLUGIN* geometry = (GEOMETRY_PLUGIN*) pPlugin; - geometry->listener_callback = (GEOMETRY_LISTENER_CALLBACK*) calloc(1, - sizeof(GEOMETRY_LISTENER_CALLBACK)); + GEOMETRY_PLUGIN* geometry = (GEOMETRY_PLUGIN*)pPlugin; + geometry->listener_callback = + (GEOMETRY_LISTENER_CALLBACK*)calloc(1, sizeof(GEOMETRY_LISTENER_CALLBACK)); if (!geometry->listener_callback) { @@ -387,8 +410,9 @@ static UINT geometry_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMa geometry->listener_callback->iface.OnNewChannelConnection = geometry_on_new_channel_connection; geometry->listener_callback->plugin = pPlugin; geometry->listener_callback->channel_mgr = pChannelMgr; - status = pChannelMgr->CreateListener(pChannelMgr, GEOMETRY_DVC_CHANNEL_NAME, 0, - (IWTSListenerCallback*) geometry->listener_callback, &(geometry->listener)); + status = + pChannelMgr->CreateListener(pChannelMgr, GEOMETRY_DVC_CHANNEL_NAME, 0, + &geometry->listener_callback->iface, &(geometry->listener)); geometry->listener->pInterface = geometry->iface.pInterface; return status; } @@ -400,8 +424,15 @@ static UINT geometry_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelMa */ static UINT geometry_plugin_terminated(IWTSPlugin* pPlugin) { - GEOMETRY_PLUGIN* geometry = (GEOMETRY_PLUGIN*) pPlugin; - GeometryClientContext* context = (GeometryClientContext *)geometry->iface.pInterface; + GEOMETRY_PLUGIN* geometry = (GEOMETRY_PLUGIN*)pPlugin; + GeometryClientContext* context = (GeometryClientContext*)geometry->iface.pInterface; + + if (geometry && geometry->listener_callback) + { + IWTSVirtualChannelManager* mgr = geometry->listener_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, geometry->listener); + } if (context) HashTable_Free(context->geometries); @@ -417,9 +448,9 @@ static UINT geometry_plugin_terminated(IWTSPlugin* pPlugin) */ #ifdef BUILTIN_CHANNELS -#define DVCPluginEntry geometry_DVCPluginEntry +#define DVCPluginEntry geometry_DVCPluginEntry #else -#define DVCPluginEntry FREERDP_API DVCPluginEntry +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** @@ -432,11 +463,11 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) UINT error = CHANNEL_RC_OK; GEOMETRY_PLUGIN* geometry; GeometryClientContext* context; - geometry = (GEOMETRY_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "geometry"); + geometry = (GEOMETRY_PLUGIN*)pEntryPoints->GetPlugin(pEntryPoints, "geometry"); if (!geometry) { - geometry = (GEOMETRY_PLUGIN*) calloc(1, sizeof(GEOMETRY_PLUGIN)); + geometry = (GEOMETRY_PLUGIN*)calloc(1, sizeof(GEOMETRY_PLUGIN)); if (!geometry) { @@ -448,7 +479,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) geometry->iface.Connected = NULL; geometry->iface.Disconnected = NULL; geometry->iface.Terminated = geometry_plugin_terminated; - context = (GeometryClientContext*) calloc(1, sizeof(GeometryClientContext)); + context = (GeometryClientContext*)calloc(1, sizeof(GeometryClientContext)); if (!context) { @@ -461,10 +492,10 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) context->geometries->keyCompare = (HASH_TABLE_KEY_COMPARE_FN)mappedGeometryKeyCompare; context->geometries->valueFree = (HASH_TABLE_VALUE_FREE_FN)mappedGeometryUnref; - context->handle = (void*) geometry; - geometry->iface.pInterface = (void*) context; + context->handle = (void*)geometry; + geometry->iface.pInterface = (void*)context; geometry->context = context; - error = pEntryPoints->RegisterPlugin(pEntryPoints, "geometry", (IWTSPlugin*) geometry); + error = pEntryPoints->RegisterPlugin(pEntryPoints, "geometry", (IWTSPlugin*)geometry); } else { @@ -477,5 +508,4 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) error_context: free(geometry); return CHANNEL_RC_NO_MEMORY; - } diff --git a/channels/geometry/client/geometry_main.h b/channels/geometry/client/geometry_main.h index 1fb5321..ff6add2 100644 --- a/channels/geometry/client/geometry_main.h +++ b/channels/geometry/client/geometry_main.h @@ -29,6 +29,4 @@ #include #include - #endif /* FREERDP_CHANNEL_GEOMETRY_CLIENT_MAIN_H */ - diff --git a/channels/parallel/client/parallel_main.c b/channels/parallel/client/parallel_main.c index 19ebce3..af3e827 100644 --- a/channels/parallel/client/parallel_main.c +++ b/channels/parallel/client/parallel_main.c @@ -83,16 +83,22 @@ static UINT parallel_process_irp_create(PARALLEL_DEVICE* parallel, IRP* irp) { char* path = NULL; int status; + WCHAR* ptr; UINT32 PathLength; - Stream_Seek(irp->input, 28); + if (!Stream_SafeSeek(irp->input, 28)) + return ERROR_INVALID_DATA; /* DesiredAccess(4) AllocationSize(8), FileAttributes(4) */ /* SharedAccess(4) CreateDisposition(4), CreateOptions(4) */ + if (Stream_GetRemainingLength(irp->input) < 4) + return ERROR_INVALID_DATA; Stream_Read_UINT32(irp->input, PathLength); - status = ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(irp->input), - PathLength / 2, &path, 0, NULL, NULL); + ptr = (WCHAR*)Stream_Pointer(irp->input); + if (!Stream_SafeSeek(irp->input, PathLength)) + return ERROR_INVALID_DATA; + status = ConvertFromUnicode(CP_UTF8, 0, ptr, PathLength / 2, &path, 0, NULL, NULL); if (status < 1) - if (!(path = (char*) calloc(1, 1))) + if (!(path = (char*)calloc(1, 1))) { WLog_ERR(TAG, "calloc failed!"); return CHANNEL_RC_NO_MEMORY; @@ -149,9 +155,11 @@ static UINT parallel_process_irp_read(PARALLEL_DEVICE* parallel, IRP* irp) UINT64 Offset; ssize_t status; BYTE* buffer = NULL; + if (Stream_GetRemainingLength(irp->input) < 12) + return ERROR_INVALID_DATA; Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); - buffer = (BYTE*) malloc(Length); + buffer = (BYTE*)malloc(Length); if (!buffer) { @@ -201,14 +209,22 @@ static UINT parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp) UINT32 Length; UINT64 Offset; ssize_t status; + void* ptr; + if (Stream_GetRemainingLength(irp->input) > 12) + return ERROR_INVALID_DATA; + Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); - Stream_Seek(irp->input, 20); /* Padding */ + if (!Stream_SafeSeek(irp->input, 20)) /* Padding */ + return ERROR_INVALID_DATA; + ptr = Stream_Pointer(irp->input); + if (!Stream_SafeSeek(irp->input, Length)) + return ERROR_INVALID_DATA; len = Length; while (len > 0) { - status = write(parallel->file, Stream_Pointer(irp->input), len); + status = write(parallel->file, ptr, len); if (status < 0) { @@ -231,8 +247,7 @@ static UINT parallel_process_irp_write(PARALLEL_DEVICE* parallel, IRP* irp) * * @return 0 on success, otherwise a Win32 error code */ -static UINT parallel_process_irp_device_control(PARALLEL_DEVICE* parallel, - IRP* irp) +static UINT parallel_process_irp_device_control(PARALLEL_DEVICE* parallel, IRP* irp) { Stream_Write_UINT32(irp->output, 0); /* OutputBufferLength */ return irp->Complete(irp); @@ -252,7 +267,7 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp) case IRP_MJ_CREATE: if ((error = parallel_process_irp_create(parallel, irp))) { - WLog_ERR(TAG, "parallel_process_irp_create failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "parallel_process_irp_create failed with error %" PRIu32 "!", error); return error; } @@ -261,7 +276,7 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp) case IRP_MJ_CLOSE: if ((error = parallel_process_irp_close(parallel, irp))) { - WLog_ERR(TAG, "parallel_process_irp_close failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "parallel_process_irp_close failed with error %" PRIu32 "!", error); return error; } @@ -270,7 +285,7 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp) case IRP_MJ_READ: if ((error = parallel_process_irp_read(parallel, irp))) { - WLog_ERR(TAG, "parallel_process_irp_read failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "parallel_process_irp_read failed with error %" PRIu32 "!", error); return error; } @@ -279,7 +294,7 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp) case IRP_MJ_WRITE: if ((error = parallel_process_irp_write(parallel, irp))) { - WLog_ERR(TAG, "parallel_process_irp_write failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "parallel_process_irp_write failed with error %" PRIu32 "!", error); return error; } @@ -288,7 +303,7 @@ static UINT parallel_process_irp(PARALLEL_DEVICE* parallel, IRP* irp) case IRP_MJ_DEVICE_CONTROL: if ((error = parallel_process_irp_device_control(parallel, irp))) { - WLog_ERR(TAG, "parallel_process_irp_device_control failed with error %"PRIu32"!", + WLog_ERR(TAG, "parallel_process_irp_device_control failed with error %" PRIu32 "!", error); return error; } @@ -308,7 +323,7 @@ static DWORD WINAPI parallel_thread_func(LPVOID arg) { IRP* irp; wMessage message; - PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) arg; + PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*)arg; UINT error = CHANNEL_RC_OK; while (1) @@ -330,18 +345,17 @@ static DWORD WINAPI parallel_thread_func(LPVOID arg) if (message.id == WMQ_QUIT) break; - irp = (IRP*) message.wParam; + irp = (IRP*)message.wParam; if ((error = parallel_process_irp(parallel, irp))) { - WLog_ERR(TAG, "parallel_process_irp failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "parallel_process_irp failed with error %" PRIu32 "!", error); break; } } if (error && parallel->rdpcontext) - setChannelError(parallel->rdpcontext, error, - "parallel_thread_func reported an error"); + setChannelError(parallel->rdpcontext, error, "parallel_thread_func reported an error"); ExitThread(error); return error; @@ -354,9 +368,9 @@ static DWORD WINAPI parallel_thread_func(LPVOID arg) */ static UINT parallel_irp_request(DEVICE* device, IRP* irp) { - PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device; + PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*)device; - if (!MessageQueue_Post(parallel->queue, NULL, 0, (void*) irp, NULL)) + if (!MessageQueue_Post(parallel->queue, NULL, 0, (void*)irp, NULL)) { WLog_ERR(TAG, "MessageQueue_Post failed!"); return ERROR_INTERNAL_ERROR; @@ -373,13 +387,13 @@ static UINT parallel_irp_request(DEVICE* device, IRP* irp) static UINT parallel_free(DEVICE* device) { UINT error; - PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*) device; + PARALLEL_DEVICE* parallel = (PARALLEL_DEVICE*)device; - if (!MessageQueue_PostQuit(parallel->queue, 0) - || (WaitForSingleObject(parallel->thread, INFINITE) == WAIT_FAILED)) + if (!MessageQueue_PostQuit(parallel->queue, 0) || + (WaitForSingleObject(parallel->thread, INFINITE) == WAIT_FAILED)) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error); return error; } @@ -391,9 +405,9 @@ static UINT parallel_free(DEVICE* device) } #ifdef BUILTIN_CHANNELS -#define DeviceServiceEntry parallel_DeviceServiceEntry +#define DeviceServiceEntry parallel_DeviceServiceEntry #else -#define DeviceServiceEntry FREERDP_API DeviceServiceEntry +#define DeviceServiceEntry FREERDP_API DeviceServiceEntry #endif /** @@ -410,7 +424,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) RDPDR_PARALLEL* device; PARALLEL_DEVICE* parallel; UINT error; - device = (RDPDR_PARALLEL*) pEntryPoints->device; + device = (RDPDR_PARALLEL*)pEntryPoints->device; name = device->Name; path = device->Path; @@ -422,7 +436,7 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) if (name[0] && path[0]) { - parallel = (PARALLEL_DEVICE*) calloc(1, sizeof(PARALLEL_DEVICE)); + parallel = (PARALLEL_DEVICE*)calloc(1, sizeof(PARALLEL_DEVICE)); if (!parallel) { @@ -458,15 +472,14 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) goto error_out; } - if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, - (DEVICE*) parallel))) + if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)parallel))) { - WLog_ERR(TAG, "RegisterDevice failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "RegisterDevice failed with error %" PRIu32 "!", error); goto error_out; } - if (!(parallel->thread = CreateThread(NULL, 0, - parallel_thread_func, (void*) parallel, 0, NULL))) + if (!(parallel->thread = + CreateThread(NULL, 0, parallel_thread_func, (void*)parallel, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); error = ERROR_INTERNAL_ERROR; diff --git a/channels/printer/client/CMakeLists.txt b/channels/printer/client/CMakeLists.txt index ea2f0df..58d44f9 100644 --- a/channels/printer/client/CMakeLists.txt +++ b/channels/printer/client/CMakeLists.txt @@ -18,39 +18,23 @@ define_channel_client("printer") set(${MODULE_PREFIX}_SRCS - printer_main.c - printer_main.h) - -if(WITH_CUPS) - set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} - printer_cups.c - printer_cups.h) - - include_directories(${CUPS_INCLUDE_DIR}) - add_definitions(-DWITH_CUPS) -endif() - -if(WIN32 AND NOT UWP) - set(${MODULE_PREFIX}_SRCS ${${MODULE_PREFIX}_SRCS} - printer_win.c - printer_win.h) -endif() + printer_main.c) add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "DeviceServiceEntry") - - set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr freerdp) - -if(WITH_CUPS) - set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${CUPS_LIBRARIES}) -endif() - target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) - if (WITH_DEBUG_SYMBOLS AND MSVC AND NOT BUILTIN_CHANNELS AND BUILD_SHARED_LIBS) install(FILES ${CMAKE_BINARY_DIR}/${MODULE_NAME}.pdb DESTINATION ${FREERDP_ADDIN_PATH} COMPONENT symbols) endif() set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client") + +if(WITH_CUPS) + add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "cups" "") +endif() + +if(WIN32 AND NOT UWP) + add_channel_client_subsystem(${MODULE_PREFIX} ${CHANNEL_NAME} "win" "") +endif() diff --git a/channels/printer/client/cups/CMakeLists.txt b/channels/printer/client/cups/CMakeLists.txt new file mode 100644 index 0000000..50d599e --- /dev/null +++ b/channels/printer/client/cups/CMakeLists.txt @@ -0,0 +1,31 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2019 Armin Novak +# Copyright 2019 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_subsystem("printer" "cups" "") + +set(${MODULE_PREFIX}_SRCS + printer_cups.c) + +include_directories(..) +include_directories(${CUPS_INCLUDE_DIR}) + +add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "") + +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr freerdp) +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${CUPS_LIBRARIES}) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) diff --git a/channels/printer/client/cups/printer_cups.c b/channels/printer/client/cups/printer_cups.c new file mode 100644 index 0000000..1f9f07b --- /dev/null +++ b/channels/printer/client/cups/printer_cups.c @@ -0,0 +1,408 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Print Virtual Channel - CUPS driver + * + * Copyright 2010-2011 Vic Lee + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Armin Novak + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include + +#include +#include + +#include +#include + +#include + +#include + +typedef struct rdp_cups_printer_driver rdpCupsPrinterDriver; +typedef struct rdp_cups_printer rdpCupsPrinter; +typedef struct rdp_cups_print_job rdpCupsPrintJob; + +struct rdp_cups_printer_driver +{ + rdpPrinterDriver driver; + + int id_sequence; + size_t references; +}; + +struct rdp_cups_printer +{ + rdpPrinter printer; + + rdpCupsPrintJob* printjob; +}; + +struct rdp_cups_print_job +{ + rdpPrintJob printjob; + + void* printjob_object; + int printjob_id; +}; + +static void printer_cups_get_printjob_name(char* buf, size_t size, size_t id) +{ + time_t tt; + struct tm* t; + + tt = time(NULL); + t = localtime(&tt); + sprintf_s(buf, size - 1, "FreeRDP Print %04d-%02d-%02d %02d-%02d-%02d - Job %" PRIdz, + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, id); +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT printer_cups_write_printjob(rdpPrintJob* printjob, const BYTE* data, size_t size) +{ + rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*)printjob; + +#ifndef _CUPS_API_1_4 + + { + FILE* fp; + + fp = fopen((const char*)cups_printjob->printjob_object, "a+b"); + + if (!fp) + return ERROR_INTERNAL_ERROR; + + if (fwrite(data, 1, size, fp) < size) + { + fclose(fp); + return ERROR_INTERNAL_ERROR; + // FIXME once this function doesn't return void anymore! + } + + fclose(fp); + } + +#else + + cupsWriteRequestData((http_t*)cups_printjob->printjob_object, (const char*)data, size); + +#endif + + return CHANNEL_RC_OK; +} + +static void printer_cups_close_printjob(rdpPrintJob* printjob) +{ + rdpCupsPrintJob* cups_printjob = (rdpCupsPrintJob*)printjob; + +#ifndef _CUPS_API_1_4 + + { + char buf[100]; + + printer_cups_get_printjob_name(buf, sizeof(buf), printjob->id); + + if (cupsPrintFile(printjob->printer->name, (const char*)cups_printjob->printjob_object, buf, + 0, NULL) == 0) + { + } + + unlink(cups_printjob->printjob_object); + free(cups_printjob->printjob_object); + } + +#else + + cupsFinishDocument((http_t*)cups_printjob->printjob_object, printjob->printer->name); + cups_printjob->printjob_id = 0; + httpClose((http_t*)cups_printjob->printjob_object); + +#endif + + ((rdpCupsPrinter*)printjob->printer)->printjob = NULL; + free(cups_printjob); +} + +static rdpPrintJob* printer_cups_create_printjob(rdpPrinter* printer, UINT32 id) +{ + rdpCupsPrinter* cups_printer = (rdpCupsPrinter*)printer; + rdpCupsPrintJob* cups_printjob; + + if (cups_printer->printjob != NULL) + return NULL; + + cups_printjob = (rdpCupsPrintJob*)calloc(1, sizeof(rdpCupsPrintJob)); + if (!cups_printjob) + return NULL; + + cups_printjob->printjob.id = id; + cups_printjob->printjob.printer = printer; + + cups_printjob->printjob.Write = printer_cups_write_printjob; + cups_printjob->printjob.Close = printer_cups_close_printjob; + +#ifndef _CUPS_API_1_4 + + cups_printjob->printjob_object = _strdup(tmpnam(NULL)); + if (!cups_printjob->printjob_object) + { + free(cups_printjob); + return NULL; + } + +#else + { + char buf[100]; + +#if !defined(_CUPS_API_1_7) + cups_printjob->printjob_object = + httpConnectEncrypt(cupsServer(), ippPort(), HTTP_ENCRYPT_IF_REQUESTED); +#else + cups_printjob->printjob_object = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC, + HTTP_ENCRYPT_IF_REQUESTED, 1, 10000, NULL); +#endif + if (!cups_printjob->printjob_object) + { + free(cups_printjob); + return NULL; + } + + printer_cups_get_printjob_name(buf, sizeof(buf), cups_printjob->printjob.id); + + cups_printjob->printjob_id = + cupsCreateJob((http_t*)cups_printjob->printjob_object, printer->name, buf, 0, NULL); + + if (!cups_printjob->printjob_id) + { + httpClose((http_t*)cups_printjob->printjob_object); + free(cups_printjob); + return NULL; + } + + cupsStartDocument((http_t*)cups_printjob->printjob_object, printer->name, + cups_printjob->printjob_id, buf, CUPS_FORMAT_AUTO, 1); + } + +#endif + + cups_printer->printjob = cups_printjob; + + return (rdpPrintJob*)cups_printjob; +} + +static rdpPrintJob* printer_cups_find_printjob(rdpPrinter* printer, UINT32 id) +{ + rdpCupsPrinter* cups_printer = (rdpCupsPrinter*)printer; + + if (cups_printer->printjob == NULL) + return NULL; + if (cups_printer->printjob->printjob.id != id) + return NULL; + + return (rdpPrintJob*)cups_printer->printjob; +} + +static void printer_cups_free_printer(rdpPrinter* printer) +{ + rdpCupsPrinter* cups_printer = (rdpCupsPrinter*)printer; + + if (cups_printer->printjob) + cups_printer->printjob->printjob.Close((rdpPrintJob*)cups_printer->printjob); + + if (printer->backend) + printer->backend->ReleaseRef(printer->backend); + free(printer->name); + free(printer->driver); + free(printer); +} + +static void printer_cups_add_ref_printer(rdpPrinter* printer) +{ + if (printer) + printer->references++; +} + +static void printer_cups_release_ref_printer(rdpPrinter* printer) +{ + if (!printer) + return; + if (printer->references <= 1) + printer_cups_free_printer(printer); + else + printer->references--; +} + +static rdpPrinter* printer_cups_new_printer(rdpCupsPrinterDriver* cups_driver, const char* name, + const char* driverName, BOOL is_default) +{ + rdpCupsPrinter* cups_printer; + + cups_printer = (rdpCupsPrinter*)calloc(1, sizeof(rdpCupsPrinter)); + if (!cups_printer) + return NULL; + + cups_printer->printer.backend = &cups_driver->driver; + + cups_printer->printer.id = cups_driver->id_sequence++; + cups_printer->printer.name = _strdup(name); + if (!cups_printer->printer.name) + { + free(cups_printer); + return NULL; + } + + if (driverName) + cups_printer->printer.driver = _strdup(driverName); + else + cups_printer->printer.driver = _strdup("MS Publisher Imagesetter"); + if (!cups_printer->printer.driver) + { + free(cups_printer->printer.name); + free(cups_printer); + return NULL; + } + cups_printer->printer.is_default = is_default; + + cups_printer->printer.CreatePrintJob = printer_cups_create_printjob; + cups_printer->printer.FindPrintJob = printer_cups_find_printjob; + cups_printer->printer.AddRef = printer_cups_add_ref_printer; + cups_printer->printer.ReleaseRef = printer_cups_release_ref_printer; + + cups_printer->printer.AddRef(&cups_printer->printer); + cups_printer->printer.backend->AddRef(cups_printer->printer.backend); + return &cups_printer->printer; +} + +static void printer_cups_release_enum_printers(rdpPrinter** printers) +{ + rdpPrinter** cur = printers; + + while ((cur != NULL) && ((*cur) != NULL)) + { + if ((*cur)->ReleaseRef) + (*cur)->ReleaseRef(*cur); + cur++; + } + free(printers); +} + +static rdpPrinter** printer_cups_enum_printers(rdpPrinterDriver* driver) +{ + rdpPrinter** printers; + int num_printers; + cups_dest_t* dests; + cups_dest_t* dest; + int num_dests; + int i; + + num_dests = cupsGetDests(&dests); + printers = (rdpPrinter**)calloc(num_dests + 1, sizeof(rdpPrinter*)); + if (!printers) + return NULL; + + num_printers = 0; + + for (i = 0, dest = dests; i < num_dests; i++, dest++) + { + if (dest->instance == NULL) + { + rdpPrinter* current = printer_cups_new_printer((rdpCupsPrinterDriver*)driver, + dest->name, NULL, dest->is_default); + if (!current) + { + printer_cups_release_enum_printers(printers); + printers = NULL; + break; + } + + printers[num_printers++] = current; + } + } + cupsFreeDests(num_dests, dests); + + return printers; +} + +static rdpPrinter* printer_cups_get_printer(rdpPrinterDriver* driver, const char* name, + const char* driverName) +{ + rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*)driver; + + return printer_cups_new_printer(cups_driver, name, driverName, + cups_driver->id_sequence == 1 ? TRUE : FALSE); +} + +static void printer_cups_add_ref_driver(rdpPrinterDriver* driver) +{ + rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*)driver; + if (cups_driver) + cups_driver->references++; +} + +/* Singleton */ +static rdpCupsPrinterDriver* uniq_cups_driver = NULL; + +static void printer_cups_release_ref_driver(rdpPrinterDriver* driver) +{ + rdpCupsPrinterDriver* cups_driver = (rdpCupsPrinterDriver*)driver; + if (cups_driver->references <= 1) + { + if (uniq_cups_driver == cups_driver) + uniq_cups_driver = NULL; + free(cups_driver); + cups_driver = NULL; + } + else + cups_driver->references--; +} + +#ifdef BUILTIN_CHANNELS +rdpPrinterDriver* cups_freerdp_printer_client_subsystem_entry(void) +#else +FREERDP_API rdpPrinterDriver* freerdp_printer_client_subsystem_entry(void) +#endif +{ + if (!uniq_cups_driver) + { + uniq_cups_driver = (rdpCupsPrinterDriver*)calloc(1, sizeof(rdpCupsPrinterDriver)); + + if (!uniq_cups_driver) + return NULL; + + uniq_cups_driver->driver.EnumPrinters = printer_cups_enum_printers; + uniq_cups_driver->driver.ReleaseEnumPrinters = printer_cups_release_enum_printers; + uniq_cups_driver->driver.GetPrinter = printer_cups_get_printer; + + uniq_cups_driver->driver.AddRef = printer_cups_add_ref_driver; + uniq_cups_driver->driver.ReleaseRef = printer_cups_release_ref_driver; + + uniq_cups_driver->id_sequence = 1; + uniq_cups_driver->driver.AddRef(&uniq_cups_driver->driver); + } + + return &uniq_cups_driver->driver; +} diff --git a/channels/printer/client/printer_main.c b/channels/printer/client/printer_main.c index 630c0c0..dbcc07d 100644 --- a/channels/printer/client/printer_main.c +++ b/channels/printer/client/printer_main.c @@ -35,20 +35,14 @@ #include #include #include +#include #include +#include #include "../printer.h" -#ifdef WITH_CUPS -#include "printer_cups.h" -#endif - -#include "printer_main.h" - -#if defined(_WIN32) && !defined(_UWP) -#include "printer_win.h" -#endif +#include #include @@ -71,6 +65,357 @@ struct _PRINTER_DEVICE char port[64]; }; +typedef enum +{ + PRN_CONF_PORT = 0, + PRN_CONF_PNP = 1, + PRN_CONF_DRIVER = 2, + PRN_CONF_DATA = 3 +} prn_conf_t; + +static const char* filemap[] = { "PortDosName", "PnPName", "DriverName", + "CachedPrinterConfigData" }; + +static char* get_printer_config_path(const rdpSettings* settings, const WCHAR* name, size_t length) +{ + char* dir = GetCombinedPath(settings->ConfigPath, "printers"); + char* bname = crypto_base64_encode((const BYTE*)name, (int)length); + char* config = GetCombinedPath(dir, bname); + + if (config && !PathFileExistsA(config)) + { + if (!PathMakePathA(config, NULL)) + { + free(config); + config = NULL; + } + } + + free(dir); + free(bname); + return config; +} + +static BOOL printer_write_setting(const char* path, prn_conf_t type, const void* data, + size_t length) +{ + DWORD written = 0; + BOOL rc = FALSE; + HANDLE file; + size_t b64len; + char* base64 = NULL; + const char* name = filemap[type]; + char* abs = GetCombinedPath(path, name); + + if (!abs || (length > INT32_MAX)) + return FALSE; + + file = CreateFileA(abs, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + free(abs); + + if (file == INVALID_HANDLE_VALUE) + return FALSE; + + if (length > 0) + { + base64 = crypto_base64_encode(data, length); + + if (!base64) + goto fail; + + /* base64 char represents 6bit -> 4*(n/3) is the length which is + * always smaller than 2*n */ + b64len = strnlen(base64, 2 * length); + rc = WriteFile(file, base64, b64len, &written, NULL); + + if (b64len != written) + rc = FALSE; + } + else + rc = TRUE; + +fail: + CloseHandle(file); + free(base64); + return rc; +} + +static BOOL printer_config_valid(const char* path) +{ + if (!path) + return FALSE; + + if (!PathFileExistsA(path)) + return FALSE; + + return TRUE; +} + +static BOOL printer_read_setting(const char* path, prn_conf_t type, void** data, UINT32* length) +{ + DWORD lowSize, highSize; + DWORD read = 0; + BOOL rc = FALSE; + HANDLE file; + char* fdata = NULL; + const char* name = filemap[type]; + char* abs = GetCombinedPath(path, name); + + if (!abs) + return FALSE; + + file = CreateFileA(abs, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + free(abs); + + if (file == INVALID_HANDLE_VALUE) + return FALSE; + + lowSize = GetFileSize(file, &highSize); + + if ((lowSize == INVALID_FILE_SIZE) || (highSize != 0)) + goto fail; + + if (lowSize != 0) + { + fdata = malloc(lowSize); + + if (!fdata) + goto fail; + + rc = ReadFile(file, fdata, lowSize, &read, NULL); + + if (lowSize != read) + rc = FALSE; + } + +fail: + CloseHandle(file); + + if (rc && (lowSize <= INT_MAX)) + { + int blen = 0; + crypto_base64_decode(fdata, (int)lowSize, (BYTE**)data, &blen); + + if (*data && (blen > 0)) + *length = (UINT32)blen; + else + { + rc = FALSE; + *length = 0; + } + } + else + { + *length = 0; + *data = NULL; + } + + free(fdata); + return rc; +} + +static BOOL printer_save_to_config(const rdpSettings* settings, const char* PortDosName, + size_t PortDosNameLen, const WCHAR* PnPName, size_t PnPNameLen, + const WCHAR* DriverName, size_t DriverNameLen, + const WCHAR* PrinterName, size_t PrintNameLen, + const BYTE* CachedPrinterConfigData, size_t CacheFieldsLen) +{ + BOOL rc = FALSE; + char* path = get_printer_config_path(settings, PrinterName, PrintNameLen); + + if (!path) + goto fail; + + if (!printer_write_setting(path, PRN_CONF_PORT, PortDosName, PortDosNameLen)) + goto fail; + + if (!printer_write_setting(path, PRN_CONF_PNP, PnPName, PnPNameLen)) + goto fail; + + if (!printer_write_setting(path, PRN_CONF_DRIVER, DriverName, DriverNameLen)) + goto fail; + + if (!printer_write_setting(path, PRN_CONF_DATA, CachedPrinterConfigData, CacheFieldsLen)) + goto fail; + +fail: + free(path); + return rc; +} + +static BOOL printer_update_to_config(const rdpSettings* settings, const WCHAR* name, size_t length, + const BYTE* data, size_t datalen) +{ + BOOL rc = FALSE; + char* path = get_printer_config_path(settings, name, length); + rc = printer_write_setting(path, PRN_CONF_DATA, data, datalen); + free(path); + return rc; +} + +static BOOL printer_remove_config(const rdpSettings* settings, const WCHAR* name, size_t length) +{ + BOOL rc = FALSE; + char* path = get_printer_config_path(settings, name, length); + + if (!printer_config_valid(path)) + goto fail; + + rc = RemoveDirectoryA(path); +fail: + free(path); + return rc; +} + +static BOOL printer_move_config(const rdpSettings* settings, const WCHAR* oldName, size_t oldLength, + const WCHAR* newName, size_t newLength) +{ + BOOL rc = FALSE; + char* oldPath = get_printer_config_path(settings, oldName, oldLength); + char* newPath = get_printer_config_path(settings, newName, newLength); + + if (printer_config_valid(oldPath)) + rc = MoveFileA(oldPath, newPath); + + free(oldPath); + free(newPath); + return rc; +} + +static BOOL printer_load_from_config(const rdpSettings* settings, rdpPrinter* printer, + PRINTER_DEVICE* printer_dev) +{ + BOOL res = FALSE; + WCHAR* wname = NULL; + size_t wlen; + char* path = NULL; + int rc; + UINT32 flags = 0; + void* DriverName = NULL; + UINT32 DriverNameLen = 0; + void* PnPName = NULL; + UINT32 PnPNameLen = 0; + void* CachedPrinterConfigData = NULL; + UINT32 CachedFieldsLen = 0; + UINT32 PrinterNameLen = 0; + + if (!settings || !printer) + return FALSE; + + rc = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &wname, 0); + + if (rc <= 0) + goto fail; + + wlen = _wcslen(wname) + 1; + path = get_printer_config_path(settings, wname, wlen * sizeof(WCHAR)); + PrinterNameLen = (wlen + 1) * sizeof(WCHAR); + + if (!path) + goto fail; + + if (printer->is_default) + flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER; + + if (!printer_read_setting(path, PRN_CONF_PNP, &PnPName, &PnPNameLen)) + { + } + + if (!printer_read_setting(path, PRN_CONF_DRIVER, &DriverName, &DriverNameLen)) + { + DriverNameLen = + ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, (LPWSTR*)&DriverName, 0) * 2 + 1; + } + + if (!printer_read_setting(path, PRN_CONF_DATA, &CachedPrinterConfigData, &CachedFieldsLen)) + { + } + + Stream_SetPosition(printer_dev->device.data, 0); + + if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, 24)) + goto fail; + + Stream_Write_UINT32(printer_dev->device.data, flags); + Stream_Write_UINT32(printer_dev->device.data, 0); /* CodePage, reserved */ + Stream_Write_UINT32(printer_dev->device.data, PnPNameLen); /* PnPNameLen */ + Stream_Write_UINT32(printer_dev->device.data, DriverNameLen); + Stream_Write_UINT32(printer_dev->device.data, PrinterNameLen); + Stream_Write_UINT32(printer_dev->device.data, CachedFieldsLen); + + if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, PnPNameLen)) + goto fail; + + if (PnPNameLen > 0) + Stream_Write(printer_dev->device.data, PnPName, PnPNameLen); + + if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, DriverNameLen)) + goto fail; + + Stream_Write(printer_dev->device.data, DriverName, DriverNameLen); + + if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, PrinterNameLen)) + goto fail; + + Stream_Write(printer_dev->device.data, wname, PrinterNameLen); + + if (!Stream_EnsureRemainingCapacity(printer_dev->device.data, CachedFieldsLen)) + goto fail; + + Stream_Write(printer_dev->device.data, CachedPrinterConfigData, CachedFieldsLen); + res = TRUE; +fail: + free(path); + free(wname); + free(PnPName); + free(DriverName); + free(CachedPrinterConfigData); + return res; +} + +static BOOL printer_save_default_config(const rdpSettings* settings, rdpPrinter* printer) +{ + BOOL res = FALSE; + WCHAR* wname = NULL; + WCHAR* driver = NULL; + size_t wlen, dlen; + char* path = NULL; + int rc; + + if (!settings || !printer) + return FALSE; + + rc = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &wname, 0); + + if (rc <= 0) + goto fail; + + rc = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &driver, 0); + + if (rc <= 0) + goto fail; + + wlen = _wcslen(wname) + 1; + dlen = _wcslen(driver) + 1; + path = get_printer_config_path(settings, wname, wlen * sizeof(WCHAR)); + + if (!path) + goto fail; + + if (dlen > 1) + { + if (!printer_write_setting(path, PRN_CONF_DRIVER, driver, dlen * sizeof(WCHAR))) + goto fail; + } + + res = TRUE; +fail: + free(path); + free(wname); + free(driver); + return res; +} + /** * Function description * @@ -81,8 +426,8 @@ static UINT printer_process_irp_create(PRINTER_DEVICE* printer_dev, IRP* irp) rdpPrintJob* printjob = NULL; if (printer_dev->printer) - printjob = printer_dev->printer->CreatePrintJob(printer_dev->printer, - irp->devman->id_sequence++); + printjob = + printer_dev->printer->CreatePrintJob(printer_dev->printer, irp->devman->id_sequence++); if (printjob) { @@ -107,8 +452,7 @@ static UINT printer_process_irp_close(PRINTER_DEVICE* printer_dev, IRP* irp) rdpPrintJob* printjob = NULL; if (printer_dev->printer) - printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, - irp->FileId); + printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, irp->FileId); if (!printjob) { @@ -134,13 +478,18 @@ static UINT printer_process_irp_write(PRINTER_DEVICE* printer_dev, IRP* irp) UINT64 Offset; rdpPrintJob* printjob = NULL; UINT error = CHANNEL_RC_OK; + void* ptr; + + if (Stream_GetRemainingLength(irp->input) < 32) + return ERROR_INVALID_DATA; Stream_Read_UINT32(irp->input, Length); Stream_Read_UINT64(irp->input, Offset); Stream_Seek(irp->input, 20); /* Padding */ - + ptr = Stream_Pointer(irp->input); + if (!Stream_SafeSeek(irp->input, Length)) + return ERROR_INVALID_DATA; if (printer_dev->printer) - printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, - irp->FileId); + printjob = printer_dev->printer->FindPrintJob(printer_dev->printer, irp->FileId); if (!printjob) { @@ -149,12 +498,12 @@ static UINT printer_process_irp_write(PRINTER_DEVICE* printer_dev, IRP* irp) } else { - error = printjob->Write(printjob, Stream_Pointer(irp->input), Length); + error = printjob->Write(printjob, ptr, Length); } if (error) { - WLog_ERR(TAG, "printjob->Write failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "printjob->Write failed with error %" PRIu32 "!", error); return error; } @@ -168,8 +517,7 @@ static UINT printer_process_irp_write(PRINTER_DEVICE* printer_dev, IRP* irp) * * @return 0 on success, otherwise a Win32 error code */ -static UINT printer_process_irp_device_control(PRINTER_DEVICE* printer_dev, - IRP* irp) +static UINT printer_process_irp_device_control(PRINTER_DEVICE* printer_dev, IRP* irp) { Stream_Write_UINT32(irp->output, 0); /* OutputBufferLength */ return irp->Complete(irp); @@ -189,7 +537,7 @@ static UINT printer_process_irp(PRINTER_DEVICE* printer_dev, IRP* irp) case IRP_MJ_CREATE: if ((error = printer_process_irp_create(printer_dev, irp))) { - WLog_ERR(TAG, "printer_process_irp_create failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "printer_process_irp_create failed with error %" PRIu32 "!", error); return error; } @@ -198,7 +546,7 @@ static UINT printer_process_irp(PRINTER_DEVICE* printer_dev, IRP* irp) case IRP_MJ_CLOSE: if ((error = printer_process_irp_close(printer_dev, irp))) { - WLog_ERR(TAG, "printer_process_irp_close failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "printer_process_irp_close failed with error %" PRIu32 "!", error); return error; } @@ -207,7 +555,7 @@ static UINT printer_process_irp(PRINTER_DEVICE* printer_dev, IRP* irp) case IRP_MJ_WRITE: if ((error = printer_process_irp_write(printer_dev, irp))) { - WLog_ERR(TAG, "printer_process_irp_write failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "printer_process_irp_write failed with error %" PRIu32 "!", error); return error; } @@ -216,7 +564,7 @@ static UINT printer_process_irp(PRINTER_DEVICE* printer_dev, IRP* irp) case IRP_MJ_DEVICE_CONTROL: if ((error = printer_process_irp_device_control(printer_dev, irp))) { - WLog_ERR(TAG, "printer_process_irp_device_control failed with error %"PRIu32"!", + WLog_ERR(TAG, "printer_process_irp_device_control failed with error %" PRIu32 "!", error); return error; } @@ -235,8 +583,8 @@ static UINT printer_process_irp(PRINTER_DEVICE* printer_dev, IRP* irp) static DWORD WINAPI printer_thread_func(LPVOID arg) { IRP* irp; - PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) arg; - HANDLE obj[] = {printer_dev->event, printer_dev->stopEvent}; + PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*)arg; + HANDLE obj[] = { printer_dev->event, printer_dev->stopEvent }; UINT error = CHANNEL_RC_OK; while (1) @@ -246,7 +594,7 @@ static DWORD WINAPI printer_thread_func(LPVOID arg) if (rc == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "WaitForMultipleObjects failed with error %" PRIu32 "!", error); break; } @@ -256,7 +604,7 @@ static DWORD WINAPI printer_thread_func(LPVOID arg) continue; ResetEvent(printer_dev->event); - irp = (IRP*) InterlockedPopEntrySList(printer_dev->pIrpList); + irp = (IRP*)InterlockedPopEntrySList(printer_dev->pIrpList); if (irp == NULL) { @@ -267,14 +615,13 @@ static DWORD WINAPI printer_thread_func(LPVOID arg) if ((error = printer_process_irp(printer_dev, irp))) { - WLog_ERR(TAG, "printer_process_irp failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "printer_process_irp failed with error %" PRIu32 "!", error); break; } } if (error && printer_dev->rdpcontext) - setChannelError(printer_dev->rdpcontext, error, - "printer_thread_func reported an error"); + setChannelError(printer_dev->rdpcontext, error, "printer_thread_func reported an error"); ExitThread(error); return error; @@ -287,12 +634,188 @@ static DWORD WINAPI printer_thread_func(LPVOID arg) */ static UINT printer_irp_request(DEVICE* device, IRP* irp) { - PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) device; + PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*)device; InterlockedPushEntrySList(printer_dev->pIrpList, &(irp->ItemEntry)); SetEvent(printer_dev->event); return CHANNEL_RC_OK; } +static UINT printer_custom_component(DEVICE* device, UINT16 component, UINT16 packetId, wStream* s) +{ + UINT32 eventID; + PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*)device; + const rdpSettings* settings = printer_dev->rdpcontext->settings; + + if (component != RDPDR_CTYP_PRN) + return ERROR_INVALID_DATA; + + if (Stream_GetRemainingLength(s) < 4) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, eventID); + + switch (packetId) + { + case PAKID_PRN_CACHE_DATA: + switch (eventID) + { + case RDPDR_ADD_PRINTER_EVENT: + { + char PortDosName[8]; + UINT32 PnPNameLen, DriverNameLen, PrintNameLen, CacheFieldsLen; + const WCHAR *PnPName, *DriverName, *PrinterName; + const BYTE* CachedPrinterConfigData; + + if (Stream_GetRemainingLength(s) < 24) + return ERROR_INVALID_DATA; + + Stream_Read(s, PortDosName, sizeof(PortDosName)); + Stream_Read_UINT32(s, PnPNameLen); + Stream_Read_UINT32(s, DriverNameLen); + Stream_Read_UINT32(s, PrintNameLen); + Stream_Read_UINT32(s, CacheFieldsLen); + + if (Stream_GetRemainingLength(s) < PnPNameLen) + return ERROR_INVALID_DATA; + + PnPName = (const WCHAR*)Stream_Pointer(s); + Stream_Seek(s, PnPNameLen); + + if (Stream_GetRemainingLength(s) < DriverNameLen) + return ERROR_INVALID_DATA; + + DriverName = (const WCHAR*)Stream_Pointer(s); + Stream_Seek(s, DriverNameLen); + + if (Stream_GetRemainingLength(s) < PrintNameLen) + return ERROR_INVALID_DATA; + + PrinterName = (const WCHAR*)Stream_Pointer(s); + Stream_Seek(s, PrintNameLen); + + if (Stream_GetRemainingLength(s) < CacheFieldsLen) + return ERROR_INVALID_DATA; + + CachedPrinterConfigData = Stream_Pointer(s); + Stream_Seek(s, CacheFieldsLen); + + if (!printer_save_to_config(settings, PortDosName, sizeof(PortDosName), PnPName, + PnPNameLen, DriverName, DriverNameLen, PrinterName, + PrintNameLen, CachedPrinterConfigData, + CacheFieldsLen)) + return ERROR_INTERNAL_ERROR; + } + break; + + case RDPDR_UPDATE_PRINTER_EVENT: + { + UINT32 PrinterNameLen, ConfigDataLen; + const WCHAR* PrinterName; + const BYTE* ConfigData; + + if (Stream_GetRemainingLength(s) < 8) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, PrinterNameLen); + Stream_Read_UINT32(s, ConfigDataLen); + + if (Stream_GetRemainingLength(s) < PrinterNameLen) + return ERROR_INVALID_DATA; + + PrinterName = (const WCHAR*)Stream_Pointer(s); + Stream_Seek(s, PrinterNameLen); + + if (Stream_GetRemainingLength(s) < ConfigDataLen) + return ERROR_INVALID_DATA; + + ConfigData = Stream_Pointer(s); + Stream_Seek(s, ConfigDataLen); + + if (!printer_update_to_config(settings, PrinterName, PrinterNameLen, ConfigData, + ConfigDataLen)) + return ERROR_INTERNAL_ERROR; + } + break; + + case RDPDR_DELETE_PRINTER_EVENT: + { + UINT32 PrinterNameLen; + const WCHAR* PrinterName; + + if (Stream_GetRemainingLength(s) < 4) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, PrinterNameLen); + + if (Stream_GetRemainingLength(s) < PrinterNameLen) + return ERROR_INVALID_DATA; + + PrinterName = (const WCHAR*)Stream_Pointer(s); + Stream_Seek(s, PrinterNameLen); + printer_remove_config(settings, PrinterName, PrinterNameLen); + } + break; + + case RDPDR_RENAME_PRINTER_EVENT: + { + UINT32 OldPrinterNameLen, NewPrinterNameLen; + const WCHAR* OldPrinterName; + const WCHAR* NewPrinterName; + + if (Stream_GetRemainingLength(s) < 8) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, OldPrinterNameLen); + Stream_Read_UINT32(s, NewPrinterNameLen); + + if (Stream_GetRemainingLength(s) < OldPrinterNameLen) + return ERROR_INVALID_DATA; + + OldPrinterName = (const WCHAR*)Stream_Pointer(s); + Stream_Seek(s, OldPrinterNameLen); + + if (Stream_GetRemainingLength(s) < NewPrinterNameLen) + return ERROR_INVALID_DATA; + + NewPrinterName = (const WCHAR*)Stream_Pointer(s); + Stream_Seek(s, NewPrinterNameLen); + + if (!printer_move_config(settings, OldPrinterName, OldPrinterNameLen, + NewPrinterName, NewPrinterNameLen)) + return ERROR_INTERNAL_ERROR; + } + break; + + default: + WLog_ERR(TAG, "Unknown cache data eventID: 0x%08" PRIX32 "", eventID); + return ERROR_INVALID_DATA; + } + + break; + + case PAKID_PRN_USING_XPS: + { + UINT32 flags; + + if (Stream_GetRemainingLength(s) < 4) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, flags); + WLog_ERR(TAG, + "Ignoring unhandled message PAKID_PRN_USING_XPS [printerID=%08" PRIx32 + ", flags=%08" PRIx32 "]", + eventID, flags); + } + break; + + default: + WLog_ERR(TAG, "Unknown printing component packetID: 0x%04" PRIX16 "", packetId); + return ERROR_INVALID_DATA; + } + + return CHANNEL_RC_OK; +} + /** * Function description * @@ -301,18 +824,24 @@ static UINT printer_irp_request(DEVICE* device, IRP* irp) static UINT printer_free(DEVICE* device) { IRP* irp; - PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) device; + PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*)device; UINT error; SetEvent(printer_dev->stopEvent); if (WaitForSingleObject(printer_dev->thread, INFINITE) == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", error); + 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; +#endif } - while ((irp = (IRP*) InterlockedPopEntrySList(printer_dev->pIrpList)) != NULL) + while ((irp = (IRP*)InterlockedPopEntrySList(printer_dev->pIrpList)) != NULL) irp->Discard(irp); CloseHandle(printer_dev->thread); @@ -321,7 +850,7 @@ static UINT printer_free(DEVICE* device) _aligned_free(printer_dev->pIrpList); if (printer_dev->printer) - printer_dev->printer->Free(printer_dev->printer); + printer_dev->printer->ReleaseRef(printer_dev->printer); Stream_Free(printer_dev->device.data, TRUE); free(printer_dev); @@ -333,19 +862,11 @@ static UINT printer_free(DEVICE* device) * * @return 0 on success, otherwise a Win32 error code */ -UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, - rdpPrinter* printer) +static UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, rdpPrinter* printer) { - UINT32 Flags; - int DriverNameLen; - WCHAR* DriverName = NULL; - int PrintNameLen; - WCHAR* PrintName = NULL; - UINT32 CachedFieldsLen; - BYTE* CachedPrinterConfigData; PRINTER_DEVICE* printer_dev; - UINT error; - printer_dev = (PRINTER_DEVICE*) calloc(1, sizeof(PRINTER_DEVICE)); + UINT error = ERROR_INTERNAL_ERROR; + printer_dev = (PRINTER_DEVICE*)calloc(1, sizeof(PRINTER_DEVICE)); if (!printer_dev) { @@ -353,57 +874,21 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, return CHANNEL_RC_NO_MEMORY; } - sprintf_s(printer_dev->port, sizeof(printer_dev->port), "PRN%d", printer->id); + printer_dev->device.data = Stream_New(NULL, 1024); + + if (!printer_dev->device.data) + goto error_out; + + sprintf_s(printer_dev->port, sizeof(printer_dev->port), "PRN%" PRIdz, printer->id); printer_dev->device.type = RDPDR_DTYP_PRINT; printer_dev->device.name = printer_dev->port; printer_dev->device.IRPRequest = printer_irp_request; + printer_dev->device.CustomComponentRequest = printer_custom_component; printer_dev->device.Free = printer_free; printer_dev->rdpcontext = pEntryPoints->rdpcontext; printer_dev->printer = printer; - CachedFieldsLen = 0; - CachedPrinterConfigData = NULL; - Flags = 0; - - if (printer->is_default) - Flags |= RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER; - - DriverNameLen = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &DriverName, - 0) * 2; - PrintNameLen = ConvertToUnicode(CP_UTF8, 0, printer->name, -1, &PrintName, - 0) * 2; - printer_dev->device.data = Stream_New(NULL, - 28 + DriverNameLen + PrintNameLen + CachedFieldsLen); - - if (!printer_dev->device.data) - { - WLog_ERR(TAG, "calloc failed!"); - error = CHANNEL_RC_NO_MEMORY; - free(DriverName); - free(PrintName); - goto error_out; - } - - Stream_Write_UINT32(printer_dev->device.data, Flags); - Stream_Write_UINT32(printer_dev->device.data, 0); /* CodePage, reserved */ - Stream_Write_UINT32(printer_dev->device.data, 0); /* PnPNameLen */ - Stream_Write_UINT32(printer_dev->device.data, DriverNameLen + 2); - Stream_Write_UINT32(printer_dev->device.data, PrintNameLen + 2); - Stream_Write_UINT32(printer_dev->device.data, CachedFieldsLen); - Stream_Write(printer_dev->device.data, DriverName, DriverNameLen); - Stream_Write_UINT16(printer_dev->device.data, 0); - Stream_Write(printer_dev->device.data, PrintName, PrintNameLen); - Stream_Write_UINT16(printer_dev->device.data, 0); - - if (CachedFieldsLen > 0) - { - Stream_Write(printer_dev->device.data, CachedPrinterConfigData, - CachedFieldsLen); - } - - free(DriverName); - free(PrintName); - printer_dev->pIrpList = (WINPR_PSLIST_HEADER) _aligned_malloc(sizeof( - WINPR_SLIST_HEADER), MEMORY_ALLOCATION_ALIGNMENT); + printer_dev->pIrpList = (WINPR_PSLIST_HEADER)_aligned_malloc(sizeof(WINPR_SLIST_HEADER), + MEMORY_ALLOCATION_ALIGNMENT); if (!printer_dev->pIrpList) { @@ -412,6 +897,9 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, goto error_out; } + 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))) @@ -428,54 +916,102 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints, goto error_out; } - if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, - (DEVICE*) printer_dev))) + if ((error = pEntryPoints->RegisterDevice(pEntryPoints->devman, (DEVICE*)printer_dev))) { - WLog_ERR(TAG, "RegisterDevice failed with error %"PRIu32"!", 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->thread = + CreateThread(NULL, 0, printer_thread_func, (void*)printer_dev, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); error = ERROR_INTERNAL_ERROR; goto error_out; } + printer->AddRef(printer); return CHANNEL_RC_OK; error_out: printer_free(&printer_dev->device); return error; } -#ifdef BUILTIN_CHANNELS -#define DeviceServiceEntry printer_DeviceServiceEntry -#else -#define DeviceServiceEntry FREERDP_API DeviceServiceEntry -#endif +static rdpPrinterDriver* printer_load_backend(const char* backend) +{ + typedef rdpPrinterDriver* (*backend_load_t)(void); + union { + PVIRTUALCHANNELENTRY entry; + backend_load_t backend; + } fktconv; + + fktconv.entry = freerdp_load_channel_addin_entry("printer", backend, NULL, 0); + if (!fktconv.entry) + return NULL; + + return fktconv.backend(); +} /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) +UINT +#ifdef BUILTIN_CHANNELS +printer_DeviceServiceEntry +#else + FREERDP_API + DeviceServiceEntry +#endif + (PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) { int i; char* name; char* driver_name; - rdpPrinter* printer; - rdpPrinter** printers; - RDPDR_PRINTER* device; + BOOL default_backend = TRUE; + RDPDR_PRINTER* device = NULL; rdpPrinterDriver* driver = NULL; - UINT error; -#ifdef WITH_CUPS - driver = printer_cups_get_driver(); -#endif -#if defined(_WIN32) && !defined(_UWP) - driver = printer_win_get_driver(); + UINT error = CHANNEL_RC_OK; + + if (!pEntryPoints || !pEntryPoints->device) + return ERROR_INVALID_PARAMETER; + + device = (RDPDR_PRINTER*)pEntryPoints->device; + name = device->Name; + driver_name = device->DriverName; + + /* Secondary argument is one of the following: + * + * ... name of a printer driver + * : ... name of a printer driver and local printer backend to use + */ + if (driver_name) + { + char* sep = strstr(driver_name, ":"); + if (sep) + { + const char* backend = sep + 1; + *sep = '\0'; + driver = printer_load_backend(backend); + default_backend = FALSE; + } + } + + if (!driver && default_backend) + { + const char* backend = +#if defined(WITH_CUPS) + "cups" +#elif defined(_WIN32) + "win" +#else + "" #endif + ; + + driver = printer_load_backend(backend); + } if (!driver) { @@ -483,44 +1019,52 @@ UINT DeviceServiceEntry(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints) return CHANNEL_RC_INITIALIZATION_ERROR; } - device = (RDPDR_PRINTER*) pEntryPoints->device; - name = device->Name; - driver_name = device->DriverName; - if (name && name[0]) { - printer = driver->GetPrinter(driver, name, driver_name); + rdpPrinter* printer = driver->GetPrinter(driver, name, driver_name); if (!printer) { WLog_ERR(TAG, "Could not get printer %s!", name); - return CHANNEL_RC_INITIALIZATION_ERROR; + error = CHANNEL_RC_INITIALIZATION_ERROR; + goto fail; + } + + if (!printer_save_default_config(pEntryPoints->rdpcontext->settings, printer)) + { + error = CHANNEL_RC_INITIALIZATION_ERROR; + printer->ReleaseRef(printer); + goto fail; } if ((error = printer_register(pEntryPoints, printer))) { - WLog_ERR(TAG, "printer_register failed with error %"PRIu32"!", error); - return error; + WLog_ERR(TAG, "printer_register failed with error %" PRIu32 "!", error); + printer->ReleaseRef(printer); + goto fail; } } else { - printers = driver->EnumPrinters(driver); + rdpPrinter** printers = driver->EnumPrinters(driver); + rdpPrinter** current = printers; - for (i = 0; printers[i]; i++) + for (i = 0; current[i]; i++) { - printer = printers[i]; + rdpPrinter* printer = current[i]; if ((error = printer_register(pEntryPoints, printer))) { - WLog_ERR(TAG, "printer_register failed with error %"PRIu32"!", error); - free(printers); - return error; + WLog_ERR(TAG, "printer_register failed with error %" PRIu32 "!", error); + break; } } - free(printers); + driver->ReleaseEnumPrinters(printers); } - return CHANNEL_RC_OK; +fail: + driver->ReleaseRef(driver); + + return error; } diff --git a/channels/printer/client/win/CMakeLists.txt b/channels/printer/client/win/CMakeLists.txt new file mode 100644 index 0000000..aa648fd --- /dev/null +++ b/channels/printer/client/win/CMakeLists.txt @@ -0,0 +1,29 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2019 Armin Novak +# Copyright 2019 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_subsystem("printer" "win" "") + +set(${MODULE_PREFIX}_SRCS + printer_win.c) + +include_directories(..) + +add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "") + +set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} winpr freerdp) + +target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) diff --git a/channels/printer/client/win/printer_win.c b/channels/printer/client/win/printer_win.c new file mode 100644 index 0000000..5306f59 --- /dev/null +++ b/channels/printer/client/win/printer_win.c @@ -0,0 +1,458 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Print Virtual Channel - WIN driver + * + * Copyright 2012 Gerald Richter + * Copyright 2015 Thincast Technologies GmbH + * Copyright 2015 DI (FH) Martin Haimberger + * Copyright 2016 Armin Novak + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#define PRINTER_TAG CHANNELS_TAG("printer.client") +#ifdef WITH_DEBUG_WINPR +#define DEBUG_WINPR(...) WLog_DBG(PRINTER_TAG, __VA_ARGS__) +#else +#define DEBUG_WINPR(...) \ + do \ + { \ + } while (0) +#endif + +typedef struct rdp_win_printer_driver rdpWinPrinterDriver; +typedef struct rdp_win_printer rdpWinPrinter; +typedef struct rdp_win_print_job rdpWinPrintJob; + +struct rdp_win_printer_driver +{ + rdpPrinterDriver driver; + + size_t id_sequence; + size_t references; +}; + +struct rdp_win_printer +{ + rdpPrinter printer; + HANDLE hPrinter; + rdpWinPrintJob* printjob; +}; + +struct rdp_win_print_job +{ + rdpPrintJob printjob; + DOC_INFO_1 di; + DWORD handle; + + void* printjob_object; + int printjob_id; +}; + +static WCHAR* printer_win_get_printjob_name(size_t id) +{ + time_t tt; + struct tm* t; + WCHAR* str; + size_t len = 1024; + int rc; + + tt = time(NULL); + t = localtime(&tt); + + str = calloc(len, sizeof(WCHAR)); + if (!str) + return NULL; + + rc = swprintf_s(str, len, L"FreeRDP Print %04d-%02d-%02d% 02d-%02d-%02d - Job %lu\0", + t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, + id); + + return str; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT printer_win_write_printjob(rdpPrintJob* printjob, const BYTE* data, size_t size) +{ + rdpWinPrinter* printer; + LPCVOID pBuf = data; + DWORD cbBuf = size; + DWORD pcWritten; + + if (!printjob || !data) + return ERROR_BAD_ARGUMENTS; + + printer = (rdpWinPrinter*)printjob->printer; + if (!printer) + return ERROR_BAD_ARGUMENTS; + + if (!WritePrinter(printer->hPrinter, pBuf, cbBuf, &pcWritten)) + return ERROR_INTERNAL_ERROR; + return CHANNEL_RC_OK; +} + +static void printer_win_close_printjob(rdpPrintJob* printjob) +{ + rdpWinPrintJob* win_printjob = (rdpWinPrintJob*)printjob; + rdpWinPrinter* win_printer; + + if (!printjob) + return; + + win_printer = (rdpWinPrinter*)printjob->printer; + if (!win_printer) + return; + + if (!EndPagePrinter(win_printer->hPrinter)) + { + } + + if (!ClosePrinter(win_printer->hPrinter)) + { + } + + win_printer->printjob = NULL; + + free(win_printjob->di.pDocName); + free(win_printjob); +} + +static rdpPrintJob* printer_win_create_printjob(rdpPrinter* printer, UINT32 id) +{ + rdpWinPrinter* win_printer = (rdpWinPrinter*)printer; + rdpWinPrintJob* win_printjob; + + if (win_printer->printjob != NULL) + return NULL; + + win_printjob = (rdpWinPrintJob*)calloc(1, sizeof(rdpWinPrintJob)); + if (!win_printjob) + return NULL; + + win_printjob->printjob.id = id; + win_printjob->printjob.printer = printer; + win_printjob->di.pDocName = printer_win_get_printjob_name(id); + win_printjob->di.pDatatype = NULL; + win_printjob->di.pOutputFile = NULL; + + win_printjob->handle = StartDocPrinter(win_printer->hPrinter, 1, (LPBYTE) & (win_printjob->di)); + + if (!win_printjob->handle) + { + free(win_printjob->di.pDocName); + free(win_printjob); + return NULL; + } + + if (!StartPagePrinter(win_printer->hPrinter)) + { + free(win_printjob->di.pDocName); + free(win_printjob); + return NULL; + } + + win_printjob->printjob.Write = printer_win_write_printjob; + win_printjob->printjob.Close = printer_win_close_printjob; + + win_printer->printjob = win_printjob; + + return &win_printjob->printjob; +} + +static rdpPrintJob* printer_win_find_printjob(rdpPrinter* printer, UINT32 id) +{ + rdpWinPrinter* win_printer = (rdpWinPrinter*)printer; + + if (!win_printer->printjob) + return NULL; + + if (win_printer->printjob->printjob.id != id) + return NULL; + + return (rdpPrintJob*)win_printer->printjob; +} + +static void printer_win_free_printer(rdpPrinter* printer) +{ + rdpWinPrinter* win_printer = (rdpWinPrinter*)printer; + + if (win_printer->printjob) + win_printer->printjob->printjob.Close((rdpPrintJob*)win_printer->printjob); + + if (printer->backend) + printer->backend->ReleaseRef(printer->backend); + + free(printer->name); + free(printer->driver); + free(printer); +} + +static void printer_win_add_ref_printer(rdpPrinter* printer) +{ + if (printer) + printer->references++; +} + +static void printer_win_release_ref_printer(rdpPrinter* printer) +{ + if (!printer) + return; + if (printer->references <= 1) + printer_win_free_printer(printer); + else + printer->references--; +} + +static rdpPrinter* printer_win_new_printer(rdpWinPrinterDriver* win_driver, const WCHAR* name, + const WCHAR* drivername, BOOL is_default) +{ + rdpWinPrinter* win_printer; + DWORD needed = 0; + int status; + PRINTER_INFO_2* prninfo = NULL; + + win_printer = (rdpWinPrinter*)calloc(1, sizeof(rdpWinPrinter)); + if (!win_printer) + return NULL; + + win_printer->printer.backend = &win_driver->driver; + win_printer->printer.id = win_driver->id_sequence++; + if (ConvertFromUnicode(CP_UTF8, 0, name, -1, &win_printer->printer.name, 0, NULL, NULL) < 1) + { + free(win_printer); + return NULL; + } + + if (!win_printer->printer.name) + { + free(win_printer); + return NULL; + } + win_printer->printer.is_default = is_default; + + win_printer->printer.CreatePrintJob = printer_win_create_printjob; + win_printer->printer.FindPrintJob = printer_win_find_printjob; + win_printer->printer.AddRef = printer_win_add_ref_printer; + win_printer->printer.ReleaseRef = printer_win_release_ref_printer; + + if (!OpenPrinter(name, &(win_printer->hPrinter), NULL)) + { + free(win_printer->printer.name); + free(win_printer); + return NULL; + } + + /* How many memory should be allocated for printer data */ + GetPrinter(win_printer->hPrinter, 2, (LPBYTE)prninfo, 0, &needed); + if (needed == 0) + { + free(win_printer->printer.name); + free(win_printer); + return NULL; + } + + prninfo = (PRINTER_INFO_2*)GlobalAlloc(GPTR, needed); + if (!prninfo) + { + free(win_printer->printer.name); + free(win_printer); + return NULL; + } + + if (!GetPrinter(win_printer->hPrinter, 2, (LPBYTE)prninfo, needed, &needed)) + { + GlobalFree(prninfo); + free(win_printer->printer.name); + free(win_printer); + return NULL; + } + + if (drivername) + status = ConvertFromUnicode(CP_UTF8, 0, drivername, -1, &win_printer->printer.driver, 0, + NULL, NULL); + else + status = ConvertFromUnicode(CP_UTF8, 0, prninfo->pDriverName, -1, + &win_printer->printer.driver, 0, NULL, NULL); + if (!win_printer->printer.driver || (status <= 0)) + { + GlobalFree(prninfo); + free(win_printer->printer.name); + free(win_printer); + return NULL; + } + + win_printer->printer.AddRef(&win_printer->printer); + win_printer->printer.backend->AddRef(win_printer->printer.backend); + return &win_printer->printer; +} + +static void printer_win_release_enum_printers(rdpPrinter** printers) +{ + rdpPrinter** cur = printers; + + while ((cur != NULL) && ((*cur) != NULL)) + { + if ((*cur)->ReleaseRef) + (*cur)->ReleaseRef(*cur); + cur++; + } + free(printers); +} + +static rdpPrinter** printer_win_enum_printers(rdpPrinterDriver* driver) +{ + rdpPrinter** printers; + int num_printers; + int i; + PRINTER_INFO_2* prninfo = NULL; + DWORD needed, returned; + + /* find required size for the buffer */ + EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &needed, + &returned); + + /* allocate array of PRINTER_INFO structures */ + prninfo = (PRINTER_INFO_2*)GlobalAlloc(GPTR, needed); + if (!prninfo) + return NULL; + + /* call again */ + if (!EnumPrinters(PRINTER_ENUM_LOCAL | PRINTER_ENUM_CONNECTIONS, NULL, 2, (LPBYTE)prninfo, + needed, &needed, &returned)) + { + } + + printers = (rdpPrinter**)calloc((returned + 1), sizeof(rdpPrinter*)); + if (!printers) + { + GlobalFree(prninfo); + return NULL; + } + + num_printers = 0; + + for (i = 0; i < (int)returned; i++) + { + rdpPrinter* current = printers[num_printers]; + current = printer_win_new_printer((rdpWinPrinterDriver*)driver, prninfo[i].pPrinterName, + prninfo[i].pDriverName, 0); + if (!current) + { + printer_win_release_enum_printers(printers); + printers = NULL; + break; + } + printers[num_printers++] = current; + } + + GlobalFree(prninfo); + return printers; +} + +static rdpPrinter* printer_win_get_printer(rdpPrinterDriver* driver, const char* name, + const char* driverName) +{ + WCHAR* driverNameW = NULL; + WCHAR* nameW = NULL; + rdpWinPrinterDriver* win_driver = (rdpWinPrinterDriver*)driver; + rdpPrinter* myPrinter = NULL; + + if (name) + { + ConvertToUnicode(CP_UTF8, 0, name, -1, &nameW, 0); + if (!driverNameW) + return NULL; + } + if (driverName) + { + ConvertToUnicode(CP_UTF8, 0, driverName, -1, &driverNameW, 0); + if (!driverNameW) + return NULL; + } + + myPrinter = printer_win_new_printer(win_driver, nameW, driverNameW, + win_driver->id_sequence == 1 ? TRUE : FALSE); + free(driverNameW); + free(nameW); + + return myPrinter; +} + +static void printer_win_add_ref_driver(rdpPrinterDriver* driver) +{ + rdpWinPrinterDriver* win = (rdpWinPrinterDriver*)driver; + if (win) + win->references++; +} + +/* Singleton */ +static rdpWinPrinterDriver* win_driver = NULL; + +static void printer_win_release_ref_driver(rdpPrinterDriver* driver) +{ + rdpWinPrinterDriver* win = (rdpWinPrinterDriver*)driver; + if (win->references <= 1) + { + free(win); + win_driver = NULL; + } + else + win->references--; +} + +#ifdef BUILTIN_CHANNELS +rdpPrinterDriver* win_freerdp_printer_client_subsystem_entry(void) +#else +FREERDP_API rdpPrinterDriver* freerdp_printer_client_subsystem_entry(void) +#endif +{ + if (!win_driver) + { + win_driver = (rdpWinPrinterDriver*)calloc(1, sizeof(rdpWinPrinterDriver)); + + if (!win_driver) + return NULL; + + win_driver->driver.EnumPrinters = printer_win_enum_printers; + win_driver->driver.ReleaseEnumPrinters = printer_win_release_enum_printers; + win_driver->driver.GetPrinter = printer_win_get_printer; + + win_driver->driver.AddRef = printer_win_add_ref_driver; + win_driver->driver.ReleaseRef = printer_win_release_ref_driver; + + win_driver->id_sequence = 1; + win_driver->driver.AddRef(&win_driver->driver); + } + + return &win_driver->driver; +} diff --git a/channels/printer/printer.h b/channels/printer/printer.h index 5ce8f5e..ae0902d 100644 --- a/channels/printer/printer.h +++ b/channels/printer/printer.h @@ -21,17 +21,16 @@ #define FREERDP_CHANNEL_PRINTER_PRINTER_H /* SERVER_PRINTER_CACHE_EVENT.cachedata */ -#define RDPDR_ADD_PRINTER_EVENT 0x00000001 -#define RDPDR_UPDATE_PRINTER_EVENT 0x00000002 -#define RDPDR_DELETE_PRINTER_EVENT 0x00000003 -#define RDPDR_RENAME_PRINTER_EVENT 0x00000004 +#define RDPDR_ADD_PRINTER_EVENT 0x00000001 +#define RDPDR_UPDATE_PRINTER_EVENT 0x00000002 +#define RDPDR_DELETE_PRINTER_EVENT 0x00000003 +#define RDPDR_RENAME_PRINTER_EVENT 0x00000004 /* DR_PRN_DEVICE_ANNOUNCE.Flags */ -#define RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII 0x00000001 -#define RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER 0x00000002 -#define RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER 0x00000004 -#define RDPDR_PRINTER_ANNOUNCE_FLAG_TSPRINTER 0x00000008 -#define RDPDR_PRINTER_ANNOUNCE_FLAG_XPSFORMAT 0x00000010 - +#define RDPDR_PRINTER_ANNOUNCE_FLAG_ASCII 0x00000001 +#define RDPDR_PRINTER_ANNOUNCE_FLAG_DEFAULTPRINTER 0x00000002 +#define RDPDR_PRINTER_ANNOUNCE_FLAG_NETWORKPRINTER 0x00000004 +#define RDPDR_PRINTER_ANNOUNCE_FLAG_TSPRINTER 0x00000008 +#define RDPDR_PRINTER_ANNOUNCE_FLAG_XPSFORMAT 0x00000010 #endif /* FREERDP_CHANNEL_PRINTER_PRINTER_H */ diff --git a/channels/rail/CMakeLists.txt b/channels/rail/CMakeLists.txt index 84100dc..d372dda 100644 --- a/channels/rail/CMakeLists.txt +++ b/channels/rail/CMakeLists.txt @@ -20,3 +20,7 @@ define_channel("rail") 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/rail/client/rail_main.c b/channels/rail/client/rail_main.c index ea772dd..e19cb92 100644 --- a/channels/rail/client/rail_main.c +++ b/channels/rail/client/rail_main.c @@ -42,7 +42,7 @@ RailClientContext* rail_get_client_interface(railPlugin* rail) if (!rail) return NULL; - pInterface = (RailClientContext*) rail->channelEntryPoints.pInterface; + pInterface = (RailClientContext*)rail->channelEntryPoints.pInterface; return pInterface; } @@ -56,15 +56,18 @@ static UINT rail_send(railPlugin* rail, wStream* s) UINT status; if (!rail) + { + Stream_Free(s, TRUE); return CHANNEL_RC_BAD_INIT_HANDLE; + } - status = rail->channelEntryPoints.pVirtualChannelWriteEx(rail->InitHandle, rail->OpenHandle, - Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s); + status = rail->channelEntryPoints.pVirtualChannelWriteEx( + rail->InitHandle, rail->OpenHandle, Stream_Buffer(s), (UINT32)Stream_GetPosition(s), s); if (status != CHANNEL_RC_OK) { Stream_Free(s, TRUE); - WLog_ERR(TAG, "pVirtualChannelWriteEx failed with %s [%08"PRIX32"]", + WLog_ERR(TAG, "pVirtualChannelWriteEx failed with %s [%08" PRIX32 "]", WTSErrorToString(status), status); } @@ -76,13 +79,15 @@ static UINT rail_send(railPlugin* rail, wStream* s) * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_send_channel_data(railPlugin* rail, void* data, size_t length) +UINT rail_send_channel_data(railPlugin* rail, wStream* src) { - wStream* s = NULL; + wStream* s; + size_t length; - if (!rail || !data) + if (!rail || !src) return ERROR_INVALID_PARAMETER; + length = Stream_GetPosition(src); s = Stream_New(NULL, length); if (!s) @@ -91,7 +96,7 @@ UINT rail_send_channel_data(railPlugin* rail, void* data, size_t length) return CHANNEL_RC_NO_MEMORY; } - Stream_Write(s, data, length); + Stream_Write(s, Stream_Buffer(src), length); return rail_send(rail, s); } @@ -104,8 +109,7 @@ UINT rail_send_channel_data(railPlugin* rail, void* data, size_t length) * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_client_execute(RailClientContext* context, - const RAIL_EXEC_ORDER* exec) +static UINT rail_client_execute(RailClientContext* context, const RAIL_EXEC_ORDER* exec) { char* exeOrFile; UINT error; @@ -118,25 +122,19 @@ static UINT rail_client_execute(RailClientContext* context, if (!context || !exec) return ERROR_INVALID_PARAMETER; - rail = (railPlugin*) context->handle; + rail = (railPlugin*)context->handle; exeOrFile = exec->RemoteApplicationProgram; flags = exec->flags; if (!exeOrFile) return ERROR_INVALID_PARAMETER; - if (strnlen(exeOrFile, MAX_PATH) >= 2) - { - if (strncmp(exeOrFile, "||", 2) != 0) - flags |= RAIL_EXEC_FLAG_FILE; - } - - if (!rail_string_to_unicode_string(exec->RemoteApplicationProgram, - &ruExeOrFile) || /* RemoteApplicationProgram */ - !rail_string_to_unicode_string(exec->RemoteApplicationWorkingDir, - &ruWorkingDir) || /* ShellWorkingDirectory */ - !rail_string_to_unicode_string(exec->RemoteApplicationArguments, - &ruArguments)) /* RemoteApplicationCmdLine */ + if (!utf8_string_to_rail_string(exec->RemoteApplicationProgram, + &ruExeOrFile) || /* RemoteApplicationProgram */ + !utf8_string_to_rail_string(exec->RemoteApplicationWorkingDir, + &ruWorkingDir) || /* ShellWorkingDirectory */ + !utf8_string_to_rail_string(exec->RemoteApplicationArguments, + &ruArguments)) /* RemoteApplicationCmdLine */ error = ERROR_INTERNAL_ERROR; else error = rail_send_client_exec_order(rail, flags, &ruExeOrFile, &ruWorkingDir, &ruArguments); @@ -152,15 +150,14 @@ static UINT rail_client_execute(RailClientContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_client_activate(RailClientContext* context, - const RAIL_ACTIVATE_ORDER* activate) +static UINT rail_client_activate(RailClientContext* context, const RAIL_ACTIVATE_ORDER* activate) { railPlugin* rail; if (!context || !activate) return ERROR_INVALID_PARAMETER; - rail = (railPlugin*) context->handle; + rail = (railPlugin*)context->handle; return rail_send_client_activate_order(rail, activate); } @@ -169,18 +166,18 @@ static UINT rail_client_activate(RailClientContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_send_client_sysparam(RailClientContext* context, - RAIL_SYSPARAM_ORDER* sysparam) +static UINT rail_send_client_sysparam(RailClientContext* context, RAIL_SYSPARAM_ORDER* sysparam) { wStream* s; size_t length = RAIL_SYSPARAM_ORDER_LENGTH; railPlugin* rail; UINT error; + BOOL extendedSpiSupported; if (!context || !sysparam) return ERROR_INVALID_PARAMETER; - rail = (railPlugin*) context->handle; + rail = (railPlugin*)context->handle; switch (sysparam->param) { @@ -201,9 +198,18 @@ static UINT rail_send_client_sysparam(RailClientContext* context, length += sysparam->highContrast.colorSchemeLength + 10; break; - default: - length += 8; + case SPI_SETFILTERKEYS: + length += 20; break; + + case SPI_SETSTICKYKEYS: + case SPI_SETCARETWIDTH: + case SPI_SETTOGGLEKEYS: + length += 4; + break; + + default: + return ERROR_BAD_ARGUMENTS; } s = rail_pdu_init(length); @@ -214,16 +220,17 @@ static UINT rail_send_client_sysparam(RailClientContext* context, return CHANNEL_RC_NO_MEMORY; } - if ((error = rail_write_client_sysparam_order(s, sysparam))) + extendedSpiSupported = rail_is_extended_spi_supported(rail->channelFlags); + if ((error = rail_write_sysparam_order(s, sysparam, extendedSpiSupported))) { - WLog_ERR(TAG, "rail_write_client_sysparam_order failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_write_client_sysparam_order failed with error %" PRIu32 "!", error); Stream_Free(s, TRUE); return error; } - if ((error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSPARAM))) + if ((error = rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSPARAM))) { - WLog_ERR(TAG, "rail_send_pdu failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_send_pdu failed with error %" PRIu32 "!", error); } Stream_Free(s, TRUE); @@ -252,7 +259,7 @@ static UINT rail_client_system_param(RailClientContext* context, if ((error = rail_send_client_sysparam(context, &sysparam))) { - WLog_ERR(TAG, "rail_send_client_sysparam failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_send_client_sysparam failed with error %" PRIu32 "!", error); return error; } } @@ -263,7 +270,7 @@ static UINT rail_client_system_param(RailClientContext* context, if ((error = rail_send_client_sysparam(context, &sysparam))) { - WLog_ERR(TAG, "rail_send_client_sysparam failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_send_client_sysparam failed with error %" PRIu32 "!", error); return error; } } @@ -274,7 +281,7 @@ static UINT rail_client_system_param(RailClientContext* context, if ((error = rail_send_client_sysparam(context, &sysparam))) { - WLog_ERR(TAG, "rail_send_client_sysparam failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_send_client_sysparam failed with error %" PRIu32 "!", error); return error; } } @@ -285,7 +292,7 @@ static UINT rail_client_system_param(RailClientContext* context, if ((error = rail_send_client_sysparam(context, &sysparam))) { - WLog_ERR(TAG, "rail_send_client_sysparam failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_send_client_sysparam failed with error %" PRIu32 "!", error); return error; } } @@ -296,7 +303,7 @@ static UINT rail_client_system_param(RailClientContext* context, if ((error = rail_send_client_sysparam(context, &sysparam))) { - WLog_ERR(TAG, "rail_send_client_sysparam failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_send_client_sysparam failed with error %" PRIu32 "!", error); return error; } } @@ -307,7 +314,7 @@ static UINT rail_client_system_param(RailClientContext* context, if ((error = rail_send_client_sysparam(context, &sysparam))) { - WLog_ERR(TAG, "rail_send_client_sysparam failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_send_client_sysparam failed with error %" PRIu32 "!", error); return error; } } @@ -318,7 +325,7 @@ static UINT rail_client_system_param(RailClientContext* context, if ((error = rail_send_client_sysparam(context, &sysparam))) { - WLog_ERR(TAG, "rail_send_client_sysparam failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_send_client_sysparam failed with error %" PRIu32 "!", error); return error; } } @@ -331,20 +338,6 @@ static UINT rail_client_system_param(RailClientContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_server_system_param(RailClientContext* context, - const RAIL_SYSPARAM_ORDER* sysparam) -{ - if (!context || !sysparam) - return ERROR_INVALID_PARAMETER; - - return CHANNEL_RC_OK; /* stub - should be registered by client */ -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ static UINT rail_client_system_command(RailClientContext* context, const RAIL_SYSCOMMAND_ORDER* syscommand) { @@ -353,7 +346,7 @@ static UINT rail_client_system_command(RailClientContext* context, if (!context || !syscommand) return ERROR_INVALID_PARAMETER; - rail = (railPlugin*) context->handle; + rail = (railPlugin*)context->handle; return rail_send_client_syscommand_order(rail, syscommand); } @@ -362,15 +355,14 @@ static UINT rail_client_system_command(RailClientContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_client_handshake(RailClientContext* context, - const RAIL_HANDSHAKE_ORDER* handshake) +static UINT rail_client_handshake(RailClientContext* context, const RAIL_HANDSHAKE_ORDER* handshake) { railPlugin* rail; if (!context || !handshake) return ERROR_INVALID_PARAMETER; - rail = (railPlugin*) context->handle; + rail = (railPlugin*)context->handle; return rail_send_handshake_order(rail, handshake); } @@ -379,51 +371,6 @@ static UINT rail_client_handshake(RailClientContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_server_handshake(RailClientContext* context, - const RAIL_HANDSHAKE_ORDER* handshake) -{ - if (!context || !handshake) - return ERROR_INVALID_PARAMETER; - - return CHANNEL_RC_OK; /* stub - should be registered by client */ -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rail_client_handshake_ex(RailClientContext* context, - const RAIL_HANDSHAKE_EX_ORDER* handshakeEx) -{ - railPlugin* rail; - - if (!context || !handshakeEx) - return ERROR_INVALID_PARAMETER; - - rail = (railPlugin*) context->handle; - return rail_send_handshake_ex_order(rail, handshakeEx); -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rail_server_handshake_ex(RailClientContext* context, - const RAIL_HANDSHAKE_EX_ORDER* handshakeEx) -{ - if (!context || !handshakeEx) - return ERROR_INVALID_PARAMETER; - - return CHANNEL_RC_OK; /* stub - should be registered by client */ -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ static UINT rail_client_notify_event(RailClientContext* context, const RAIL_NOTIFY_EVENT_ORDER* notifyEvent) { @@ -432,7 +379,7 @@ static UINT rail_client_notify_event(RailClientContext* context, if (!context || !notifyEvent) return ERROR_INVALID_PARAMETER; - rail = (railPlugin*) context->handle; + rail = (railPlugin*)context->handle; return rail_send_client_notify_event_order(rail, notifyEvent); } @@ -449,7 +396,7 @@ static UINT rail_client_window_move(RailClientContext* context, if (!context || !windowMove) return ERROR_INVALID_PARAMETER; - rail = (railPlugin*) context->handle; + rail = (railPlugin*)context->handle; return rail_send_client_window_move_order(rail, windowMove); } @@ -458,34 +405,6 @@ static UINT rail_client_window_move(RailClientContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_server_local_move_size(RailClientContext* context, - const RAIL_LOCALMOVESIZE_ORDER* localMoveSize) -{ - if (!context || !localMoveSize) - return ERROR_INVALID_PARAMETER; - - return CHANNEL_RC_OK; /* stub - should be registered by client */ -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rail_server_min_max_info(RailClientContext* context, - const RAIL_MINMAXINFO_ORDER* minMaxInfo) -{ - if (!context || !minMaxInfo) - return ERROR_INVALID_PARAMETER; - - return CHANNEL_RC_OK; /* stub - should be registered by client */ -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ static UINT rail_client_information(RailClientContext* context, const RAIL_CLIENT_STATUS_ORDER* clientStatus) { @@ -494,7 +413,7 @@ static UINT rail_client_information(RailClientContext* context, if (!context || !clientStatus) return ERROR_INVALID_PARAMETER; - rail = (railPlugin*) context->handle; + rail = (railPlugin*)context->handle; return rail_send_client_status_order(rail, clientStatus); } @@ -503,15 +422,14 @@ static UINT rail_client_information(RailClientContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_client_system_menu(RailClientContext* context, - const RAIL_SYSMENU_ORDER* sysmenu) +static UINT rail_client_system_menu(RailClientContext* context, const RAIL_SYSMENU_ORDER* sysmenu) { railPlugin* rail; if (!context || !sysmenu) return ERROR_INVALID_PARAMETER; - rail = (railPlugin*) context->handle; + rail = (railPlugin*)context->handle; return rail_send_client_sysmenu_order(rail, sysmenu); } @@ -521,29 +439,27 @@ static UINT rail_client_system_menu(RailClientContext* context, * @return 0 on success, otherwise a Win32 error code */ static UINT rail_client_language_bar_info(RailClientContext* context, - const RAIL_LANGBAR_INFO_ORDER* langBarInfo) + const RAIL_LANGBAR_INFO_ORDER* langBarInfo) { railPlugin* rail; if (!context || !langBarInfo) return ERROR_INVALID_PARAMETER; - rail = (railPlugin*) context->handle; + rail = (railPlugin*)context->handle; return rail_send_client_langbar_info_order(rail, langBarInfo); } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rail_server_language_bar_info(RailClientContext* context, - const RAIL_LANGBAR_INFO_ORDER* langBarInfo) +static UINT rail_client_language_ime_info(RailClientContext* context, + const RAIL_LANGUAGEIME_INFO_ORDER* langImeInfo) { - if (!context || !langBarInfo) + railPlugin* rail; + + if (!context || !langImeInfo) return ERROR_INVALID_PARAMETER; - return CHANNEL_RC_OK; /* stub - should be registered by client */ + rail = (railPlugin*)context->handle; + return rail_send_client_languageime_info_order(rail, langImeInfo); } /** @@ -551,44 +467,50 @@ static UINT rail_server_language_bar_info(RailClientContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_server_execute_result(RailClientContext* context, - const RAIL_EXEC_RESULT_ORDER* execResult) +static UINT rail_client_get_appid_request(RailClientContext* context, + const RAIL_GET_APPID_REQ_ORDER* getAppIdReq) { - if (!context || !execResult) + railPlugin* rail; + + if (!context || !getAppIdReq || !context->handle) return ERROR_INVALID_PARAMETER; - return CHANNEL_RC_OK; /* stub - should be registered by client */ + rail = (railPlugin*)context->handle; + return rail_send_client_get_appid_req_order(rail, getAppIdReq); } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rail_client_get_appid_request(RailClientContext* context, - const RAIL_GET_APPID_REQ_ORDER* getAppIdReq) +static UINT rail_client_compartment_info(RailClientContext* context, + const RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo) { railPlugin* rail; - if (!context || !getAppIdReq || !context->handle) + if (!context || !compartmentInfo || !context->handle) return ERROR_INVALID_PARAMETER; - rail = (railPlugin*) context->handle; - return rail_send_client_get_appid_req_order(rail, getAppIdReq); + rail = (railPlugin*)context->handle; + return rail_send_client_compartment_info_order(rail, compartmentInfo); } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rail_server_get_appid_response(RailClientContext* context, - const RAIL_GET_APPID_RESP_ORDER* getAppIdResp) +static UINT rail_client_cloak(RailClientContext* context, const RAIL_CLOAK* cloak) +{ + railPlugin* rail; + + if (!context || !cloak || !context->handle) + return ERROR_INVALID_PARAMETER; + + rail = (railPlugin*)context->handle; + return rail_send_client_cloak_order(rail, cloak); +} + +static UINT rail_client_snap_arrange(RailClientContext* context, const RAIL_SNAP_ARRANGE* snap) { - if (!context || !getAppIdResp) + railPlugin* rail; + + if (!context || !snap || !context->handle) return ERROR_INVALID_PARAMETER; - return CHANNEL_RC_OK; /* stub - should be registered by client */ + rail = (railPlugin*)context->handle; + return rail_send_client_snap_arrange_order(rail, snap); } /** @@ -596,8 +518,9 @@ static UINT rail_server_get_appid_response(RailClientContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_virtual_channel_event_data_received(railPlugin* rail, - void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) +static UINT rail_virtual_channel_event_data_received(railPlugin* rail, void* pData, + UINT32 dataLength, UINT32 totalLength, + UINT32 dataFlags) { wStream* data_in; @@ -622,7 +545,7 @@ static UINT rail_virtual_channel_event_data_received(railPlugin* rail, data_in = rail->data_in; - if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength)) + if (!Stream_EnsureRemainingCapacity(data_in, dataLength)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); return CHANNEL_RC_NO_MEMORY; @@ -634,7 +557,7 @@ static UINT rail_virtual_channel_event_data_received(railPlugin* rail, { if (Stream_Capacity(data_in) != Stream_GetPosition(data_in)) { - WLog_ERR(TAG, "rail_plugin_process_received: read error"); + WLog_ERR(TAG, "rail_plugin_process_received: read error"); return ERROR_INTERNAL_ERROR; } @@ -642,7 +565,7 @@ static UINT rail_virtual_channel_event_data_received(railPlugin* rail, Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); - if (!MessageQueue_Post(rail->queue, NULL, 0, (void*) data_in, NULL)) + if (!MessageQueue_Post(rail->queue, NULL, 0, (void*)data_in, NULL)) { WLog_ERR(TAG, "MessageQueue_Post failed!"); return ERROR_INTERNAL_ERROR; @@ -653,36 +576,42 @@ static UINT rail_virtual_channel_event_data_received(railPlugin* rail, } static VOID VCAPITYPE rail_virtual_channel_open_event_ex(LPVOID lpUserParam, DWORD openHandle, - UINT event, - LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) + UINT event, LPVOID pData, + UINT32 dataLength, UINT32 totalLength, + UINT32 dataFlags) { UINT error = CHANNEL_RC_OK; - railPlugin* rail = (railPlugin*) lpUserParam; - - if (!rail || (rail->OpenHandle != openHandle)) - { - WLog_ERR(TAG, "error no match"); - return; - } + railPlugin* rail = (railPlugin*)lpUserParam; switch (event) { case CHANNEL_EVENT_DATA_RECEIVED: + if (!rail || (rail->OpenHandle != openHandle)) + { + WLog_ERR(TAG, "error no match"); + return; + } if ((error = rail_virtual_channel_event_data_received(rail, pData, dataLength, - totalLength, dataFlags))) - WLog_ERR(TAG, "rail_virtual_channel_event_data_received failed with error %"PRIu32"!", + totalLength, dataFlags))) + WLog_ERR(TAG, + "rail_virtual_channel_event_data_received failed with error %" PRIu32 "!", error); break; + case CHANNEL_EVENT_WRITE_CANCELLED: case CHANNEL_EVENT_WRITE_COMPLETE: - break; + { + wStream* s = (wStream*)pData; + Stream_Free(s, TRUE); + } + break; case CHANNEL_EVENT_USER: break; } - if (error && rail->rdpcontext) + if (error && rail && rail->rdpcontext) setChannelError(rail->rdpcontext, error, "rail_virtual_channel_open_event reported an error"); @@ -693,7 +622,7 @@ static DWORD WINAPI rail_virtual_channel_client_thread(LPVOID arg) { wStream* data; wMessage message; - railPlugin* rail = (railPlugin*) arg; + railPlugin* rail = (railPlugin*)arg; UINT error = CHANNEL_RC_OK; while (1) @@ -717,13 +646,13 @@ static DWORD WINAPI rail_virtual_channel_client_thread(LPVOID arg) if (message.id == 0) { - data = (wStream*) message.wParam; + data = (wStream*)message.wParam; error = rail_order_recv(rail, data); Stream_Free(data, TRUE); if (error) { - WLog_ERR(TAG, "rail_order_recv failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_order_recv failed with error %" PRIu32 "!", error); break; } } @@ -742,20 +671,30 @@ static DWORD WINAPI rail_virtual_channel_client_thread(LPVOID arg) * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_virtual_channel_event_connected(railPlugin* rail, LPVOID pData, - UINT32 dataLength) +static UINT rail_virtual_channel_event_connected(railPlugin* rail, LPVOID pData, UINT32 dataLength) { + RailClientContext* context = rail_get_client_interface(rail); UINT status; - status = rail->channelEntryPoints.pVirtualChannelOpenEx(rail->InitHandle, - &rail->OpenHandle, rail->channelDef.name, rail_virtual_channel_open_event_ex); + status = rail->channelEntryPoints.pVirtualChannelOpenEx(rail->InitHandle, &rail->OpenHandle, + rail->channelDef.name, + rail_virtual_channel_open_event_ex); if (status != CHANNEL_RC_OK) { - WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08"PRIX32"]", + WLog_ERR(TAG, "pVirtualChannelOpen failed with %s [%08" PRIX32 "]", WTSErrorToString(status), status); return status; } + if (context) + { + IFCALLRET(context->OnOpen, status, context, &rail->sendHandshake); + + if (status != CHANNEL_RC_OK) + WLog_ERR(TAG, "context->OnOpen failed with %s [%08" PRIX32 "]", + WTSErrorToString(status), status); + } + rail->queue = MessageQueue_New(NULL); if (!rail->queue) @@ -764,9 +703,8 @@ static UINT rail_virtual_channel_event_connected(railPlugin* rail, LPVOID pData, return CHANNEL_RC_NO_MEMORY; } - if (!(rail->thread = CreateThread(NULL, 0, - rail_virtual_channel_client_thread, (void*) rail, 0, - NULL))) + if (!(rail->thread = + CreateThread(NULL, 0, rail_virtual_channel_client_thread, (void*)rail, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); MessageQueue_Free(rail->queue); @@ -789,11 +727,11 @@ static UINT rail_virtual_channel_event_disconnected(railPlugin* rail) if (rail->OpenHandle == 0) return CHANNEL_RC_OK; - if (MessageQueue_PostQuit(rail->queue, 0) - && (WaitForSingleObject(rail->thread, INFINITE) == WAIT_FAILED)) + if (MessageQueue_PostQuit(rail->queue, 0) && + (WaitForSingleObject(rail->thread, INFINITE) == WAIT_FAILED)) { rc = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"", rc); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", rc); return rc; } @@ -805,8 +743,8 @@ static UINT rail_virtual_channel_event_disconnected(railPlugin* rail) if (CHANNEL_RC_OK != rc) { - WLog_ERR(TAG, "pVirtualChannelCloseEx failed with %s [%08"PRIX32"]", - WTSErrorToString(rc), rc); + WLog_ERR(TAG, "pVirtualChannelCloseEx failed with %s [%08" PRIX32 "]", WTSErrorToString(rc), + rc); return rc; } @@ -829,14 +767,14 @@ static void rail_virtual_channel_event_terminated(railPlugin* rail) } static VOID VCAPITYPE rail_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle, - UINT event, LPVOID pData, UINT dataLength) + UINT event, LPVOID pData, UINT dataLength) { UINT error = CHANNEL_RC_OK; - railPlugin* rail = (railPlugin*) lpUserParam; + railPlugin* rail = (railPlugin*)lpUserParam; if (!rail || (rail->InitHandle != pInitHandle)) { - WLog_ERR(TAG, "error no match"); + WLog_ERR(TAG, "error no match"); return; } @@ -844,14 +782,15 @@ static VOID VCAPITYPE rail_virtual_channel_init_event_ex(LPVOID lpUserParam, LPV { case CHANNEL_EVENT_CONNECTED: if ((error = rail_virtual_channel_event_connected(rail, pData, dataLength))) - WLog_ERR(TAG, "rail_virtual_channel_event_connected failed with error %"PRIu32"!", + WLog_ERR(TAG, "rail_virtual_channel_event_connected failed with error %" PRIu32 "!", error); break; case CHANNEL_EVENT_DISCONNECTED: if ((error = rail_virtual_channel_event_disconnected(rail))) - WLog_ERR(TAG, "rail_virtual_channel_event_disconnected failed with error %"PRIu32"!", + WLog_ERR(TAG, + "rail_virtual_channel_event_disconnected failed with error %" PRIu32 "!", error); break; @@ -867,11 +806,12 @@ static VOID VCAPITYPE rail_virtual_channel_init_event_ex(LPVOID lpUserParam, LPV } if (error && rail->rdpcontext) - setChannelError(rail->rdpcontext, error, "rail_virtual_channel_init_event_ex reported an error"); + setChannelError(rail->rdpcontext, error, + "rail_virtual_channel_init_event_ex reported an error"); } /* rail is always built-in */ -#define VirtualChannelEntryEx rail_VirtualChannelEntryEx +#define VirtualChannelEntryEx rail_VirtualChannelEntryEx BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID pInitHandle) { @@ -880,7 +820,7 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p RailClientContext* context = NULL; CHANNEL_ENTRY_POINTS_FREERDP_EX* pEntryPointsEx; BOOL isFreerdp = FALSE; - rail = (railPlugin*) calloc(1, sizeof(railPlugin)); + rail = (railPlugin*)calloc(1, sizeof(railPlugin)); if (!rail) { @@ -888,18 +828,17 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p return FALSE; } - rail->channelDef.options = - CHANNEL_OPTION_INITIALIZED | - CHANNEL_OPTION_ENCRYPT_RDP | - CHANNEL_OPTION_COMPRESS_RDP | - CHANNEL_OPTION_SHOW_PROTOCOL; - sprintf_s(rail->channelDef.name, ARRAYSIZE(rail->channelDef.name), "rail"); - pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*) pEntryPoints; + /* Default to automatically replying to server handshakes */ + rail->sendHandshake = TRUE; + rail->channelDef.options = CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | + CHANNEL_OPTION_COMPRESS_RDP | CHANNEL_OPTION_SHOW_PROTOCOL; + sprintf_s(rail->channelDef.name, ARRAYSIZE(rail->channelDef.name), RAIL_SVC_CHANNEL_NAME); + pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*)pEntryPoints; if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)) && (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) { - context = (RailClientContext*) calloc(1, sizeof(RailClientContext)); + context = (RailClientContext*)calloc(1, sizeof(RailClientContext)); if (!context) { @@ -908,28 +847,23 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p return FALSE; } - context->handle = (void*) rail; + context->handle = (void*)rail; context->custom = NULL; context->ClientExecute = rail_client_execute; context->ClientActivate = rail_client_activate; context->ClientSystemParam = rail_client_system_param; - context->ServerSystemParam = rail_server_system_param; context->ClientSystemCommand = rail_client_system_command; context->ClientHandshake = rail_client_handshake; - context->ServerHandshake = rail_server_handshake; - context->ClientHandshakeEx = rail_client_handshake_ex; - context->ServerHandshakeEx = rail_server_handshake_ex; context->ClientNotifyEvent = rail_client_notify_event; context->ClientWindowMove = rail_client_window_move; - context->ServerLocalMoveSize = rail_server_local_move_size; - context->ServerMinMaxInfo = rail_server_min_max_info; context->ClientInformation = rail_client_information; context->ClientSystemMenu = rail_client_system_menu; context->ClientLanguageBarInfo = rail_client_language_bar_info; - context->ServerLanguageBarInfo = rail_server_language_bar_info; - context->ServerExecuteResult = rail_server_execute_result; + context->ClientLanguageIMEInfo = rail_client_language_ime_info; context->ClientGetAppIdRequest = rail_client_get_appid_request; - context->ServerGetAppIdResponse = rail_server_get_appid_response; + context->ClientSnapArrange = rail_client_snap_arrange; + context->ClientCloak = rail_client_cloak; + context->ClientCompartmentInfo = rail_client_compartment_info; rail->rdpcontext = pEntryPointsEx->context; rail->context = context; isFreerdp = TRUE; @@ -937,17 +871,15 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p rail->log = WLog_Get("com.freerdp.channels.rail.client"); WLog_Print(rail->log, WLOG_DEBUG, "VirtualChannelEntryEx"); - CopyMemory(&(rail->channelEntryPoints), pEntryPoints, - sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)); + CopyMemory(&(rail->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)); rail->InitHandle = pInitHandle; - rc = rail->channelEntryPoints.pVirtualChannelInitEx(rail, context, pInitHandle, - &rail->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, - rail_virtual_channel_init_event_ex); + rc = rail->channelEntryPoints.pVirtualChannelInitEx( + rail, context, pInitHandle, &rail->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, + rail_virtual_channel_init_event_ex); if (CHANNEL_RC_OK != rc) { - WLog_ERR(TAG, "failed with %s [%08"PRIX32"]", - WTSErrorToString(rc), rc); + WLog_ERR(TAG, "failed with %s [%08" PRIX32 "]", WTSErrorToString(rc), rc); goto error_out; } diff --git a/channels/rail/client/rail_main.h b/channels/rail/client/rail_main.h index 86e752f..63e522e 100644 --- a/channels/rail/client/rail_main.h +++ b/channels/rail/client/rail_main.h @@ -50,10 +50,14 @@ struct rail_plugin DWORD OpenHandle; wMessageQueue* queue; rdpContext* rdpcontext; + DWORD channelBuildNumber; + DWORD channelFlags; + RAIL_CLIENT_STATUS_ORDER clientStatus; + BOOL sendHandshake; }; typedef struct rail_plugin railPlugin; RailClientContext* rail_get_client_interface(railPlugin* rail); -UINT rail_send_channel_data(railPlugin* rail, void* data, size_t length); +UINT rail_send_channel_data(railPlugin* rail, wStream* s); #endif /* FREERDP_CHANNEL_RAIL_CLIENT_MAIN_H */ diff --git a/channels/rail/client/rail_orders.c b/channels/rail/client/rail_orders.c index 7e6cf42..c394a59 100644 --- a/channels/rail/client/rail_orders.c +++ b/channels/rail/client/rail_orders.c @@ -37,55 +37,6 @@ * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_write_unicode_string(wStream* s, const RAIL_UNICODE_STRING* unicode_string) -{ - if (!s || !unicode_string) - return ERROR_INVALID_PARAMETER; - - if (!Stream_EnsureRemainingCapacity(s, 2 + unicode_string->length)) - { - WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - Stream_Write_UINT16(s, unicode_string->length); /* cbString (2 bytes) */ - Stream_Write(s, unicode_string->string, unicode_string->length); /* string */ - return CHANNEL_RC_OK; -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rail_write_unicode_string_value(wStream* s, const RAIL_UNICODE_STRING* unicode_string) -{ - size_t length; - - if (!s || !unicode_string) - return ERROR_INVALID_PARAMETER; - - length = unicode_string->length; - - if (length > 0) - { - if (!Stream_EnsureRemainingCapacity(s, length)) - { - WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); - return CHANNEL_RC_NO_MEMORY; - } - - Stream_Write(s, unicode_string->string, length); /* string */ - } - - return CHANNEL_RC_OK; -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ UINT rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType) { UINT16 orderLength; @@ -93,31 +44,13 @@ UINT rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType) if (!rail || !s) return ERROR_INVALID_PARAMETER; - orderLength = (UINT16) Stream_GetPosition(s); + orderLength = (UINT16)Stream_GetPosition(s); Stream_SetPosition(s, 0); rail_write_pdu_header(s, orderType, orderLength); Stream_SetPosition(s, orderLength); - WLog_Print(rail->log, WLOG_DEBUG, "Sending %s PDU, length: %"PRIu16"", - RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength); - return rail_send_channel_data(rail, Stream_Buffer(s), orderLength); -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rail_write_high_contrast(wStream* s, const RAIL_HIGH_CONTRAST* highContrast) -{ - UINT32 colorSchemeLength; - - if (!s || !highContrast) - return ERROR_INVALID_PARAMETER; - - colorSchemeLength = highContrast->colorScheme.length + 2; - Stream_Write_UINT32(s, highContrast->flags); /* flags (4 bytes) */ - Stream_Write_UINT32(s, colorSchemeLength); /* colorSchemeLength (4 bytes) */ - return rail_write_unicode_string(s, &highContrast->colorScheme); /* colorScheme */ + WLog_Print(rail->log, WLOG_DEBUG, "Sending %s PDU, length: %" PRIu16 "", + rail_get_order_type_string(orderType), orderLength); + return rail_send_channel_data(rail, s); } /** @@ -130,56 +63,19 @@ static UINT rail_read_server_exec_result_order(wStream* s, RAIL_EXEC_RESULT_ORDE if (!s || !execResult) return ERROR_INVALID_PARAMETER; - if (Stream_GetRemainingLength(s) < 8) + if (Stream_GetRemainingLength(s) < RAIL_EXEC_RESULT_ORDER_LENGTH) { WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); return ERROR_INVALID_DATA; } - Stream_Read_UINT16(s, execResult->flags); /* flags (2 bytes) */ + Stream_Read_UINT16(s, execResult->flags); /* flags (2 bytes) */ Stream_Read_UINT16(s, execResult->execResult); /* execResult (2 bytes) */ - Stream_Read_UINT32(s, execResult->rawResult); /* rawResult (4 bytes) */ - Stream_Seek_UINT16(s); /* padding (2 bytes) */ - return rail_read_unicode_string(s, - &execResult->exeOrFile) ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; /* exeOrFile */ -} - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT rail_read_server_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam) -{ - BYTE body; - - if (!s || !sysparam) - return ERROR_INVALID_PARAMETER; - - if (Stream_GetRemainingLength(s) < 5) - { - WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); - return ERROR_INVALID_DATA; - } - - Stream_Read_UINT32(s, sysparam->param); /* systemParam (4 bytes) */ - Stream_Read_UINT8(s, body); /* body (1 byte) */ - - switch (sysparam->param) - { - case SPI_SET_SCREEN_SAVE_ACTIVE: - sysparam->setScreenSaveActive = (body != 0) ? TRUE : FALSE; - break; - - case SPI_SET_SCREEN_SAVE_SECURE: - sysparam->setScreenSaveSecure = (body != 0) ? TRUE : FALSE; - break; - - default: - break; - } - - return CHANNEL_RC_OK; + Stream_Read_UINT32(s, execResult->rawResult); /* rawResult (4 bytes) */ + Stream_Seek_UINT16(s); /* padding (2 bytes) */ + return rail_read_unicode_string(s, &execResult->exeOrFile) + ? CHANNEL_RC_OK + : ERROR_INTERNAL_ERROR; /* exeOrFile */ } /** @@ -192,21 +88,21 @@ static UINT rail_read_server_minmaxinfo_order(wStream* s, RAIL_MINMAXINFO_ORDER* if (!s || !minmaxinfo) return ERROR_INVALID_PARAMETER; - if (Stream_GetRemainingLength(s) < 20) + if (Stream_GetRemainingLength(s) < RAIL_MINMAXINFO_ORDER_LENGTH) { WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); return ERROR_INVALID_DATA; } - Stream_Read_UINT32(s, minmaxinfo->windowId); /* windowId (4 bytes) */ - Stream_Read_UINT16(s, minmaxinfo->maxWidth); /* maxWidth (2 bytes) */ - Stream_Read_UINT16(s, minmaxinfo->maxHeight); /* maxHeight (2 bytes) */ - Stream_Read_UINT16(s, minmaxinfo->maxPosX); /* maxPosX (2 bytes) */ - Stream_Read_UINT16(s, minmaxinfo->maxPosY); /* maxPosY (2 bytes) */ - Stream_Read_UINT16(s, minmaxinfo->minTrackWidth); /* minTrackWidth (2 bytes) */ - Stream_Read_UINT16(s, minmaxinfo->minTrackHeight); /* minTrackHeight (2 bytes) */ - Stream_Read_UINT16(s, minmaxinfo->maxTrackWidth); /* maxTrackWidth (2 bytes) */ - Stream_Read_UINT16(s, minmaxinfo->maxTrackHeight); /* maxTrackHeight (2 bytes) */ + Stream_Read_UINT32(s, minmaxinfo->windowId); /* windowId (4 bytes) */ + Stream_Read_INT16(s, minmaxinfo->maxWidth); /* maxWidth (2 bytes) */ + Stream_Read_INT16(s, minmaxinfo->maxHeight); /* maxHeight (2 bytes) */ + Stream_Read_INT16(s, minmaxinfo->maxPosX); /* maxPosX (2 bytes) */ + Stream_Read_INT16(s, minmaxinfo->maxPosY); /* maxPosY (2 bytes) */ + Stream_Read_INT16(s, minmaxinfo->minTrackWidth); /* minTrackWidth (2 bytes) */ + Stream_Read_INT16(s, minmaxinfo->minTrackHeight); /* minTrackHeight (2 bytes) */ + Stream_Read_INT16(s, minmaxinfo->maxTrackWidth); /* maxTrackWidth (2 bytes) */ + Stream_Read_INT16(s, minmaxinfo->maxTrackHeight); /* maxTrackHeight (2 bytes) */ return CHANNEL_RC_OK; } @@ -216,25 +112,25 @@ static UINT rail_read_server_minmaxinfo_order(wStream* s, RAIL_MINMAXINFO_ORDER* * @return 0 on success, otherwise a Win32 error code */ static UINT rail_read_server_localmovesize_order(wStream* s, - RAIL_LOCALMOVESIZE_ORDER* localMoveSize) + RAIL_LOCALMOVESIZE_ORDER* localMoveSize) { UINT16 isMoveSizeStart; if (!s || !localMoveSize) return ERROR_INVALID_PARAMETER; - if (Stream_GetRemainingLength(s) < 12) + if (Stream_GetRemainingLength(s) < RAIL_LOCALMOVESIZE_ORDER_LENGTH) { WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, localMoveSize->windowId); /* windowId (4 bytes) */ - Stream_Read_UINT16(s, isMoveSizeStart); /* isMoveSizeStart (2 bytes) */ + Stream_Read_UINT16(s, isMoveSizeStart); /* isMoveSizeStart (2 bytes) */ localMoveSize->isMoveSizeStart = (isMoveSizeStart != 0) ? TRUE : FALSE; Stream_Read_UINT16(s, localMoveSize->moveSizeType); /* moveSizeType (2 bytes) */ - Stream_Read_UINT16(s, localMoveSize->posX); /* posX (2 bytes) */ - Stream_Read_UINT16(s, localMoveSize->posY); /* posY (2 bytes) */ + Stream_Read_INT16(s, localMoveSize->posX); /* posX (2 bytes) */ + Stream_Read_INT16(s, localMoveSize->posY); /* posY (2 bytes) */ return CHANNEL_RC_OK; } @@ -244,20 +140,21 @@ static UINT rail_read_server_localmovesize_order(wStream* s, * @return 0 on success, otherwise a Win32 error code */ static UINT rail_read_server_get_appid_resp_order(wStream* s, - RAIL_GET_APPID_RESP_ORDER* getAppidResp) + RAIL_GET_APPID_RESP_ORDER* getAppidResp) { if (!s || !getAppidResp) return ERROR_INVALID_PARAMETER; - if (Stream_GetRemainingLength(s) < 516) + if (Stream_GetRemainingLength(s) < RAIL_GET_APPID_RESP_ORDER_LENGTH) { WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); return ERROR_INVALID_DATA; } Stream_Read_UINT32(s, getAppidResp->windowId); /* windowId (4 bytes) */ - Stream_Read(s, (BYTE*) & (getAppidResp->applicationId), - 512); /* applicationId (256 UNICODE chars) */ + Stream_Read_UTF16_String( + s, getAppidResp->applicationId, + ARRAYSIZE(getAppidResp->applicationId)); /* applicationId (260 UNICODE chars) */ return CHANNEL_RC_OK; } @@ -271,7 +168,7 @@ static UINT rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* la if (!s || !langbarInfo) return ERROR_INVALID_PARAMETER; - if (Stream_GetRemainingLength(s) < 4) + if (Stream_GetRemainingLength(s) < RAIL_LANGBAR_INFO_ORDER_LENGTH) { WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); return ERROR_INVALID_DATA; @@ -296,8 +193,9 @@ static UINT rail_write_client_status_order(wStream* s, const RAIL_CLIENT_STATUS_ * @return 0 on success, otherwise a Win32 error code */ static UINT rail_write_client_exec_order(wStream* s, UINT16 flags, - const RAIL_UNICODE_STRING* exeOrFile, const RAIL_UNICODE_STRING* workingDir, - const RAIL_UNICODE_STRING* arguments) + const RAIL_UNICODE_STRING* exeOrFile, + const RAIL_UNICODE_STRING* workingDir, + const RAIL_UNICODE_STRING* arguments) { UINT error; @@ -306,107 +204,41 @@ static UINT rail_write_client_exec_order(wStream* s, UINT16 flags, /* [MS-RDPERP] 2.2.2.3.1 Client Execute PDU (TS_RAIL_ORDER_EXEC) * Check argument limits */ - if ((exeOrFile->length > 520) || (workingDir->length > 520) || - (arguments->length > 16000)) + if ((exeOrFile->length > 520) || (workingDir->length > 520) || (arguments->length > 16000)) { WLog_ERR(TAG, - "TS_RAIL_ORDER_EXEC argument limits exceeded: ExeOrFile=%"PRIu16" [max=520], WorkingDir=%"PRIu16" [max=520], Arguments=%"PRIu16" [max=16000]", + "TS_RAIL_ORDER_EXEC argument limits exceeded: ExeOrFile=%" PRIu16 + " [max=520], WorkingDir=%" PRIu16 " [max=520], Arguments=%" PRIu16 " [max=16000]", exeOrFile->length, workingDir->length, arguments->length); return ERROR_BAD_ARGUMENTS; } - Stream_Write_UINT16(s, flags); /* flags (2 bytes) */ - Stream_Write_UINT16(s, exeOrFile->length); /* exeOrFileLength (2 bytes) */ + Stream_Write_UINT16(s, flags); /* flags (2 bytes) */ + Stream_Write_UINT16(s, exeOrFile->length); /* exeOrFileLength (2 bytes) */ Stream_Write_UINT16(s, workingDir->length); /* workingDirLength (2 bytes) */ - Stream_Write_UINT16(s, arguments->length); /* argumentsLength (2 bytes) */ + Stream_Write_UINT16(s, arguments->length); /* argumentsLength (2 bytes) */ if ((error = rail_write_unicode_string_value(s, exeOrFile))) { - WLog_ERR(TAG, "rail_write_unicode_string_value failed with error %"PRIu32"", error); + WLog_ERR(TAG, "rail_write_unicode_string_value failed with error %" PRIu32 "", error); return error; } if ((error = rail_write_unicode_string_value(s, workingDir))) { - WLog_ERR(TAG, "rail_write_unicode_string_value failed with error %"PRIu32"", error); + WLog_ERR(TAG, "rail_write_unicode_string_value failed with error %" PRIu32 "", error); return error; } if ((error = rail_write_unicode_string_value(s, arguments))) { - WLog_ERR(TAG, "rail_write_unicode_string_value failed with error %"PRIu32"", error); + WLog_ERR(TAG, "rail_write_unicode_string_value failed with error %" PRIu32 "", error); return error; } return error; } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -UINT rail_write_client_sysparam_order(wStream* s, const RAIL_SYSPARAM_ORDER* sysparam) -{ - BYTE body; - UINT error = CHANNEL_RC_OK; - - if (!s || !sysparam) - return ERROR_INVALID_PARAMETER; - - Stream_Write_UINT32(s, sysparam->param); /* systemParam (4 bytes) */ - - switch (sysparam->param) - { - case SPI_SET_DRAG_FULL_WINDOWS: - body = sysparam->dragFullWindows ? 1 : 0; - Stream_Write_UINT8(s, body); - break; - - case SPI_SET_KEYBOARD_CUES: - body = sysparam->keyboardCues ? 1 : 0; - Stream_Write_UINT8(s, body); - break; - - case SPI_SET_KEYBOARD_PREF: - body = sysparam->keyboardPref ? 1 : 0; - Stream_Write_UINT8(s, body); - break; - - case SPI_SET_MOUSE_BUTTON_SWAP: - body = sysparam->mouseButtonSwap ? 1 : 0; - Stream_Write_UINT8(s, body); - break; - - case SPI_SET_WORK_AREA: - Stream_Write_UINT16(s, sysparam->workArea.left); /* left (2 bytes) */ - Stream_Write_UINT16(s, sysparam->workArea.top); /* top (2 bytes) */ - Stream_Write_UINT16(s, sysparam->workArea.right); /* right (2 bytes) */ - Stream_Write_UINT16(s, sysparam->workArea.bottom); /* bottom (2 bytes) */ - break; - - case SPI_DISPLAY_CHANGE: - Stream_Write_UINT16(s, sysparam->displayChange.left); /* left (2 bytes) */ - Stream_Write_UINT16(s, sysparam->displayChange.top); /* top (2 bytes) */ - Stream_Write_UINT16(s, sysparam->displayChange.right); /* right (2 bytes) */ - Stream_Write_UINT16(s, sysparam->displayChange.bottom); /* bottom (2 bytes) */ - break; - - case SPI_TASKBAR_POS: - Stream_Write_UINT16(s, sysparam->taskbarPos.left); /* left (2 bytes) */ - Stream_Write_UINT16(s, sysparam->taskbarPos.top); /* top (2 bytes) */ - Stream_Write_UINT16(s, sysparam->taskbarPos.right); /* right (2 bytes) */ - Stream_Write_UINT16(s, sysparam->taskbarPos.bottom); /* bottom (2 bytes) */ - break; - - case SPI_SET_HIGH_CONTRAST: - error = rail_write_high_contrast(s, &sysparam->highContrast); - break; - } - - return error; -} - static UINT rail_write_client_activate_order(wStream* s, const RAIL_ACTIVATE_ORDER* activate) { BYTE enabled; @@ -426,8 +258,8 @@ static UINT rail_write_client_sysmenu_order(wStream* s, const RAIL_SYSMENU_ORDER return ERROR_INVALID_PARAMETER; Stream_Write_UINT32(s, sysmenu->windowId); /* windowId (4 bytes) */ - Stream_Write_UINT16(s, sysmenu->left); /* left (2 bytes) */ - Stream_Write_UINT16(s, sysmenu->top); /* top (2 bytes) */ + Stream_Write_INT16(s, sysmenu->left); /* left (2 bytes) */ + Stream_Write_INT16(s, sysmenu->top); /* top (2 bytes) */ return ERROR_SUCCESS; } @@ -437,38 +269,38 @@ static UINT rail_write_client_syscommand_order(wStream* s, const RAIL_SYSCOMMAND return ERROR_INVALID_PARAMETER; Stream_Write_UINT32(s, syscommand->windowId); /* windowId (4 bytes) */ - Stream_Write_UINT16(s, syscommand->command); /* command (2 bytes) */ + Stream_Write_UINT16(s, syscommand->command); /* command (2 bytes) */ return ERROR_SUCCESS; } static UINT rail_write_client_notify_event_order(wStream* s, - const RAIL_NOTIFY_EVENT_ORDER* notifyEvent) + const RAIL_NOTIFY_EVENT_ORDER* notifyEvent) { if (!s || !notifyEvent) return ERROR_INVALID_PARAMETER; - Stream_Write_UINT32(s, notifyEvent->windowId); /* windowId (4 bytes) */ + Stream_Write_UINT32(s, notifyEvent->windowId); /* windowId (4 bytes) */ Stream_Write_UINT32(s, notifyEvent->notifyIconId); /* notifyIconId (4 bytes) */ - Stream_Write_UINT32(s, notifyEvent->message); /* notifyIconId (4 bytes) */ + Stream_Write_UINT32(s, notifyEvent->message); /* notifyIconId (4 bytes) */ return ERROR_SUCCESS; } static UINT rail_write_client_window_move_order(wStream* s, - const RAIL_WINDOW_MOVE_ORDER* windowMove) + const RAIL_WINDOW_MOVE_ORDER* windowMove) { if (!s || !windowMove) return ERROR_INVALID_PARAMETER; Stream_Write_UINT32(s, windowMove->windowId); /* windowId (4 bytes) */ - Stream_Write_UINT16(s, windowMove->left); /* left (2 bytes) */ - Stream_Write_UINT16(s, windowMove->top); /* top (2 bytes) */ - Stream_Write_UINT16(s, windowMove->right); /* right (2 bytes) */ - Stream_Write_UINT16(s, windowMove->bottom); /* bottom (2 bytes) */ + Stream_Write_INT16(s, windowMove->left); /* left (2 bytes) */ + Stream_Write_INT16(s, windowMove->top); /* top (2 bytes) */ + Stream_Write_INT16(s, windowMove->right); /* right (2 bytes) */ + Stream_Write_INT16(s, windowMove->bottom); /* bottom (2 bytes) */ return ERROR_SUCCESS; } static UINT rail_write_client_get_appid_req_order(wStream* s, - const RAIL_GET_APPID_REQ_ORDER* getAppidReq) + const RAIL_GET_APPID_REQ_ORDER* getAppidReq) { if (!s || !getAppidReq) return ERROR_INVALID_PARAMETER; @@ -486,62 +318,137 @@ static UINT rail_write_langbar_info_order(wStream* s, const RAIL_LANGBAR_INFO_OR return ERROR_SUCCESS; } +static UINT rail_write_languageime_info_order(wStream* s, + const RAIL_LANGUAGEIME_INFO_ORDER* langImeInfo) +{ + if (!s || !langImeInfo) + return ERROR_INVALID_PARAMETER; + + Stream_Write_UINT32(s, langImeInfo->ProfileType); + Stream_Write_UINT16(s, langImeInfo->LanguageID); + Stream_Write(s, &langImeInfo->LanguageProfileCLSID, sizeof(langImeInfo->LanguageProfileCLSID)); + Stream_Write(s, &langImeInfo->ProfileGUID, sizeof(langImeInfo->ProfileGUID)); + Stream_Write_UINT32(s, langImeInfo->KeyboardLayout); + return ERROR_SUCCESS; +} + +static UINT rail_write_compartment_info_order(wStream* s, + const RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo) +{ + if (!s || !compartmentInfo) + return ERROR_INVALID_PARAMETER; + + Stream_Write_UINT32(s, compartmentInfo->ImeState); + Stream_Write_UINT32(s, compartmentInfo->ImeConvMode); + Stream_Write_UINT32(s, compartmentInfo->ImeSentenceMode); + Stream_Write_UINT32(s, compartmentInfo->KanaMode); + return ERROR_SUCCESS; +} + /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_recv_handshake_order(railPlugin* rail, RAIL_HANDSHAKE_ORDER* handshake, wStream* s) +static UINT rail_recv_handshake_order(railPlugin* rail, wStream* s) { RailClientContext* context = rail_get_client_interface(rail); + RAIL_HANDSHAKE_ORDER serverHandshake = { 0 }; UINT error; - if (!context || !handshake || !s) + if (!context || !s) return ERROR_INVALID_PARAMETER; - if ((error = rail_read_handshake_order(s, handshake))) + if ((error = rail_read_handshake_order(s, &serverHandshake))) { - WLog_ERR(TAG, "rail_read_handshake_order failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_read_handshake_order failed with error %" PRIu32 "!", error); return error; } + rail->channelBuildNumber = serverHandshake.buildNumber; + + if (rail->sendHandshake) + { + RAIL_HANDSHAKE_ORDER clientHandshake = { 0 }; + clientHandshake.buildNumber = 0x00001DB0; + error = context->ClientHandshake(context, &clientHandshake); + } + + if (error != CHANNEL_RC_OK) + return error; + if (context->custom) { - IFCALLRET(context->ServerHandshake, error, context, handshake); + IFCALLRET(context->ServerHandshake, error, context, &serverHandshake); if (error) - WLog_ERR(TAG, "context.ServerHandshake failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context.ServerHandshake failed with error %" PRIu32 "", error); } return error; } +static BOOL rail_is_feature_supported(const rdpContext* context, UINT32 featureMask) +{ + UINT32 supported, masked; + + if (!context || !context->settings) + return FALSE; + + supported = context->settings->RemoteApplicationSupportLevel & + context->settings->RemoteApplicationSupportMask; + masked = (supported & featureMask); + + if (masked != featureMask) + return FALSE; + + return TRUE; +} + /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_recv_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORDER* handshakeEx, - wStream* s) +static UINT rail_recv_handshake_ex_order(railPlugin* rail, wStream* s) { RailClientContext* context = rail_get_client_interface(rail); + RAIL_HANDSHAKE_EX_ORDER serverHandshake = { 0 }; UINT error; - if (!context || !handshakeEx || !s) + if (!rail || !context || !s) return ERROR_INVALID_PARAMETER; - if ((error = rail_read_handshake_ex_order(s, handshakeEx))) + if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_HANDSHAKE_EX_SUPPORTED)) + return ERROR_BAD_CONFIGURATION; + + if ((error = rail_read_handshake_ex_order(s, &serverHandshake))) { - WLog_ERR(TAG, "rail_read_handshake_ex_order failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_read_handshake_ex_order failed with error %" PRIu32 "!", error); return error; } + rail->channelBuildNumber = serverHandshake.buildNumber; + rail->channelFlags = serverHandshake.railHandshakeFlags; + + if (rail->sendHandshake) + { + RAIL_HANDSHAKE_ORDER clientHandshake = { 0 }; + clientHandshake.buildNumber = 0x00001DB0; + /* 2.2.2.2.3 HandshakeEx PDU (TS_RAIL_ORDER_HANDSHAKE_EX) + * Client response is really a Handshake PDU */ + error = context->ClientHandshake(context, &clientHandshake); + } + + if (error != CHANNEL_RC_OK) + return error; + if (context->custom) { - IFCALLRET(context->ClientHandshakeEx, error, context, handshakeEx); + IFCALLRET(context->ServerHandshakeEx, error, context, &serverHandshake); if (error) - WLog_ERR(TAG, "context.ClientHandshakeEx failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context.ServerHandshakeEx failed with error %" PRIu32 "", error); } return error; @@ -552,31 +459,31 @@ static UINT rail_recv_handshake_ex_order(railPlugin* rail, RAIL_HANDSHAKE_EX_ORD * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_recv_exec_result_order(railPlugin* rail, RAIL_EXEC_RESULT_ORDER* execResult, - wStream* s) +static UINT rail_recv_exec_result_order(railPlugin* rail, wStream* s) { RailClientContext* context = rail_get_client_interface(rail); + RAIL_EXEC_RESULT_ORDER execResult = { 0 }; UINT error; - if (!context || !execResult || !s) + if (!context || !s) return ERROR_INVALID_PARAMETER; - ZeroMemory(execResult, sizeof(RAIL_EXEC_RESULT_ORDER)); - - if ((error = rail_read_server_exec_result_order(s, execResult))) + if ((error = rail_read_server_exec_result_order(s, &execResult))) { - WLog_ERR(TAG, "rail_read_server_exec_result_order failed with error %"PRIu32"!", error); - return error; + WLog_ERR(TAG, "rail_read_server_exec_result_order failed with error %" PRIu32 "!", error); + goto fail; } if (context->custom) { - IFCALLRET(context->ServerExecuteResult, error, context, execResult); + IFCALLRET(context->ServerExecuteResult, error, context, &execResult); if (error) - WLog_ERR(TAG, "context.ServerExecuteResult failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context.ServerExecuteResult failed with error %" PRIu32 "", error); } +fail: + free(execResult.exeOrFile.string); return error; } @@ -585,27 +492,29 @@ static UINT rail_recv_exec_result_order(railPlugin* rail, RAIL_EXEC_RESULT_ORDER * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_recv_server_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam, - wStream* s) +static UINT rail_recv_server_sysparam_order(railPlugin* rail, wStream* s) { RailClientContext* context = rail_get_client_interface(rail); + RAIL_SYSPARAM_ORDER sysparam; UINT error; + BOOL extendedSpiSupported; - if (!context || !sysparam || !s) + if (!context || !s) return ERROR_INVALID_PARAMETER; - if ((error = rail_read_server_sysparam_order(s, sysparam))) + extendedSpiSupported = rail_is_extended_spi_supported(rail->channelFlags); + if ((error = rail_read_sysparam_order(s, &sysparam, extendedSpiSupported))) { - WLog_ERR(TAG, "rail_read_server_sysparam_order failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_read_sysparam_order failed with error %" PRIu32 "!", error); return error; } if (context->custom) { - IFCALLRET(context->ServerSystemParam, error, context, sysparam); + IFCALLRET(context->ServerSystemParam, error, context, &sysparam); if (error) - WLog_ERR(TAG, "context.ServerSystemParam failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context.ServerSystemParam failed with error %" PRIu32 "", error); } return error; @@ -616,27 +525,27 @@ static UINT rail_recv_server_sysparam_order(railPlugin* rail, RAIL_SYSPARAM_ORDE * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_recv_server_minmaxinfo_order(railPlugin* rail, RAIL_MINMAXINFO_ORDER* minMaxInfo, - wStream* s) +static UINT rail_recv_server_minmaxinfo_order(railPlugin* rail, wStream* s) { RailClientContext* context = rail_get_client_interface(rail); + RAIL_MINMAXINFO_ORDER minMaxInfo = { 0 }; UINT error; - if (!context || !minMaxInfo || !s) + if (!context || !s) return ERROR_INVALID_PARAMETER; - if ((error = rail_read_server_minmaxinfo_order(s, minMaxInfo))) + if ((error = rail_read_server_minmaxinfo_order(s, &minMaxInfo))) { - WLog_ERR(TAG, "rail_read_server_minmaxinfo_order failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_read_server_minmaxinfo_order failed with error %" PRIu32 "!", error); return error; } if (context->custom) { - IFCALLRET(context->ServerMinMaxInfo, error, context, minMaxInfo); + IFCALLRET(context->ServerMinMaxInfo, error, context, &minMaxInfo); if (error) - WLog_ERR(TAG, "context.ServerMinMaxInfo failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context.ServerMinMaxInfo failed with error %" PRIu32 "", error); } return error; @@ -647,28 +556,27 @@ static UINT rail_recv_server_minmaxinfo_order(railPlugin* rail, RAIL_MINMAXINFO_ * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_recv_server_localmovesize_order(railPlugin* rail, - RAIL_LOCALMOVESIZE_ORDER* localMoveSize, - wStream* s) +static UINT rail_recv_server_localmovesize_order(railPlugin* rail, wStream* s) { RailClientContext* context = rail_get_client_interface(rail); + RAIL_LOCALMOVESIZE_ORDER localMoveSize = { 0 }; UINT error; - if (!context || !localMoveSize || !s) + if (!context || !s) return ERROR_INVALID_PARAMETER; - if ((error = rail_read_server_localmovesize_order(s, localMoveSize))) + if ((error = rail_read_server_localmovesize_order(s, &localMoveSize))) { - WLog_ERR(TAG, "rail_read_server_localmovesize_order failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_read_server_localmovesize_order failed with error %" PRIu32 "!", error); return error; } if (context->custom) { - IFCALLRET(context->ServerLocalMoveSize, error, context, localMoveSize); + IFCALLRET(context->ServerLocalMoveSize, error, context, &localMoveSize); if (error) - WLog_ERR(TAG, "context.ServerLocalMoveSize failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context.ServerLocalMoveSize failed with error %" PRIu32 "", error); } return error; @@ -679,27 +587,28 @@ static UINT rail_recv_server_localmovesize_order(railPlugin* rail, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_recv_server_get_appid_resp_order(railPlugin* rail, - RAIL_GET_APPID_RESP_ORDER* getAppIdResp, wStream* s) +static UINT rail_recv_server_get_appid_resp_order(railPlugin* rail, wStream* s) { RailClientContext* context = rail_get_client_interface(rail); + RAIL_GET_APPID_RESP_ORDER getAppIdResp = { 0 }; UINT error; - if (!context || !getAppIdResp || !s) + if (!context || !s) return ERROR_INVALID_PARAMETER; - if ((error = rail_read_server_get_appid_resp_order(s, getAppIdResp))) + if ((error = rail_read_server_get_appid_resp_order(s, &getAppIdResp))) { - WLog_ERR(TAG, "rail_read_server_get_appid_resp_order failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_read_server_get_appid_resp_order failed with error %" PRIu32 "!", + error); return error; } if (context->custom) { - IFCALLRET(context->ServerGetAppIdResponse, error, context, getAppIdResp); + IFCALLRET(context->ServerGetAppIdResponse, error, context, &getAppIdResp); if (error) - WLog_ERR(TAG, "context.ServerGetAppIdResponse failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context.ServerGetAppIdResponse failed with error %" PRIu32 "", error); } return error; @@ -710,27 +619,286 @@ static UINT rail_recv_server_get_appid_resp_order(railPlugin* rail, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_recv_langbar_info_order(railPlugin* rail, RAIL_LANGBAR_INFO_ORDER* langBarInfo, - wStream* s) +static UINT rail_recv_langbar_info_order(railPlugin* rail, wStream* s) +{ + RailClientContext* context = rail_get_client_interface(rail); + RAIL_LANGBAR_INFO_ORDER langBarInfo = { 0 }; + UINT error; + + if (!context) + return ERROR_INVALID_PARAMETER; + + if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED)) + return ERROR_BAD_CONFIGURATION; + + if ((error = rail_read_langbar_info_order(s, &langBarInfo))) + { + WLog_ERR(TAG, "rail_read_langbar_info_order failed with error %" PRIu32 "!", error); + return error; + } + + if (context->custom) + { + IFCALLRET(context->ServerLanguageBarInfo, error, context, &langBarInfo); + + if (error) + WLog_ERR(TAG, "context.ServerLanguageBarInfo failed with error %" PRIu32 "", error); + } + + return error; +} + +static UINT rail_read_taskbar_info_order(wStream* s, RAIL_TASKBAR_INFO_ORDER* taskbarInfo) +{ + if (!s || !taskbarInfo) + return ERROR_INVALID_PARAMETER; + + if (Stream_GetRemainingLength(s) < RAIL_TASKBAR_INFO_ORDER_LENGTH) + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, taskbarInfo->TaskbarMessage); + Stream_Read_UINT32(s, taskbarInfo->WindowIdTab); + Stream_Read_UINT32(s, taskbarInfo->Body); + return CHANNEL_RC_OK; +} + +static UINT rail_recv_taskbar_info_order(railPlugin* rail, wStream* s) +{ + RailClientContext* context = rail_get_client_interface(rail); + RAIL_TASKBAR_INFO_ORDER taskBarInfo = { 0 }; + UINT error; + + if (!context) + return ERROR_INVALID_PARAMETER; + + /* 2.2.2.14.1 Taskbar Tab Info PDU (TS_RAIL_ORDER_TASKBARINFO) + * server -> client message only supported if announced. */ + if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_SHELL_INTEGRATION_SUPPORTED)) + return ERROR_BAD_CONFIGURATION; + + if ((error = rail_read_taskbar_info_order(s, &taskBarInfo))) + { + WLog_ERR(TAG, "rail_read_langbar_info_order failed with error %" PRIu32 "!", error); + return error; + } + + if (context->custom) + { + IFCALLRET(context->ServerTaskBarInfo, error, context, &taskBarInfo); + + if (error) + WLog_ERR(TAG, "context.ServerTaskBarInfo failed with error %" PRIu32 "", error); + } + + return error; +} + +static UINT rail_read_zorder_sync_order(wStream* s, RAIL_ZORDER_SYNC* zorder) +{ + if (!s || !zorder) + return ERROR_INVALID_PARAMETER; + + if (Stream_GetRemainingLength(s) < RAIL_Z_ORDER_SYNC_ORDER_LENGTH) + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, zorder->windowIdMarker); + return CHANNEL_RC_OK; +} + +static UINT rail_recv_zorder_sync_order(railPlugin* rail, wStream* s) { RailClientContext* context = rail_get_client_interface(rail); + RAIL_ZORDER_SYNC zorder = { 0 }; UINT error; - if (!context || !langBarInfo) + if (!context) return ERROR_INVALID_PARAMETER; - if ((error = rail_read_langbar_info_order(s, langBarInfo))) + if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_ZORDER_SYNC) == 0) + return ERROR_INVALID_DATA; + + if ((error = rail_read_zorder_sync_order(s, &zorder))) { - WLog_ERR(TAG, "rail_read_langbar_info_order failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_read_zorder_sync_order failed with error %" PRIu32 "!", error); return error; } if (context->custom) { - IFCALLRET(context->ServerLanguageBarInfo, error, context, langBarInfo); + IFCALLRET(context->ServerZOrderSync, error, context, &zorder); if (error) - WLog_ERR(TAG, "context.ServerLanguageBarInfo failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context.ServerZOrderSync failed with error %" PRIu32 "", error); + } + + return error; +} + +static UINT rail_read_cloak_order(wStream* s, RAIL_CLOAK* cloak) +{ + BYTE cloaked; + + if (Stream_GetRemainingLength(s) < RAIL_CLOAK_ORDER_LENGTH) + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, cloak->windowId); /* WindowId (4 bytes) */ + Stream_Read_UINT8(s, cloaked); /* Cloaked (1 byte) */ + cloak->cloak = (cloaked != 0) ? TRUE : FALSE; + return CHANNEL_RC_OK; +} + +static UINT rail_recv_cloak_order(railPlugin* rail, wStream* s) +{ + RailClientContext* context = rail_get_client_interface(rail); + RAIL_CLOAK cloak = { 0 }; + UINT error; + + if (!context) + return ERROR_INVALID_PARAMETER; + + /* 2.2.2.12.1 Window Cloak State Change PDU (TS_RAIL_ORDER_CLOAK) + * server -> client message only supported if announced. */ + if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_BIDIRECTIONAL_CLOAK_SUPPORTED) == 0) + return ERROR_INVALID_DATA; + + if ((error = rail_read_cloak_order(s, &cloak))) + { + WLog_ERR(TAG, "rail_read_zorder_sync_order failed with error %" PRIu32 "!", error); + return error; + } + + if (context->custom) + { + IFCALLRET(context->ServerCloak, error, context, &cloak); + + if (error) + WLog_ERR(TAG, "context.ServerZOrderSync failed with error %" PRIu32 "", error); + } + + return error; +} + +static UINT rail_read_power_display_request_order(wStream* s, RAIL_POWER_DISPLAY_REQUEST* power) +{ + UINT32 active; + + if (!s || !power) + return ERROR_INVALID_PARAMETER; + + if (Stream_GetRemainingLength(s) < RAIL_POWER_DISPLAY_REQUEST_ORDER_LENGTH) + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, active); + power->active = active != 0; + return CHANNEL_RC_OK; +} + +static UINT rail_recv_power_display_request_order(railPlugin* rail, wStream* s) +{ + RailClientContext* context = rail_get_client_interface(rail); + RAIL_POWER_DISPLAY_REQUEST power = { 0 }; + UINT error; + + if (!context) + return ERROR_INVALID_PARAMETER; + + /* 2.2.2.13.1 Power Display Request PDU(TS_RAIL_ORDER_POWER_DISPLAY_REQUEST) + */ + if ((rail->clientStatus.flags & TS_RAIL_CLIENTSTATUS_POWER_DISPLAY_REQUEST_SUPPORTED) == 0) + return ERROR_INVALID_DATA; + + if ((error = rail_read_power_display_request_order(s, &power))) + { + WLog_ERR(TAG, "rail_read_zorder_sync_order failed with error %" PRIu32 "!", error); + return error; + } + + if (context->custom) + { + IFCALLRET(context->ServerPowerDisplayRequest, error, context, &power); + + if (error) + WLog_ERR(TAG, "context.ServerPowerDisplayRequest failed with error %" PRIu32 "", error); + } + + return error; +} + +static UINT rail_read_get_application_id_extended_response_order(wStream* s, + RAIL_GET_APPID_RESP_EX* id) +{ + if (!s || !id) + return ERROR_INVALID_PARAMETER; + + if (Stream_GetRemainingLength(s) < 4) + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, id->windowID); + + if (!Stream_Read_UTF16_String(s, id->applicationID, ARRAYSIZE(id->applicationID))) + return ERROR_INVALID_DATA; + + if (_wcsnlen(id->applicationID, ARRAYSIZE(id->applicationID)) >= ARRAYSIZE(id->applicationID)) + return ERROR_INVALID_DATA; + + if (Stream_GetRemainingLength(s) < 4) + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, id->processId); + + if (!Stream_Read_UTF16_String(s, id->processImageName, ARRAYSIZE(id->processImageName))) + return ERROR_INVALID_DATA; + + if (_wcsnlen(id->applicationID, ARRAYSIZE(id->processImageName)) >= + ARRAYSIZE(id->processImageName)) + return ERROR_INVALID_DATA; + + return CHANNEL_RC_OK; +} + +static UINT rail_recv_get_application_id_extended_response_order(railPlugin* rail, wStream* s) +{ + RailClientContext* context = rail_get_client_interface(rail); + RAIL_GET_APPID_RESP_EX id = { 0 }; + UINT error; + + if (!context) + return ERROR_INVALID_PARAMETER; + + if ((error = rail_read_get_application_id_extended_response_order(s, &id))) + { + WLog_ERR(TAG, + "rail_read_get_application_id_extended_response_order failed with error %" PRIu32 + "!", + error); + return error; + } + + if (context->custom) + { + IFCALLRET(context->ServerGetAppidResponseExtended, error, context, &id); + + if (error) + WLog_ERR(TAG, "context.ServerGetAppidResponseExtended failed with error %" PRIu32 "", + error); } return error; @@ -752,67 +920,56 @@ UINT rail_order_recv(railPlugin* rail, wStream* s) if ((error = rail_read_pdu_header(s, &orderType, &orderLength))) { - WLog_ERR(TAG, "rail_read_pdu_header failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_read_pdu_header failed with error %" PRIu32 "!", error); return error; } - WLog_Print(rail->log, WLOG_DEBUG, "Received %s PDU, length:%"PRIu16"", - RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)], orderLength); + WLog_Print(rail->log, WLOG_DEBUG, "Received %s PDU, length:%" PRIu16 "", + rail_get_order_type_string(orderType), orderLength); switch (orderType) { - case RDP_RAIL_ORDER_HANDSHAKE: - { - RAIL_HANDSHAKE_ORDER handshake; - return rail_recv_handshake_order(rail, &handshake, s); - } - - case RDP_RAIL_ORDER_HANDSHAKE_EX: - { - RAIL_HANDSHAKE_EX_ORDER handshakeEx; - return rail_recv_handshake_ex_order(rail, &handshakeEx, s); - } - - case RDP_RAIL_ORDER_EXEC_RESULT: - { - RAIL_EXEC_RESULT_ORDER execResult = { 0 }; - error = rail_recv_exec_result_order(rail, &execResult, s); - free(execResult.exeOrFile.string); - return error; - } - - case RDP_RAIL_ORDER_SYSPARAM: - { - RAIL_SYSPARAM_ORDER sysparam; - return rail_recv_server_sysparam_order(rail, &sysparam, s); - } - - case RDP_RAIL_ORDER_MINMAXINFO: - { - RAIL_MINMAXINFO_ORDER minMaxInfo; - return rail_recv_server_minmaxinfo_order(rail, &minMaxInfo, s); - } - - case RDP_RAIL_ORDER_LOCALMOVESIZE: - { - RAIL_LOCALMOVESIZE_ORDER localMoveSize; - return rail_recv_server_localmovesize_order(rail, &localMoveSize, s); - } - - case RDP_RAIL_ORDER_GET_APPID_RESP: - { - RAIL_GET_APPID_RESP_ORDER getAppIdResp; - return rail_recv_server_get_appid_resp_order(rail, &getAppIdResp, s); - } - - case RDP_RAIL_ORDER_LANGBARINFO: - { - RAIL_LANGBAR_INFO_ORDER langBarInfo; - return rail_recv_langbar_info_order(rail, &langBarInfo, s); - } + case TS_RAIL_ORDER_HANDSHAKE: + return rail_recv_handshake_order(rail, s); + + case TS_RAIL_ORDER_HANDSHAKE_EX: + return rail_recv_handshake_ex_order(rail, s); + + case TS_RAIL_ORDER_EXEC_RESULT: + return rail_recv_exec_result_order(rail, s); + + case TS_RAIL_ORDER_SYSPARAM: + return rail_recv_server_sysparam_order(rail, s); + + case TS_RAIL_ORDER_MINMAXINFO: + return rail_recv_server_minmaxinfo_order(rail, s); + + case TS_RAIL_ORDER_LOCALMOVESIZE: + return rail_recv_server_localmovesize_order(rail, s); + + case TS_RAIL_ORDER_GET_APPID_RESP: + return rail_recv_server_get_appid_resp_order(rail, s); + + case TS_RAIL_ORDER_LANGBARINFO: + return rail_recv_langbar_info_order(rail, s); + + case TS_RAIL_ORDER_TASKBARINFO: + return rail_recv_taskbar_info_order(rail, s); + + case TS_RAIL_ORDER_ZORDER_SYNC: + return rail_recv_zorder_sync_order(rail, s); + + case TS_RAIL_ORDER_CLOAK: + return rail_recv_cloak_order(rail, s); + + case TS_RAIL_ORDER_POWER_DISPLAY_REQUEST: + return rail_recv_power_display_request_order(rail, s); + + case TS_RAIL_ORDER_GET_APPID_RESP_EX: + return rail_recv_get_application_id_extended_response_order(rail, s); default: - WLog_ERR(TAG, "Unknown RAIL PDU order reveived."); + WLog_ERR(TAG, "Unknown RAIL PDU order reveived."); return ERROR_INVALID_DATA; } @@ -841,7 +998,7 @@ UINT rail_send_handshake_order(railPlugin* rail, const RAIL_HANDSHAKE_ORDER* han } rail_write_handshake_order(s, handshake); - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_HANDSHAKE); + error = rail_send_pdu(rail, s, TS_RAIL_ORDER_HANDSHAKE); Stream_Free(s, TRUE); return error; } @@ -868,7 +1025,7 @@ UINT rail_send_handshake_ex_order(railPlugin* rail, const RAIL_HANDSHAKE_EX_ORDE } rail_write_handshake_ex_order(s, handshakeEx); - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_HANDSHAKE_EX); + error = rail_send_pdu(rail, s, TS_RAIL_ORDER_HANDSHAKE_EX); Stream_Free(s, TRUE); return error; } @@ -886,6 +1043,7 @@ UINT rail_send_client_status_order(railPlugin* rail, const RAIL_CLIENT_STATUS_OR if (!rail || !clientStatus) return ERROR_INVALID_PARAMETER; + rail->clientStatus = *clientStatus; s = rail_pdu_init(RAIL_CLIENT_STATUS_ORDER_LENGTH); if (!s) @@ -897,7 +1055,7 @@ UINT rail_send_client_status_order(railPlugin* rail, const RAIL_CLIENT_STATUS_OR error = rail_write_client_status_order(s, clientStatus); if (error == ERROR_SUCCESS) - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_CLIENTSTATUS); + error = rail_send_pdu(rail, s, TS_RAIL_ORDER_CLIENTSTATUS); Stream_Free(s, TRUE); return error; @@ -909,7 +1067,8 @@ UINT rail_send_client_status_order(railPlugin* rail, const RAIL_CLIENT_STATUS_OR * @return 0 on success, otherwise a Win32 error code */ UINT rail_send_client_exec_order(railPlugin* rail, UINT16 flags, - const RAIL_UNICODE_STRING* exeOrFile, const RAIL_UNICODE_STRING* workingDir, + const RAIL_UNICODE_STRING* exeOrFile, + const RAIL_UNICODE_STRING* workingDir, const RAIL_UNICODE_STRING* arguments) { wStream* s; @@ -919,10 +1078,7 @@ UINT rail_send_client_exec_order(railPlugin* rail, UINT16 flags, if (!rail || !exeOrFile || !workingDir || !arguments) return ERROR_INVALID_PARAMETER; - length = RAIL_EXEC_ORDER_LENGTH + - exeOrFile->length + - workingDir->length + - arguments->length; + length = RAIL_EXEC_ORDER_LENGTH + exeOrFile->length + workingDir->length + arguments->length; s = rail_pdu_init(length); if (!s) @@ -933,13 +1089,13 @@ UINT rail_send_client_exec_order(railPlugin* rail, UINT16 flags, if ((error = rail_write_client_exec_order(s, flags, exeOrFile, workingDir, arguments))) { - WLog_ERR(TAG, "rail_write_client_exec_order failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_write_client_exec_order failed with error %" PRIu32 "!", error); goto out; } - if ((error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_EXEC))) + if ((error = rail_send_pdu(rail, s, TS_RAIL_ORDER_EXEC))) { - WLog_ERR(TAG, "rail_send_pdu failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rail_send_pdu failed with error %" PRIu32 "!", error); goto out; } @@ -953,40 +1109,15 @@ out: * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_send_client_sysparam_order(railPlugin* rail, const RAIL_SYSPARAM_ORDER* sysparam) +UINT rail_send_client_activate_order(railPlugin* rail, const RAIL_ACTIVATE_ORDER* activate) { wStream* s; - size_t length = RAIL_SYSPARAM_ORDER_LENGTH; UINT error; - if (!rail || !sysparam) + if (!rail || !activate) return ERROR_INVALID_PARAMETER; - switch (sysparam->param) - { - case SPI_SET_DRAG_FULL_WINDOWS: - case SPI_SET_KEYBOARD_CUES: - case SPI_SET_KEYBOARD_PREF: - case SPI_SET_MOUSE_BUTTON_SWAP: - length += 1; - break; - - case SPI_SET_WORK_AREA: - case SPI_DISPLAY_CHANGE: - case SPI_TASKBAR_POS: - length += 8; - break; - - case SPI_SET_HIGH_CONTRAST: - length += sysparam->highContrast.colorSchemeLength + 10; - break; - - default: - length += 8; - break; - } - - s = rail_pdu_init(length); + s = rail_pdu_init(RAIL_ACTIVATE_ORDER_LENGTH); if (!s) { @@ -994,19 +1125,11 @@ static UINT rail_send_client_sysparam_order(railPlugin* rail, const RAIL_SYSPARA return CHANNEL_RC_NO_MEMORY; } - if ((error = rail_write_client_sysparam_order(s, sysparam))) - { - WLog_ERR(TAG, "rail_write_client_sysparam_order failed with error %"PRIu32"!", error); - goto out; - } + error = rail_write_client_activate_order(s, activate); - if ((error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSPARAM))) - { - WLog_ERR(TAG, "rail_send_pdu failed with error %"PRIu32"!", error); - goto out; - } + if (error == ERROR_SUCCESS) + error = rail_send_pdu(rail, s, TS_RAIL_ORDER_ACTIVATE); -out: Stream_Free(s, TRUE); return error; } @@ -1016,90 +1139,58 @@ out: * * @return 0 on success, otherwise a Win32 error code */ -static UINT rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORDER* sysparam) +UINT rail_send_client_sysmenu_order(railPlugin* rail, const RAIL_SYSMENU_ORDER* sysmenu) { - UINT error = CHANNEL_RC_OK; + wStream* s; + UINT error; - if (!rail || !sysparam) + if (!rail || !sysmenu) return ERROR_INVALID_PARAMETER; - if (sysparam->params & SPI_MASK_SET_HIGH_CONTRAST) - { - sysparam->param = SPI_SET_HIGH_CONTRAST; - - if ((error = rail_send_client_sysparam_order(rail, sysparam))) - { - WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %"PRIu32"!", error); - return error; - } - } + s = rail_pdu_init(RAIL_SYSMENU_ORDER_LENGTH); - if (sysparam->params & SPI_MASK_TASKBAR_POS) + if (!s) { - sysparam->param = SPI_TASKBAR_POS; - - if ((error = rail_send_client_sysparam_order(rail, sysparam))) - { - WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %"PRIu32"!", error); - return error; - } + WLog_ERR(TAG, "rail_pdu_init failed!"); + return CHANNEL_RC_NO_MEMORY; } - if (sysparam->params & SPI_MASK_SET_MOUSE_BUTTON_SWAP) - { - sysparam->param = SPI_SET_MOUSE_BUTTON_SWAP; + error = rail_write_client_sysmenu_order(s, sysmenu); - if ((error = rail_send_client_sysparam_order(rail, sysparam))) - { - WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %"PRIu32"!", error); - return error; - } - } + if (error == ERROR_SUCCESS) + error = rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSMENU); - if (sysparam->params & SPI_MASK_SET_KEYBOARD_PREF) - { - sysparam->param = SPI_SET_KEYBOARD_PREF; + Stream_Free(s, TRUE); + return error; +} - if ((error = rail_send_client_sysparam_order(rail, sysparam))) - { - WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %"PRIu32"!", error); - return error; - } - } +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +UINT rail_send_client_syscommand_order(railPlugin* rail, const RAIL_SYSCOMMAND_ORDER* syscommand) +{ + wStream* s; + UINT error; - if (sysparam->params & SPI_MASK_SET_DRAG_FULL_WINDOWS) - { - sysparam->param = SPI_SET_DRAG_FULL_WINDOWS; + if (!rail || !syscommand) + return ERROR_INVALID_PARAMETER; - if ((error = rail_send_client_sysparam_order(rail, sysparam))) - { - WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %"PRIu32"!", error); - return error; - } - } + s = rail_pdu_init(RAIL_SYSCOMMAND_ORDER_LENGTH); - if (sysparam->params & SPI_MASK_SET_KEYBOARD_CUES) + if (!s) { - sysparam->param = SPI_SET_KEYBOARD_CUES; - - if ((error = rail_send_client_sysparam_order(rail, sysparam))) - { - WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %"PRIu32"!", error); - return error; - } + WLog_ERR(TAG, "rail_pdu_init failed!"); + return CHANNEL_RC_NO_MEMORY; } - if (sysparam->params & SPI_MASK_SET_WORK_AREA) - { - sysparam->param = SPI_SET_WORK_AREA; + error = rail_write_client_syscommand_order(s, syscommand); - if ((error = rail_send_client_sysparam_order(rail, sysparam))) - { - WLog_ERR(TAG, "rail_send_client_sysparam_order failed with error %"PRIu32"!", error); - return error; - } - } + if (error == ERROR_SUCCESS) + error = rail_send_pdu(rail, s, TS_RAIL_ORDER_SYSCOMMAND); + Stream_Free(s, TRUE); return error; } @@ -1108,15 +1199,16 @@ static UINT rail_send_client_sysparams_order(railPlugin* rail, RAIL_SYSPARAM_ORD * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_send_client_activate_order(railPlugin* rail, const RAIL_ACTIVATE_ORDER* activate) +UINT rail_send_client_notify_event_order(railPlugin* rail, + const RAIL_NOTIFY_EVENT_ORDER* notifyEvent) { wStream* s; UINT error; - if (!rail || !activate) + if (!rail || !notifyEvent) return ERROR_INVALID_PARAMETER; - s = rail_pdu_init(RAIL_ACTIVATE_ORDER_LENGTH); + s = rail_pdu_init(RAIL_NOTIFY_EVENT_ORDER_LENGTH); if (!s) { @@ -1124,10 +1216,10 @@ UINT rail_send_client_activate_order(railPlugin* rail, const RAIL_ACTIVATE_ORDER return CHANNEL_RC_NO_MEMORY; } - error = rail_write_client_activate_order(s, activate); + error = rail_write_client_notify_event_order(s, notifyEvent); - if (error == ERROR_SUCCESS) - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_ACTIVATE); + if (ERROR_SUCCESS == error) + error = rail_send_pdu(rail, s, TS_RAIL_ORDER_NOTIFY_EVENT); Stream_Free(s, TRUE); return error; @@ -1138,15 +1230,15 @@ UINT rail_send_client_activate_order(railPlugin* rail, const RAIL_ACTIVATE_ORDER * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_send_client_sysmenu_order(railPlugin* rail, const RAIL_SYSMENU_ORDER* sysmenu) +UINT rail_send_client_window_move_order(railPlugin* rail, const RAIL_WINDOW_MOVE_ORDER* windowMove) { wStream* s; UINT error; - if (!rail || !sysmenu) + if (!rail || !windowMove) return ERROR_INVALID_PARAMETER; - s = rail_pdu_init(RAIL_SYSMENU_ORDER_LENGTH); + s = rail_pdu_init(RAIL_WINDOW_MOVE_ORDER_LENGTH); if (!s) { @@ -1154,10 +1246,10 @@ UINT rail_send_client_sysmenu_order(railPlugin* rail, const RAIL_SYSMENU_ORDER* return CHANNEL_RC_NO_MEMORY; } - error = rail_write_client_sysmenu_order(s, sysmenu); + error = rail_write_client_window_move_order(s, windowMove); if (error == ERROR_SUCCESS) - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSMENU); + error = rail_send_pdu(rail, s, TS_RAIL_ORDER_WINDOWMOVE); Stream_Free(s, TRUE); return error; @@ -1168,15 +1260,16 @@ UINT rail_send_client_sysmenu_order(railPlugin* rail, const RAIL_SYSMENU_ORDER* * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_send_client_syscommand_order(railPlugin* rail, const RAIL_SYSCOMMAND_ORDER* syscommand) +UINT rail_send_client_get_appid_req_order(railPlugin* rail, + const RAIL_GET_APPID_REQ_ORDER* getAppIdReq) { wStream* s; UINT error; - if (!rail || !syscommand) + if (!rail || !getAppIdReq) return ERROR_INVALID_PARAMETER; - s = rail_pdu_init(RAIL_SYSCOMMAND_ORDER_LENGTH); + s = rail_pdu_init(RAIL_GET_APPID_REQ_ORDER_LENGTH); if (!s) { @@ -1184,10 +1277,10 @@ UINT rail_send_client_syscommand_order(railPlugin* rail, const RAIL_SYSCOMMAND_O return CHANNEL_RC_NO_MEMORY; } - error = rail_write_client_syscommand_order(s, syscommand); + error = rail_write_client_get_appid_req_order(s, getAppIdReq); if (error == ERROR_SUCCESS) - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_SYSCOMMAND); + error = rail_send_pdu(rail, s, TS_RAIL_ORDER_GET_APPID_REQ); Stream_Free(s, TRUE); return error; @@ -1198,16 +1291,19 @@ UINT rail_send_client_syscommand_order(railPlugin* rail, const RAIL_SYSCOMMAND_O * * @return 0 on success, otherwise a Win32 error code */ -UINT rail_send_client_notify_event_order(railPlugin* rail, - const RAIL_NOTIFY_EVENT_ORDER* notifyEvent) +UINT rail_send_client_langbar_info_order(railPlugin* rail, + const RAIL_LANGBAR_INFO_ORDER* langBarInfo) { wStream* s; UINT error; - if (!rail || !notifyEvent) + if (!rail || !langBarInfo) return ERROR_INVALID_PARAMETER; - s = rail_pdu_init(RAIL_NOTIFY_EVENT_ORDER_LENGTH); + if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_DOCKED_LANGBAR_SUPPORTED)) + return ERROR_BAD_CONFIGURATION; + + s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH); if (!s) { @@ -1215,29 +1311,28 @@ UINT rail_send_client_notify_event_order(railPlugin* rail, return CHANNEL_RC_NO_MEMORY; } - error = rail_write_client_notify_event_order(s, notifyEvent); + error = rail_write_langbar_info_order(s, langBarInfo); if (ERROR_SUCCESS == error) - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_NOTIFY_EVENT); + error = rail_send_pdu(rail, s, TS_RAIL_ORDER_LANGBARINFO); Stream_Free(s, TRUE); return error; } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -UINT rail_send_client_window_move_order(railPlugin* rail, const RAIL_WINDOW_MOVE_ORDER* windowMove) +UINT rail_send_client_languageime_info_order(railPlugin* rail, + const RAIL_LANGUAGEIME_INFO_ORDER* langImeInfo) { wStream* s; UINT error; - if (!rail || !windowMove) + if (!rail || !langImeInfo) return ERROR_INVALID_PARAMETER; - s = rail_pdu_init(RAIL_WINDOW_MOVE_ORDER_LENGTH); + if (!rail_is_feature_supported(rail->rdpcontext, RAIL_LEVEL_LANGUAGE_IME_SYNC_SUPPORTED)) + return ERROR_BAD_CONFIGURATION; + + s = rail_pdu_init(RAIL_LANGUAGEIME_INFO_ORDER_LENGTH); if (!s) { @@ -1245,30 +1340,25 @@ UINT rail_send_client_window_move_order(railPlugin* rail, const RAIL_WINDOW_MOVE return CHANNEL_RC_NO_MEMORY; } - error = rail_write_client_window_move_order(s, windowMove); + error = rail_write_languageime_info_order(s, langImeInfo); - if (error == ERROR_SUCCESS) - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_WINDOWMOVE); + if (ERROR_SUCCESS == error) + error = rail_send_pdu(rail, s, TS_RAIL_ORDER_LANGUAGEIMEINFO); Stream_Free(s, TRUE); return error; } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -UINT rail_send_client_get_appid_req_order(railPlugin* rail, - const RAIL_GET_APPID_REQ_ORDER* getAppIdReq) +UINT rail_send_client_compartment_info_order(railPlugin* rail, + const RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo) { wStream* s; UINT error; - if (!rail || !getAppIdReq) + if (!rail || !compartmentInfo) return ERROR_INVALID_PARAMETER; - s = rail_pdu_init(RAIL_GET_APPID_REQ_ORDER_LENGTH); + s = rail_pdu_init(RAIL_COMPARTMENT_INFO_ORDER_LENGTH); if (!s) { @@ -1276,30 +1366,24 @@ UINT rail_send_client_get_appid_req_order(railPlugin* rail, return CHANNEL_RC_NO_MEMORY; } - error = rail_write_client_get_appid_req_order(s, getAppIdReq); + error = rail_write_compartment_info_order(s, compartmentInfo); - if (error == ERROR_SUCCESS) - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_GET_APPID_REQ); + if (ERROR_SUCCESS == error) + error = rail_send_pdu(rail, s, TS_RAIL_ORDER_COMPARTMENTINFO); Stream_Free(s, TRUE); return error; } -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -UINT rail_send_client_langbar_info_order(railPlugin* rail, - const RAIL_LANGBAR_INFO_ORDER* langBarInfo) +UINT rail_send_client_cloak_order(railPlugin* rail, const RAIL_CLOAK* cloak) { wStream* s; UINT error; - if (!rail || !langBarInfo) + if (!rail || !cloak) return ERROR_INVALID_PARAMETER; - s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH); + s = rail_pdu_init(5); if (!s) { @@ -1307,11 +1391,47 @@ UINT rail_send_client_langbar_info_order(railPlugin* rail, return CHANNEL_RC_NO_MEMORY; } - error = rail_write_langbar_info_order(s, langBarInfo); + Stream_Write_UINT32(s, cloak->windowId); + Stream_Write_UINT8(s, cloak->cloak ? 1 : 0); + error = rail_send_pdu(rail, s, TS_RAIL_ORDER_CLOAK); + Stream_Free(s, TRUE); + return error; +} - if (ERROR_SUCCESS == error) - error = rail_send_pdu(rail, s, RDP_RAIL_ORDER_LANGBARINFO); +UINT rail_send_client_snap_arrange_order(railPlugin* rail, const RAIL_SNAP_ARRANGE* snap) +{ + wStream* s; + UINT error; + + if (!rail) + return ERROR_INVALID_PARAMETER; + + /* 2.2.2.7.5 Client Window Snap PDU (TS_RAIL_ORDER_SNAP_ARRANGE) */ + if ((rail->channelFlags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_SNAP_ARRANGE_SUPPORTED) == 0) + { + RAIL_WINDOW_MOVE_ORDER move = { 0 }; + move.top = snap->top; + move.left = snap->left; + move.right = snap->right; + move.bottom = snap->bottom; + move.windowId = snap->windowId; + return rail_send_client_window_move_order(rail, &move); + } + + s = rail_pdu_init(12); + + if (!s) + { + WLog_ERR(TAG, "rail_pdu_init failed!"); + return CHANNEL_RC_NO_MEMORY; + } + Stream_Write_UINT32(s, snap->windowId); + Stream_Write_INT16(s, snap->left); + Stream_Write_INT16(s, snap->top); + Stream_Write_INT16(s, snap->right); + Stream_Write_INT16(s, snap->bottom); + error = rail_send_pdu(rail, s, TS_RAIL_ORDER_SNAP_ARRANGE); Stream_Free(s, TRUE); return error; } diff --git a/channels/rail/client/rail_orders.h b/channels/rail/client/rail_orders.h index 0b4fd93..89ba6cc 100644 --- a/channels/rail/client/rail_orders.h +++ b/channels/rail/client/rail_orders.h @@ -29,8 +29,6 @@ #define TAG CHANNELS_TAG("rail.client") -UINT rail_write_client_sysparam_order(wStream* s, const RAIL_SYSPARAM_ORDER* sysparam); - UINT rail_order_recv(railPlugin* rail, wStream* s); UINT rail_send_pdu(railPlugin* rail, wStream* s, UINT16 orderType); @@ -38,18 +36,25 @@ UINT rail_send_handshake_order(railPlugin* rail, const RAIL_HANDSHAKE_ORDER* han UINT rail_send_handshake_ex_order(railPlugin* rail, const RAIL_HANDSHAKE_EX_ORDER* handshakeEx); UINT rail_send_client_status_order(railPlugin* rail, const RAIL_CLIENT_STATUS_ORDER* clientStatus); UINT rail_send_client_exec_order(railPlugin* rail, UINT16 flags, - const RAIL_UNICODE_STRING* exeOrFile, const RAIL_UNICODE_STRING* workingDir, + const RAIL_UNICODE_STRING* exeOrFile, + const RAIL_UNICODE_STRING* workingDir, const RAIL_UNICODE_STRING* arguments); UINT rail_send_client_activate_order(railPlugin* rail, const RAIL_ACTIVATE_ORDER* activate); UINT rail_send_client_sysmenu_order(railPlugin* rail, const RAIL_SYSMENU_ORDER* sysmenu); UINT rail_send_client_syscommand_order(railPlugin* rail, const RAIL_SYSCOMMAND_ORDER* syscommand); UINT rail_send_client_notify_event_order(railPlugin* rail, - const RAIL_NOTIFY_EVENT_ORDER* notifyEvent); + const RAIL_NOTIFY_EVENT_ORDER* notifyEvent); UINT rail_send_client_window_move_order(railPlugin* rail, const RAIL_WINDOW_MOVE_ORDER* windowMove); UINT rail_send_client_get_appid_req_order(railPlugin* rail, - const RAIL_GET_APPID_REQ_ORDER* getAppIdReq); + const RAIL_GET_APPID_REQ_ORDER* getAppIdReq); UINT rail_send_client_langbar_info_order(railPlugin* rail, - const RAIL_LANGBAR_INFO_ORDER* langBarInfo); + const RAIL_LANGBAR_INFO_ORDER* langBarInfo); +UINT rail_send_client_languageime_info_order(railPlugin* rail, + const RAIL_LANGUAGEIME_INFO_ORDER* langImeInfo); +UINT rail_send_client_cloak_order(railPlugin* rail, const RAIL_CLOAK* cloak); +UINT rail_send_client_snap_arrange_order(railPlugin* rail, const RAIL_SNAP_ARRANGE* snap); +UINT rail_send_client_compartment_info_order(railPlugin* rail, + const RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo); #endif /* FREERDP_CHANNEL_RAIL_CLIENT_ORDERS_H */ diff --git a/channels/rail/rail_common.c b/channels/rail/rail_common.c index ac0103f..902a738 100644 --- a/channels/rail/rail_common.c +++ b/channels/rail/rail_common.c @@ -23,56 +23,37 @@ #include "rail_common.h" #include +#include -const char* const RAIL_ORDER_TYPE_STRINGS[] = -{ - "", - "Execute", - "Activate", - "System Parameters Update", - "System Command", - "Handshake", - "Notify Event", - "", - "Window Move", - "Local Move/Size", - "Min Max Info", - "Client Status", - "System Menu", - "Language Bar Info", - "Get Application ID Request", - "Get Application ID Response", - "Execute Result", - "", - "", - "", - "", - "", - "" -}; - -BOOL rail_string_to_unicode_string(const char* string, RAIL_UNICODE_STRING* unicode_string) -{ - WCHAR* buffer = NULL; - int length = 0; - free(unicode_string->string); - unicode_string->string = NULL; - unicode_string->length = 0; - - if (!string || strlen(string) < 1) - return TRUE; - - length = ConvertToUnicode(CP_UTF8, 0, string, -1, &buffer, 0); - - if ((length < 0) || ((size_t)length * sizeof(WCHAR) > UINT16_MAX)) - { - free(buffer); - return FALSE; - } +#define TAG CHANNELS_TAG("rail.common") + +static const char* const RAIL_ORDER_TYPE_STRINGS[] = { "", + "Execute", + "Activate", + "System Parameters Update", + "System Command", + "Handshake", + "Notify Event", + "", + "Window Move", + "Local Move/Size", + "Min Max Info", + "Client Status", + "System Menu", + "Language Bar Info", + "Get Application ID Request", + "Get Application ID Response", + "Execute Result", + "", + "", + "", + "", + "", + "" }; - unicode_string->string = (BYTE*) buffer; - unicode_string->length = (UINT16) length * sizeof(WCHAR); - return TRUE; +const char* rail_get_order_type_string(BYTE orderType) +{ + return RAIL_ORDER_TYPE_STRINGS[((orderType & 0xF0) >> 3) + (orderType & 0x0F)]; } /** @@ -88,14 +69,14 @@ UINT rail_read_pdu_header(wStream* s, UINT16* orderType, UINT16* orderLength) if (Stream_GetRemainingLength(s) < 4) return ERROR_INVALID_DATA; - Stream_Read_UINT16(s, *orderType); /* orderType (2 bytes) */ + Stream_Read_UINT16(s, *orderType); /* orderType (2 bytes) */ Stream_Read_UINT16(s, *orderLength); /* orderLength (2 bytes) */ return CHANNEL_RC_OK; } void rail_write_pdu_header(wStream* s, UINT16 orderType, UINT16 orderLength) { - Stream_Write_UINT16(s, orderType); /* orderType (2 bytes) */ + Stream_Write_UINT16(s, orderType); /* orderType (2 bytes) */ Stream_Write_UINT16(s, orderLength); /* orderLength (2 bytes) */ } @@ -140,13 +121,459 @@ UINT rail_read_handshake_ex_order(wStream* s, RAIL_HANDSHAKE_EX_ORDER* handshake if (Stream_GetRemainingLength(s) < 8) return ERROR_INVALID_DATA; - Stream_Read_UINT32(s, handshakeEx->buildNumber); /* buildNumber (4 bytes) */ + Stream_Read_UINT32(s, handshakeEx->buildNumber); /* buildNumber (4 bytes) */ Stream_Read_UINT32(s, handshakeEx->railHandshakeFlags); /* railHandshakeFlags (4 bytes) */ return CHANNEL_RC_OK; } void rail_write_handshake_ex_order(wStream* s, const RAIL_HANDSHAKE_EX_ORDER* handshakeEx) { - Stream_Write_UINT32(s, handshakeEx->buildNumber); /* buildNumber (4 bytes) */ + Stream_Write_UINT32(s, handshakeEx->buildNumber); /* buildNumber (4 bytes) */ Stream_Write_UINT32(s, handshakeEx->railHandshakeFlags); /* railHandshakeFlags (4 bytes) */ } + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +UINT rail_write_unicode_string(wStream* s, const RAIL_UNICODE_STRING* unicode_string) +{ + if (!s || !unicode_string) + return ERROR_INVALID_PARAMETER; + + if (!Stream_EnsureRemainingCapacity(s, 2 + unicode_string->length)) + { + WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + Stream_Write_UINT16(s, unicode_string->length); /* cbString (2 bytes) */ + Stream_Write(s, unicode_string->string, unicode_string->length); /* string */ + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +UINT rail_write_unicode_string_value(wStream* s, const RAIL_UNICODE_STRING* unicode_string) +{ + size_t length; + + if (!s || !unicode_string) + return ERROR_INVALID_PARAMETER; + + length = unicode_string->length; + + if (length > 0) + { + if (!Stream_EnsureRemainingCapacity(s, length)) + { + WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + Stream_Write(s, unicode_string->string, length); /* string */ + } + + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_read_high_contrast(wStream* s, RAIL_HIGH_CONTRAST* highContrast) +{ + if (!s || !highContrast) + return ERROR_INVALID_PARAMETER; + + if (Stream_GetRemainingLength(s) < 8) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, highContrast->flags); /* flags (4 bytes) */ + Stream_Read_UINT32(s, highContrast->colorSchemeLength); /* colorSchemeLength (4 bytes) */ + + if (!rail_read_unicode_string(s, &highContrast->colorScheme)) /* colorScheme */ + return ERROR_INTERNAL_ERROR; + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_write_high_contrast(wStream* s, const RAIL_HIGH_CONTRAST* highContrast) +{ + UINT32 colorSchemeLength; + + if (!s || !highContrast) + return ERROR_INVALID_PARAMETER; + + if (!Stream_EnsureRemainingCapacity(s, 8)) + return CHANNEL_RC_NO_MEMORY; + + colorSchemeLength = highContrast->colorScheme.length + 2; + Stream_Write_UINT32(s, highContrast->flags); /* flags (4 bytes) */ + Stream_Write_UINT32(s, colorSchemeLength); /* colorSchemeLength (4 bytes) */ + return rail_write_unicode_string(s, &highContrast->colorScheme); /* colorScheme */ +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_read_filterkeys(wStream* s, TS_FILTERKEYS* filterKeys) +{ + if (!s || !filterKeys) + return ERROR_INVALID_PARAMETER; + + if (Stream_GetRemainingLength(s) < 20) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, filterKeys->Flags); + Stream_Read_UINT32(s, filterKeys->WaitTime); + Stream_Read_UINT32(s, filterKeys->DelayTime); + Stream_Read_UINT32(s, filterKeys->RepeatTime); + Stream_Read_UINT32(s, filterKeys->BounceTime); + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_write_filterkeys(wStream* s, const TS_FILTERKEYS* filterKeys) +{ + if (!s || !filterKeys) + return ERROR_INVALID_PARAMETER; + + if (!Stream_EnsureRemainingCapacity(s, 20)) + return CHANNEL_RC_NO_MEMORY; + + Stream_Write_UINT32(s, filterKeys->Flags); + Stream_Write_UINT32(s, filterKeys->WaitTime); + Stream_Write_UINT32(s, filterKeys->DelayTime); + Stream_Write_UINT32(s, filterKeys->RepeatTime); + Stream_Write_UINT32(s, filterKeys->BounceTime); + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +UINT rail_read_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam, BOOL extendedSpiSupported) +{ + BYTE body; + UINT error = CHANNEL_RC_OK; + + if (!s || !sysparam) + return ERROR_INVALID_PARAMETER; + + if (Stream_GetRemainingLength(s) < 5) + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, sysparam->param); /* systemParam (4 bytes) */ + + sysparam->params = 0; /* bitflags of received params */ + + switch (sysparam->param) + { + /* Client sysparams */ + case SPI_SET_DRAG_FULL_WINDOWS: + sysparam->params |= SPI_MASK_SET_DRAG_FULL_WINDOWS; + Stream_Read_UINT8(s, body); /* body (1 byte) */ + sysparam->dragFullWindows = body != 0; + break; + + case SPI_SET_KEYBOARD_CUES: + sysparam->params |= SPI_MASK_SET_KEYBOARD_CUES; + Stream_Read_UINT8(s, body); /* body (1 byte) */ + sysparam->keyboardCues = body != 0; + break; + + case SPI_SET_KEYBOARD_PREF: + sysparam->params |= SPI_MASK_SET_KEYBOARD_PREF; + Stream_Read_UINT8(s, body); /* body (1 byte) */ + sysparam->keyboardPref = body != 0; + break; + + case SPI_SET_MOUSE_BUTTON_SWAP: + sysparam->params |= SPI_MASK_SET_MOUSE_BUTTON_SWAP; + Stream_Read_UINT8(s, body); /* body (1 byte) */ + sysparam->mouseButtonSwap = body != 0; + break; + + case SPI_SET_WORK_AREA: + sysparam->params |= SPI_MASK_SET_WORK_AREA; + + if (Stream_GetRemainingLength(s) < 8) + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT16(s, sysparam->workArea.left); /* left (2 bytes) */ + Stream_Read_UINT16(s, sysparam->workArea.top); /* top (2 bytes) */ + Stream_Read_UINT16(s, sysparam->workArea.right); /* right (2 bytes) */ + Stream_Read_UINT16(s, sysparam->workArea.bottom); /* bottom (2 bytes) */ + break; + + case SPI_DISPLAY_CHANGE: + sysparam->params |= SPI_MASK_DISPLAY_CHANGE; + + if (Stream_GetRemainingLength(s) < 8) + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT16(s, sysparam->displayChange.left); /* left (2 bytes) */ + Stream_Read_UINT16(s, sysparam->displayChange.top); /* top (2 bytes) */ + Stream_Read_UINT16(s, sysparam->displayChange.right); /* right (2 bytes) */ + Stream_Read_UINT16(s, sysparam->displayChange.bottom); /* bottom (2 bytes) */ + break; + + case SPI_TASKBAR_POS: + sysparam->params |= SPI_MASK_TASKBAR_POS; + + if (Stream_GetRemainingLength(s) < 8) + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT16(s, sysparam->taskbarPos.left); /* left (2 bytes) */ + Stream_Read_UINT16(s, sysparam->taskbarPos.top); /* top (2 bytes) */ + Stream_Read_UINT16(s, sysparam->taskbarPos.right); /* right (2 bytes) */ + Stream_Read_UINT16(s, sysparam->taskbarPos.bottom); /* bottom (2 bytes) */ + break; + + case SPI_SET_HIGH_CONTRAST: + sysparam->params |= SPI_MASK_SET_HIGH_CONTRAST; + if (Stream_GetRemainingLength(s) < 8) + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } + + error = rail_read_high_contrast(s, &sysparam->highContrast); + break; + + case SPI_SETCARETWIDTH: + sysparam->params |= SPI_MASK_SET_CARET_WIDTH; + + if (!extendedSpiSupported) + return ERROR_INVALID_DATA; + + if (Stream_GetRemainingLength(s) < 4) + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, sysparam->caretWidth); + + if (sysparam->caretWidth < 0x0001) + return ERROR_INVALID_DATA; + + break; + + case SPI_SETSTICKYKEYS: + sysparam->params |= SPI_MASK_SET_STICKY_KEYS; + + if (!extendedSpiSupported) + return ERROR_INVALID_DATA; + + if (Stream_GetRemainingLength(s) < 4) + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, sysparam->stickyKeys); + break; + + case SPI_SETTOGGLEKEYS: + sysparam->params |= SPI_MASK_SET_TOGGLE_KEYS; + + if (!extendedSpiSupported) + return ERROR_INVALID_DATA; + + if (Stream_GetRemainingLength(s) < 4) + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } + + Stream_Read_UINT32(s, sysparam->toggleKeys); + break; + + case SPI_SETFILTERKEYS: + sysparam->params |= SPI_MASK_SET_FILTER_KEYS; + + if (!extendedSpiSupported) + return ERROR_INVALID_DATA; + + if (Stream_GetRemainingLength(s) < 20) + { + WLog_ERR(TAG, "Stream_GetRemainingLength failed!"); + return ERROR_INVALID_DATA; + } + + error = rail_read_filterkeys(s, &sysparam->filterKeys); + break; + + /* Server sysparams */ + case SPI_SETSCREENSAVEACTIVE: + sysparam->params |= SPI_MASK_SET_SCREEN_SAVE_ACTIVE; + + Stream_Read_UINT8(s, body); /* body (1 byte) */ + sysparam->setScreenSaveActive = body != 0; + break; + + case SPI_SETSCREENSAVESECURE: + sysparam->params |= SPI_MASK_SET_SET_SCREEN_SAVE_SECURE; + + Stream_Read_UINT8(s, body); /* body (1 byte) */ + sysparam->setScreenSaveSecure = body != 0; + break; + + default: + break; + } + + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 err2or code + */ +UINT rail_write_sysparam_order(wStream* s, const RAIL_SYSPARAM_ORDER* sysparam, + BOOL extendedSpiSupported) +{ + BYTE body; + UINT error = CHANNEL_RC_OK; + + if (!s || !sysparam) + return ERROR_INVALID_PARAMETER; + + if (!Stream_EnsureRemainingCapacity(s, 12)) + return CHANNEL_RC_NO_MEMORY; + + Stream_Write_UINT32(s, sysparam->param); /* systemParam (4 bytes) */ + + switch (sysparam->param) + { + /* Client sysparams */ + case SPI_SET_DRAG_FULL_WINDOWS: + body = sysparam->dragFullWindows ? 1 : 0; + Stream_Write_UINT8(s, body); + break; + + case SPI_SET_KEYBOARD_CUES: + body = sysparam->keyboardCues ? 1 : 0; + Stream_Write_UINT8(s, body); + break; + + case SPI_SET_KEYBOARD_PREF: + body = sysparam->keyboardPref ? 1 : 0; + Stream_Write_UINT8(s, body); + break; + + case SPI_SET_MOUSE_BUTTON_SWAP: + body = sysparam->mouseButtonSwap ? 1 : 0; + Stream_Write_UINT8(s, body); + break; + + case SPI_SET_WORK_AREA: + Stream_Write_UINT16(s, sysparam->workArea.left); /* left (2 bytes) */ + Stream_Write_UINT16(s, sysparam->workArea.top); /* top (2 bytes) */ + Stream_Write_UINT16(s, sysparam->workArea.right); /* right (2 bytes) */ + Stream_Write_UINT16(s, sysparam->workArea.bottom); /* bottom (2 bytes) */ + break; + + case SPI_DISPLAY_CHANGE: + Stream_Write_UINT16(s, sysparam->displayChange.left); /* left (2 bytes) */ + Stream_Write_UINT16(s, sysparam->displayChange.top); /* top (2 bytes) */ + Stream_Write_UINT16(s, sysparam->displayChange.right); /* right (2 bytes) */ + Stream_Write_UINT16(s, sysparam->displayChange.bottom); /* bottom (2 bytes) */ + break; + + case SPI_TASKBAR_POS: + Stream_Write_UINT16(s, sysparam->taskbarPos.left); /* left (2 bytes) */ + Stream_Write_UINT16(s, sysparam->taskbarPos.top); /* top (2 bytes) */ + Stream_Write_UINT16(s, sysparam->taskbarPos.right); /* right (2 bytes) */ + Stream_Write_UINT16(s, sysparam->taskbarPos.bottom); /* bottom (2 bytes) */ + break; + + case SPI_SET_HIGH_CONTRAST: + error = rail_write_high_contrast(s, &sysparam->highContrast); + break; + + case SPI_SETCARETWIDTH: + if (!extendedSpiSupported) + return ERROR_INVALID_DATA; + + if (sysparam->caretWidth < 0x0001) + return ERROR_INVALID_DATA; + + Stream_Write_UINT32(s, sysparam->caretWidth); + break; + + case SPI_SETSTICKYKEYS: + if (!extendedSpiSupported) + return ERROR_INVALID_DATA; + + Stream_Write_UINT32(s, sysparam->stickyKeys); + break; + + case SPI_SETTOGGLEKEYS: + if (!extendedSpiSupported) + return ERROR_INVALID_DATA; + + Stream_Write_UINT32(s, sysparam->toggleKeys); + break; + + case SPI_SETFILTERKEYS: + if (!extendedSpiSupported) + return ERROR_INVALID_DATA; + + error = rail_write_filterkeys(s, &sysparam->filterKeys); + break; + + /* Server sysparams */ + case SPI_SETSCREENSAVEACTIVE: + body = sysparam->setScreenSaveActive ? 1 : 0; + Stream_Write_UINT8(s, body); + break; + + case SPI_SETSCREENSAVESECURE: + body = sysparam->setScreenSaveSecure ? 1 : 0; + Stream_Write_UINT8(s, body); + break; + + default: + return ERROR_INVALID_PARAMETER; + } + + return error; +} + +BOOL rail_is_extended_spi_supported(UINT32 channelFlags) +{ + return channelFlags & TS_RAIL_ORDER_HANDSHAKE_EX_FLAGS_EXTENDED_SPI_SUPPORTED; +} diff --git a/channels/rail/rail_common.h b/channels/rail/rail_common.h index fe1bc02..6d411eb 100644 --- a/channels/rail/rail_common.h +++ b/channels/rail/rail_common.h @@ -26,25 +26,36 @@ #include -extern const char* const RAIL_ORDER_TYPE_STRINGS[]; +const char* rail_get_order_type_string(BYTE orderType); -#define RAIL_PDU_HEADER_LENGTH 4 +#define RAIL_PDU_HEADER_LENGTH 4 /* Fixed length of PDUs, excluding variable lengths */ -#define RAIL_HANDSHAKE_ORDER_LENGTH 4 /* fixed */ -#define RAIL_HANDSHAKE_EX_ORDER_LENGTH 8 /* fixed */ -#define RAIL_CLIENT_STATUS_ORDER_LENGTH 4 /* fixed */ -#define RAIL_EXEC_ORDER_LENGTH 8 /* variable */ -#define RAIL_SYSPARAM_ORDER_LENGTH 4 /* variable */ -#define RAIL_ACTIVATE_ORDER_LENGTH 5 /* fixed */ -#define RAIL_SYSMENU_ORDER_LENGTH 8 /* fixed */ -#define RAIL_SYSCOMMAND_ORDER_LENGTH 6 /* fixed */ -#define RAIL_NOTIFY_EVENT_ORDER_LENGTH 12 /* fixed */ -#define RAIL_WINDOW_MOVE_ORDER_LENGTH 12 /* fixed */ -#define RAIL_GET_APPID_REQ_ORDER_LENGTH 4 /* fixed */ -#define RAIL_LANGBAR_INFO_ORDER_LENGTH 4 /* fixed */ - -BOOL rail_string_to_unicode_string(const char* string, RAIL_UNICODE_STRING* unicode_string); +#define RAIL_HANDSHAKE_ORDER_LENGTH 4 /* fixed */ +#define RAIL_HANDSHAKE_EX_ORDER_LENGTH 8 /* fixed */ +#define RAIL_CLIENT_STATUS_ORDER_LENGTH 4 /* fixed */ +#define RAIL_EXEC_ORDER_LENGTH 8 /* variable */ +#define RAIL_EXEC_RESULT_ORDER_LENGTH 12 /* variable */ +#define RAIL_SYSPARAM_ORDER_LENGTH 4 /* variable */ +#define RAIL_MINMAXINFO_ORDER_LENGTH 20 /* fixed */ +#define RAIL_LOCALMOVESIZE_ORDER_LENGTH 12 /* fixed */ +#define RAIL_ACTIVATE_ORDER_LENGTH 5 /* fixed */ +#define RAIL_SYSMENU_ORDER_LENGTH 8 /* fixed */ +#define RAIL_SYSCOMMAND_ORDER_LENGTH 6 /* fixed */ +#define RAIL_NOTIFY_EVENT_ORDER_LENGTH 12 /* fixed */ +#define RAIL_WINDOW_MOVE_ORDER_LENGTH 12 /* fixed */ +#define RAIL_SNAP_ARRANGE_ORDER_LENGTH 12 /* fixed */ +#define RAIL_GET_APPID_REQ_ORDER_LENGTH 4 /* fixed */ +#define RAIL_LANGBAR_INFO_ORDER_LENGTH 4 /* fixed */ +#define RAIL_LANGUAGEIME_INFO_ORDER_LENGTH 42 /* fixed */ +#define RAIL_COMPARTMENT_INFO_ORDER_LENGTH 16 /* fixed */ +#define RAIL_CLOAK_ORDER_LENGTH 5 /* fixed */ +#define RAIL_TASKBAR_INFO_ORDER_LENGTH 12 /* fixed */ +#define RAIL_Z_ORDER_SYNC_ORDER_LENGTH 4 /* fixed */ +#define RAIL_POWER_DISPLAY_REQUEST_ORDER_LENGTH 4 /* fixed */ +#define RAIL_GET_APPID_RESP_ORDER_LENGTH 524 /* fixed */ +#define RAIL_GET_APPID_RESP_EX_ORDER_LENGTH 1048 /* fixed */ + UINT rail_read_handshake_order(wStream* s, RAIL_HANDSHAKE_ORDER* handshake); void rail_write_handshake_order(wStream* s, const RAIL_HANDSHAKE_ORDER* handshake); UINT rail_read_handshake_ex_order(wStream* s, RAIL_HANDSHAKE_EX_ORDER* handshakeEx); @@ -54,4 +65,12 @@ wStream* rail_pdu_init(size_t length); UINT rail_read_pdu_header(wStream* s, UINT16* orderType, UINT16* orderLength); void rail_write_pdu_header(wStream* s, UINT16 orderType, UINT16 orderLength); +UINT rail_write_unicode_string(wStream* s, const RAIL_UNICODE_STRING* unicode_string); +UINT rail_write_unicode_string_value(wStream* s, const RAIL_UNICODE_STRING* unicode_string); + +UINT rail_read_sysparam_order(wStream* s, RAIL_SYSPARAM_ORDER* sysparam, BOOL extendedSpiSupported); +UINT rail_write_sysparam_order(wStream* s, const RAIL_SYSPARAM_ORDER* sysparam, + BOOL extendedSpiSupported); +BOOL rail_is_extended_spi_supported(UINT32 channelsFlags); + #endif /* FREERDP_CHANNEL_RAIL_COMMON_H */ diff --git a/channels/rail/server/CMakeLists.txt b/channels/rail/server/CMakeLists.txt new file mode 100644 index 0000000..c7f1c7a --- /dev/null +++ b/channels/rail/server/CMakeLists.txt @@ -0,0 +1,32 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2019 Mati Shabtay +# +# 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_server("rail") + +set(${MODULE_PREFIX}_SRCS + ../rail_common.c + ../rail_common.h + rail_main.c + rail_main.h) + +include_directories(..) + +add_channel_server_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} FALSE "VirtualChannelEntryEx") + +target_link_libraries(${MODULE_NAME} freerdp) + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Server") diff --git a/channels/rail/server/rail_main.c b/channels/rail/server/rail_main.c new file mode 100644 index 0000000..18a7072 --- /dev/null +++ b/channels/rail/server/rail_main.c @@ -0,0 +1,1675 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * RAIL Virtual Channel Plugin + * + * Copyright 2019 Mati Shabtay + * + + * 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 +#include + +#include + +#include +#include +#include +#include + +#include "rail_main.h" + +#define TAG CHANNELS_TAG("rail.server") + +/** + * Sends a single rail PDU on the channel + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_send(RailServerContext* context, wStream* s, ULONG length) +{ + UINT status = CHANNEL_RC_OK; + ULONG written; + + if (!context) + return CHANNEL_RC_BAD_INIT_HANDLE; + + if (!WTSVirtualChannelWrite(context->priv->rail_channel, (PCHAR)Stream_Buffer(s), length, + &written)) + { + WLog_ERR(TAG, "WTSVirtualChannelWrite failed!"); + status = ERROR_INTERNAL_ERROR; + } + + return status; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +UINT rail_send_pdu(RailServerContext* context, wStream* s, UINT16 orderType) +{ + UINT16 orderLength; + + if (!context || !s) + return ERROR_INVALID_PARAMETER; + + orderLength = (UINT16)Stream_GetPosition(s); + Stream_SetPosition(s, 0); + rail_write_pdu_header(s, orderType, orderLength); + Stream_SetPosition(s, orderLength); + WLog_DBG(TAG, "Sending %s PDU, length: %" PRIu16 "", rail_get_order_type_string(orderType), + orderLength); + return rail_send(context, s, orderLength); +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_write_local_move_size_order(wStream* s, + const RAIL_LOCALMOVESIZE_ORDER* localMoveSize) +{ + if (!s || !localMoveSize) + return ERROR_INVALID_PARAMETER; + + Stream_Write_UINT32(s, localMoveSize->windowId); /* WindowId (4 bytes) */ + Stream_Write_UINT16(s, localMoveSize->isMoveSizeStart ? 1 : 0); /* IsMoveSizeStart (2 bytes) */ + Stream_Write_UINT16(s, localMoveSize->moveSizeType); /* MoveSizeType (2 bytes) */ + Stream_Write_UINT16(s, localMoveSize->posX); /* PosX (2 bytes) */ + Stream_Write_UINT16(s, localMoveSize->posY); /* PosY (2 bytes) */ + return ERROR_SUCCESS; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_write_min_max_info_order(wStream* s, const RAIL_MINMAXINFO_ORDER* minMaxInfo) +{ + if (!s || !minMaxInfo) + return ERROR_INVALID_PARAMETER; + + Stream_Write_UINT32(s, minMaxInfo->windowId); /* WindowId (4 bytes) */ + Stream_Write_INT16(s, minMaxInfo->maxWidth); /* MaxWidth (2 bytes) */ + Stream_Write_INT16(s, minMaxInfo->maxHeight); /* MaxHeight (2 bytes) */ + Stream_Write_INT16(s, minMaxInfo->maxPosX); /* MaxPosX (2 bytes) */ + Stream_Write_INT16(s, minMaxInfo->maxPosY); /* MaxPosY (2 bytes) */ + Stream_Write_INT16(s, minMaxInfo->minTrackWidth); /* MinTrackWidth (2 bytes) */ + Stream_Write_INT16(s, minMaxInfo->minTrackHeight); /* MinTrackHeight (2 bytes) */ + Stream_Write_INT16(s, minMaxInfo->maxTrackWidth); /* MaxTrackWidth (2 bytes) */ + Stream_Write_INT16(s, minMaxInfo->maxTrackHeight); /* MaxTrackHeight (2 bytes) */ + return ERROR_SUCCESS; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_write_taskbar_info_order(wStream* s, const RAIL_TASKBAR_INFO_ORDER* taskbarInfo) +{ + if (!s || !taskbarInfo) + return ERROR_INVALID_PARAMETER; + + Stream_Write_UINT32(s, taskbarInfo->TaskbarMessage); /* TaskbarMessage (4 bytes) */ + Stream_Write_UINT32(s, taskbarInfo->WindowIdTab); /* WindowIdTab (4 bytes) */ + Stream_Write_UINT32(s, taskbarInfo->Body); /* Body (4 bytes) */ + return ERROR_SUCCESS; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_write_langbar_info_order(wStream* s, const RAIL_LANGBAR_INFO_ORDER* langbarInfo) +{ + if (!s || !langbarInfo) + return ERROR_INVALID_PARAMETER; + + Stream_Write_UINT32(s, langbarInfo->languageBarStatus); /* LanguageBarStatus (4 bytes) */ + return ERROR_SUCCESS; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_write_exec_result_order(wStream* s, const RAIL_EXEC_RESULT_ORDER* execResult) +{ + if (!s || !execResult) + return ERROR_INVALID_PARAMETER; + + if (execResult->exeOrFile.length > 520 || execResult->exeOrFile.length < 1) + return ERROR_INVALID_DATA; + + Stream_Write_UINT16(s, execResult->flags); /* Flags (2 bytes) */ + Stream_Write_UINT16(s, execResult->execResult); /* ExecResult (2 bytes) */ + Stream_Write_UINT32(s, execResult->rawResult); /* RawResult (4 bytes) */ + Stream_Write_UINT16(s, 0); /* Padding (2 bytes) */ + Stream_Write_UINT16(s, execResult->exeOrFile.length); /* ExeOrFileLength (2 bytes) */ + Stream_Write(s, execResult->exeOrFile.string, + execResult->exeOrFile.length); /* ExeOrFile (variable) */ + return ERROR_SUCCESS; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_write_z_order_sync_order(wStream* s, const RAIL_ZORDER_SYNC* zOrderSync) +{ + if (!s || !zOrderSync) + return ERROR_INVALID_PARAMETER; + + Stream_Write_UINT32(s, zOrderSync->windowIdMarker); /* WindowIdMarker (4 bytes) */ + return ERROR_SUCCESS; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_write_cloak_order(wStream* s, const RAIL_CLOAK* cloak) +{ + if (!s || !cloak) + return ERROR_INVALID_PARAMETER; + + Stream_Write_UINT32(s, cloak->windowId); /* WindowId (4 bytes) */ + Stream_Write_UINT8(s, cloak->cloak ? 1 : 0); /* Cloaked (1 byte) */ + return ERROR_SUCCESS; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT +rail_write_power_display_request_order(wStream* s, + const RAIL_POWER_DISPLAY_REQUEST* powerDisplayRequest) +{ + if (!s || !powerDisplayRequest) + return ERROR_INVALID_PARAMETER; + + Stream_Write_UINT32(s, powerDisplayRequest->active ? 1 : 0); /* Active (4 bytes) */ + return ERROR_SUCCESS; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_write_get_app_id_resp_order(wStream* s, + const RAIL_GET_APPID_RESP_ORDER* getAppidResp) +{ + if (!s || !getAppidResp) + return ERROR_INVALID_PARAMETER; + + Stream_Write_UINT32(s, getAppidResp->windowId); /* WindowId (4 bytes) */ + Stream_Write_UTF16_String( + s, getAppidResp->applicationId, + ARRAYSIZE(getAppidResp->applicationId)); /* ApplicationId (512 bytes) */ + return ERROR_SUCCESS; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_write_get_appid_resp_ex_order(wStream* s, + const RAIL_GET_APPID_RESP_EX* getAppidRespEx) +{ + if (!s || !getAppidRespEx) + return ERROR_INVALID_PARAMETER; + + Stream_Write_UINT32(s, getAppidRespEx->windowID); /* WindowId (4 bytes) */ + Stream_Write_UTF16_String( + s, getAppidRespEx->applicationID, + ARRAYSIZE(getAppidRespEx->applicationID)); /* ApplicationId (520 bytes) */ + Stream_Write_UINT32(s, getAppidRespEx->processId); /* ProcessId (4 bytes) */ + Stream_Write_UTF16_String( + s, getAppidRespEx->processImageName, + ARRAYSIZE(getAppidRespEx->processImageName)); /* ProcessImageName (520 bytes) */ + return ERROR_SUCCESS; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_send_server_handshake(RailServerContext* context, + const RAIL_HANDSHAKE_ORDER* handshake) +{ + wStream* s; + UINT error; + + if (!context || !handshake) + return ERROR_INVALID_PARAMETER; + + s = rail_pdu_init(RAIL_HANDSHAKE_ORDER_LENGTH); + + if (!s) + { + WLog_ERR(TAG, "rail_pdu_init failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + rail_write_handshake_order(s, handshake); + error = rail_send_pdu(context, s, TS_RAIL_ORDER_HANDSHAKE); + Stream_Free(s, TRUE); + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_send_server_handshake_ex(RailServerContext* context, + const RAIL_HANDSHAKE_EX_ORDER* handshakeEx) +{ + wStream* s; + UINT error; + + if (!context || !handshakeEx || !context->priv) + return ERROR_INVALID_PARAMETER; + + /* Save channel flags to context */ + context->priv->channelFlags = handshakeEx->railHandshakeFlags; + s = rail_pdu_init(RAIL_HANDSHAKE_EX_ORDER_LENGTH); + + if (!s) + { + WLog_ERR(TAG, "rail_pdu_init failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + rail_write_handshake_ex_order(s, handshakeEx); + error = rail_send_pdu(context, s, TS_RAIL_ORDER_HANDSHAKE_EX); + Stream_Free(s, TRUE); + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_send_server_sysparam(RailServerContext* context, + const RAIL_SYSPARAM_ORDER* sysparam) +{ + wStream* s; + UINT error; + RailServerPrivate* priv; + BOOL extendedSpiSupported; + + if (!context || !sysparam) + return ERROR_INVALID_PARAMETER; + + priv = context->priv; + + if (!priv) + return ERROR_INVALID_PARAMETER; + + extendedSpiSupported = rail_is_extended_spi_supported(context->priv->channelFlags); + s = rail_pdu_init(RAIL_SYSPARAM_ORDER_LENGTH); + + if (!s) + { + WLog_ERR(TAG, "rail_pdu_init failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + rail_write_sysparam_order(s, sysparam, extendedSpiSupported); + error = rail_send_pdu(context, s, TS_RAIL_ORDER_SYSPARAM); + Stream_Free(s, TRUE); + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_send_server_local_move_size(RailServerContext* context, + const RAIL_LOCALMOVESIZE_ORDER* localMoveSize) +{ + wStream* s; + UINT error; + + if (!context || !localMoveSize) + return ERROR_INVALID_PARAMETER; + + s = rail_pdu_init(RAIL_LOCALMOVESIZE_ORDER_LENGTH); + + if (!s) + { + WLog_ERR(TAG, "rail_pdu_init failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + rail_write_local_move_size_order(s, localMoveSize); + error = rail_send_pdu(context, s, TS_RAIL_ORDER_LOCALMOVESIZE); + Stream_Free(s, TRUE); + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_send_server_min_max_info(RailServerContext* context, + const RAIL_MINMAXINFO_ORDER* minMaxInfo) +{ + wStream* s; + UINT error; + + if (!context || !minMaxInfo) + return ERROR_INVALID_PARAMETER; + + s = rail_pdu_init(RAIL_MINMAXINFO_ORDER_LENGTH); + + if (!s) + { + WLog_ERR(TAG, "rail_pdu_init failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + rail_write_min_max_info_order(s, minMaxInfo); + error = rail_send_pdu(context, s, TS_RAIL_ORDER_MINMAXINFO); + Stream_Free(s, TRUE); + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_send_server_taskbar_info(RailServerContext* context, + const RAIL_TASKBAR_INFO_ORDER* taskbarInfo) +{ + wStream* s; + UINT error; + + if (!context || !taskbarInfo) + return ERROR_INVALID_PARAMETER; + + s = rail_pdu_init(RAIL_TASKBAR_INFO_ORDER_LENGTH); + + if (!s) + { + WLog_ERR(TAG, "rail_pdu_init failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + rail_write_taskbar_info_order(s, taskbarInfo); + error = rail_send_pdu(context, s, TS_RAIL_ORDER_TASKBARINFO); + Stream_Free(s, TRUE); + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_send_server_langbar_info(RailServerContext* context, + const RAIL_LANGBAR_INFO_ORDER* langbarInfo) +{ + wStream* s; + UINT error; + + if (!context || !langbarInfo) + return ERROR_INVALID_PARAMETER; + + s = rail_pdu_init(RAIL_LANGBAR_INFO_ORDER_LENGTH); + + if (!s) + { + WLog_ERR(TAG, "rail_pdu_init failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + rail_write_langbar_info_order(s, langbarInfo); + error = rail_send_pdu(context, s, TS_RAIL_ORDER_LANGBARINFO); + Stream_Free(s, TRUE); + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_send_server_exec_result(RailServerContext* context, + const RAIL_EXEC_RESULT_ORDER* execResult) +{ + wStream* s; + UINT error; + + if (!context || !execResult) + return ERROR_INVALID_PARAMETER; + + s = rail_pdu_init(RAIL_EXEC_RESULT_ORDER_LENGTH + execResult->exeOrFile.length); + + if (!s) + { + WLog_ERR(TAG, "rail_pdu_init failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + rail_write_exec_result_order(s, execResult); + error = rail_send_pdu(context, s, TS_RAIL_ORDER_EXEC_RESULT); + Stream_Free(s, TRUE); + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_send_server_z_order_sync(RailServerContext* context, + const RAIL_ZORDER_SYNC* zOrderSync) +{ + wStream* s; + UINT error; + + if (!context || !zOrderSync) + return ERROR_INVALID_PARAMETER; + + s = rail_pdu_init(RAIL_Z_ORDER_SYNC_ORDER_LENGTH); + + if (!s) + { + WLog_ERR(TAG, "rail_pdu_init failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + rail_write_z_order_sync_order(s, zOrderSync); + error = rail_send_pdu(context, s, TS_RAIL_ORDER_ZORDER_SYNC); + Stream_Free(s, TRUE); + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_send_server_cloak(RailServerContext* context, const RAIL_CLOAK* cloak) +{ + wStream* s; + UINT error; + + if (!context || !cloak) + return ERROR_INVALID_PARAMETER; + + s = rail_pdu_init(RAIL_CLOAK_ORDER_LENGTH); + + if (!s) + { + WLog_ERR(TAG, "rail_pdu_init failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + rail_write_cloak_order(s, cloak); + error = rail_send_pdu(context, s, TS_RAIL_ORDER_CLOAK); + Stream_Free(s, TRUE); + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT +rail_send_server_power_display_request(RailServerContext* context, + const RAIL_POWER_DISPLAY_REQUEST* powerDisplayRequest) +{ + wStream* s; + UINT error; + + if (!context || !powerDisplayRequest) + return ERROR_INVALID_PARAMETER; + + s = rail_pdu_init(RAIL_POWER_DISPLAY_REQUEST_ORDER_LENGTH); + + if (!s) + { + WLog_ERR(TAG, "rail_pdu_init failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + rail_write_power_display_request_order(s, powerDisplayRequest); + error = rail_send_pdu(context, s, TS_RAIL_ORDER_POWER_DISPLAY_REQUEST); + Stream_Free(s, TRUE); + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error coie + */ +static UINT rail_send_server_get_app_id_resp(RailServerContext* context, + const RAIL_GET_APPID_RESP_ORDER* getAppidResp) +{ + wStream* s; + UINT error; + + if (!context || !getAppidResp) + return ERROR_INVALID_PARAMETER; + + s = rail_pdu_init(RAIL_GET_APPID_RESP_ORDER_LENGTH); + + if (!s) + { + WLog_ERR(TAG, "rail_pdu_init failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + rail_write_get_app_id_resp_order(s, getAppidResp); + error = rail_send_pdu(context, s, TS_RAIL_ORDER_GET_APPID_RESP); + Stream_Free(s, TRUE); + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_send_server_get_appid_resp_ex(RailServerContext* context, + const RAIL_GET_APPID_RESP_EX* getAppidRespEx) +{ + wStream* s; + UINT error; + + if (!context || !getAppidRespEx) + return ERROR_INVALID_PARAMETER; + + s = rail_pdu_init(RAIL_GET_APPID_RESP_EX_ORDER_LENGTH); + + if (!s) + { + WLog_ERR(TAG, "rail_pdu_init failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + rail_write_get_appid_resp_ex_order(s, getAppidRespEx); + error = rail_send_pdu(context, s, TS_RAIL_ORDER_GET_APPID_RESP_EX); + Stream_Free(s, TRUE); + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_read_client_status_order(wStream* s, RAIL_CLIENT_STATUS_ORDER* clientStatus) +{ + if (Stream_GetRemainingLength(s) < RAIL_CLIENT_STATUS_ORDER_LENGTH) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, clientStatus->flags); /* Flags (4 bytes) */ + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_read_exec_order(wStream* s, RAIL_EXEC_ORDER* exec) +{ + RAIL_EXEC_ORDER order = { 0 }; + UINT16 exeLen, workLen, argLen; + + if (Stream_GetRemainingLength(s) < RAIL_EXEC_ORDER_LENGTH) + return ERROR_INVALID_DATA; + + Stream_Read_UINT16(s, exec->flags); /* Flags (2 bytes) */ + Stream_Read_UINT16(s, exeLen); /* ExeOrFileLength (2 bytes) */ + Stream_Read_UINT16(s, workLen); /* WorkingDirLength (2 bytes) */ + Stream_Read_UINT16(s, argLen); /* ArgumentsLength (2 bytes) */ + + if (Stream_GetRemainingLength(s) < (size_t)exeLen + workLen + argLen) + return ERROR_INVALID_DATA; + + { + const int len = exeLen / sizeof(WCHAR); + int rc; + const WCHAR* str = (const WCHAR*)Stream_Pointer(s); + rc = ConvertFromUnicode(CP_UTF8, 0, str, len, &exec->RemoteApplicationProgram, 0, NULL, + NULL); + if (rc != len) + goto fail; + Stream_Seek(s, exeLen); + } + { + const int len = workLen / sizeof(WCHAR); + int rc; + + const WCHAR* str = (const WCHAR*)Stream_Pointer(s); + rc = ConvertFromUnicode(CP_UTF8, 0, str, len, &exec->RemoteApplicationProgram, 0, NULL, + NULL); + if (rc != len) + goto fail; + Stream_Seek(s, workLen); + } + { + const int len = argLen / sizeof(WCHAR); + int rc; + const WCHAR* str = (const WCHAR*)Stream_Pointer(s); + rc = ConvertFromUnicode(CP_UTF8, 0, str, len, &exec->RemoteApplicationProgram, 0, NULL, + NULL); + if (rc != len) + goto fail; + Stream_Seek(s, argLen); + } + + return CHANNEL_RC_OK; +fail: + free(exec->RemoteApplicationProgram); + free(exec->RemoteApplicationArguments); + free(exec->RemoteApplicationWorkingDir); + *exec = order; + return ERROR_INTERNAL_ERROR; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_read_activate_order(wStream* s, RAIL_ACTIVATE_ORDER* activate) +{ + BYTE enabled; + + if (Stream_GetRemainingLength(s) < RAIL_ACTIVATE_ORDER_LENGTH) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, activate->windowId); /* WindowId (4 bytes) */ + Stream_Read_UINT8(s, enabled); /* Enabled (1 byte) */ + activate->enabled = (enabled != 0) ? TRUE : FALSE; + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_read_sysmenu_order(wStream* s, RAIL_SYSMENU_ORDER* sysmenu) +{ + if (Stream_GetRemainingLength(s) < RAIL_SYSMENU_ORDER_LENGTH) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, sysmenu->windowId); /* WindowId (4 bytes) */ + Stream_Read_INT16(s, sysmenu->left); /* Left (2 bytes) */ + Stream_Read_INT16(s, sysmenu->top); /* Top (2 bytes) */ + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_read_syscommand_order(wStream* s, RAIL_SYSCOMMAND_ORDER* syscommand) +{ + if (Stream_GetRemainingLength(s) < RAIL_SYSCOMMAND_ORDER_LENGTH) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, syscommand->windowId); /* WindowId (4 bytes) */ + Stream_Read_UINT16(s, syscommand->command); /* Command (2 bytes) */ + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_read_notify_event_order(wStream* s, RAIL_NOTIFY_EVENT_ORDER* notifyEvent) +{ + if (Stream_GetRemainingLength(s) < RAIL_NOTIFY_EVENT_ORDER_LENGTH) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, notifyEvent->windowId); /* WindowId (4 bytes) */ + Stream_Read_UINT32(s, notifyEvent->notifyIconId); /* NotifyIconId (4 bytes) */ + Stream_Read_UINT32(s, notifyEvent->message); /* Message (4 bytes) */ + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_read_get_appid_req_order(wStream* s, RAIL_GET_APPID_REQ_ORDER* getAppidReq) +{ + if (Stream_GetRemainingLength(s) < RAIL_GET_APPID_REQ_ORDER_LENGTH) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, getAppidReq->windowId); /* WindowId (4 bytes) */ + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_read_window_move_order(wStream* s, RAIL_WINDOW_MOVE_ORDER* windowMove) +{ + if (Stream_GetRemainingLength(s) < RAIL_WINDOW_MOVE_ORDER_LENGTH) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, windowMove->windowId); /* WindowId (4 bytes) */ + Stream_Read_INT16(s, windowMove->left); /* Left (2 bytes) */ + Stream_Read_INT16(s, windowMove->top); /* Top (2 bytes) */ + Stream_Read_INT16(s, windowMove->right); /* Right (2 bytes) */ + Stream_Read_INT16(s, windowMove->bottom); /* Bottom (2 bytes) */ + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_read_snap_arange_order(wStream* s, RAIL_SNAP_ARRANGE* snapArrange) +{ + if (Stream_GetRemainingLength(s) < RAIL_SNAP_ARRANGE_ORDER_LENGTH) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, snapArrange->windowId); /* WindowId (4 bytes) */ + Stream_Read_INT16(s, snapArrange->left); /* Left (2 bytes) */ + Stream_Read_INT16(s, snapArrange->top); /* Top (2 bytes) */ + Stream_Read_INT16(s, snapArrange->right); /* Right (2 bytes) */ + Stream_Read_INT16(s, snapArrange->bottom); /* Bottom (2 bytes) */ + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_read_langbar_info_order(wStream* s, RAIL_LANGBAR_INFO_ORDER* langbarInfo) +{ + if (Stream_GetRemainingLength(s) < RAIL_LANGBAR_INFO_ORDER_LENGTH) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, langbarInfo->languageBarStatus); /* LanguageBarStatus (4 bytes) */ + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_read_language_ime_info_order(wStream* s, + RAIL_LANGUAGEIME_INFO_ORDER* languageImeInfo) +{ + if (Stream_GetRemainingLength(s) < RAIL_LANGUAGEIME_INFO_ORDER_LENGTH) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, languageImeInfo->ProfileType); /* ProfileType (4 bytes) */ + Stream_Read_UINT16(s, languageImeInfo->LanguageID); /* LanguageID (2 bytes) */ + Stream_Read( + s, &languageImeInfo->LanguageProfileCLSID, + sizeof(languageImeInfo->LanguageProfileCLSID)); /* LanguageProfileCLSID (16 bytes) */ + Stream_Read(s, &languageImeInfo->ProfileGUID, + sizeof(languageImeInfo->ProfileGUID)); /* ProfileGUID (16 bytes) */ + Stream_Read_UINT32(s, languageImeInfo->KeyboardLayout); /* KeyboardLayout (4 bytes) */ + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_read_compartment_info_order(wStream* s, + RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo) +{ + if (Stream_GetRemainingLength(s) < RAIL_COMPARTMENT_INFO_ORDER_LENGTH) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, compartmentInfo->ImeState); /* ImeState (4 bytes) */ + Stream_Read_UINT32(s, compartmentInfo->ImeConvMode); /* ImeConvMode (4 bytes) */ + Stream_Read_UINT32(s, compartmentInfo->ImeSentenceMode); /* ImeSentenceMode (4 bytes) */ + Stream_Read_UINT32(s, compartmentInfo->KanaMode); /* KANAMode (4 bytes) */ + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_read_cloak_order(wStream* s, RAIL_CLOAK* cloak) +{ + BYTE cloaked; + + if (Stream_GetRemainingLength(s) < RAIL_CLOAK_ORDER_LENGTH) + return ERROR_INVALID_DATA; + + Stream_Read_UINT32(s, cloak->windowId); /* WindowId (4 bytes) */ + Stream_Read_UINT8(s, cloaked); /* Cloaked (1 byte) */ + cloak->cloak = (cloaked != 0) ? TRUE : FALSE; + return CHANNEL_RC_OK; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_recv_client_handshake_order(RailServerContext* context, + RAIL_HANDSHAKE_ORDER* handshake, wStream* s) +{ + UINT error; + + if (!context || !handshake || !s) + return ERROR_INVALID_PARAMETER; + + if ((error = rail_read_handshake_order(s, handshake))) + { + WLog_ERR(TAG, "rail_read_handshake_order failed with error %" PRIu32 "!", error); + return error; + } + + IFCALLRET(context->ClientHandshake, error, context, handshake); + + if (error) + WLog_ERR(TAG, "context.ClientHandshake failed with error %" PRIu32 "", error); + + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_recv_client_client_status_order(RailServerContext* context, + RAIL_CLIENT_STATUS_ORDER* clientStatus, wStream* s) +{ + UINT error; + + if (!context || !clientStatus || !s) + return ERROR_INVALID_PARAMETER; + + if ((error = rail_read_client_status_order(s, clientStatus))) + { + WLog_ERR(TAG, "rail_read_client_status_order failed with error %" PRIu32 "!", error); + return error; + } + + IFCALLRET(context->ClientClientStatus, error, context, clientStatus); + + if (error) + WLog_ERR(TAG, "context.ClientClientStatus failed with error %" PRIu32 "", error); + + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_recv_client_exec_order(RailServerContext* context, wStream* s) +{ + UINT error; + RAIL_EXEC_ORDER exec = { 0 }; + + if (!context || !s) + return ERROR_INVALID_PARAMETER; + + if ((error = rail_read_exec_order(s, &exec))) + { + WLog_ERR(TAG, "rail_read_client_status_order failed with error %" PRIu32 "!", error); + return error; + } + + IFCALLRET(context->ClientExec, error, context, &exec); + + if (error) + WLog_ERR(TAG, "context.Exec failed with error %" PRIu32 "", error); + + free(exec.RemoteApplicationProgram); + free(exec.RemoteApplicationArguments); + free(exec.RemoteApplicationWorkingDir); + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_recv_client_sysparam_order(RailServerContext* context, + RAIL_SYSPARAM_ORDER* sysparam, wStream* s) +{ + UINT error; + BOOL extendedSpiSupported; + + if (!context || !sysparam || !s) + return ERROR_INVALID_PARAMETER; + + extendedSpiSupported = rail_is_extended_spi_supported(context->priv->channelFlags); + if ((error = rail_read_sysparam_order(s, sysparam, extendedSpiSupported))) + { + WLog_ERR(TAG, "rail_read_sysparam_order failed with error %" PRIu32 "!", error); + return error; + } + + IFCALLRET(context->ClientSysparam, error, context, sysparam); + + if (error) + WLog_ERR(TAG, "context.ClientSysparam failed with error %" PRIu32 "", error); + + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_recv_client_activate_order(RailServerContext* context, + RAIL_ACTIVATE_ORDER* activate, wStream* s) +{ + UINT error; + + if (!context || !activate || !s) + return ERROR_INVALID_PARAMETER; + + if ((error = rail_read_activate_order(s, activate))) + { + WLog_ERR(TAG, "rail_read_activate_order failed with error %" PRIu32 "!", error); + return error; + } + + IFCALLRET(context->ClientActivate, error, context, activate); + + if (error) + WLog_ERR(TAG, "context.ClientActivate failed with error %" PRIu32 "", error); + + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_recv_client_sysmenu_order(RailServerContext* context, RAIL_SYSMENU_ORDER* sysmenu, + wStream* s) +{ + UINT error; + + if (!context || !sysmenu || !s) + return ERROR_INVALID_PARAMETER; + + if ((error = rail_read_sysmenu_order(s, sysmenu))) + { + WLog_ERR(TAG, "rail_read_sysmenu_order failed with error %" PRIu32 "!", error); + return error; + } + + IFCALLRET(context->ClientSysmenu, error, context, sysmenu); + + if (error) + WLog_ERR(TAG, "context.ClientSysmenu failed with error %" PRIu32 "", error); + + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_recv_client_syscommand_order(RailServerContext* context, + RAIL_SYSCOMMAND_ORDER* syscommand, wStream* s) +{ + UINT error; + + if (!context || !syscommand || !s) + return ERROR_INVALID_PARAMETER; + + if ((error = rail_read_syscommand_order(s, syscommand))) + { + WLog_ERR(TAG, "rail_read_syscommand_order failed with error %" PRIu32 "!", error); + return error; + } + + IFCALLRET(context->ClientSyscommand, error, context, syscommand); + + if (error) + WLog_ERR(TAG, "context.ClientSyscommand failed with error %" PRIu32 "", error); + + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_recv_client_notify_event_order(RailServerContext* context, + RAIL_NOTIFY_EVENT_ORDER* notifyEvent, wStream* s) +{ + UINT error; + + if (!context || !notifyEvent || !s) + return ERROR_INVALID_PARAMETER; + + if ((error = rail_read_notify_event_order(s, notifyEvent))) + { + WLog_ERR(TAG, "rail_read_notify_event_order failed with error %" PRIu32 "!", error); + return error; + } + + IFCALLRET(context->ClientNotifyEvent, error, context, notifyEvent); + + if (error) + WLog_ERR(TAG, "context.ClientNotifyEvent failed with error %" PRIu32 "", error); + + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_recv_client_window_move_order(RailServerContext* context, + RAIL_WINDOW_MOVE_ORDER* windowMove, wStream* s) +{ + UINT error; + + if (!context || !windowMove || !s) + return ERROR_INVALID_PARAMETER; + + if ((error = rail_read_window_move_order(s, windowMove))) + { + WLog_ERR(TAG, "rail_read_window_move_order failed with error %" PRIu32 "!", error); + return error; + } + + IFCALLRET(context->ClientWindowMove, error, context, windowMove); + + if (error) + WLog_ERR(TAG, "context.ClientWindowMove failed with error %" PRIu32 "", error); + + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_recv_client_snap_arrange_order(RailServerContext* context, + RAIL_SNAP_ARRANGE* snapArrange, wStream* s) +{ + UINT error; + + if (!context || !snapArrange || !s) + return ERROR_INVALID_PARAMETER; + + if ((error = rail_read_snap_arange_order(s, snapArrange))) + { + WLog_ERR(TAG, "rail_read_snap_arange_order failed with error %" PRIu32 "!", error); + return error; + } + + IFCALLRET(context->ClientSnapArrange, error, context, snapArrange); + + if (error) + WLog_ERR(TAG, "context.ClientSnapArrange failed with error %" PRIu32 "", error); + + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_recv_client_get_appid_req_order(RailServerContext* context, + RAIL_GET_APPID_REQ_ORDER* getAppidReq, wStream* s) +{ + UINT error; + + if (!context || !getAppidReq || !s) + return ERROR_INVALID_PARAMETER; + + if ((error = rail_read_get_appid_req_order(s, getAppidReq))) + { + WLog_ERR(TAG, "rail_read_get_appid_req_order failed with error %" PRIu32 "!", error); + return error; + } + + IFCALLRET(context->ClientGetAppidReq, error, context, getAppidReq); + + if (error) + WLog_ERR(TAG, "context.ClientGetAppidReq failed with error %" PRIu32 "", error); + + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_recv_client_langbar_info_order(RailServerContext* context, + RAIL_LANGBAR_INFO_ORDER* langbarInfo, wStream* s) +{ + UINT error; + + if (!context || !langbarInfo || !s) + return ERROR_INVALID_PARAMETER; + + if ((error = rail_read_langbar_info_order(s, langbarInfo))) + { + WLog_ERR(TAG, "rail_read_langbar_info_order failed with error %" PRIu32 "!", error); + return error; + } + + IFCALLRET(context->ClientLangbarInfo, error, context, langbarInfo); + + if (error) + WLog_ERR(TAG, "context.ClientLangbarInfo failed with error %" PRIu32 "", error); + + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_recv_client_language_ime_info_order(RailServerContext* context, + RAIL_LANGUAGEIME_INFO_ORDER* languageImeInfo, + wStream* s) +{ + UINT error; + + if (!context || !languageImeInfo || !s) + return ERROR_INVALID_PARAMETER; + + if ((error = rail_read_language_ime_info_order(s, languageImeInfo))) + { + WLog_ERR(TAG, "rail_read_language_ime_info_order failed with error %" PRIu32 "!", error); + return error; + } + + IFCALLRET(context->ClientLanguageImeInfo, error, context, languageImeInfo); + + if (error) + WLog_ERR(TAG, "context.ClientLanguageImeInfo failed with error %" PRIu32 "", error); + + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_recv_client_compartment_info(RailServerContext* context, + RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo, + wStream* s) +{ + UINT error; + + if (!context || !compartmentInfo || !s) + return ERROR_INVALID_PARAMETER; + + if ((error = rail_read_compartment_info_order(s, compartmentInfo))) + { + WLog_ERR(TAG, "rail_read_compartment_info_order failed with error %" PRIu32 "!", error); + return error; + } + + IFCALLRET(context->ClientCompartmentInfo, error, context, compartmentInfo); + + if (error) + WLog_ERR(TAG, "context.ClientCompartmentInfo failed with error %" PRIu32 "", error); + + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_recv_client_cloak_order(RailServerContext* context, RAIL_CLOAK* cloak, wStream* s) +{ + UINT error; + + if (!context || !cloak || !s) + return ERROR_INVALID_PARAMETER; + + if ((error = rail_read_cloak_order(s, cloak))) + { + WLog_ERR(TAG, "rail_read_cloak_order failed with error %" PRIu32 "!", error); + return error; + } + + IFCALLRET(context->ClientCloak, error, context, cloak); + + if (error) + WLog_ERR(TAG, "context.Cloak failed with error %" PRIu32 "", error); + + return error; +} + +static DWORD WINAPI rail_server_thread(LPVOID arg) +{ + RailServerContext* context = (RailServerContext*)arg; + RailServerPrivate* priv = context->priv; + DWORD status; + DWORD nCount = 0; + HANDLE events[8]; + UINT error = CHANNEL_RC_OK; + events[nCount++] = priv->channelEvent; + events[nCount++] = priv->stopEvent; + + while (TRUE) + { + status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE); + + if (status == WAIT_FAILED) + { + error = GetLastError(); + WLog_ERR(TAG, "WaitForMultipleObjects failed with error %" PRIu32 "!", error); + break; + } + + status = WaitForSingleObject(context->priv->stopEvent, 0); + + if (status == WAIT_FAILED) + { + error = GetLastError(); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error); + break; + } + + if (status == WAIT_OBJECT_0) + break; + + status = WaitForSingleObject(context->priv->channelEvent, 0); + + if (status == WAIT_FAILED) + { + error = GetLastError(); + WLog_ERR( + TAG, + "WaitForSingleObject(context->priv->channelEvent, 0) failed with error %" PRIu32 + "!", + error); + break; + } + + if (status == WAIT_OBJECT_0) + { + if ((error = rail_server_handle_messages(context))) + { + WLog_ERR(TAG, "rail_server_handle_messages failed with error %" PRIu32 "", error); + break; + } + } + } + + if (error && context->rdpcontext) + setChannelError(context->rdpcontext, error, "rail_server_thread reported an error"); + + ExitThread(error); + return error; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rail_server_start(RailServerContext* context) +{ + void* buffer = NULL; + DWORD bytesReturned; + RailServerPrivate* priv = context->priv; + UINT error = ERROR_INTERNAL_ERROR; + priv->rail_channel = + WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, RAIL_SVC_CHANNEL_NAME); + + if (!priv->rail_channel) + { + WLog_ERR(TAG, "WTSVirtualChannelOpen failed!"); + return error; + } + + if (!WTSVirtualChannelQuery(priv->rail_channel, WTSVirtualEventHandle, &buffer, + &bytesReturned) || + (bytesReturned != sizeof(HANDLE))) + { + WLog_ERR(TAG, + "error during WTSVirtualChannelQuery(WTSVirtualEventHandle) or invalid returned " + "size(%" PRIu32 ")", + bytesReturned); + + if (buffer) + WTSFreeMemory(buffer); + + goto out_close; + } + + CopyMemory(&priv->channelEvent, buffer, sizeof(HANDLE)); + WTSFreeMemory(buffer); + context->priv->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (!context->priv->stopEvent) + { + WLog_ERR(TAG, "CreateEvent failed!"); + goto out_close; + } + + context->priv->thread = CreateThread(NULL, 0, rail_server_thread, (void*)context, 0, NULL); + + if (!context->priv->thread) + { + WLog_ERR(TAG, "CreateThread failed!"); + goto out_stop_event; + } + + return CHANNEL_RC_OK; +out_stop_event: + CloseHandle(context->priv->stopEvent); + context->priv->stopEvent = NULL; +out_close: + WTSVirtualChannelClose(context->priv->rail_channel); + context->priv->rail_channel = NULL; + return error; +} + +static BOOL rail_server_stop(RailServerContext* context) +{ + RailServerPrivate* priv = (RailServerPrivate*)context->priv; + + if (priv->thread) + { + SetEvent(priv->stopEvent); + + if (WaitForSingleObject(priv->thread, INFINITE) == WAIT_FAILED) + { + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "", GetLastError()); + return FALSE; + } + + CloseHandle(priv->thread); + CloseHandle(priv->stopEvent); + priv->thread = NULL; + priv->stopEvent = NULL; + } + + if (priv->rail_channel) + { + WTSVirtualChannelClose(priv->rail_channel); + priv->rail_channel = NULL; + } + + priv->channelEvent = NULL; + return TRUE; +} + +RailServerContext* rail_server_context_new(HANDLE vcm) +{ + RailServerContext* context; + RailServerPrivate* priv; + context = (RailServerContext*)calloc(1, sizeof(RailServerContext)); + + if (!context) + { + WLog_ERR(TAG, "calloc failed!"); + return NULL; + } + + context->vcm = vcm; + context->Start = rail_server_start; + context->Stop = rail_server_stop; + context->ServerHandshake = rail_send_server_handshake; + context->ServerHandshakeEx = rail_send_server_handshake_ex; + context->ServerSysparam = rail_send_server_sysparam; + context->ServerLocalMoveSize = rail_send_server_local_move_size; + context->ServerMinMaxInfo = rail_send_server_min_max_info; + context->ServerTaskbarInfo = rail_send_server_taskbar_info; + context->ServerLangbarInfo = rail_send_server_langbar_info; + context->ServerExecResult = rail_send_server_exec_result; + context->ServerGetAppidResp = rail_send_server_get_app_id_resp; + context->ServerZOrderSync = rail_send_server_z_order_sync; + context->ServerCloak = rail_send_server_cloak; + context->ServerPowerDisplayRequest = rail_send_server_power_display_request; + context->ServerGetAppidRespEx = rail_send_server_get_appid_resp_ex; + context->priv = priv = (RailServerPrivate*)calloc(1, sizeof(RailServerPrivate)); + + if (!priv) + { + WLog_ERR(TAG, "calloc failed!"); + goto out_free; + } + + /* Create shared input stream */ + priv->input_stream = Stream_New(NULL, 4096); + + if (!priv->input_stream) + { + WLog_ERR(TAG, "Stream_New failed!"); + goto out_free_priv; + } + + return context; +out_free_priv: + free(context->priv); +out_free: + free(context); + return NULL; +} + +void rail_server_context_free(RailServerContext* context) +{ + if (context->priv) + Stream_Free(context->priv->input_stream, TRUE); + + free(context->priv); + free(context); +} + +UINT rail_server_handle_messages(RailServerContext* context) +{ + UINT status = CHANNEL_RC_OK; + DWORD bytesReturned; + UINT16 orderType; + UINT16 orderLength; + RailServerPrivate* priv = context->priv; + wStream* s = priv->input_stream; + + /* Read header */ + if (!Stream_EnsureRemainingCapacity(s, RAIL_PDU_HEADER_LENGTH)) + { + WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed, RAIL_PDU_HEADER_LENGTH"); + return CHANNEL_RC_NO_MEMORY; + } + + if (!WTSVirtualChannelRead(priv->rail_channel, 0, (PCHAR)Stream_Pointer(s), + RAIL_PDU_HEADER_LENGTH, &bytesReturned)) + { + if (GetLastError() == ERROR_NO_DATA) + return ERROR_NO_DATA; + + WLog_ERR(TAG, "channel connection closed"); + return ERROR_INTERNAL_ERROR; + } + + /* Parse header */ + if ((status = rail_read_pdu_header(s, &orderType, &orderLength)) != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "rail_read_pdu_header failed with error %" PRIu32 "!", status); + return status; + } + + if (!Stream_EnsureRemainingCapacity(s, orderLength - RAIL_PDU_HEADER_LENGTH)) + { + WLog_ERR(TAG, + "Stream_EnsureRemainingCapacity failed, orderLength - RAIL_PDU_HEADER_LENGTH"); + return CHANNEL_RC_NO_MEMORY; + } + + /* Read body */ + if (!WTSVirtualChannelRead(priv->rail_channel, 0, (PCHAR)Stream_Pointer(s), + orderLength - RAIL_PDU_HEADER_LENGTH, &bytesReturned)) + { + if (GetLastError() == ERROR_NO_DATA) + return ERROR_NO_DATA; + + WLog_ERR(TAG, "channel connection closed"); + return ERROR_INTERNAL_ERROR; + } + + WLog_DBG(TAG, "Received %s PDU, length:%" PRIu16 "", rail_get_order_type_string(orderType), + orderLength); + + switch (orderType) + { + case TS_RAIL_ORDER_HANDSHAKE: + { + RAIL_HANDSHAKE_ORDER handshake; + return rail_recv_client_handshake_order(context, &handshake, s); + } + + case TS_RAIL_ORDER_CLIENTSTATUS: + { + RAIL_CLIENT_STATUS_ORDER clientStatus; + return rail_recv_client_client_status_order(context, &clientStatus, s); + } + + case TS_RAIL_ORDER_EXEC: + return rail_recv_client_exec_order(context, s); + + case TS_RAIL_ORDER_SYSPARAM: + { + RAIL_SYSPARAM_ORDER sysparam = { 0 }; + return rail_recv_client_sysparam_order(context, &sysparam, s); + } + + case TS_RAIL_ORDER_ACTIVATE: + { + RAIL_ACTIVATE_ORDER activate; + return rail_recv_client_activate_order(context, &activate, s); + } + + case TS_RAIL_ORDER_SYSMENU: + { + RAIL_SYSMENU_ORDER sysmenu; + return rail_recv_client_sysmenu_order(context, &sysmenu, s); + } + + case TS_RAIL_ORDER_SYSCOMMAND: + { + RAIL_SYSCOMMAND_ORDER syscommand; + return rail_recv_client_syscommand_order(context, &syscommand, s); + } + + case TS_RAIL_ORDER_NOTIFY_EVENT: + { + RAIL_NOTIFY_EVENT_ORDER notifyEvent; + return rail_recv_client_notify_event_order(context, ¬ifyEvent, s); + } + + case TS_RAIL_ORDER_WINDOWMOVE: + { + RAIL_WINDOW_MOVE_ORDER windowMove; + return rail_recv_client_window_move_order(context, &windowMove, s); + } + + case TS_RAIL_ORDER_SNAP_ARRANGE: + { + RAIL_SNAP_ARRANGE snapArrange; + return rail_recv_client_snap_arrange_order(context, &snapArrange, s); + } + + case TS_RAIL_ORDER_GET_APPID_REQ: + { + RAIL_GET_APPID_REQ_ORDER getAppidReq; + return rail_recv_client_get_appid_req_order(context, &getAppidReq, s); + } + + case TS_RAIL_ORDER_LANGBARINFO: + { + RAIL_LANGBAR_INFO_ORDER langbarInfo; + return rail_recv_client_langbar_info_order(context, &langbarInfo, s); + } + + case TS_RAIL_ORDER_LANGUAGEIMEINFO: + { + RAIL_LANGUAGEIME_INFO_ORDER languageImeInfo; + return rail_recv_client_language_ime_info_order(context, &languageImeInfo, s); + } + + case TS_RAIL_ORDER_COMPARTMENTINFO: + { + RAIL_COMPARTMENT_INFO_ORDER compartmentInfo; + return rail_recv_client_compartment_info(context, &compartmentInfo, s); + } + + case TS_RAIL_ORDER_CLOAK: + { + RAIL_CLOAK cloak; + return rail_recv_client_cloak_order(context, &cloak, s); + } + + default: + WLog_ERR(TAG, "Unknown RAIL PDU order received."); + return ERROR_INVALID_DATA; + } + + Stream_SetPosition(s, 0); + return status; +} diff --git a/channels/rail/server/rail_main.h b/channels/rail/server/rail_main.h new file mode 100644 index 0000000..5c56331 --- /dev/null +++ b/channels/rail/server/rail_main.h @@ -0,0 +1,44 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * RAIL Virtual Channel Plugin + * + * Copyright 2019 Mati Shabtay + * + * 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_RAIL_SERVER_MAIN_H +#define FREERDP_CHANNEL_RAIL_SERVER_MAIN_H + +#include +#include + +#include +#include +#include + +#include "../rail_common.h" + +struct _rail_server_private +{ + HANDLE thread; + HANDLE stopEvent; + HANDLE channelEvent; + void* rail_channel; + + wStream* input_stream; + + DWORD channelFlags; +}; + +#endif /* FREERDP_CHANNEL_RAIL_SERVER_MAIN_H */ \ No newline at end of file diff --git a/channels/rdp2tcp/CMakeLists.txt b/channels/rdp2tcp/CMakeLists.txt new file mode 100644 index 0000000..31de127 --- /dev/null +++ b/channels/rdp2tcp/CMakeLists.txt @@ -0,0 +1,22 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2012 Marc-Andre Moreau +# +# 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("rdp2tcp") + +if(WITH_CLIENT_CHANNELS) + add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME}) +endif() diff --git a/channels/rdp2tcp/ChannelOptions.cmake b/channels/rdp2tcp/ChannelOptions.cmake new file mode 100644 index 0000000..3cad9b1 --- /dev/null +++ b/channels/rdp2tcp/ChannelOptions.cmake @@ -0,0 +1,10 @@ +set(OPTION_DEFAULT OFF) +set(OPTION_CLIENT_DEFAULT ON) +set(OPTION_SERVER_DEFAULT OFF) + +define_channel_options(NAME "rdp2tcp" TYPE "static" + DESCRIPTION "Tunneling TCP over RDP" + DEFAULT ${OPTION_DEFAULT}) + +define_channel_client_options(${OPTION_CLIENT_DEFAULT}) +define_channel_server_options(${OPTION_SERVER_DEFAULT}) diff --git a/channels/rdp2tcp/client/CMakeLists.txt b/channels/rdp2tcp/client/CMakeLists.txt new file mode 100644 index 0000000..2e51020 --- /dev/null +++ b/channels/rdp2tcp/client/CMakeLists.txt @@ -0,0 +1,27 @@ +# FreeRDP: A Remote Desktop Protocol Implementation +# FreeRDP cmake build script +# +# Copyright 2012 Marc-Andre Moreau +# +# 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("rdp2tcp") + +set(${MODULE_PREFIX}_SRCS + rdp2tcp_main.c) + +add_channel_client_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} TRUE "VirtualChannelEntryEx") + +target_link_libraries(${MODULE_NAME} freerdp) + +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Channels/${CHANNEL_NAME}/Client") diff --git a/channels/rdp2tcp/client/rdp2tcp_main.c b/channels/rdp2tcp/client/rdp2tcp_main.c new file mode 100644 index 0000000..58a2ef5 --- /dev/null +++ b/channels/rdp2tcp/client/rdp2tcp_main.c @@ -0,0 +1,327 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * rdp2tcp Virtual Channel Extension + * + * Copyright 2017 Artur Zaprzala + * + * 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 +#include + +#include +#include +#include + +#include + +#define RDP2TCP_CHAN_NAME "rdp2tcp" + +#include +#define TAG CLIENT_TAG(RDP2TCP_CHAN_NAME) + +static int const debug = 0; + +typedef struct +{ + HANDLE hStdOutputRead; + HANDLE hStdInputWrite; + HANDLE hProcess; + HANDLE copyThread; + HANDLE writeComplete; + DWORD openHandle; + void* initHandle; + CHANNEL_ENTRY_POINTS_FREERDP_EX channelEntryPoints; + char buffer[16 * 1024]; +} Plugin; + +static int init_external_addin(Plugin* plugin) +{ + SECURITY_ATTRIBUTES saAttr; + STARTUPINFO siStartInfo; + PROCESS_INFORMATION procInfo; + saAttr.nLength = sizeof(SECURITY_ATTRIBUTES); + saAttr.bInheritHandle = TRUE; + saAttr.lpSecurityDescriptor = NULL; + siStartInfo.cb = sizeof(STARTUPINFO); + siStartInfo.hStdError = GetStdHandle(STD_ERROR_HANDLE); + siStartInfo.dwFlags = STARTF_USESTDHANDLES; + + // Create pipes + if (!CreatePipe(&plugin->hStdOutputRead, &siStartInfo.hStdOutput, &saAttr, 0)) + { + WLog_ERR(TAG, "stdout CreatePipe"); + return -1; + } + + if (!SetHandleInformation(plugin->hStdOutputRead, HANDLE_FLAG_INHERIT, 0)) + { + WLog_ERR(TAG, "stdout SetHandleInformation"); + return -1; + } + + if (!CreatePipe(&siStartInfo.hStdInput, &plugin->hStdInputWrite, &saAttr, 0)) + { + WLog_ERR(TAG, "stdin CreatePipe"); + return -1; + } + + if (!SetHandleInformation(plugin->hStdInputWrite, HANDLE_FLAG_INHERIT, 0)) + { + WLog_ERR(TAG, "stdin SetHandleInformation"); + return -1; + } + + // Execute plugin + if (!CreateProcess(NULL, + plugin->channelEntryPoints.pExtendedData, // command line + NULL, // process security attributes + NULL, // primary thread security attributes + TRUE, // handles are inherited + 0, // creation flags + NULL, // use parent's environment + NULL, // use parent's current directory + &siStartInfo, // STARTUPINFO pointer + &procInfo // receives PROCESS_INFORMATION + )) + { + WLog_ERR(TAG, "fork for addin"); + return -1; + } + + plugin->hProcess = procInfo.hProcess; + CloseHandle(procInfo.hThread); + CloseHandle(siStartInfo.hStdOutput); + CloseHandle(siStartInfo.hStdInput); + return 0; +} + +static void dumpData(char* data, unsigned length) +{ + unsigned const limit = 98; + unsigned l = length > limit ? limit / 2 : length; + unsigned i; + + for (i = 0; i < l; ++i) + { + printf("%02hhx", data[i]); + } + + if (length > limit) + { + printf("..."); + + for (i = length - l; i < length; ++i) + printf("%02hhx", data[i]); + } + + puts(""); +} + +static DWORD WINAPI copyThread(void* data) +{ + Plugin* plugin = (Plugin*)data; + size_t const bufsize = 16 * 1024; + + while (1) + { + DWORD dwRead; + char* buffer = malloc(bufsize); + + if (!buffer) + { + fprintf(stderr, "rdp2tcp copyThread: malloc failed\n"); + goto fail; + } + + // if (!ReadFile(plugin->hStdOutputRead, plugin->buffer, sizeof plugin->buffer, &dwRead, + // NULL)) + if (!ReadFile(plugin->hStdOutputRead, buffer, bufsize, &dwRead, NULL)) + { + free(buffer); + goto fail; + } + + if (debug > 1) + { + printf(">%8u ", (unsigned)dwRead); + dumpData(buffer, dwRead); + } + + if (plugin->channelEntryPoints.pVirtualChannelWriteEx( + plugin->initHandle, plugin->openHandle, buffer, dwRead, buffer) != CHANNEL_RC_OK) + { + free(buffer); + fprintf(stderr, "rdp2tcp copyThread failed %i\n", (int)dwRead); + goto fail; + } + + WaitForSingleObject(plugin->writeComplete, INFINITE); + ResetEvent(plugin->writeComplete); + } + +fail: + ExitThread(0); + return 0; +} + +static void closeChannel(Plugin* plugin) +{ + if (debug) + puts("rdp2tcp closing channel"); + + plugin->channelEntryPoints.pVirtualChannelCloseEx(plugin->initHandle, plugin->openHandle); +} + +static void dataReceived(Plugin* plugin, void* pData, UINT32 dataLength, UINT32 totalLength, + UINT32 dataFlags) +{ + DWORD dwWritten; + + if (dataFlags & CHANNEL_FLAG_SUSPEND) + { + if (debug) + puts("rdp2tcp Channel Suspend"); + + return; + } + + if (dataFlags & CHANNEL_FLAG_RESUME) + { + if (debug) + puts("rdp2tcp Channel Resume"); + + return; + } + + if (debug > 1) + { + printf("<%c%3u/%3u ", dataFlags & CHANNEL_FLAG_FIRST ? ' ' : '+', totalLength, dataLength); + dumpData(pData, dataLength); + } + + if (dataFlags & CHANNEL_FLAG_FIRST) + { + if (!WriteFile(plugin->hStdInputWrite, &totalLength, sizeof(totalLength), &dwWritten, NULL)) + closeChannel(plugin); + } + + if (!WriteFile(plugin->hStdInputWrite, pData, dataLength, &dwWritten, NULL)) + closeChannel(plugin); +} + +static void VCAPITYPE VirtualChannelOpenEventEx(LPVOID lpUserParam, DWORD openHandle, UINT event, + LPVOID pData, UINT32 dataLength, UINT32 totalLength, + UINT32 dataFlags) +{ + Plugin* plugin = (Plugin*)lpUserParam; + + switch (event) + { + case CHANNEL_EVENT_DATA_RECEIVED: + dataReceived(plugin, pData, dataLength, totalLength, dataFlags); + break; + + case CHANNEL_EVENT_WRITE_CANCELLED: + free(pData); + break; + case CHANNEL_EVENT_WRITE_COMPLETE: + SetEvent(plugin->writeComplete); + free(pData); + break; + } +} + +static VOID VCAPITYPE VirtualChannelInitEventEx(LPVOID lpUserParam, LPVOID pInitHandle, UINT event, + LPVOID pData, UINT dataLength) +{ + Plugin* plugin = (Plugin*)lpUserParam; + + switch (event) + { + case CHANNEL_EVENT_CONNECTED: + if (debug) + puts("rdp2tcp connected"); + + plugin->writeComplete = CreateEvent(NULL, TRUE, FALSE, NULL); + plugin->copyThread = CreateThread(NULL, 0, copyThread, plugin, 0, NULL); + + if (plugin->channelEntryPoints.pVirtualChannelOpenEx( + pInitHandle, &plugin->openHandle, RDP2TCP_CHAN_NAME, + VirtualChannelOpenEventEx) != CHANNEL_RC_OK) + return; + + break; + + case CHANNEL_EVENT_DISCONNECTED: + if (debug) + puts("rdp2tcp disconnected"); + + break; + + case CHANNEL_EVENT_TERMINATED: + if (debug) + puts("rdp2tcp terminated"); + + if (plugin->copyThread) + { + TerminateThread(plugin->copyThread, 0); + CloseHandle(plugin->writeComplete); + } + + CloseHandle(plugin->hStdInputWrite); + CloseHandle(plugin->hStdOutputRead); + TerminateProcess(plugin->hProcess, 0); + CloseHandle(plugin->hProcess); + free(plugin); + break; + } +} + +#if 1 +#define VirtualChannelEntryEx rdp2tcp_VirtualChannelEntryEx +#else +#define VirtualChannelEntryEx FREERDP_API VirtualChannelEntryEx +#endif +BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID pInitHandle) +{ + CHANNEL_ENTRY_POINTS_FREERDP_EX* pEntryPointsEx; + CHANNEL_DEF channelDef; + Plugin* plugin = (Plugin*)calloc(1, sizeof(Plugin)); + + if (!plugin) + return FALSE; + + pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*)pEntryPoints; + assert(pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX) && + pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER); + plugin->initHandle = pInitHandle; + plugin->channelEntryPoints = *pEntryPointsEx; + + if (init_external_addin(plugin) < 0) + return FALSE; + + strncpy(channelDef.name, RDP2TCP_CHAN_NAME, sizeof(channelDef.name)); + channelDef.options = + CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP; + + if (pEntryPointsEx->pVirtualChannelInitEx(plugin, NULL, pInitHandle, &channelDef, 1, + VIRTUAL_CHANNEL_VERSION_WIN2000, + VirtualChannelInitEventEx) != CHANNEL_RC_OK) + return FALSE; + + return TRUE; +} + +// vim:ts=4 diff --git a/channels/rdpdr/client/devman.c b/channels/rdpdr/client/devman.c index 93db1b7..af3cdd6 100644 --- a/channels/rdpdr/client/devman.c +++ b/channels/rdpdr/client/devman.c @@ -43,7 +43,7 @@ static void devman_device_free(void* obj) { - DEVICE* device = (DEVICE*) obj; + DEVICE* device = (DEVICE*)obj; if (!device) return; @@ -58,27 +58,26 @@ DEVMAN* devman_new(rdpdrPlugin* rdpdr) if (!rdpdr) return NULL; - devman = (DEVMAN*) calloc(1, sizeof(DEVMAN)); + devman = (DEVMAN*)calloc(1, sizeof(DEVMAN)); if (!devman) { - WLog_INFO(TAG, "calloc failed!"); + WLog_INFO(TAG, "calloc failed!"); return NULL; } - devman->plugin = (void*) rdpdr; + devman->plugin = (void*)rdpdr; devman->id_sequence = 1; - devman->devices = ListDictionary_New(TRUE); + if (!devman->devices) { - WLog_INFO(TAG, "ListDictionary_New failed!"); + WLog_INFO(TAG, "ListDictionary_New failed!"); free(devman); return NULL; } ListDictionary_ValueObject(devman->devices)->fnObjectFree = devman_device_free; - return devman; } @@ -95,7 +94,7 @@ void devman_unregister_device(DEVMAN* devman, void* key) if (!devman || !key) return; - device = (DEVICE*) ListDictionary_Remove(devman->devices, key); + device = (DEVICE*)ListDictionary_Remove(devman->devices, key); if (device) devman_device_free(device); @@ -114,46 +113,82 @@ static UINT devman_register_device(DEVMAN* devman, DEVICE* device) return ERROR_INVALID_PARAMETER; device->id = devman->id_sequence++; - key = (void*) (size_t) device->id; + key = (void*)(size_t)device->id; if (!ListDictionary_Add(devman->devices, key, device)) { - WLog_INFO(TAG, "ListDictionary_Add failed!"); + WLog_INFO(TAG, "ListDictionary_Add failed!"); return ERROR_INTERNAL_ERROR; } + return CHANNEL_RC_OK; } DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id) { DEVICE* device = NULL; - void* key = (void*) (size_t) id; + void* key = (void*)(size_t)id; if (!devman) return NULL; - device = (DEVICE*) ListDictionary_GetItemValue(devman->devices, key); + device = (DEVICE*)ListDictionary_GetItemValue(devman->devices, key); + return device; +} +DEVICE* devman_get_device_by_type(DEVMAN* devman, UINT32 type) +{ + DEVICE* device = NULL; + ULONG_PTR* keys; + int count, x; + + if (!devman) + return NULL; + + ListDictionary_Lock(devman->devices); + count = ListDictionary_GetKeys(devman->devices, &keys); + + for (x = 0; x < count; x++) + { + DEVICE* cur = (DEVICE*)ListDictionary_GetItemValue(devman->devices, (void*)keys[x]); + + if (!cur) + continue; + + if (cur->type != type) + continue; + + device = cur; + break; + } + + free(keys); + ListDictionary_Unlock(devman->devices); return device; } -static char DRIVE_SERVICE_NAME[] = "drive"; -static char PRINTER_SERVICE_NAME[] = "printer"; -static char SMARTCARD_SERVICE_NAME[] = "smartcard"; -static char SERIAL_SERVICE_NAME[] = "serial"; -static char PARALLEL_SERVICE_NAME[] = "parallel"; +static const char DRIVE_SERVICE_NAME[] = "drive"; +static const char PRINTER_SERVICE_NAME[] = "printer"; +static const char SMARTCARD_SERVICE_NAME[] = "smartcard"; +static const char SERIAL_SERVICE_NAME[] = "serial"; +static const char PARALLEL_SERVICE_NAME[] = "parallel"; /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext* rdpcontext) +UINT devman_load_device_service(DEVMAN* devman, const RDPDR_DEVICE* device, rdpContext* rdpcontext) { - char* ServiceName = NULL; + const char* ServiceName = NULL; DEVICE_SERVICE_ENTRY_POINTS ep; PDEVICE_SERVICE_ENTRY entry = NULL; + union { + const RDPDR_DEVICE* cdp; + RDPDR_DEVICE* dp; + } devconv; + devconv.cdp = device; if (!devman || !device || !rdpcontext) return ERROR_INVALID_PARAMETER; @@ -170,26 +205,27 @@ UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext if (!ServiceName) { - WLog_INFO(TAG, "ServiceName %s did not match!", ServiceName); + WLog_INFO(TAG, "ServiceName %s did not match!", ServiceName); return ERROR_INVALID_NAME; } if (device->Name) - WLog_INFO(TAG, "Loading device service %s [%s] (static)", ServiceName, device->Name); + WLog_INFO(TAG, "Loading device service %s [%s] (static)", ServiceName, device->Name); else - WLog_INFO(TAG, "Loading device service %s (static)", ServiceName); - entry = (PDEVICE_SERVICE_ENTRY) freerdp_load_channel_addin_entry(ServiceName, NULL, "DeviceServiceEntry", 0); + WLog_INFO(TAG, "Loading device service %s (static)", ServiceName); + + entry = (PDEVICE_SERVICE_ENTRY)freerdp_load_channel_addin_entry(ServiceName, NULL, + "DeviceServiceEntry", 0); if (!entry) { - WLog_INFO(TAG, "freerdp_load_channel_addin_entry failed!"); + WLog_INFO(TAG, "freerdp_load_channel_addin_entry failed!"); return ERROR_INTERNAL_ERROR; } ep.devman = devman; ep.RegisterDevice = devman_register_device; - ep.device = device; + ep.device = devconv.dp; ep.rdpcontext = rdpcontext; - return entry(&ep); } diff --git a/channels/rdpdr/client/devman.h b/channels/rdpdr/client/devman.h index c99a179..2e6019e 100644 --- a/channels/rdpdr/client/devman.h +++ b/channels/rdpdr/client/devman.h @@ -26,8 +26,9 @@ #include "rdpdr_main.h" void devman_unregister_device(DEVMAN* devman, void* key); -UINT devman_load_device_service(DEVMAN* devman, RDPDR_DEVICE* device, rdpContext* rdpcontext); +UINT devman_load_device_service(DEVMAN* devman, const RDPDR_DEVICE* device, rdpContext* rdpcontext); DEVICE* devman_get_device_by_id(DEVMAN* devman, UINT32 id); +DEVICE* devman_get_device_by_type(DEVMAN* devman, UINT32 type); DEVMAN* devman_new(rdpdrPlugin* rdpdr); void devman_free(DEVMAN* devman); diff --git a/channels/rdpdr/client/irp.c b/channels/rdpdr/client/irp.c index 21d4a46..b818b67 100644 --- a/channels/rdpdr/client/irp.c +++ b/channels/rdpdr/client/irp.c @@ -63,7 +63,7 @@ static UINT irp_complete(IRP* irp) rdpdrPlugin* rdpdr; UINT error; - rdpdr = (rdpdrPlugin*) irp->devman->plugin; + rdpdr = (rdpdrPlugin*)irp->devman->plugin; pos = Stream_GetPosition(irp->output); Stream_SetPosition(irp->output, RDPDR_DEVICE_IO_RESPONSE_LENGTH - 4); @@ -73,8 +73,7 @@ static UINT irp_complete(IRP* irp) error = rdpdr_send(rdpdr, irp->output); irp->output = NULL; - irp_free(irp); - return error; + return irp_free(irp); } IRP* irp_new(DEVMAN* devman, wStream* s, UINT* error) @@ -102,7 +101,7 @@ IRP* irp_new(DEVMAN* devman, wStream* s, UINT* error) return NULL; }; - irp = (IRP*) _aligned_malloc(sizeof(IRP), MEMORY_ALLOCATION_ALIGNMENT); + irp = (IRP*)_aligned_malloc(sizeof(IRP), MEMORY_ALLOCATION_ALIGNMENT); if (!irp) { @@ -112,15 +111,14 @@ IRP* irp_new(DEVMAN* devman, wStream* s, UINT* error) return NULL; } - ZeroMemory(irp, sizeof(IRP)); irp->input = s; irp->device = device; irp->devman = devman; - Stream_Read_UINT32(s, irp->FileId); /* FileId (4 bytes) */ - Stream_Read_UINT32(s, irp->CompletionId); /* CompletionId (4 bytes) */ + Stream_Read_UINT32(s, irp->FileId); /* FileId (4 bytes) */ + Stream_Read_UINT32(s, irp->CompletionId); /* CompletionId (4 bytes) */ Stream_Read_UINT32(s, irp->MajorFunction); /* MajorFunction (4 bytes) */ Stream_Read_UINT32(s, irp->MinorFunction); /* MinorFunction (4 bytes) */ @@ -133,11 +131,11 @@ IRP* irp_new(DEVMAN* devman, wStream* s, UINT* error) *error = CHANNEL_RC_NO_MEMORY; return NULL; } - Stream_Write_UINT16(irp->output, RDPDR_CTYP_CORE); /* Component (2 bytes) */ + Stream_Write_UINT16(irp->output, RDPDR_CTYP_CORE); /* Component (2 bytes) */ Stream_Write_UINT16(irp->output, PAKID_CORE_DEVICE_IOCOMPLETION); /* PacketId (2 bytes) */ - Stream_Write_UINT32(irp->output, DeviceId); /* DeviceId (4 bytes) */ - Stream_Write_UINT32(irp->output, irp->CompletionId); /* CompletionId (4 bytes) */ - Stream_Write_UINT32(irp->output, 0); /* IoStatus (4 bytes) */ + Stream_Write_UINT32(irp->output, DeviceId); /* DeviceId (4 bytes) */ + Stream_Write_UINT32(irp->output, irp->CompletionId); /* CompletionId (4 bytes) */ + Stream_Write_UINT32(irp->output, 0); /* IoStatus (4 bytes) */ irp->Complete = irp_complete; irp->Discard = irp_free; diff --git a/channels/rdpdr/client/rdpdr_capabilities.c b/channels/rdpdr/client/rdpdr_capabilities.c index 4ff3ef5..97c876b 100644 --- a/channels/rdpdr/client/rdpdr_capabilities.c +++ b/channels/rdpdr/client/rdpdr_capabilities.c @@ -36,7 +36,8 @@ #include "rdpdr_capabilities.h" /* Output device redirection capability set header */ -static void rdpdr_write_capset_header(wStream* s, UINT16 capabilityType, UINT16 capabilityLength, UINT32 version) +static void rdpdr_write_capset_header(wStream* s, UINT16 capabilityType, UINT16 capabilityLength, + UINT32 version) { Stream_Write_UINT16(s, capabilityType); Stream_Write_UINT16(s, capabilityLength); @@ -46,41 +47,47 @@ static void rdpdr_write_capset_header(wStream* s, UINT16 capabilityType, UINT16 /* Output device direction general capability set */ static void rdpdr_write_general_capset(rdpdrPlugin* rdpdr, wStream* s) { + WINPR_UNUSED(rdpdr); rdpdr_write_capset_header(s, CAP_GENERAL_TYPE, 44, GENERAL_CAPABILITY_VERSION_02); - Stream_Write_UINT32(s, 0); /* osType, ignored on receipt */ Stream_Write_UINT32(s, 0); /* osVersion, unused and must be set to zero */ Stream_Write_UINT16(s, 1); /* protocolMajorVersion, must be set to 1 */ Stream_Write_UINT16(s, RDPDR_MINOR_RDP_VERSION_5_2); /* protocolMinorVersion */ - Stream_Write_UINT32(s, 0x0000FFFF); /* ioCode1 */ + Stream_Write_UINT32(s, 0x0000FFFF); /* ioCode1 */ Stream_Write_UINT32(s, 0); /* ioCode2, must be set to zero, reserved for future use */ - Stream_Write_UINT32(s, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */ - Stream_Write_UINT32(s, ENABLE_ASYNCIO); /* extraFlags1 */ + Stream_Write_UINT32(s, RDPDR_DEVICE_REMOVE_PDUS | RDPDR_CLIENT_DISPLAY_NAME_PDU | + RDPDR_USER_LOGGEDON_PDU); /* extendedPDU */ + Stream_Write_UINT32(s, ENABLE_ASYNCIO); /* extraFlags1 */ Stream_Write_UINT32(s, 0); /* extraFlags2, must be set to zero, reserved for future use */ - Stream_Write_UINT32(s, 0); /* SpecialTypeDeviceCap, number of special devices to be redirected before logon */ + Stream_Write_UINT32( + s, 0); /* SpecialTypeDeviceCap, number of special devices to be redirected before logon */ } /* Process device direction general capability set */ static UINT rdpdr_process_general_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; + WINPR_UNUSED(rdpdr); if (Stream_GetRemainingLength(s) < 2) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, capabilityLength); - if (Stream_GetRemainingLength(s) < capabilityLength - 4) + if (capabilityLength < 4) return ERROR_INVALID_DATA; - Stream_Seek(s, capabilityLength - 4); + if (Stream_GetRemainingLength(s) < capabilityLength - 4U) + return ERROR_INVALID_DATA; + Stream_Seek(s, capabilityLength - 4U); return CHANNEL_RC_OK; } /* Output printer direction capability set */ static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, wStream* s) { + WINPR_UNUSED(rdpdr); rdpdr_write_capset_header(s, CAP_PRINTER_TYPE, 8, PRINT_CAPABILITY_VERSION_01); } @@ -88,23 +95,27 @@ static void rdpdr_write_printer_capset(rdpdrPlugin* rdpdr, wStream* s) static UINT rdpdr_process_printer_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; + WINPR_UNUSED(rdpdr); if (Stream_GetRemainingLength(s) < 2) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, capabilityLength); - if (Stream_GetRemainingLength(s) < capabilityLength - 4) + if (capabilityLength < 4) return ERROR_INVALID_DATA; - Stream_Seek(s, capabilityLength - 4); + if (Stream_GetRemainingLength(s) < capabilityLength - 4U) + return ERROR_INVALID_DATA; + Stream_Seek(s, capabilityLength - 4U); return CHANNEL_RC_OK; } /* Output port redirection capability set */ static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, wStream* s) { + WINPR_UNUSED(rdpdr); rdpdr_write_capset_header(s, CAP_PORT_TYPE, 8, PORT_CAPABILITY_VERSION_01); } @@ -112,23 +123,27 @@ static void rdpdr_write_port_capset(rdpdrPlugin* rdpdr, wStream* s) static UINT rdpdr_process_port_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; + WINPR_UNUSED(rdpdr); if (Stream_GetRemainingLength(s) < 2) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, capabilityLength); - if (Stream_GetRemainingLength(s) < capabilityLength - 4) + if (capabilityLength < 4U) return ERROR_INVALID_DATA; - Stream_Seek(s, capabilityLength - 4); + if (Stream_GetRemainingLength(s) < capabilityLength - 4U) + return ERROR_INVALID_DATA; + Stream_Seek(s, capabilityLength - 4U); return CHANNEL_RC_OK; } /* Output drive redirection capability set */ static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, wStream* s) { + WINPR_UNUSED(rdpdr); rdpdr_write_capset_header(s, CAP_DRIVE_TYPE, 8, DRIVE_CAPABILITY_VERSION_02); } @@ -136,23 +151,27 @@ static void rdpdr_write_drive_capset(rdpdrPlugin* rdpdr, wStream* s) static UINT rdpdr_process_drive_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; + WINPR_UNUSED(rdpdr); if (Stream_GetRemainingLength(s) < 2) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, capabilityLength); - if (Stream_GetRemainingLength(s) < capabilityLength - 4) + if (capabilityLength < 4) return ERROR_INVALID_DATA; - Stream_Seek(s, capabilityLength - 4); + if (Stream_GetRemainingLength(s) < capabilityLength - 4U) + return ERROR_INVALID_DATA; + Stream_Seek(s, capabilityLength - 4U); return CHANNEL_RC_OK; } /* Output smart card redirection capability set */ static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s) { + WINPR_UNUSED(rdpdr); rdpdr_write_capset_header(s, CAP_SMARTCARD_TYPE, 8, SMARTCARD_CAPABILITY_VERSION_01); } @@ -160,17 +179,20 @@ static void rdpdr_write_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s) static UINT rdpdr_process_smartcard_capset(rdpdrPlugin* rdpdr, wStream* s) { UINT16 capabilityLength; + WINPR_UNUSED(rdpdr); if (Stream_GetRemainingLength(s) < 2) return ERROR_INVALID_DATA; Stream_Read_UINT16(s, capabilityLength); - if (Stream_GetRemainingLength(s) < capabilityLength - 4) + if (capabilityLength < 4) return ERROR_INVALID_DATA; - Stream_Seek(s, capabilityLength - 4); + if (Stream_GetRemainingLength(s) < capabilityLength - 4U) + return ERROR_INVALID_DATA; + Stream_Seek(s, capabilityLength - 4U); return CHANNEL_RC_OK; } @@ -199,28 +221,28 @@ UINT rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s) switch (capabilityType) { - case CAP_GENERAL_TYPE: - status = rdpdr_process_general_capset(rdpdr, s); - break; + case CAP_GENERAL_TYPE: + status = rdpdr_process_general_capset(rdpdr, s); + break; - case CAP_PRINTER_TYPE: - status = rdpdr_process_printer_capset(rdpdr, s); - break; + case CAP_PRINTER_TYPE: + status = rdpdr_process_printer_capset(rdpdr, s); + break; - case CAP_PORT_TYPE: - status = rdpdr_process_port_capset(rdpdr, s); - break; + case CAP_PORT_TYPE: + status = rdpdr_process_port_capset(rdpdr, s); + break; - case CAP_DRIVE_TYPE: - status = rdpdr_process_drive_capset(rdpdr, s); - break; + case CAP_DRIVE_TYPE: + status = rdpdr_process_drive_capset(rdpdr, s); + break; - case CAP_SMARTCARD_TYPE: - status = rdpdr_process_smartcard_capset(rdpdr, s); - break; + case CAP_SMARTCARD_TYPE: + status = rdpdr_process_smartcard_capset(rdpdr, s); + break; - default: - break; + default: + break; } if (status != CHANNEL_RC_OK) @@ -238,8 +260,8 @@ UINT rdpdr_process_capability_request(rdpdrPlugin* rdpdr, wStream* s) UINT rdpdr_send_capability_response(rdpdrPlugin* rdpdr) { wStream* s; - s = Stream_New(NULL, 256); + if (!s) { WLog_ERR(TAG, "Stream_New failed!"); @@ -248,15 +270,12 @@ UINT rdpdr_send_capability_response(rdpdrPlugin* rdpdr) Stream_Write_UINT16(s, RDPDR_CTYP_CORE); Stream_Write_UINT16(s, PAKID_CORE_CLIENT_CAPABILITY); - Stream_Write_UINT16(s, 5); /* numCapabilities */ Stream_Write_UINT16(s, 0); /* pad */ - rdpdr_write_general_capset(rdpdr, s); rdpdr_write_printer_capset(rdpdr, s); rdpdr_write_port_capset(rdpdr, s); rdpdr_write_drive_capset(rdpdr, s); rdpdr_write_smartcard_capset(rdpdr, s); - return rdpdr_send(rdpdr, s); } diff --git a/channels/rdpdr/client/rdpdr_main.c b/channels/rdpdr/client/rdpdr_main.c index 602268f..7f6dc94 100644 --- a/channels/rdpdr/client/rdpdr_main.c +++ b/channels/rdpdr/client/rdpdr_main.c @@ -81,16 +81,14 @@ struct _DEVICE_DRIVE_EXT * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, - BOOL userLoggedOn); +static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL userLoggedOn); /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, - UINT32 count, UINT32 ids[]) +static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, UINT32 count, UINT32 ids[]) { UINT32 i; wStream* s; @@ -113,7 +111,7 @@ static UINT rdpdr_send_device_list_remove_request(rdpdrPlugin* rdpdr, return rdpdr_send(rdpdr, s); } -#ifdef _UWP +#if defined(_UWP) || defined(__IOS__) void first_hotplug(rdpdrPlugin* rdpdr) { @@ -135,7 +133,8 @@ BOOL check_path(char* path) { UINT type = GetDriveTypeA(path); - if (!(type == DRIVE_FIXED ||type == DRIVE_REMOVABLE || type == DRIVE_CDROM || type == DRIVE_REMOTE)) + if (!(type == DRIVE_FIXED || type == DRIVE_REMOVABLE || type == DRIVE_CDROM || + type == DRIVE_REMOTE)) return FALSE; return GetVolumeInformationA(path, NULL, 0, NULL, NULL, NULL, NULL, 0); @@ -143,28 +142,26 @@ BOOL check_path(char* path) void first_hotplug(rdpdrPlugin* rdpdr) { - int i; - char drive_path[5] = { 'c', ':', '\\', '\0' }; + size_t i; DWORD unitmask = GetLogicalDrives(); for (i = 0; i < 26; i++) { if (unitmask & 0x01) { - RDPDR_DRIVE* drive; - drive_path[0] = 'A' + i; - drive_path[1] = ':'; + char drive_path[] = { 'c', ':', '\\', '\0' }; + char drive_name[] = { 'c', '\0' }; + RDPDR_DRIVE drive = { 0 }; + drive_path[0] = 'A' + (char)i; + drive_name[0] = 'A' + (char)i; if (check_path(drive_path)) { - drive = (RDPDR_DRIVE*)malloc(sizeof(RDPDR_DRIVE)); - ZeroMemory(drive, sizeof(RDPDR_DRIVE)); - drive->Type = RDPDR_DTYP_FILESYSTEM; - drive->Path = _strdup(drive_path); - drive_path[1] = '\0'; - drive->Name = _strdup(drive_path); - drive->automount = TRUE; - devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE*)drive, + drive.Type = RDPDR_DTYP_FILESYSTEM; + drive.Path = drive_path; + drive.Name = drive_name; + drive.automount = TRUE; + devman_load_device_service(rdpdr->devman, (const RDPDR_DEVICE*)&drive, rdpdr->rdpcontext); } } @@ -186,31 +183,32 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) switch (wParam) { case DBT_DEVICEARRIVAL: - if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME) + if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) { PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb; DWORD unitmask = lpdbv->dbcv_unitmask; int i; - char drive_path[4] = { 'c', ':', '/', '\0'}; for (i = 0; i < 26; i++) { if (unitmask & 0x01) { - RDPDR_DRIVE* drive; - drive_path[0] = 'A' + i; - drive_path[1] = ':'; + char drive_path[] = { 'c', ':', '/', '\0' }; + char drive_name[] = { 'c', '\0' }; + drive_path[0] = 'A' + (char)i; + drive_name[0] = 'A' + (char)i; if (check_path(drive_path)) { - drive = (RDPDR_DRIVE*) malloc(sizeof(RDPDR_DRIVE)); - ZeroMemory(drive, sizeof(RDPDR_DRIVE)); - drive->Type = RDPDR_DTYP_FILESYSTEM; - drive->Path = _strdup(drive_path); + RDPDR_DRIVE drive = { 0 }; + + drive.Type = RDPDR_DTYP_FILESYSTEM; + drive.Path = drive_path; drive_path[1] = '\0'; - drive->automount = TRUE; - drive->Name = _strdup(drive_path); - devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE*)drive, + drive.automount = TRUE; + drive.Name = drive_name; + devman_load_device_service(rdpdr->devman, + (const RDPDR_DEVICE*)&drive, rdpdr->rdpcontext); rdpdr_send_device_list_announce_request(rdpdr, TRUE); } @@ -223,7 +221,7 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) break; case DBT_DEVICEREMOVECOMPLETE: - if (lpdb -> dbch_devicetype == DBT_DEVTYP_VOLUME) + if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME) { PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb; DWORD unitmask = lpdbv->dbcv_unitmask; @@ -244,21 +242,25 @@ LRESULT CALLBACK hotplug_proc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) for (j = 0; j < count; j++) { device_ext = (DEVICE_DRIVE_EXT*)ListDictionary_GetItemValue( - rdpdr->devman->devices, (void*)keys[j]); + rdpdr->devman->devices, (void*)keys[j]); - if (device_ext->path[0] == drive_name_upper - || device_ext->path[0] == drive_name_lower) + if (device_ext->path[0] == drive_name_upper || + device_ext->path[0] == drive_name_lower) { if (device_ext->automount) { devman_unregister_device(rdpdr->devman, (void*)keys[j]); ids[0] = keys[j]; - if ((error = rdpdr_send_device_list_remove_request(rdpdr, 1, ids))) + if ((error = rdpdr_send_device_list_remove_request( + rdpdr, 1, ids))) { // dont end on error, just report ? - WLog_ERR(TAG, "rdpdr_send_device_list_remove_request failed with error %"PRIu32"!", - error); + WLog_ERR( + TAG, + "rdpdr_send_device_list_remove_request failed " + "with error %" PRIu32 "!", + error); } break; @@ -299,30 +301,27 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg) HDEVNOTIFY hDevNotify; rdpdr = (rdpdrPlugin*)arg; /* init windows class */ - wnd_cls.cbSize = sizeof(WNDCLASSEX); - wnd_cls.style = CS_HREDRAW | CS_VREDRAW; - wnd_cls.lpfnWndProc = hotplug_proc; - wnd_cls.cbClsExtra = 0; - wnd_cls.cbWndExtra = 0; - wnd_cls.hIcon = LoadIcon(NULL, IDI_APPLICATION); - wnd_cls.hCursor = NULL; + wnd_cls.cbSize = sizeof(WNDCLASSEX); + wnd_cls.style = CS_HREDRAW | CS_VREDRAW; + wnd_cls.lpfnWndProc = hotplug_proc; + wnd_cls.cbClsExtra = 0; + wnd_cls.cbWndExtra = 0; + wnd_cls.hIcon = LoadIcon(NULL, IDI_APPLICATION); + wnd_cls.hCursor = NULL; wnd_cls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); - wnd_cls.lpszMenuName = NULL; + wnd_cls.lpszMenuName = NULL; wnd_cls.lpszClassName = L"DRIVE_HOTPLUG"; - wnd_cls.hInstance = NULL; - wnd_cls.hIconSm = LoadIcon(NULL, IDI_APPLICATION); + wnd_cls.hInstance = NULL; + wnd_cls.hIconSm = LoadIcon(NULL, IDI_APPLICATION); RegisterClassEx(&wnd_cls); /* create window */ - hwnd = CreateWindowEx(0, L"DRIVE_HOTPLUG", NULL, - 0, 0, 0, 0, 0, - NULL, NULL, NULL, NULL); + hwnd = CreateWindowEx(0, L"DRIVE_HOTPLUG", NULL, 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)rdpdr); rdpdr->hotplug_wnd = hwnd; /* register device interface to hwnd */ NotificationFilter.dbch_size = sizeof(DEV_BROADCAST_HANDLE); NotificationFilter.dbch_devicetype = DBT_DEVTYP_HANDLE; - hDevNotify = RegisterDeviceNotification(hwnd, &NotificationFilter, - DEVICE_NOTIFY_WINDOW_HANDLE); + hDevNotify = RegisterDeviceNotification(hwnd, &NotificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE); /* message loop */ while ((bRet = GetMessage(&msg, 0, 0, 0)) != 0) @@ -354,23 +353,22 @@ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) if (rdpdr->hotplug_wnd && !PostMessage(rdpdr->hotplug_wnd, WM_QUIT, 0, 0)) { error = GetLastError(); - WLog_ERR(TAG, "PostMessage failed with error %"PRIu32"", error); + WLog_ERR(TAG, "PostMessage failed with error %" PRIu32 "", error); } return error; } -#elif __MACOSX__ +#elif defined(__MACOSX__) #define MAX_USB_DEVICES 100 typedef struct _hotplug_dev { char* path; - BOOL to_add; + BOOL to_add; } hotplug_dev; - /** * Function description * @@ -404,7 +402,8 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) if (pDirent->d_name[0] != '.') { sprintf_s(fullpath, ARRAYSIZE(fullpath), "%s/%s", szdir, pDirent->d_name); - lstat(fullpath, &buf); + if (stat(fullpath, &buf) != 0) + continue; if (S_ISDIR(buf.st_mode)) { @@ -430,12 +429,15 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) { char* path = NULL; BOOL dev_found = FALSE; - device_ext = (DEVICE_DRIVE_EXT*)ListDictionary_GetItemValue( - rdpdr->devman->devices, (void*)keys[j]); + device_ext = + (DEVICE_DRIVE_EXT*)ListDictionary_GetItemValue(rdpdr->devman->devices, (void*)keys[j]); if (!device_ext || !device_ext->automount) continue; + if (device_ext->device.type != RDPDR_DTYP_FILESYSTEM) + continue; + if (device_ext->path == NULL) continue; @@ -468,7 +470,8 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) if ((error = rdpdr_send_device_list_remove_request(rdpdr, 1, ids))) { - WLog_ERR(TAG, "rdpdr_send_device_list_remove_request failed with error %"PRIu32"!", + WLog_ERR(TAG, + "rdpdr_send_device_list_remove_request failed with error %" PRIu32 "!", error); goto cleanup; } @@ -478,43 +481,27 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) /* add new devices */ for (i = 0; i < size; i++) { - RDPDR_DRIVE* drive; - if (dev_array[i].to_add) { + RDPDR_DRIVE drive = { 0 }; char* name; - drive = (RDPDR_DRIVE*) calloc(1, sizeof(RDPDR_DRIVE)); - - if (!drive) - { - WLog_ERR(TAG, "calloc failed!"); - error = CHANNEL_RC_NO_MEMORY; - goto cleanup; - } - drive->Type = RDPDR_DTYP_FILESYSTEM; - drive->Path = dev_array[i].path; - drive->automount = TRUE; - dev_array[i].path = NULL; - name = strrchr(drive->Path, '/') + 1; - drive->Name = _strdup(name); + drive.Type = RDPDR_DTYP_FILESYSTEM; + drive.Path = dev_array[i].path; + drive.automount = TRUE; + name = strrchr(drive.Path, '/') + 1; + drive.Name = name; - if (!drive->Name) + if (!drive.Name) { - WLog_ERR(TAG, "_strdup failed!"); - free(drive->Path); - free(drive); error = CHANNEL_RC_NO_MEMORY; goto cleanup; } - if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE*)drive, + if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE*)&drive, rdpdr->rdpcontext))) { WLog_ERR(TAG, "devman_load_device_service failed!"); - free(drive->Path); - free(drive->Name); - free(drive); error = CHANNEL_RC_NO_MEMORY; goto cleanup; } @@ -530,17 +517,17 @@ cleanup: return error; } - static void drive_hotplug_fsevent_callback(ConstFSEventStreamRef streamRef, - void* clientCallBackInfo, - size_t numEvents, void* eventPaths, const FSEventStreamEventFlags eventFlags[], - const FSEventStreamEventId eventIds[]) + void* clientCallBackInfo, size_t numEvents, + void* eventPaths, + const FSEventStreamEventFlags eventFlags[], + const FSEventStreamEventId eventIds[]) { rdpdrPlugin* rdpdr; - int i; + size_t i; UINT error; char** paths = (char**)eventPaths; - rdpdr = (rdpdrPlugin*) clientCallBackInfo; + rdpdr = (rdpdrPlugin*)clientCallBackInfo; for (i = 0; i < numEvents; i++) { @@ -548,7 +535,7 @@ static void drive_hotplug_fsevent_callback(ConstFSEventStreamRef streamRef, { if ((error = handle_hotplug(rdpdr))) { - WLog_ERR(TAG, "handle_hotplug failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "handle_hotplug failed with error %" PRIu32 "!", error); } else rdpdr_send_device_list_announce_request(rdpdr, TRUE); @@ -564,7 +551,7 @@ void first_hotplug(rdpdrPlugin* rdpdr) if ((error = handle_hotplug(rdpdr))) { - WLog_ERR(TAG, "handle_hotplug failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "handle_hotplug failed with error %" PRIu32 "!", error); } } @@ -572,16 +559,15 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg) { rdpdrPlugin* rdpdr; FSEventStreamRef fsev; - rdpdr = (rdpdrPlugin*) arg; + rdpdr = (rdpdrPlugin*)arg; CFStringRef path = CFSTR("/Volumes/"); - CFArrayRef pathsToWatch = CFArrayCreate(kCFAllocatorMalloc, (const void**)&path, - 1, NULL); + CFArrayRef pathsToWatch = CFArrayCreate(kCFAllocatorMalloc, (const void**)&path, 1, NULL); FSEventStreamContext ctx; ZeroMemory(&ctx, sizeof(ctx)); ctx.info = arg; - fsev = FSEventStreamCreate(kCFAllocatorMalloc, drive_hotplug_fsevent_callback, - &ctx, pathsToWatch, kFSEventStreamEventIdSinceNow, 1, - kFSEventStreamCreateFlagNone); + fsev = + FSEventStreamCreate(kCFAllocatorMalloc, drive_hotplug_fsevent_callback, &ctx, pathsToWatch, + kFSEventStreamEventIdSinceNow, 1, kFSEventStreamCreateFlagNone); rdpdr->runLoop = CFRunLoopGetCurrent(); FSEventStreamScheduleWithRunLoop(fsev, rdpdr->runLoop, kCFRunLoopDefaultMode); FSEventStreamStart(fsev); @@ -592,52 +578,19 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg) return CHANNEL_RC_OK; } - -/** - * Function description - * - * @return 0 on success, otherwise a Win32 error code - */ -static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) -{ - UINT error; - - if (rdpdr->hotplugThread) - { - CFRunLoopStop(rdpdr->runLoop); - - if (WaitForSingleObject(rdpdr->hotplugThread, INFINITE) == WAIT_FAILED) - { - error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error); - return error; - } - - rdpdr->hotplugThread = NULL; - } - - return CHANNEL_RC_OK; -} - #else +#include #define MAX_USB_DEVICES 100 typedef struct _hotplug_dev { char* path; - BOOL to_add; + BOOL to_add; } hotplug_dev; - -static const char* automountLocations[] = -{ - "/run/user/%lu/gvfs", - "/run/media/%s", - "/media/%s", - "/media", - "/mnt" -}; +static const char* automountLocations[] = { "/run/user/%lu/gvfs", "/run/media/%s", "/media/%s", + "/media", "/mnt" }; static BOOL isAutomountLocation(const char* path) { @@ -685,99 +638,6 @@ static BOOL isAutomountLocation(const char* path) return FALSE; } -static char* next_line(FILE* fd, size_t* len) -{ - size_t newsiz; - int c; - char* newbuf; - char* lrbuf; - int lrsiz; - *len = 0; - lrsiz = 0; - lrbuf = NULL; - newbuf = NULL; - - for (;;) - { - c = fgetc(fd); - - if (ferror(fd)) - { - free(newbuf); - return NULL; - } - - if (c == EOF) - { - if (*len == 0) - return NULL; - else - { - lrbuf[(*len)] = '\0'; - return lrbuf; - } - } - else - { - if (*len == lrsiz) - { - newsiz = lrsiz + 4096; - newbuf = realloc(lrbuf, newsiz); - - if (newbuf == NULL) - return NULL; - - lrbuf = newbuf; - lrsiz = newsiz; - } - - lrbuf[(*len)] = c; - - if (c == '\n') - { - lrbuf[(*len)] = '\0'; - return lrbuf; - } - - (*len)++; - } - } -} - -static char* get_word(char* str, unsigned int* offset) -{ - char* p; - char* tmp; - char* word; - int wlen; - - if (*offset >= strlen(str)) - return NULL; - - p = str + *offset; - tmp = p; - - while (*tmp != ' ' && *tmp != '\0') - tmp++; - - wlen = tmp - p; - *offset += wlen; - - /* in case there are more than one space between words */ - while (*(str + *offset) == ' ') - (*offset)++; - - word = malloc(wlen + 1); - - if (word != NULL) - { - CopyMemory(word, p, wlen); - word[wlen] = '\0'; - } - - return word; -} - /** * Function description * @@ -786,18 +646,15 @@ static char* get_word(char* str, unsigned int* offset) static UINT handle_hotplug(rdpdrPlugin* rdpdr) { FILE* f; - size_t len; - char* line; - char* word; - unsigned int wlen; - hotplug_dev dev_array[MAX_USB_DEVICES]; - int i, j; - int size = 0; - int count; + hotplug_dev dev_array[MAX_USB_DEVICES] = { 0 }; + size_t i; + size_t size = 0; + int count, j; + struct mntent* ent; ULONG_PTR* keys = NULL; UINT32 ids[1]; UINT error = 0; - memset(dev_array, 0, sizeof(dev_array)); + f = fopen("/proc/mounts", "r"); if (f == NULL) @@ -806,23 +663,18 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) return ERROR_OPEN_FAILED; } - while ((line = next_line(f, &len))) + while ((ent = getmntent(f)) != NULL) { - wlen = 0; - - while ((word = get_word(line, &wlen))) + /* Copy the line, path must obviously be shorter */ + const char* path = ent->mnt_dir; + if (!path) + continue; + /* copy hotpluged device mount point to the dev_array */ + if (isAutomountLocation(path) && (size < MAX_USB_DEVICES)) { - /* copy hotpluged device mount point to the dev_array */ - if (isAutomountLocation(word)) - { - dev_array[size].path = word; - dev_array[size++].to_add = TRUE; - } - else - free(word); + dev_array[size].path = _strdup(path); + dev_array[size++].to_add = TRUE; } - - free(line); } fclose(f); @@ -833,10 +685,11 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) { char* path = NULL; BOOL dev_found = FALSE; - DEVICE_DRIVE_EXT* device_ext = (DEVICE_DRIVE_EXT*)ListDictionary_GetItemValue( - rdpdr->devman->devices, (void*)keys[j]); + DEVICE_DRIVE_EXT* device_ext = + (DEVICE_DRIVE_EXT*)ListDictionary_GetItemValue(rdpdr->devman->devices, (void*)keys[j]); - if (!device_ext || !device_ext->path || !device_ext->automount) + if (!device_ext || (device_ext->device.type != RDPDR_DTYP_FILESYSTEM) || + !device_ext->path || !device_ext->automount) continue; ConvertFromUnicode(CP_UTF8, 0, device_ext->path, -1, &path, 0, NULL, NULL); @@ -867,7 +720,8 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) if ((error = rdpdr_send_device_list_remove_request(rdpdr, 1, ids))) { - WLog_ERR(TAG, "rdpdr_send_device_list_remove_request failed with error %"PRIu32"!", + WLog_ERR(TAG, + "rdpdr_send_device_list_remove_request failed with error %" PRIu32 "!", error); goto cleanup; } @@ -877,43 +731,28 @@ static UINT handle_hotplug(rdpdrPlugin* rdpdr) /* add new devices */ for (i = 0; i < size; i++) { - RDPDR_DRIVE* drive; - if (dev_array[i].to_add) { + RDPDR_DRIVE drive = { 0 }; char* name; - drive = (RDPDR_DRIVE*) calloc(1, sizeof(RDPDR_DRIVE)); - if (!drive) - { - WLog_ERR(TAG, "calloc failed!"); - error = CHANNEL_RC_NO_MEMORY; - goto cleanup; - } + drive.Type = RDPDR_DTYP_FILESYSTEM; + drive.Path = dev_array[i].path; + drive.automount = TRUE; + name = strrchr(drive.Path, '/') + 1; + drive.Name = name; - drive->Type = RDPDR_DTYP_FILESYSTEM; - drive->Path = dev_array[i].path; - drive->automount = TRUE; - dev_array[i].path = NULL; - name = strrchr(drive->Path, '/') + 1; - drive->Name = _strdup(name); - - if (!drive->Name) + if (!drive.Name) { WLog_ERR(TAG, "_strdup failed!"); - free(drive->Path); - free(drive); error = CHANNEL_RC_NO_MEMORY; goto cleanup; } - if ((error = devman_load_device_service(rdpdr->devman, (RDPDR_DEVICE*)drive, + if ((error = devman_load_device_service(rdpdr->devman, (const RDPDR_DEVICE*)&drive, rdpdr->rdpcontext))) { WLog_ERR(TAG, "devman_load_device_service failed!"); - free(drive->Path); - free(drive->Name); - free(drive); goto cleanup; } } @@ -934,7 +773,7 @@ static void first_hotplug(rdpdrPlugin* rdpdr) if ((error = handle_hotplug(rdpdr))) { - WLog_ERR(TAG, "handle_hotplug failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "handle_hotplug failed with error %" PRIu32 "!", error); } } @@ -947,15 +786,7 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg) int rv; UINT error = 0; DWORD status; - rdpdr = (rdpdrPlugin*) arg; - - if (!(rdpdr->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) - { - WLog_ERR(TAG, "CreateEvent failed!"); - error = ERROR_INTERNAL_ERROR; - goto out; - } - + rdpdr = (rdpdrPlugin*)arg; mfd = open("/proc/mounts", O_RDONLY, 0); if (mfd < 0) @@ -977,7 +808,7 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg) if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error); goto out; } @@ -989,7 +820,7 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg) /* file /proc/mounts changed, handle this */ if ((error = handle_hotplug(rdpdr))) { - WLog_ERR(TAG, "handle_hotplug failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "handle_hotplug failed with error %" PRIu32 "!", error); goto out; } else @@ -1005,14 +836,15 @@ static DWORD WINAPI drive_hotplug_thread_func(LPVOID arg) out: if (error && rdpdr->rdpcontext) - setChannelError(rdpdr->rdpcontext, error, - "drive_hotplug_thread_func reported an error"); + setChannelError(rdpdr->rdpcontext, error, "drive_hotplug_thread_func reported an error"); - CloseHandle(rdpdr->stopEvent); ExitThread(error); return error; } +#endif + +#if !defined(_WIN32) && !defined(__IOS__) /** * Function description * @@ -1024,16 +856,21 @@ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) if (rdpdr->hotplugThread) { - if (rdpdr->stopEvent) - SetEvent(rdpdr->stopEvent); + SetEvent(rdpdr->stopEvent); +#ifdef __MACOSX__ + CFRunLoopStop(rdpdr->runLoop); +#endif if (WaitForSingleObject(rdpdr->hotplugThread, INFINITE) == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error); return error; } + CloseHandle(rdpdr->hotplugThread); + CloseHandle(rdpdr->stopEvent); + rdpdr->stopEvent = NULL; rdpdr->hotplugThread = NULL; } @@ -1042,7 +879,6 @@ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) #endif - /** * Function description * @@ -1051,7 +887,6 @@ static UINT drive_hotplug_thread_terminate(rdpdrPlugin* rdpdr) static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr) { UINT32 index; - RDPDR_DEVICE* device; rdpSettings* settings; UINT error = CHANNEL_RC_OK; rdpdr->devman = devman_new(rdpdr); @@ -1062,31 +897,45 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr) return CHANNEL_RC_NO_MEMORY; } - settings = (rdpSettings*) rdpdr->channelEntryPoints.pExtendedData; + settings = (rdpSettings*)rdpdr->channelEntryPoints.pExtendedData; if (settings->ClientHostname) - strncpy(rdpdr->computerName, settings->ClientHostname, - sizeof(rdpdr->computerName) - 1); + strncpy(rdpdr->computerName, settings->ClientHostname, sizeof(rdpdr->computerName) - 1); else - strncpy(rdpdr->computerName, settings->ComputerName, - sizeof(rdpdr->computerName) - 1); + strncpy(rdpdr->computerName, settings->ComputerName, sizeof(rdpdr->computerName) - 1); for (index = 0; index < settings->DeviceCount; index++) { - device = settings->DeviceArray[index]; + const RDPDR_DEVICE* device = settings->DeviceArray[index]; if (device->Type == RDPDR_DTYP_FILESYSTEM) { - RDPDR_DRIVE* drive = (RDPDR_DRIVE*)device; - - if (drive->Path && (strcmp(drive->Path, "*") == 0)) + const char DynamicDrives[] = "DynamicDrives"; + const RDPDR_DRIVE* drive = (const RDPDR_DRIVE*)device; + BOOL hotplugAll = strncmp(drive->Path, "*", 2) == 0; + BOOL hotplugLater = strncmp(drive->Path, DynamicDrives, sizeof(DynamicDrives)) == 0; + if (drive->Path && (hotplugAll || hotplugLater)) { - first_hotplug(rdpdr); + if (hotplugAll) + first_hotplug(rdpdr); +#ifndef _WIN32 + + if (!(rdpdr->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) + { + WLog_ERR(TAG, "CreateEvent failed!"); + return ERROR_INTERNAL_ERROR; + } + +#endif - if (!(rdpdr->hotplugThread = CreateThread(NULL, 0, - drive_hotplug_thread_func, rdpdr, 0, NULL))) + if (!(rdpdr->hotplugThread = + CreateThread(NULL, 0, drive_hotplug_thread_func, rdpdr, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); +#ifndef _WIN32 + CloseHandle(rdpdr->stopEvent); + rdpdr->stopEvent = NULL; +#endif return ERROR_INTERNAL_ERROR; } @@ -1094,10 +943,9 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr) } } - if ((error = devman_load_device_service(rdpdr->devman, device, - rdpdr->rdpcontext))) + if ((error = devman_load_device_service(rdpdr->devman, device, rdpdr->rdpcontext))) { - WLog_ERR(TAG, "devman_load_device_service failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "devman_load_device_service failed with error %" PRIu32 "!", error); return error; } } @@ -1105,8 +953,7 @@ static UINT rdpdr_process_connect(rdpdrPlugin* rdpdr) return error; } -static UINT rdpdr_process_server_announce_request(rdpdrPlugin* rdpdr, - wStream* s) +static UINT rdpdr_process_server_announce_request(rdpdrPlugin* rdpdr, wStream* s) { if (Stream_GetRemainingLength(s) < 8) return ERROR_INVALID_DATA; @@ -1134,11 +981,11 @@ static UINT rdpdr_send_client_announce_reply(rdpdrPlugin* rdpdr) return CHANNEL_RC_NO_MEMORY; } - Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */ + Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */ Stream_Write_UINT16(s, PAKID_CORE_CLIENTID_CONFIRM); /* PacketId (2 bytes) */ Stream_Write_UINT16(s, rdpdr->versionMajor); Stream_Write_UINT16(s, rdpdr->versionMinor); - Stream_Write_UINT32(s, (UINT32) rdpdr->clientID); + Stream_Write_UINT32(s, (UINT32)rdpdr->clientID); return rdpdr_send(rdpdr, s); } @@ -1156,8 +1003,7 @@ static UINT rdpdr_send_client_name_request(rdpdrPlugin* rdpdr) if (!rdpdr->computerName[0]) gethostname(rdpdr->computerName, sizeof(rdpdr->computerName) - 1); - computerNameLenW = ConvertToUnicode(CP_UTF8, 0, rdpdr->computerName, -1, - &computerNameW, 0) * 2; + computerNameLenW = ConvertToUnicode(CP_UTF8, 0, rdpdr->computerName, -1, &computerNameW, 0) * 2; s = Stream_New(NULL, 16 + computerNameLenW + 2); if (!s) @@ -1167,20 +1013,18 @@ static UINT rdpdr_send_client_name_request(rdpdrPlugin* rdpdr) return CHANNEL_RC_NO_MEMORY; } - Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */ + Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */ Stream_Write_UINT16(s, PAKID_CORE_CLIENT_NAME); /* PacketId (2 bytes) */ - Stream_Write_UINT32(s, 1); /* unicodeFlag, 0 for ASCII and 1 for Unicode */ - Stream_Write_UINT32(s, 0); /* codePage, must be set to zero */ - Stream_Write_UINT32(s, computerNameLenW + - 2); /* computerNameLen, including null terminator */ + Stream_Write_UINT32(s, 1); /* unicodeFlag, 0 for ASCII and 1 for Unicode */ + Stream_Write_UINT32(s, 0); /* codePage, must be set to zero */ + Stream_Write_UINT32(s, computerNameLenW + 2); /* computerNameLen, including null terminator */ Stream_Write(s, computerNameW, computerNameLenW); Stream_Write_UINT16(s, 0); /* null terminator */ free(computerNameW); return rdpdr_send(rdpdr, s); } -static UINT rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr, - wStream* s) +static UINT rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr, wStream* s) { UINT16 versionMajor; UINT16 versionMinor; @@ -1210,8 +1054,7 @@ static UINT rdpdr_process_server_clientid_confirm(rdpdrPlugin* rdpdr, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, - BOOL userLoggedOn) +static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, BOOL userLoggedOn) { int i; BYTE c; @@ -1232,7 +1075,7 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, return CHANNEL_RC_NO_MEMORY; } - Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */ + Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */ Stream_Write_UINT16(s, PAKID_CORE_DEVICELIST_ANNOUNCE); /* PacketId (2 bytes) */ count_pos = Stream_GetPosition(s); count = 0; @@ -1242,8 +1085,7 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, for (index = 0; index < keyCount; index++) { - device = (DEVICE*) ListDictionary_GetItemValue(rdpdr->devman->devices, - (void*) pKeys[index]); + device = (DEVICE*)ListDictionary_GetItemValue(rdpdr->devman->devices, (void*)pKeys[index]); /** * 1. versionMinor 0x0005 doesn't send PAKID_CORE_USER_LOGGEDON @@ -1252,8 +1094,8 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, * 3. other devices are sent only after user_loggedon */ - if ((rdpdr->versionMinor == 0x0005) || - (device->type == RDPDR_DTYP_SMARTCARD) || userLoggedOn) + if ((rdpdr->versionMinor == 0x0005) || (device->type == RDPDR_DTYP_SMARTCARD) || + userLoggedOn) { data_len = (device->data == NULL ? 0 : Stream_GetPosition(device->data)); @@ -1266,8 +1108,8 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, } Stream_Write_UINT32(s, device->type); /* deviceType */ - Stream_Write_UINT32(s, device->id); /* deviceID */ - strncpy((char*) Stream_Pointer(s), device->name, 8); + Stream_Write_UINT32(s, device->id); /* deviceID */ + strncpy((char*)Stream_Pointer(s), device->name, 8); for (i = 0; i < 8; i++) { @@ -1285,7 +1127,7 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, Stream_Write(s, Stream_Buffer(device->data), data_len); count++; - WLog_INFO(TAG, "registered device #%"PRIu32": %s (type=%"PRIu32" id=%"PRIu32")", + WLog_INFO(TAG, "registered device #%" PRIu32 ": %s (type=%" PRIu32 " id=%" PRIu32 ")", count, device->name, device->type, device->id); } } @@ -1299,6 +1141,40 @@ static UINT rdpdr_send_device_list_announce_request(rdpdrPlugin* rdpdr, return rdpdr_send(rdpdr, s); } +static UINT dummy_irp_response(rdpdrPlugin* rdpdr, wStream* s) +{ + + UINT32 DeviceId; + UINT32 FileId; + UINT32 CompletionId; + + wStream* output = Stream_New(NULL, 256); // RDPDR_DEVICE_IO_RESPONSE_LENGTH + if (!output) + { + WLog_ERR(TAG, "Stream_New failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + Stream_SetPosition(s, 4); /* see "rdpdr_process_receive" */ + + Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */ + Stream_Read_UINT32(s, FileId); /* FileId (4 bytes) */ + Stream_Read_UINT32(s, CompletionId); /* CompletionId (4 bytes) */ + + Stream_Write_UINT16(output, RDPDR_CTYP_CORE); /* Component (2 bytes) */ + Stream_Write_UINT16(output, PAKID_CORE_DEVICE_IOCOMPLETION); /* PacketId (2 bytes) */ + Stream_Write_UINT32(output, DeviceId); /* DeviceId (4 bytes) */ + Stream_Write_UINT32(output, CompletionId); /* CompletionId (4 bytes) */ + Stream_Write_UINT32(output, STATUS_UNSUCCESSFUL); /* IoStatus (4 bytes) */ + + Stream_Zero(output, 256 - RDPDR_DEVICE_IO_RESPONSE_LENGTH); + // or usage + // Stream_Write_UINT32(output, 0); /* Length */ + // Stream_Write_UINT8(output, 0); /* Padding */ + + return rdpdr_send(rdpdr, output); +} + /** * Function description * @@ -1312,18 +1188,49 @@ static UINT rdpdr_process_irp(rdpdrPlugin* rdpdr, wStream* s) if (!irp) { - WLog_ERR(TAG, "irp_new failed with %"PRIu32"!", error); + WLog_ERR(TAG, "irp_new failed with %" PRIu32 "!", error); + + if (error == CHANNEL_RC_OK) + { + return dummy_irp_response(rdpdr, s); + } + return error; } IFCALLRET(irp->device->IRPRequest, error, irp->device, irp); if (error) - WLog_ERR(TAG, "device->IRPRequest failed with error %"PRIu32"", error); + WLog_ERR(TAG, "device->IRPRequest failed with error %" PRIu32 "", error); return error; } +static UINT rdpdr_process_component(rdpdrPlugin* rdpdr, UINT16 component, UINT16 packetId, + wStream* s) +{ + UINT32 type; + DEVICE* device; + + switch (component) + { + case RDPDR_CTYP_PRN: + type = RDPDR_DTYP_PRINT; + break; + + default: + return ERROR_INVALID_DATA; + } + + device = devman_get_device_by_type(rdpdr->devman, type); + + if (!device) + return ERROR_INVALID_PARAMETER; + + return IFCALLRESULT(ERROR_INVALID_PARAMETER, device->CustomComponentRequest, device, component, + packetId, s); +} + /** * Function description * @@ -1341,8 +1248,7 @@ static UINT rdpdr_process_init(rdpdrPlugin* rdpdr) for (index = 0; index < keyCount; index++) { - device = (DEVICE*) ListDictionary_GetItemValue(rdpdr->devman->devices, - (void*) pKeys[index]); + device = (DEVICE*)ListDictionary_GetItemValue(rdpdr->devman->devices, (void*)pKeys[index]); IFCALLRET(device->Init, error, device); if (error != CHANNEL_RC_OK) @@ -1368,141 +1274,125 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) UINT16 packetId; UINT32 deviceId; UINT32 status; - UINT error; + UINT error = ERROR_INVALID_DATA; if (!rdpdr || !s) return CHANNEL_RC_NULL_DATA; - if (Stream_GetRemainingLength(s) < 4) - return ERROR_INVALID_DATA; - - Stream_Read_UINT16(s, component); /* Component (2 bytes) */ - Stream_Read_UINT16(s, packetId); /* PacketId (2 bytes) */ - - if (component == RDPDR_CTYP_CORE) + if (Stream_GetRemainingLength(s) >= 4) { - switch (packetId) - { - case PAKID_CORE_SERVER_ANNOUNCE: - if ((error = rdpdr_process_server_announce_request(rdpdr, s))) - return error; + Stream_Read_UINT16(s, component); /* Component (2 bytes) */ + Stream_Read_UINT16(s, packetId); /* PacketId (2 bytes) */ - if ((error = rdpdr_send_client_announce_reply(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_send_client_announce_reply failed with error %"PRIu32"", error); - return error; - } - - if ((error = rdpdr_send_client_name_request(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_send_client_name_request failed with error %"PRIu32"", error); - return error; - } - - if ((error = rdpdr_process_init(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_process_init failed with error %"PRIu32"", error); - return error; - } - - break; - - case PAKID_CORE_SERVER_CAPABILITY: - if ((error = rdpdr_process_capability_request(rdpdr, s))) - return error; + if (component == RDPDR_CTYP_CORE) + { + switch (packetId) + { + case PAKID_CORE_SERVER_ANNOUNCE: + if ((error = rdpdr_process_server_announce_request(rdpdr, s))) + { + } + else if ((error = rdpdr_send_client_announce_reply(rdpdr))) + { + WLog_ERR(TAG, + "rdpdr_send_client_announce_reply failed with error %" PRIu32 "", + error); + } + else if ((error = rdpdr_send_client_name_request(rdpdr))) + { + WLog_ERR(TAG, + "rdpdr_send_client_name_request failed with error %" PRIu32 "", + error); + } + else if ((error = rdpdr_process_init(rdpdr))) + { + WLog_ERR(TAG, "rdpdr_process_init failed with error %" PRIu32 "", error); + } - if ((error = rdpdr_send_capability_response(rdpdr))) - { - WLog_ERR(TAG, "rdpdr_send_capability_response failed with error %"PRIu32"", error); - return error; - } + break; - break; + case PAKID_CORE_SERVER_CAPABILITY: + if ((error = rdpdr_process_capability_request(rdpdr, s))) + { + } + else if ((error = rdpdr_send_capability_response(rdpdr))) + { + WLog_ERR(TAG, + "rdpdr_send_capability_response failed with error %" PRIu32 "", + error); + } - case PAKID_CORE_CLIENTID_CONFIRM: - if ((error = rdpdr_process_server_clientid_confirm(rdpdr, s))) - return error; + break; - if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE))) - { - WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %"PRIu32"", - error); - return error; - } + case PAKID_CORE_CLIENTID_CONFIRM: + if ((error = rdpdr_process_server_clientid_confirm(rdpdr, s))) + { + } + else if ((error = rdpdr_send_device_list_announce_request(rdpdr, FALSE))) + { + WLog_ERR( + TAG, + "rdpdr_send_device_list_announce_request failed with error %" PRIu32 "", + error); + } - break; + break; - case PAKID_CORE_USER_LOGGEDON: - if ((error = rdpdr_send_device_list_announce_request(rdpdr, TRUE))) - { - WLog_ERR(TAG, "rdpdr_send_device_list_announce_request failed with error %"PRIu32"", - error); - return error; - } + case PAKID_CORE_USER_LOGGEDON: + if ((error = rdpdr_send_device_list_announce_request(rdpdr, TRUE))) + { + WLog_ERR( + TAG, + "rdpdr_send_device_list_announce_request failed with error %" PRIu32 "", + error); + } - break; + break; - case PAKID_CORE_DEVICE_REPLY: + case PAKID_CORE_DEVICE_REPLY: - /* connect to a specific resource */ - if (Stream_GetRemainingLength(s) < 8) - return ERROR_INVALID_DATA; + /* connect to a specific resource */ + if (Stream_GetRemainingLength(s) >= 8) + { + Stream_Read_UINT32(s, deviceId); + Stream_Read_UINT32(s, status); + error = CHANNEL_RC_OK; + } - Stream_Read_UINT32(s, deviceId); - Stream_Read_UINT32(s, status); - break; + break; - case PAKID_CORE_DEVICE_IOREQUEST: - if ((error = rdpdr_process_irp(rdpdr, s))) - { - WLog_ERR(TAG, "rdpdr_process_irp failed with error %"PRIu32"", error); - return error; - } + case PAKID_CORE_DEVICE_IOREQUEST: + if ((error = rdpdr_process_irp(rdpdr, s))) + { + WLog_ERR(TAG, "rdpdr_process_irp failed with error %" PRIu32 "", error); + return error; + } + else + s = NULL; - s = NULL; - break; + break; - default: - WLog_ERR(TAG, "RDPDR_CTYP_CORE unknown PacketId: 0x%04"PRIX16"", packetId); - return ERROR_INVALID_DATA; - break; + default: + WLog_ERR(TAG, "RDPDR_CTYP_CORE unknown PacketId: 0x%04" PRIX16 "", packetId); + error = ERROR_INVALID_DATA; + break; + } } - } - else if (component == RDPDR_CTYP_PRN) - { - switch (packetId) + else { - case PAKID_PRN_CACHE_DATA: - { - UINT32 eventID; - - if (Stream_GetRemainingLength(s) < 4) - return ERROR_INVALID_DATA; - - Stream_Read_UINT32(s, eventID); - WLog_ERR(TAG, - "Ignoring unhandled message PAKID_PRN_CACHE_DATA (EventID: 0x%08"PRIX32")", eventID); - } - break; - - case PAKID_PRN_USING_XPS: - WLog_ERR(TAG, "Ignoring unhandled message PAKID_PRN_USING_XPS"); - break; + error = rdpdr_process_component(rdpdr, component, packetId, s); - default: - WLog_ERR(TAG, "Unknown printing component packetID: 0x%04"PRIX16"", packetId); - return ERROR_INVALID_DATA; + if (error != CHANNEL_RC_OK) + { + WLog_ERR(TAG, + "Unknown message: Component: 0x%04" PRIX16 " PacketId: 0x%04" PRIX16 "", + component, packetId); + } } } - else - { - WLog_ERR(TAG, "Unknown message: Component: 0x%04"PRIX16" PacketId: 0x%04"PRIX16"", component, - packetId); - return ERROR_INVALID_DATA; - } Stream_Free(s, TRUE); - return CHANNEL_RC_OK; + return error; } /** @@ -1513,23 +1403,30 @@ static UINT rdpdr_process_receive(rdpdrPlugin* rdpdr, wStream* s) UINT rdpdr_send(rdpdrPlugin* rdpdr, wStream* s) { UINT status; - rdpdrPlugin* plugin = (rdpdrPlugin*) rdpdr; + rdpdrPlugin* plugin = (rdpdrPlugin*)rdpdr; if (!rdpdr || !s) + { + Stream_Free(s, TRUE); return CHANNEL_RC_NULL_DATA; + } if (!plugin) + { + Stream_Free(s, TRUE); status = CHANNEL_RC_BAD_INIT_HANDLE; + } else { - status = plugin->channelEntryPoints.pVirtualChannelWriteEx(plugin->InitHandle, plugin->OpenHandle, - Stream_Buffer(s), (UINT32) Stream_GetPosition(s), s); + status = plugin->channelEntryPoints.pVirtualChannelWriteEx( + plugin->InitHandle, plugin->OpenHandle, Stream_Buffer(s), (UINT32)Stream_GetPosition(s), + s); } if (status != CHANNEL_RC_OK) { Stream_Free(s, TRUE); - WLog_ERR(TAG, "pVirtualChannelWriteEx failed with %s [%08"PRIX32"]", + WLog_ERR(TAG, "pVirtualChannelWriteEx failed with %s [%08" PRIX32 "]", WTSErrorToString(status), status); } @@ -1541,8 +1438,9 @@ UINT rdpdr_send(rdpdrPlugin* rdpdr, wStream* s) * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, - void* pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) +static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, void* pData, + UINT32 dataLength, UINT32 totalLength, + UINT32 dataFlags) { wStream* data_in; @@ -1566,16 +1464,16 @@ static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, if (!rdpdr->data_in) { - WLog_ERR(TAG, "Stream_New failed!"); + WLog_ERR(TAG, "Stream_New failed!"); return CHANNEL_RC_NO_MEMORY; } } data_in = rdpdr->data_in; - if (!Stream_EnsureRemainingCapacity(data_in, (int) dataLength)) + if (!Stream_EnsureRemainingCapacity(data_in, dataLength)) { - WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); + WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); return ERROR_INVALID_DATA; } @@ -1593,7 +1491,7 @@ static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, Stream_SealLength(data_in); Stream_SetPosition(data_in, 0); - if (!MessageQueue_Post(rdpdr->queue, NULL, 0, (void*) data_in, NULL)) + if (!MessageQueue_Post(rdpdr->queue, NULL, 0, (void*)data_in, NULL)) { WLog_ERR(TAG, "MessageQueue_Post failed!"); return ERROR_INTERNAL_ERROR; @@ -1604,36 +1502,42 @@ static UINT rdpdr_virtual_channel_event_data_received(rdpdrPlugin* rdpdr, } static VOID VCAPITYPE rdpdr_virtual_channel_open_event_ex(LPVOID lpUserParam, DWORD openHandle, - UINT event, - LPVOID pData, UINT32 dataLength, UINT32 totalLength, UINT32 dataFlags) + UINT event, LPVOID pData, + UINT32 dataLength, UINT32 totalLength, + UINT32 dataFlags) { UINT error = CHANNEL_RC_OK; - rdpdrPlugin* rdpdr = (rdpdrPlugin*) lpUserParam; - - if (!rdpdr || !pData || (rdpdr->OpenHandle != openHandle)) - { - WLog_ERR(TAG, "error no match"); - return; - } + rdpdrPlugin* rdpdr = (rdpdrPlugin*)lpUserParam; switch (event) { case CHANNEL_EVENT_DATA_RECEIVED: - if ((error = rdpdr_virtual_channel_event_data_received(rdpdr, pData, - dataLength, totalLength, dataFlags))) + if (!rdpdr || !pData || (rdpdr->OpenHandle != openHandle)) + { + WLog_ERR(TAG, "error no match"); + return; + } + if ((error = rdpdr_virtual_channel_event_data_received(rdpdr, pData, dataLength, + totalLength, dataFlags))) WLog_ERR(TAG, - "rdpdr_virtual_channel_event_data_received failed with error %"PRIu32"!", error); + "rdpdr_virtual_channel_event_data_received failed with error %" PRIu32 "!", + error); break; + case CHANNEL_EVENT_WRITE_CANCELLED: case CHANNEL_EVENT_WRITE_COMPLETE: - break; + { + wStream* s = (wStream*)pData; + Stream_Free(s, TRUE); + } + break; case CHANNEL_EVENT_USER: break; } - if (error && rdpdr->rdpcontext) + if (error && rdpdr && rdpdr->rdpcontext) setChannelError(rdpdr->rdpcontext, error, "rdpdr_virtual_channel_open_event_ex reported an error"); @@ -1644,18 +1548,18 @@ static DWORD WINAPI rdpdr_virtual_channel_client_thread(LPVOID arg) { wStream* data; wMessage message; - rdpdrPlugin* rdpdr = (rdpdrPlugin*) arg; + rdpdrPlugin* rdpdr = (rdpdrPlugin*)arg; UINT error; if (!rdpdr) { - ExitThread((DWORD) CHANNEL_RC_NULL_DATA); + ExitThread((DWORD)CHANNEL_RC_NULL_DATA); return CHANNEL_RC_NULL_DATA; } if ((error = rdpdr_process_connect(rdpdr))) { - WLog_ERR(TAG, "rdpdr_process_connect failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rdpdr_process_connect failed with error %" PRIu32 "!", error); if (rdpdr->rdpcontext) setChannelError(rdpdr->rdpcontext, error, @@ -1677,17 +1581,17 @@ static DWORD WINAPI rdpdr_virtual_channel_client_thread(LPVOID arg) if (message.id == 0) { - data = (wStream*) message.wParam; + data = (wStream*)message.wParam; if ((error = rdpdr_process_receive(rdpdr, data))) { - WLog_ERR(TAG, "rdpdr_process_receive failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rdpdr_process_receive failed with error %" PRIu32 "!", error); if (rdpdr->rdpcontext) setChannelError(rdpdr->rdpcontext, error, "rdpdr_virtual_channel_client_thread reported an error"); - ExitThread((DWORD) error); + ExitThread((DWORD)error); return error; } } @@ -1698,21 +1602,28 @@ static DWORD WINAPI rdpdr_virtual_channel_client_thread(LPVOID arg) return 0; } +static void queue_free(void* obj) +{ + wStream* s = obj; + Stream_Free(s, TRUE); +} + /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, - LPVOID pData, UINT32 dataLength) +static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, LPVOID pData, + UINT32 dataLength) { UINT32 status; - status = rdpdr->channelEntryPoints.pVirtualChannelOpenEx(rdpdr->InitHandle, - &rdpdr->OpenHandle, rdpdr->channelDef.name, rdpdr_virtual_channel_open_event_ex); + status = rdpdr->channelEntryPoints.pVirtualChannelOpenEx(rdpdr->InitHandle, &rdpdr->OpenHandle, + rdpdr->channelDef.name, + rdpdr_virtual_channel_open_event_ex); if (status != CHANNEL_RC_OK) { - WLog_ERR(TAG, "pVirtualChannelOpenEx failed with %s [%08"PRIX32"]", + WLog_ERR(TAG, "pVirtualChannelOpenEx failed with %s [%08" PRIX32 "]", WTSErrorToString(status), status); return status; } @@ -1725,9 +1636,10 @@ static UINT rdpdr_virtual_channel_event_connected(rdpdrPlugin* rdpdr, return CHANNEL_RC_NO_MEMORY; } - if (!(rdpdr->thread = CreateThread(NULL, 0, - rdpdr_virtual_channel_client_thread, (void*) rdpdr, 0, - NULL))) + rdpdr->queue->object.fnObjectFree = queue_free; + + if (!(rdpdr->thread = + CreateThread(NULL, 0, rdpdr_virtual_channel_client_thread, (void*)rdpdr, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); return ERROR_INTERNAL_ERROR; @@ -1748,11 +1660,11 @@ static UINT rdpdr_virtual_channel_event_disconnected(rdpdrPlugin* rdpdr) if (rdpdr->OpenHandle == 0) return CHANNEL_RC_OK; - if (MessageQueue_PostQuit(rdpdr->queue, 0) - && (WaitForSingleObject(rdpdr->thread, INFINITE) == WAIT_FAILED)) + if (MessageQueue_PostQuit(rdpdr->queue, 0) && + (WaitForSingleObject(rdpdr->thread, INFINITE) == WAIT_FAILED)) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error); return error; } @@ -1763,7 +1675,7 @@ static UINT rdpdr_virtual_channel_event_disconnected(rdpdrPlugin* rdpdr) if ((error = drive_hotplug_thread_terminate(rdpdr))) { - WLog_ERR(TAG, "drive_hotplug_thread_terminate failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "drive_hotplug_thread_terminate failed with error %" PRIu32 "!", error); return error; } @@ -1771,7 +1683,7 @@ static UINT rdpdr_virtual_channel_event_disconnected(rdpdrPlugin* rdpdr) if (CHANNEL_RC_OK != error) { - WLog_ERR(TAG, "pVirtualChannelCloseEx failed with %s [%08"PRIX32"]", + WLog_ERR(TAG, "pVirtualChannelCloseEx failed with %s [%08" PRIX32 "]", WTSErrorToString(error), error); } @@ -1799,11 +1711,10 @@ static void rdpdr_virtual_channel_event_terminated(rdpdrPlugin* rdpdr) } static VOID VCAPITYPE rdpdr_virtual_channel_init_event_ex(LPVOID lpUserParam, LPVOID pInitHandle, - UINT event, - LPVOID pData, UINT dataLength) + UINT event, LPVOID pData, UINT dataLength) { UINT error = CHANNEL_RC_OK; - rdpdrPlugin* rdpdr = (rdpdrPlugin*) lpUserParam; + rdpdrPlugin* rdpdr = (rdpdrPlugin*)lpUserParam; if (!rdpdr || (rdpdr->InitHandle != pInitHandle)) { @@ -1818,14 +1729,16 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event_ex(LPVOID lpUserParam, LP case CHANNEL_EVENT_CONNECTED: if ((error = rdpdr_virtual_channel_event_connected(rdpdr, pData, dataLength))) - WLog_ERR(TAG, "rdpdr_virtual_channel_event_connected failed with error %"PRIu32"!", + WLog_ERR(TAG, + "rdpdr_virtual_channel_event_connected failed with error %" PRIu32 "!", error); break; case CHANNEL_EVENT_DISCONNECTED: if ((error = rdpdr_virtual_channel_event_disconnected(rdpdr))) - WLog_ERR(TAG, "rdpdr_virtual_channel_event_disconnected failed with error %"PRIu32"!", + WLog_ERR(TAG, + "rdpdr_virtual_channel_event_disconnected failed with error %" PRIu32 "!", error); break; @@ -1837,7 +1750,7 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event_ex(LPVOID lpUserParam, LP case CHANNEL_EVENT_ATTACHED: case CHANNEL_EVENT_DETACHED: default: - WLog_ERR(TAG, "unknown event %"PRIu32"!", event); + WLog_ERR(TAG, "unknown event %" PRIu32 "!", event); break; } @@ -1847,14 +1760,14 @@ static VOID VCAPITYPE rdpdr_virtual_channel_init_event_ex(LPVOID lpUserParam, LP } /* rdpdr is always built-in */ -#define VirtualChannelEntryEx rdpdr_VirtualChannelEntryEx +#define VirtualChannelEntryEx rdpdr_VirtualChannelEntryEx BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID pInitHandle) { UINT rc; rdpdrPlugin* rdpdr; CHANNEL_ENTRY_POINTS_FREERDP_EX* pEntryPointsEx; - rdpdr = (rdpdrPlugin*) calloc(1, sizeof(rdpdrPlugin)); + rdpdr = (rdpdrPlugin*)calloc(1, sizeof(rdpdrPlugin)); if (!rdpdr) { @@ -1863,12 +1776,10 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p } rdpdr->channelDef.options = - CHANNEL_OPTION_INITIALIZED | - CHANNEL_OPTION_ENCRYPT_RDP | - CHANNEL_OPTION_COMPRESS_RDP; + CHANNEL_OPTION_INITIALIZED | CHANNEL_OPTION_ENCRYPT_RDP | CHANNEL_OPTION_COMPRESS_RDP; sprintf_s(rdpdr->channelDef.name, ARRAYSIZE(rdpdr->channelDef.name), "rdpdr"); rdpdr->sequenceId = 0; - pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*) pEntryPoints; + pEntryPointsEx = (CHANNEL_ENTRY_POINTS_FREERDP_EX*)pEntryPoints; if ((pEntryPointsEx->cbSize >= sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)) && (pEntryPointsEx->MagicNumber == FREERDP_CHANNEL_MAGIC_NUMBER)) @@ -1876,17 +1787,16 @@ BOOL VCAPITYPE VirtualChannelEntryEx(PCHANNEL_ENTRY_POINTS pEntryPoints, PVOID p rdpdr->rdpcontext = pEntryPointsEx->context; } - CopyMemory(&(rdpdr->channelEntryPoints), pEntryPoints, - sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)); + CopyMemory(&(rdpdr->channelEntryPoints), pEntryPoints, sizeof(CHANNEL_ENTRY_POINTS_FREERDP_EX)); rdpdr->InitHandle = pInitHandle; - rc = rdpdr->channelEntryPoints.pVirtualChannelInitEx(rdpdr, NULL, pInitHandle, - &rdpdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, - rdpdr_virtual_channel_init_event_ex); + rc = rdpdr->channelEntryPoints.pVirtualChannelInitEx( + rdpdr, NULL, pInitHandle, &rdpdr->channelDef, 1, VIRTUAL_CHANNEL_VERSION_WIN2000, + rdpdr_virtual_channel_init_event_ex); if (CHANNEL_RC_OK != rc) { - WLog_ERR(TAG, "pVirtualChannelInitEx failed with %s [%08"PRIX32"]", - WTSErrorToString(rc), rc); + WLog_ERR(TAG, "pVirtualChannelInitEx failed with %s [%08" PRIX32 "]", WTSErrorToString(rc), + rc); free(rdpdr); return FALSE; } diff --git a/channels/rdpdr/client/rdpdr_main.h b/channels/rdpdr/client/rdpdr_main.h index 1cdd2ce..4c372da 100644 --- a/channels/rdpdr/client/rdpdr_main.h +++ b/channels/rdpdr/client/rdpdr_main.h @@ -70,9 +70,11 @@ struct rdpdr_plugin HANDLE hotplugThread; #ifdef _WIN32 HWND hotplug_wnd; -#elif __MACOSX__ +#endif +#ifdef __MACOSX__ CFRunLoopRef runLoop; -#else +#endif +#ifndef _WIN32 HANDLE stopEvent; #endif rdpContext* rdpcontext; diff --git a/channels/rdpdr/server/rdpdr_main.c b/channels/rdpdr/server/rdpdr_main.c index 5abf8d0..3e005da 100644 --- a/channels/rdpdr/server/rdpdr_main.c +++ b/channels/rdpdr/server/rdpdr_main.c @@ -39,7 +39,7 @@ static UINT32 g_ClientId = 0; static RDPDR_IRP* rdpdr_server_irp_new() { RDPDR_IRP* irp; - irp = (RDPDR_IRP*) calloc(1, sizeof(RDPDR_IRP)); + irp = (RDPDR_IRP*)calloc(1, sizeof(RDPDR_IRP)); return irp; } @@ -48,19 +48,15 @@ static void rdpdr_server_irp_free(RDPDR_IRP* irp) free(irp); } -static BOOL rdpdr_server_enqueue_irp(RdpdrServerContext* context, - RDPDR_IRP* irp) +static BOOL rdpdr_server_enqueue_irp(RdpdrServerContext* context, RDPDR_IRP* irp) { - return ListDictionary_Add(context->priv->IrpList, - (void*)(size_t) irp->CompletionId, irp); + return ListDictionary_Add(context->priv->IrpList, (void*)(size_t)irp->CompletionId, irp); } -static RDPDR_IRP* rdpdr_server_dequeue_irp(RdpdrServerContext* context, - UINT32 completionId) +static RDPDR_IRP* rdpdr_server_dequeue_irp(RdpdrServerContext* context, UINT32 completionId) { RDPDR_IRP* irp; - irp = (RDPDR_IRP*) ListDictionary_Remove(context->priv->IrpList, - (void*)(size_t) completionId); + irp = (RDPDR_IRP*)ListDictionary_Remove(context->priv->IrpList, (void*)(size_t)completionId); return irp; } @@ -86,17 +82,15 @@ static UINT rdpdr_server_send_announce_request(RdpdrServerContext* context) return CHANNEL_RC_NO_MEMORY; } - Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */ - Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ - Stream_Write_UINT16(s, - context->priv->VersionMajor); /* VersionMajor (2 bytes) */ - Stream_Write_UINT16(s, - context->priv->VersionMinor); /* VersionMinor (2 bytes) */ - Stream_Write_UINT32(s, context->priv->ClientId); /* ClientId (4 bytes) */ + Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */ + Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ + Stream_Write_UINT16(s, context->priv->VersionMajor); /* VersionMajor (2 bytes) */ + Stream_Write_UINT16(s, context->priv->VersionMinor); /* VersionMinor (2 bytes) */ + Stream_Write_UINT32(s, context->priv->ClientId); /* ClientId (4 bytes) */ Stream_SealLength(s); winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), Stream_Length(s)); - status = WTSVirtualChannelWrite(context->priv->ChannelHandle, - (PCHAR) Stream_Buffer(s), Stream_Length(s), &written); + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR)Stream_Buffer(s), + Stream_Length(s), &written); Stream_Free(s, TRUE); return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } @@ -106,8 +100,8 @@ static UINT rdpdr_server_send_announce_request(RdpdrServerContext* context) * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context, - wStream* s, RDPDR_HEADER* header) +static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context, wStream* s, + RDPDR_HEADER* header) { UINT32 ClientId; UINT16 VersionMajor; @@ -121,9 +115,10 @@ static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context, Stream_Read_UINT16(s, VersionMajor); /* VersionMajor (2 bytes) */ Stream_Read_UINT16(s, VersionMinor); /* VersionMinor (2 bytes) */ - Stream_Read_UINT32(s, ClientId); /* ClientId (4 bytes) */ + Stream_Read_UINT32(s, ClientId); /* ClientId (4 bytes) */ WLog_DBG(TAG, - "Client Announce Response: VersionMajor: 0x%08"PRIX16" VersionMinor: 0x%04"PRIX16" ClientId: 0x%08"PRIX32"", + "Client Announce Response: VersionMajor: 0x%08" PRIX16 " VersionMinor: 0x%04" PRIX16 + " ClientId: 0x%08" PRIX32 "", VersionMajor, VersionMinor, ClientId); context->priv->ClientId = ClientId; return CHANNEL_RC_OK; @@ -134,8 +129,8 @@ static UINT rdpdr_server_receive_announce_response(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* - context, wStream* s, RDPDR_HEADER* header) +static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* context, wStream* s, + RDPDR_HEADER* header) { UINT32 UnicodeFlag; UINT32 ComputerNameLen; @@ -146,8 +141,8 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* return ERROR_INVALID_DATA; } - Stream_Read_UINT32(s, UnicodeFlag); /* UnicodeFlag (4 bytes) */ - Stream_Seek_UINT32(s); /* CodePage (4 bytes), MUST be set to zero */ + Stream_Read_UINT32(s, UnicodeFlag); /* UnicodeFlag (4 bytes) */ + Stream_Seek_UINT32(s); /* CodePage (4 bytes), MUST be set to zero */ Stream_Read_UINT32(s, ComputerNameLen); /* ComputerNameLen (4 bytes) */ /* UnicodeFlag is either 0 or 1, the other 31 bits must be ignored. */ @@ -162,7 +157,7 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* { if ((ComputerNameLen % 2) || ComputerNameLen > 512 || ComputerNameLen < 2) { - WLog_ERR(TAG, "invalid unicode computer name length: %"PRIu32"", ComputerNameLen); + WLog_ERR(TAG, "invalid unicode computer name length: %" PRIu32 "", ComputerNameLen); return ERROR_INVALID_DATA; } } @@ -170,7 +165,7 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* { if (ComputerNameLen > 256 || ComputerNameLen < 1) { - WLog_ERR(TAG, "invalid ascii computer name length: %"PRIu32"", ComputerNameLen); + WLog_ERR(TAG, "invalid ascii computer name length: %" PRIu32 "", ComputerNameLen); return ERROR_INVALID_DATA; } } @@ -198,7 +193,7 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* if (UnicodeFlag) { - if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*) Stream_Pointer(s), -1, + if (ConvertFromUnicode(CP_UTF8, 0, (WCHAR*)Stream_Pointer(s), -1, &(context->priv->ClientComputerName), 0, NULL, NULL) < 1) { WLog_ERR(TAG, "failed to convert client computer name"); @@ -207,7 +202,7 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* } else { - context->priv->ClientComputerName = _strdup((char*) Stream_Pointer(s)); + context->priv->ClientComputerName = _strdup((char*)Stream_Pointer(s)); if (!context->priv->ClientComputerName) { @@ -226,8 +221,7 @@ static UINT rdpdr_server_receive_client_name_request(RdpdrServerContext* * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_read_capability_set_header(wStream* s, - RDPDR_CAPABILITY_HEADER* header) +static UINT rdpdr_server_read_capability_set_header(wStream* s, RDPDR_CAPABILITY_HEADER* header) { if (Stream_GetRemainingLength(s) < 8) { @@ -235,10 +229,9 @@ static UINT rdpdr_server_read_capability_set_header(wStream* s, return ERROR_INVALID_DATA; } - Stream_Read_UINT16(s, header->CapabilityType); /* CapabilityType (2 bytes) */ - Stream_Read_UINT16(s, - header->CapabilityLength); /* CapabilityLength (2 bytes) */ - Stream_Read_UINT32(s, header->Version); /* Version (4 bytes) */ + Stream_Read_UINT16(s, header->CapabilityType); /* CapabilityType (2 bytes) */ + Stream_Read_UINT16(s, header->CapabilityLength); /* CapabilityLength (2 bytes) */ + Stream_Read_UINT32(s, header->Version); /* Version (4 bytes) */ return CHANNEL_RC_OK; } @@ -247,8 +240,7 @@ static UINT rdpdr_server_read_capability_set_header(wStream* s, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_write_capability_set_header(wStream* s, - RDPDR_CAPABILITY_HEADER* header) +static UINT rdpdr_server_write_capability_set_header(wStream* s, RDPDR_CAPABILITY_HEADER* header) { if (!Stream_EnsureRemainingCapacity(s, 8)) { @@ -256,10 +248,9 @@ static UINT rdpdr_server_write_capability_set_header(wStream* s, return ERROR_INVALID_DATA; } - Stream_Write_UINT16(s, header->CapabilityType); /* CapabilityType (2 bytes) */ - Stream_Write_UINT16(s, - header->CapabilityLength); /* CapabilityLength (2 bytes) */ - Stream_Write_UINT32(s, header->Version); /* Version (4 bytes) */ + Stream_Write_UINT16(s, header->CapabilityType); /* CapabilityType (2 bytes) */ + Stream_Write_UINT16(s, header->CapabilityLength); /* CapabilityLength (2 bytes) */ + Stream_Write_UINT32(s, header->Version); /* Version (4 bytes) */ return CHANNEL_RC_OK; } @@ -268,8 +259,8 @@ static UINT rdpdr_server_write_capability_set_header(wStream* s, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* - context, wStream* s, RDPDR_CAPABILITY_HEADER* header) +static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* context, wStream* s, + RDPDR_CAPABILITY_HEADER* header) { UINT32 ioCode1; UINT32 extraFlags1; @@ -284,17 +275,15 @@ static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* return ERROR_INVALID_DATA; } - Stream_Seek_UINT32(s); /* osType (4 bytes), ignored on receipt */ - Stream_Seek_UINT32(s); /* osVersion (4 bytes), unused and must be set to zero */ + Stream_Seek_UINT32(s); /* osType (4 bytes), ignored on receipt */ + Stream_Seek_UINT32(s); /* osVersion (4 bytes), unused and must be set to zero */ Stream_Read_UINT16(s, VersionMajor); /* protocolMajorVersion (2 bytes) */ Stream_Read_UINT16(s, VersionMinor); /* protocolMinorVersion (2 bytes) */ - Stream_Read_UINT32(s, ioCode1); /* ioCode1 (4 bytes) */ - Stream_Seek_UINT32( - s); /* ioCode2 (4 bytes), must be set to zero, reserved for future use */ + Stream_Read_UINT32(s, ioCode1); /* ioCode1 (4 bytes) */ + Stream_Seek_UINT32(s); /* ioCode2 (4 bytes), must be set to zero, reserved for future use */ Stream_Read_UINT32(s, extendedPdu); /* extendedPdu (4 bytes) */ Stream_Read_UINT32(s, extraFlags1); /* extraFlags1 (4 bytes) */ - Stream_Seek_UINT32( - s); /* extraFlags2 (4 bytes), must be set to zero, reserved for future use */ + Stream_Seek_UINT32(s); /* extraFlags2 (4 bytes), must be set to zero, reserved for future use */ if (header->Version == GENERAL_CAPABILITY_VERSION_02) { @@ -304,12 +293,10 @@ static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* return ERROR_INVALID_DATA; } - Stream_Read_UINT32(s, - SpecialTypeDeviceCap); /* SpecialTypeDeviceCap (4 bytes) */ + Stream_Read_UINT32(s, SpecialTypeDeviceCap); /* SpecialTypeDeviceCap (4 bytes) */ } - context->priv->UserLoggedOnPdu = (extendedPdu & RDPDR_USER_LOGGEDON_PDU) ? - TRUE : FALSE; + context->priv->UserLoggedOnPdu = (extendedPdu & RDPDR_USER_LOGGEDON_PDU) ? TRUE : FALSE; return CHANNEL_RC_OK; } @@ -318,8 +305,7 @@ static UINT rdpdr_server_read_general_capability_set(RdpdrServerContext* * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* - context, wStream* s) +static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* context, wStream* s) { UINT32 ioCode1; UINT32 extendedPdu; @@ -330,25 +316,25 @@ static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* header.CapabilityLength = RDPDR_CAPABILITY_HEADER_LENGTH + 36; header.Version = GENERAL_CAPABILITY_VERSION_02; ioCode1 = 0; - ioCode1 |= RDPDR_IRP_MJ_CREATE; /* always set */ - ioCode1 |= RDPDR_IRP_MJ_CLEANUP; /* always set */ - ioCode1 |= RDPDR_IRP_MJ_CLOSE; /* always set */ - ioCode1 |= RDPDR_IRP_MJ_READ; /* always set */ - ioCode1 |= RDPDR_IRP_MJ_WRITE; /* always set */ - ioCode1 |= RDPDR_IRP_MJ_FLUSH_BUFFERS; /* always set */ - ioCode1 |= RDPDR_IRP_MJ_SHUTDOWN; /* always set */ - ioCode1 |= RDPDR_IRP_MJ_DEVICE_CONTROL; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_CREATE; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_CLEANUP; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_CLOSE; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_READ; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_WRITE; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_FLUSH_BUFFERS; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_SHUTDOWN; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_DEVICE_CONTROL; /* always set */ ioCode1 |= RDPDR_IRP_MJ_QUERY_VOLUME_INFORMATION; /* always set */ - ioCode1 |= RDPDR_IRP_MJ_SET_VOLUME_INFORMATION; /* always set */ - ioCode1 |= RDPDR_IRP_MJ_QUERY_INFORMATION; /* always set */ - ioCode1 |= RDPDR_IRP_MJ_SET_INFORMATION; /* always set */ - ioCode1 |= RDPDR_IRP_MJ_DIRECTORY_CONTROL; /* always set */ - ioCode1 |= RDPDR_IRP_MJ_LOCK_CONTROL; /* always set */ - ioCode1 |= RDPDR_IRP_MJ_QUERY_SECURITY; /* optional */ - ioCode1 |= RDPDR_IRP_MJ_SET_SECURITY; /* optional */ + ioCode1 |= RDPDR_IRP_MJ_SET_VOLUME_INFORMATION; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_QUERY_INFORMATION; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_SET_INFORMATION; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_DIRECTORY_CONTROL; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_LOCK_CONTROL; /* always set */ + ioCode1 |= RDPDR_IRP_MJ_QUERY_SECURITY; /* optional */ + ioCode1 |= RDPDR_IRP_MJ_SET_SECURITY; /* optional */ extendedPdu = 0; extendedPdu |= RDPDR_CLIENT_DISPLAY_NAME_PDU; /* always set */ - extendedPdu |= RDPDR_DEVICE_REMOVE_PDUS; /* optional */ + extendedPdu |= RDPDR_DEVICE_REMOVE_PDUS; /* optional */ if (context->priv->UserLoggedOnPdu) extendedPdu |= RDPDR_USER_LOGGEDON_PDU; /* optional */ @@ -365,21 +351,16 @@ static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* rdpdr_server_write_capability_set_header(s, &header); Stream_Write_UINT32(s, 0); /* osType (4 bytes), ignored on receipt */ - Stream_Write_UINT32(s, - 0); /* osVersion (4 bytes), unused and must be set to zero */ - Stream_Write_UINT16(s, - context->priv->VersionMajor); /* protocolMajorVersion (2 bytes) */ - Stream_Write_UINT16(s, - context->priv->VersionMinor); /* protocolMinorVersion (2 bytes) */ - Stream_Write_UINT32(s, ioCode1); /* ioCode1 (4 bytes) */ - Stream_Write_UINT32(s, - 0); /* ioCode2 (4 bytes), must be set to zero, reserved for future use */ + Stream_Write_UINT32(s, 0); /* osVersion (4 bytes), unused and must be set to zero */ + Stream_Write_UINT16(s, context->priv->VersionMajor); /* protocolMajorVersion (2 bytes) */ + Stream_Write_UINT16(s, context->priv->VersionMinor); /* protocolMinorVersion (2 bytes) */ + Stream_Write_UINT32(s, ioCode1); /* ioCode1 (4 bytes) */ + Stream_Write_UINT32(s, 0); /* ioCode2 (4 bytes), must be set to zero, reserved for future use */ Stream_Write_UINT32(s, extendedPdu); /* extendedPdu (4 bytes) */ Stream_Write_UINT32(s, extraFlags1); /* extraFlags1 (4 bytes) */ - Stream_Write_UINT32(s, - 0); /* extraFlags2 (4 bytes), must be set to zero, reserved for future use */ - Stream_Write_UINT32(s, - SpecialTypeDeviceCap); /* SpecialTypeDeviceCap (4 bytes) */ + Stream_Write_UINT32( + s, 0); /* extraFlags2 (4 bytes), must be set to zero, reserved for future use */ + Stream_Write_UINT32(s, SpecialTypeDeviceCap); /* SpecialTypeDeviceCap (4 bytes) */ return CHANNEL_RC_OK; } @@ -388,8 +369,8 @@ static UINT rdpdr_server_write_general_capability_set(RdpdrServerContext* * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_read_printer_capability_set(RdpdrServerContext* - context, wStream* s, RDPDR_CAPABILITY_HEADER* header) +static UINT rdpdr_server_read_printer_capability_set(RdpdrServerContext* context, wStream* s, + RDPDR_CAPABILITY_HEADER* header) { return CHANNEL_RC_OK; } @@ -399,8 +380,7 @@ static UINT rdpdr_server_read_printer_capability_set(RdpdrServerContext* * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_write_printer_capability_set(RdpdrServerContext* - context, wStream* s) +static UINT rdpdr_server_write_printer_capability_set(RdpdrServerContext* context, wStream* s) { RDPDR_CAPABILITY_HEADER header; header.CapabilityType = CAP_PRINTER_TYPE; @@ -421,8 +401,8 @@ static UINT rdpdr_server_write_printer_capability_set(RdpdrServerContext* * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_read_port_capability_set(RdpdrServerContext* context, - wStream* s, RDPDR_CAPABILITY_HEADER* header) +static UINT rdpdr_server_read_port_capability_set(RdpdrServerContext* context, wStream* s, + RDPDR_CAPABILITY_HEADER* header) { return CHANNEL_RC_OK; } @@ -432,8 +412,7 @@ static UINT rdpdr_server_read_port_capability_set(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_write_port_capability_set(RdpdrServerContext* context, - wStream* s) +static UINT rdpdr_server_write_port_capability_set(RdpdrServerContext* context, wStream* s) { RDPDR_CAPABILITY_HEADER header; header.CapabilityType = CAP_PORT_TYPE; @@ -454,8 +433,8 @@ static UINT rdpdr_server_write_port_capability_set(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_read_drive_capability_set(RdpdrServerContext* context, - wStream* s, RDPDR_CAPABILITY_HEADER* header) +static UINT rdpdr_server_read_drive_capability_set(RdpdrServerContext* context, wStream* s, + RDPDR_CAPABILITY_HEADER* header) { return CHANNEL_RC_OK; } @@ -465,8 +444,7 @@ static UINT rdpdr_server_read_drive_capability_set(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_write_drive_capability_set(RdpdrServerContext* context, - wStream* s) +static UINT rdpdr_server_write_drive_capability_set(RdpdrServerContext* context, wStream* s) { RDPDR_CAPABILITY_HEADER header; header.CapabilityType = CAP_DRIVE_TYPE; @@ -487,8 +465,8 @@ static UINT rdpdr_server_write_drive_capability_set(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_read_smartcard_capability_set(RdpdrServerContext* - context, wStream* s, RDPDR_CAPABILITY_HEADER* header) +static UINT rdpdr_server_read_smartcard_capability_set(RdpdrServerContext* context, wStream* s, + RDPDR_CAPABILITY_HEADER* header) { return CHANNEL_RC_OK; } @@ -498,8 +476,7 @@ static UINT rdpdr_server_read_smartcard_capability_set(RdpdrServerContext* * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_write_smartcard_capability_set( - RdpdrServerContext* context, wStream* s) +static UINT rdpdr_server_write_smartcard_capability_set(RdpdrServerContext* context, wStream* s) { RDPDR_CAPABILITY_HEADER header; header.CapabilityType = CAP_SMARTCARD_TYPE; @@ -520,8 +497,7 @@ static UINT rdpdr_server_write_smartcard_capability_set( * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* - context) +static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* context) { wStream* s; BOOL status; @@ -555,14 +531,14 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* } Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */ - Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ - Stream_Write_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */ - Stream_Write_UINT16(s, 0); /* Padding (2 bytes) */ + Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ + Stream_Write_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */ + Stream_Write_UINT16(s, 0); /* Padding (2 bytes) */ if ((error = rdpdr_server_write_general_capability_set(context, s))) { - WLog_ERR(TAG, - "rdpdr_server_write_general_capability_set failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rdpdr_server_write_general_capability_set failed with error %" PRIu32 "!", + error); goto out; } @@ -570,7 +546,7 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* { if ((error = rdpdr_server_write_drive_capability_set(context, s))) { - WLog_ERR(TAG, "rdpdr_server_write_drive_capability_set failed with error %"PRIu32"!", + WLog_ERR(TAG, "rdpdr_server_write_drive_capability_set failed with error %" PRIu32 "!", error); goto out; } @@ -580,7 +556,7 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* { if ((error = rdpdr_server_write_port_capability_set(context, s))) { - WLog_ERR(TAG, "rdpdr_server_write_port_capability_set failed with error %"PRIu32"!", + WLog_ERR(TAG, "rdpdr_server_write_port_capability_set failed with error %" PRIu32 "!", error); goto out; } @@ -591,7 +567,8 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* if ((error = rdpdr_server_write_printer_capability_set(context, s))) { WLog_ERR(TAG, - "rdpdr_server_write_printer_capability_set failed with error %"PRIu32"!", error); + "rdpdr_server_write_printer_capability_set failed with error %" PRIu32 "!", + error); goto out; } } @@ -601,15 +578,16 @@ static UINT rdpdr_server_send_core_capability_request(RdpdrServerContext* if ((error = rdpdr_server_write_smartcard_capability_set(context, s))) { WLog_ERR(TAG, - "rdpdr_server_write_printer_capability_set failed with error %"PRIu32"!", error); + "rdpdr_server_write_printer_capability_set failed with error %" PRIu32 "!", + error); goto out; } } Stream_SealLength(s); winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), Stream_Length(s)); - status = WTSVirtualChannelWrite(context->priv->ChannelHandle, - (PCHAR) Stream_Buffer(s), Stream_Length(s), &written); + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR)Stream_Buffer(s), + Stream_Length(s), &written); Stream_Free(s, TRUE); return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; out: @@ -622,8 +600,8 @@ out: * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_receive_core_capability_response( - RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header) +static UINT rdpdr_server_receive_core_capability_response(RdpdrServerContext* context, wStream* s, + RDPDR_HEADER* header) { int i; UINT status; @@ -637,13 +615,13 @@ static UINT rdpdr_server_receive_core_capability_response( } Stream_Read_UINT16(s, numCapabilities); /* numCapabilities (2 bytes) */ - Stream_Seek_UINT16(s); /* Padding (2 bytes) */ + Stream_Seek_UINT16(s); /* Padding (2 bytes) */ for (i = 0; i < numCapabilities; i++) { if ((status = rdpdr_server_read_capability_set_header(s, &capabilityHeader))) { - WLog_ERR(TAG, "rdpdr_server_read_capability_set_header failed with error %"PRIu32"!", + WLog_ERR(TAG, "rdpdr_server_read_capability_set_header failed with error %" PRIu32 "!", status); return status; } @@ -651,10 +629,12 @@ static UINT rdpdr_server_receive_core_capability_response( switch (capabilityHeader.CapabilityType) { case CAP_GENERAL_TYPE: - if ((status = rdpdr_server_read_general_capability_set(context, s, - &capabilityHeader))) + if ((status = + rdpdr_server_read_general_capability_set(context, s, &capabilityHeader))) { - WLog_ERR(TAG, "rdpdr_server_read_general_capability_set failed with error %"PRIu32"!", + WLog_ERR(TAG, + "rdpdr_server_read_general_capability_set failed with error %" PRIu32 + "!", status); return status; } @@ -662,10 +642,12 @@ static UINT rdpdr_server_receive_core_capability_response( break; case CAP_PRINTER_TYPE: - if ((status = rdpdr_server_read_printer_capability_set(context, s, - &capabilityHeader))) + if ((status = + rdpdr_server_read_printer_capability_set(context, s, &capabilityHeader))) { - WLog_ERR(TAG, "rdpdr_server_read_printer_capability_set failed with error %"PRIu32"!", + WLog_ERR(TAG, + "rdpdr_server_read_printer_capability_set failed with error %" PRIu32 + "!", status); return status; } @@ -673,10 +655,10 @@ static UINT rdpdr_server_receive_core_capability_response( break; case CAP_PORT_TYPE: - if ((status = rdpdr_server_read_port_capability_set(context, s, - &capabilityHeader))) + if ((status = rdpdr_server_read_port_capability_set(context, s, &capabilityHeader))) { - WLog_ERR(TAG, "rdpdr_server_read_port_capability_set failed with error %"PRIu32"!", + WLog_ERR(TAG, + "rdpdr_server_read_port_capability_set failed with error %" PRIu32 "!", status); return status; } @@ -684,10 +666,12 @@ static UINT rdpdr_server_receive_core_capability_response( break; case CAP_DRIVE_TYPE: - if ((status = rdpdr_server_read_drive_capability_set(context, s, - &capabilityHeader))) + if ((status = + rdpdr_server_read_drive_capability_set(context, s, &capabilityHeader))) { - WLog_ERR(TAG, "rdpdr_server_read_drive_capability_set failed with error %"PRIu32"!", + WLog_ERR(TAG, + "rdpdr_server_read_drive_capability_set failed with error %" PRIu32 + "!", status); return status; } @@ -695,20 +679,22 @@ static UINT rdpdr_server_receive_core_capability_response( break; case CAP_SMARTCARD_TYPE: - if ((status = rdpdr_server_read_smartcard_capability_set(context, s, - &capabilityHeader))) + if ((status = + rdpdr_server_read_smartcard_capability_set(context, s, &capabilityHeader))) { WLog_ERR(TAG, - "rdpdr_server_read_smartcard_capability_set failed with error %"PRIu32"!", status); + "rdpdr_server_read_smartcard_capability_set failed with error %" PRIu32 + "!", + status); return status; } break; default: - WLog_DBG(TAG, "Unknown capabilityType %"PRIu16"", capabilityHeader.CapabilityType); - Stream_Seek(s, capabilityHeader.CapabilityLength - - RDPDR_CAPABILITY_HEADER_LENGTH); + WLog_DBG(TAG, "Unknown capabilityType %" PRIu16 "", + capabilityHeader.CapabilityType); + Stream_Seek(s, capabilityHeader.CapabilityLength - RDPDR_CAPABILITY_HEADER_LENGTH); return ERROR_INVALID_DATA; break; } @@ -739,17 +725,15 @@ static UINT rdpdr_server_send_client_id_confirm(RdpdrServerContext* context) return CHANNEL_RC_NO_MEMORY; } - Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */ - Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ - Stream_Write_UINT16(s, - context->priv->VersionMajor); /* VersionMajor (2 bytes) */ - Stream_Write_UINT16(s, - context->priv->VersionMinor); /* VersionMinor (2 bytes) */ - Stream_Write_UINT32(s, context->priv->ClientId); /* ClientId (4 bytes) */ + Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */ + Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ + Stream_Write_UINT16(s, context->priv->VersionMajor); /* VersionMajor (2 bytes) */ + Stream_Write_UINT16(s, context->priv->VersionMinor); /* VersionMinor (2 bytes) */ + Stream_Write_UINT32(s, context->priv->ClientId); /* ClientId (4 bytes) */ Stream_SealLength(s); winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), Stream_Length(s)); - status = WTSVirtualChannelWrite(context->priv->ChannelHandle, - (PCHAR) Stream_Buffer(s), Stream_Length(s), &written); + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR)Stream_Buffer(s), + Stream_Length(s), &written); Stream_Free(s, TRUE); return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } @@ -759,10 +743,10 @@ static UINT rdpdr_server_send_client_id_confirm(RdpdrServerContext* context) * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_receive_device_list_announce_request( - RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header) +static UINT rdpdr_server_receive_device_list_announce_request(RdpdrServerContext* context, + wStream* s, RDPDR_HEADER* header) { - int i; + UINT32 i; UINT32 DeviceCount; UINT32 DeviceType; UINT32 DeviceId; @@ -776,7 +760,7 @@ static UINT rdpdr_server_receive_device_list_announce_request( } Stream_Read_UINT32(s, DeviceCount); /* DeviceCount (4 bytes) */ - WLog_DBG(TAG, "DeviceCount: %"PRIu32"", DeviceCount); + WLog_DBG(TAG, "DeviceCount: %" PRIu32 "", DeviceCount); for (i = 0; i < DeviceCount; i++) { @@ -788,9 +772,9 @@ static UINT rdpdr_server_receive_device_list_announce_request( return ERROR_INVALID_DATA; } - Stream_Read_UINT32(s, DeviceType); /* DeviceType (4 bytes) */ - Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */ - Stream_Read(s, PreferredDosName, 8); /* PreferredDosName (8 bytes) */ + Stream_Read_UINT32(s, DeviceType); /* DeviceType (4 bytes) */ + Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */ + Stream_Read(s, PreferredDosName, 8); /* PreferredDosName (8 bytes) */ Stream_Read_UINT32(s, DeviceDataLength); /* DeviceDataLength (4 bytes) */ if (Stream_GetRemainingLength(s) < DeviceDataLength) @@ -799,8 +783,8 @@ static UINT rdpdr_server_receive_device_list_announce_request( return ERROR_INVALID_DATA; } - WLog_DBG(TAG, "Device %d Name: %s Id: 0x%08"PRIX32" DataLength: %"PRIu32"", - i, PreferredDosName, DeviceId, DeviceDataLength); + WLog_DBG(TAG, "Device %d Name: %s Id: 0x%08" PRIX32 " DataLength: %" PRIu32 "", i, + PreferredDosName, DeviceId, DeviceDataLength); switch (DeviceType) { @@ -852,10 +836,10 @@ static UINT rdpdr_server_receive_device_list_announce_request( * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_receive_device_list_remove_request( - RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header) +static UINT rdpdr_server_receive_device_list_remove_request(RdpdrServerContext* context, wStream* s, + RDPDR_HEADER* header) { - int i; + UINT32 i; UINT32 DeviceCount; UINT32 DeviceType; UINT32 DeviceId; @@ -867,7 +851,7 @@ static UINT rdpdr_server_receive_device_list_remove_request( } Stream_Read_UINT32(s, DeviceCount); /* DeviceCount (4 bytes) */ - WLog_DBG(TAG, "DeviceCount: %"PRIu32"", DeviceCount); + WLog_DBG(TAG, "DeviceCount: %" PRIu32 "", DeviceCount); for (i = 0; i < DeviceCount; i++) { @@ -878,7 +862,7 @@ static UINT rdpdr_server_receive_device_list_remove_request( } Stream_Read_UINT32(s, DeviceId); /* DeviceId (4 bytes) */ - WLog_DBG(TAG, "Device %d Id: 0x%08"PRIX32"", i, DeviceId); + WLog_DBG(TAG, "Device %d Id: 0x%08" PRIX32 "", i, DeviceId); DeviceType = 0; /* TODO: Save the device type on the announce request. */ switch (DeviceType) @@ -929,8 +913,8 @@ static UINT rdpdr_server_receive_device_list_remove_request( * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_receive_device_io_completion(RdpdrServerContext* - context, wStream* s, RDPDR_HEADER* header) +static UINT rdpdr_server_receive_device_io_completion(RdpdrServerContext* context, wStream* s, + RDPDR_HEADER* header) { UINT32 deviceId; UINT32 completionId; @@ -947,13 +931,13 @@ static UINT rdpdr_server_receive_device_io_completion(RdpdrServerContext* Stream_Read_UINT32(s, deviceId); Stream_Read_UINT32(s, completionId); Stream_Read_UINT32(s, ioStatus); - WLog_DBG(TAG, "deviceId=%"PRIu32", completionId=0x%"PRIx32", ioStatus=0x%"PRIx32"", deviceId, - completionId, ioStatus); + WLog_DBG(TAG, "deviceId=%" PRIu32 ", completionId=0x%" PRIx32 ", ioStatus=0x%" PRIx32 "", + deviceId, completionId, ioStatus); irp = rdpdr_server_dequeue_irp(context, completionId); if (!irp) { - WLog_ERR(TAG, "IRP not found for completionId=0x%"PRIx32"", completionId); + WLog_ERR(TAG, "IRP not found for completionId=0x%" PRIx32 "", completionId); return ERROR_INTERNAL_ERROR; } @@ -989,11 +973,11 @@ static UINT rdpdr_server_send_user_logged_on(RdpdrServerContext* context) } Stream_Write_UINT16(s, header.Component); /* Component (2 bytes) */ - Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ + Stream_Write_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ Stream_SealLength(s); winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), Stream_Length(s)); - status = WTSVirtualChannelWrite(context->priv->ChannelHandle, - (PCHAR) Stream_Buffer(s), Stream_Length(s), &written); + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR)Stream_Buffer(s), + Stream_Length(s), &written); Stream_Free(s, TRUE); return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } @@ -1003,11 +987,10 @@ static UINT rdpdr_server_send_user_logged_on(RdpdrServerContext* context) * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s, - RDPDR_HEADER* header) +static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s, RDPDR_HEADER* header) { UINT error = CHANNEL_RC_OK; - WLog_DBG(TAG, "RdpdrServerReceivePdu: Component: 0x%04"PRIX16" PacketId: 0x%04"PRIX16"", + WLog_DBG(TAG, "RdpdrServerReceivePdu: Component: 0x%04" PRIX16 " PacketId: 0x%04" PRIX16 "", header->Component, header->PacketId); winpr_HexDump(TAG, WLOG_DEBUG, Stream_Buffer(s), Stream_Length(s)); @@ -1018,7 +1001,9 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s, case PAKID_CORE_CLIENTID_CONFIRM: if ((error = rdpdr_server_receive_announce_response(context, s, header))) { - WLog_ERR(TAG, "rdpdr_server_receive_announce_response failed with error %"PRIu32"!", + WLog_ERR(TAG, + "rdpdr_server_receive_announce_response failed with error %" PRIu32 + "!", error); return error; } @@ -1028,7 +1013,9 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s, case PAKID_CORE_CLIENT_NAME: if ((error = rdpdr_server_receive_client_name_request(context, s, header))) { - WLog_ERR(TAG, "rdpdr_server_receive_client_name_request failed with error %"PRIu32"!", + WLog_ERR(TAG, + "rdpdr_server_receive_client_name_request failed with error %" PRIu32 + "!", error); return error; } @@ -1036,13 +1023,16 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s, if ((error = rdpdr_server_send_core_capability_request(context))) { WLog_ERR(TAG, - "rdpdr_server_send_core_capability_request failed with error %"PRIu32"!", error); + "rdpdr_server_send_core_capability_request failed with error %" PRIu32 + "!", + error); return error; } if ((error = rdpdr_server_send_client_id_confirm(context))) { - WLog_ERR(TAG, "rdpdr_server_send_client_id_confirm failed with error %"PRIu32"!", + WLog_ERR(TAG, + "rdpdr_server_send_client_id_confirm failed with error %" PRIu32 "!", error); return error; } @@ -1052,26 +1042,31 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s, case PAKID_CORE_CLIENT_CAPABILITY: if ((error = rdpdr_server_receive_core_capability_response(context, s, header))) { - WLog_ERR(TAG, - "rdpdr_server_receive_core_capability_response failed with error %"PRIu32"!", error); + WLog_ERR( + TAG, + "rdpdr_server_receive_core_capability_response failed with error %" PRIu32 + "!", + error); return error; } if (context->priv->UserLoggedOnPdu) if ((error = rdpdr_server_send_user_logged_on(context))) { - WLog_ERR(TAG, "rdpdr_server_send_user_logged_on failed with error %"PRIu32"!", error); + WLog_ERR(TAG, + "rdpdr_server_send_user_logged_on failed with error %" PRIu32 "!", + error); return error; } break; case PAKID_CORE_DEVICELIST_ANNOUNCE: - if ((error = rdpdr_server_receive_device_list_announce_request(context, s, - header))) + if ((error = rdpdr_server_receive_device_list_announce_request(context, s, header))) { WLog_ERR(TAG, - "rdpdr_server_receive_device_list_announce_request failed with error %"PRIu32"!", + "rdpdr_server_receive_device_list_announce_request failed with error " + "%" PRIu32 "!", error); return error; } @@ -1088,18 +1083,21 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s, if ((error = rdpdr_server_receive_device_io_completion(context, s, header))) { WLog_ERR(TAG, - "rdpdr_server_receive_device_io_completion failed with error %"PRIu32"!", error); + "rdpdr_server_receive_device_io_completion failed with error %" PRIu32 + "!", + error); return error; } break; case PAKID_CORE_DEVICELIST_REMOVE: - if ((error = rdpdr_server_receive_device_list_remove_request(context, s, - header))) + if ((error = rdpdr_server_receive_device_list_remove_request(context, s, header))) { WLog_ERR(TAG, - "rdpdr_server_receive_device_io_completion failed with error %"PRIu32"!", error); + "rdpdr_server_receive_device_io_completion failed with error %" PRIu32 + "!", + error); return error; } @@ -1125,7 +1123,7 @@ static UINT rdpdr_server_receive_pdu(RdpdrServerContext* context, wStream* s, } else { - WLog_WARN(TAG, "Unknown RDPDR_HEADER.Component: 0x%04"PRIX16"", header->Component); + WLog_WARN(TAG, "Unknown RDPDR_HEADER.Component: 0x%04" PRIX16 "", header->Component); return ERROR_INVALID_DATA; } @@ -1144,7 +1142,7 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg) DWORD BytesReturned; RdpdrServerContext* context; UINT error; - context = (RdpdrServerContext*) arg; + context = (RdpdrServerContext*)arg; buffer = NULL; BytesReturned = 0; ChannelEvent = NULL; @@ -1157,8 +1155,8 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg) goto out; } - if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, - &buffer, &BytesReturned) == TRUE) + if (WTSVirtualChannelQuery(context->priv->ChannelHandle, WTSVirtualEventHandle, &buffer, + &BytesReturned) == TRUE) { if (BytesReturned == sizeof(HANDLE)) CopyMemory(&ChannelEvent, buffer, sizeof(HANDLE)); @@ -1172,8 +1170,7 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg) if ((error = rdpdr_server_send_announce_request(context))) { - WLog_ERR(TAG, "rdpdr_server_send_announce_request failed with error %"PRIu32"!", - error); + WLog_ERR(TAG, "rdpdr_server_send_announce_request failed with error %" PRIu32 "!", error); goto out_stream; } @@ -1185,7 +1182,7 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg) if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "WaitForMultipleObjects failed with error %" PRIu32 "!", error); goto out_stream; } @@ -1194,15 +1191,15 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg) if (status == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error); goto out_stream; } if (status == WAIT_OBJECT_0) break; - if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, - (PCHAR) Stream_Buffer(s), Stream_Capacity(s), &BytesReturned)) + if (!WTSVirtualChannelRead(context->priv->ChannelHandle, 0, (PCHAR)Stream_Buffer(s), + Stream_Capacity(s), &BytesReturned)) { WLog_ERR(TAG, "WTSVirtualChannelRead failed!"); error = ERROR_INTERNAL_ERROR; @@ -1217,11 +1214,11 @@ static DWORD WINAPI rdpdr_server_thread(LPVOID arg) while (Stream_GetRemainingLength(s) >= RDPDR_HEADER_LENGTH) { Stream_Read_UINT16(s, header.Component); /* Component (2 bytes) */ - Stream_Read_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ + Stream_Read_UINT16(s, header.PacketId); /* PacketId (2 bytes) */ if ((error = rdpdr_server_receive_pdu(context, s, &header))) { - WLog_ERR(TAG, "rdpdr_server_receive_pdu failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rdpdr_server_receive_pdu failed with error %" PRIu32 "!", error); goto out_stream; } } @@ -1233,8 +1230,7 @@ out_stream: out: if (error && context->rdpcontext) - setChannelError(context->rdpcontext, error, - "rdpdr_server_thread reported an error"); + setChannelError(context->rdpcontext, error, "rdpdr_server_thread reported an error"); ExitThread(error); return error; @@ -1247,8 +1243,8 @@ out: */ static UINT rdpdr_server_start(RdpdrServerContext* context) { - context->priv->ChannelHandle = WTSVirtualChannelOpen(context->vcm, - WTS_CURRENT_SESSION, "rdpdr"); + context->priv->ChannelHandle = + WTSVirtualChannelOpen(context->vcm, WTS_CURRENT_SESSION, "rdpdr"); if (!context->priv->ChannelHandle) { @@ -1262,8 +1258,8 @@ static UINT rdpdr_server_start(RdpdrServerContext* context) return ERROR_INTERNAL_ERROR; } - if (!(context->priv->Thread = CreateThread(NULL, 0, - rdpdr_server_thread, (void*) context, 0, NULL))) + if (!(context->priv->Thread = + CreateThread(NULL, 0, rdpdr_server_thread, (void*)context, 0, NULL))) { WLog_ERR(TAG, "CreateThread failed!"); CloseHandle(context->priv->StopEvent); @@ -1290,7 +1286,7 @@ static UINT rdpdr_server_stop(RdpdrServerContext* context) if (WaitForSingleObject(context->priv->Thread, INFINITE) == WAIT_FAILED) { error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "WaitForSingleObject failed with error %" PRIu32 "!", error); return error; } @@ -1303,21 +1299,17 @@ static UINT rdpdr_server_stop(RdpdrServerContext* context) return CHANNEL_RC_OK; } -static void rdpdr_server_write_device_iorequest( - wStream* s, - UINT32 deviceId, - UINT32 fileId, - UINT32 completionId, - UINT32 majorFunction, - UINT32 minorFunction) +static void rdpdr_server_write_device_iorequest(wStream* s, UINT32 deviceId, UINT32 fileId, + UINT32 completionId, UINT32 majorFunction, + UINT32 minorFunction) { - Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */ + Stream_Write_UINT16(s, RDPDR_CTYP_CORE); /* Component (2 bytes) */ Stream_Write_UINT16(s, PAKID_CORE_DEVICE_IOREQUEST); /* PacketId (2 bytes) */ - Stream_Write_UINT32(s, deviceId); /* DeviceId (4 bytes) */ - Stream_Write_UINT32(s, fileId); /* FileId (4 bytes) */ - Stream_Write_UINT32(s, completionId); /* CompletionId (4 bytes) */ - Stream_Write_UINT32(s, majorFunction); /* MajorFunction (4 bytes) */ - Stream_Write_UINT32(s, minorFunction); /* MinorFunction (4 bytes) */ + Stream_Write_UINT32(s, deviceId); /* DeviceId (4 bytes) */ + Stream_Write_UINT32(s, fileId); /* FileId (4 bytes) */ + Stream_Write_UINT32(s, completionId); /* CompletionId (4 bytes) */ + Stream_Write_UINT32(s, majorFunction); /* MajorFunction (4 bytes) */ + Stream_Write_UINT32(s, minorFunction); /* MinorFunction (4 bytes) */ } /** @@ -1326,7 +1318,7 @@ static void rdpdr_server_write_device_iorequest( * @return 0 on success, otherwise a Win32 error code */ static UINT rdpdr_server_read_file_directory_information(wStream* s, - FILE_DIRECTORY_INFORMATION* fdi) + FILE_DIRECTORY_INFORMATION* fdi) { UINT32 fileNameLength; ZeroMemory(fdi, sizeof(FILE_DIRECTORY_INFORMATION)); @@ -1338,15 +1330,15 @@ static UINT rdpdr_server_read_file_directory_information(wStream* s, } Stream_Read_UINT32(s, fdi->NextEntryOffset); /* NextEntryOffset (4 bytes) */ - Stream_Read_UINT32(s, fdi->FileIndex); /* FileIndex (4 bytes) */ - Stream_Read_UINT64(s, fdi->CreationTime); /* CreationTime (8 bytes) */ - Stream_Read_UINT64(s, fdi->LastAccessTime); /* LastAccessTime (8 bytes) */ - Stream_Read_UINT64(s, fdi->LastWriteTime); /* LastWriteTime (8 bytes) */ - Stream_Read_UINT64(s, fdi->ChangeTime); /* ChangeTime (8 bytes) */ - Stream_Read_UINT64(s, fdi->EndOfFile); /* EndOfFile (8 bytes) */ - Stream_Read_UINT64(s, fdi->AllocationSize); /* AllocationSize (8 bytes) */ - Stream_Read_UINT32(s, fdi->FileAttributes); /* FileAttributes (4 bytes) */ - Stream_Read_UINT32(s, fileNameLength); /* FileNameLength (4 bytes) */ + Stream_Read_UINT32(s, fdi->FileIndex); /* FileIndex (4 bytes) */ + Stream_Read_UINT64(s, fdi->CreationTime); /* CreationTime (8 bytes) */ + Stream_Read_UINT64(s, fdi->LastAccessTime); /* LastAccessTime (8 bytes) */ + Stream_Read_UINT64(s, fdi->LastWriteTime); /* LastWriteTime (8 bytes) */ + Stream_Read_UINT64(s, fdi->ChangeTime); /* ChangeTime (8 bytes) */ + Stream_Read_UINT64(s, fdi->EndOfFile); /* EndOfFile (8 bytes) */ + Stream_Read_UINT64(s, fdi->AllocationSize); /* AllocationSize (8 bytes) */ + Stream_Read_UINT32(s, fdi->FileAttributes); /* FileAttributes (4 bytes) */ + Stream_Read_UINT32(s, fileNameLength); /* FileNameLength (4 bytes) */ if (Stream_GetRemainingLength(s) < fileNameLength) { @@ -1354,8 +1346,8 @@ static UINT rdpdr_server_read_file_directory_information(wStream* s, return ERROR_INVALID_DATA; } - WideCharToMultiByte(CP_ACP, 0, (LPCWSTR) Stream_Pointer(s), fileNameLength / 2, - fdi->FileName, sizeof(fdi->FileName), NULL, NULL); + WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)Stream_Pointer(s), fileNameLength / 2, fdi->FileName, + sizeof(fdi->FileName), NULL, NULL); Stream_Seek(s, fileNameLength); return CHANNEL_RC_OK; } @@ -1365,21 +1357,19 @@ static UINT rdpdr_server_read_file_directory_information(wStream* s, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_send_device_create_request( - RdpdrServerContext* context, - UINT32 deviceId, - UINT32 completionId, - const char* path, - UINT32 desiredAccess, - UINT32 createOptions, - UINT32 createDisposition) +static UINT rdpdr_server_send_device_create_request(RdpdrServerContext* context, UINT32 deviceId, + UINT32 completionId, const char* path, + UINT32 desiredAccess, UINT32 createOptions, + UINT32 createDisposition) { UINT32 pathLength; ULONG written; BOOL status; wStream* s; WLog_DBG(TAG, - "RdpdrServerSendDeviceCreateRequest: deviceId=%"PRIu32", path=%s, desiredAccess=0x%"PRIx32" createOptions=0x%"PRIx32" createDisposition=0x%"PRIx32"", + "RdpdrServerSendDeviceCreateRequest: deviceId=%" PRIu32 + ", path=%s, desiredAccess=0x%" PRIx32 " createOptions=0x%" PRIx32 + " createDisposition=0x%" PRIx32 "", deviceId, path, desiredAccess, createOptions, createDisposition); /* Compute the required Unicode size. */ pathLength = (strlen(path) + 1) * sizeof(WCHAR); @@ -1391,23 +1381,21 @@ static UINT rdpdr_server_send_device_create_request( return CHANNEL_RC_NO_MEMORY; } - rdpdr_server_write_device_iorequest(s, deviceId, 0, completionId, IRP_MJ_CREATE, - 0); + rdpdr_server_write_device_iorequest(s, deviceId, 0, completionId, IRP_MJ_CREATE, 0); Stream_Write_UINT32(s, desiredAccess); /* DesiredAccess (4 bytes) */ - Stream_Write_UINT32(s, 0); /* AllocationSize (8 bytes) */ + Stream_Write_UINT32(s, 0); /* AllocationSize (8 bytes) */ Stream_Write_UINT32(s, 0); - Stream_Write_UINT32(s, 0); /* FileAttributes (4 bytes) */ - Stream_Write_UINT32(s, 3); /* SharedAccess (4 bytes) */ + Stream_Write_UINT32(s, 0); /* FileAttributes (4 bytes) */ + Stream_Write_UINT32(s, 3); /* SharedAccess (4 bytes) */ Stream_Write_UINT32(s, createDisposition); /* CreateDisposition (4 bytes) */ - Stream_Write_UINT32(s, createOptions); /* CreateOptions (4 bytes) */ - Stream_Write_UINT32(s, pathLength); /* PathLength (4 bytes) */ + Stream_Write_UINT32(s, createOptions); /* CreateOptions (4 bytes) */ + Stream_Write_UINT32(s, pathLength); /* PathLength (4 bytes) */ /* Convert the path to Unicode. */ - MultiByteToWideChar(CP_ACP, 0, path, -1, (LPWSTR) Stream_Pointer(s), - pathLength); + MultiByteToWideChar(CP_ACP, 0, path, -1, (LPWSTR)Stream_Pointer(s), pathLength); Stream_Seek(s, pathLength); Stream_SealLength(s); - status = WTSVirtualChannelWrite(context->priv->ChannelHandle, - (PCHAR) Stream_Buffer(s), Stream_Length(s), &written); + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR)Stream_Buffer(s), + Stream_Length(s), &written); Stream_Free(s, TRUE); return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } @@ -1417,16 +1405,13 @@ static UINT rdpdr_server_send_device_create_request( * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_send_device_close_request( - RdpdrServerContext* context, - UINT32 deviceId, - UINT32 fileId, - UINT32 completionId) +static UINT rdpdr_server_send_device_close_request(RdpdrServerContext* context, UINT32 deviceId, + UINT32 fileId, UINT32 completionId) { ULONG written; BOOL status; wStream* s; - WLog_DBG(TAG, "RdpdrServerSendDeviceCloseRequest: deviceId=%"PRIu32", fileId=%"PRIu32"", + WLog_DBG(TAG, "RdpdrServerSendDeviceCloseRequest: deviceId=%" PRIu32 ", fileId=%" PRIu32 "", deviceId, fileId); s = Stream_New(NULL, 128); @@ -1436,12 +1421,11 @@ static UINT rdpdr_server_send_device_close_request( return CHANNEL_RC_NO_MEMORY; } - rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, - IRP_MJ_CLOSE, 0); + rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_CLOSE, 0); Stream_Zero(s, 32); /* Padding (32 bytes) */ Stream_SealLength(s); - status = WTSVirtualChannelWrite(context->priv->ChannelHandle, - (PCHAR) Stream_Buffer(s), Stream_Length(s), &written); + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR)Stream_Buffer(s), + Stream_Length(s), &written); Stream_Free(s, TRUE); return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } @@ -1451,19 +1435,16 @@ static UINT rdpdr_server_send_device_close_request( * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_send_device_read_request( - RdpdrServerContext* context, - UINT32 deviceId, - UINT32 fileId, - UINT32 completionId, - UINT32 length, - UINT32 offset) +static UINT rdpdr_server_send_device_read_request(RdpdrServerContext* context, UINT32 deviceId, + UINT32 fileId, UINT32 completionId, UINT32 length, + UINT32 offset) { ULONG written; BOOL status; wStream* s; WLog_DBG(TAG, - "RdpdrServerSendDeviceReadRequest: deviceId=%"PRIu32", fileId=%"PRIu32", length=%"PRIu32", offset=%"PRIu32"", + "RdpdrServerSendDeviceReadRequest: deviceId=%" PRIu32 ", fileId=%" PRIu32 + ", length=%" PRIu32 ", offset=%" PRIu32 "", deviceId, fileId, length, offset); s = Stream_New(NULL, 128); @@ -1473,15 +1454,14 @@ static UINT rdpdr_server_send_device_read_request( return CHANNEL_RC_NO_MEMORY; } - rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, - IRP_MJ_READ, 0); + rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_READ, 0); Stream_Write_UINT32(s, length); /* Length (4 bytes) */ Stream_Write_UINT32(s, offset); /* Offset (8 bytes) */ Stream_Write_UINT32(s, 0); Stream_Zero(s, 20); /* Padding (20 bytes) */ Stream_SealLength(s); - status = WTSVirtualChannelWrite(context->priv->ChannelHandle, - (PCHAR) Stream_Buffer(s), Stream_Length(s), &written); + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR)Stream_Buffer(s), + Stream_Length(s), &written); Stream_Free(s, TRUE); return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } @@ -1491,20 +1471,16 @@ static UINT rdpdr_server_send_device_read_request( * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_send_device_write_request( - RdpdrServerContext* context, - UINT32 deviceId, - UINT32 fileId, - UINT32 completionId, - const char* data, - UINT32 length, - UINT32 offset) +static UINT rdpdr_server_send_device_write_request(RdpdrServerContext* context, UINT32 deviceId, + UINT32 fileId, UINT32 completionId, + const char* data, UINT32 length, UINT32 offset) { ULONG written; BOOL status; wStream* s; WLog_DBG(TAG, - "RdpdrServerSendDeviceWriteRequest: deviceId=%"PRIu32", fileId=%"PRIu32", length=%"PRIu32", offset=%"PRIu32"", + "RdpdrServerSendDeviceWriteRequest: deviceId=%" PRIu32 ", fileId=%" PRIu32 + ", length=%" PRIu32 ", offset=%" PRIu32 "", deviceId, fileId, length, offset); s = Stream_New(NULL, 64 + length); @@ -1514,16 +1490,15 @@ static UINT rdpdr_server_send_device_write_request( return CHANNEL_RC_NO_MEMORY; } - rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, - IRP_MJ_WRITE, 0); + rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_WRITE, 0); Stream_Write_UINT32(s, length); /* Length (4 bytes) */ Stream_Write_UINT32(s, offset); /* Offset (8 bytes) */ Stream_Write_UINT32(s, 0); - Stream_Zero(s, 20); /* Padding (20 bytes) */ + Stream_Zero(s, 20); /* Padding (20 bytes) */ Stream_Write(s, data, length); /* WriteData (variable) */ Stream_SealLength(s); - status = WTSVirtualChannelWrite(context->priv->ChannelHandle, - (PCHAR) Stream_Buffer(s), Stream_Length(s), &written); + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR)Stream_Buffer(s), + Stream_Length(s), &written); Stream_Free(s, TRUE); return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } @@ -1533,19 +1508,17 @@ static UINT rdpdr_server_send_device_write_request( * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_send_device_query_directory_request( - RdpdrServerContext* context, - UINT32 deviceId, - UINT32 fileId, - UINT32 completionId, - const char* path) +static UINT rdpdr_server_send_device_query_directory_request(RdpdrServerContext* context, + UINT32 deviceId, UINT32 fileId, + UINT32 completionId, const char* path) { UINT32 pathLength; ULONG written; BOOL status; wStream* s; WLog_DBG(TAG, - "RdpdrServerSendDeviceQueryDirectoryRequest: deviceId=%"PRIu32", fileId=%"PRIu32", path=%s", + "RdpdrServerSendDeviceQueryDirectoryRequest: deviceId=%" PRIu32 ", fileId=%" PRIu32 + ", path=%s", deviceId, fileId, path); /* Compute the required Unicode size. */ pathLength = path ? (strlen(path) + 1) * sizeof(WCHAR) : 0; @@ -1557,25 +1530,23 @@ static UINT rdpdr_server_send_device_query_directory_request( return CHANNEL_RC_NO_MEMORY; } - rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, - IRP_MJ_DIRECTORY_CONTROL, IRP_MN_QUERY_DIRECTORY); - Stream_Write_UINT32(s, - FileDirectoryInformation); /* FsInformationClass (4 bytes) */ - Stream_Write_UINT8(s, path ? 1 : 0); /* InitialQuery (1 byte) */ - Stream_Write_UINT32(s, pathLength); /* PathLength (4 bytes) */ - Stream_Zero(s, 23); /* Padding (23 bytes) */ + rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_DIRECTORY_CONTROL, + IRP_MN_QUERY_DIRECTORY); + Stream_Write_UINT32(s, FileDirectoryInformation); /* FsInformationClass (4 bytes) */ + Stream_Write_UINT8(s, path ? 1 : 0); /* InitialQuery (1 byte) */ + Stream_Write_UINT32(s, pathLength); /* PathLength (4 bytes) */ + Stream_Zero(s, 23); /* Padding (23 bytes) */ /* Convert the path to Unicode. */ if (pathLength > 0) { - MultiByteToWideChar(CP_ACP, 0, path, -1, (LPWSTR) Stream_Pointer(s), - pathLength); + MultiByteToWideChar(CP_ACP, 0, path, -1, (LPWSTR)Stream_Pointer(s), pathLength); Stream_Seek(s, pathLength); } Stream_SealLength(s); - status = WTSVirtualChannelWrite(context->priv->ChannelHandle, - (PCHAR) Stream_Buffer(s), Stream_Length(s), &written); + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR)Stream_Buffer(s), + Stream_Length(s), &written); Stream_Free(s, TRUE); return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } @@ -1585,19 +1556,17 @@ static UINT rdpdr_server_send_device_query_directory_request( * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_send_device_file_rename_request( - RdpdrServerContext* context, - UINT32 deviceId, - UINT32 fileId, - UINT32 completionId, - const char* path) +static UINT rdpdr_server_send_device_file_rename_request(RdpdrServerContext* context, + UINT32 deviceId, UINT32 fileId, + UINT32 completionId, const char* path) { UINT32 pathLength; ULONG written; BOOL status; wStream* s; WLog_DBG(TAG, - "RdpdrServerSendDeviceFileNameRequest: deviceId=%"PRIu32", fileId=%"PRIu32", path=%s", + "RdpdrServerSendDeviceFileNameRequest: deviceId=%" PRIu32 ", fileId=%" PRIu32 + ", path=%s", deviceId, fileId, path); /* Compute the required Unicode size. */ pathLength = path ? (strlen(path) + 1) * sizeof(WCHAR) : 0; @@ -1609,28 +1578,26 @@ static UINT rdpdr_server_send_device_file_rename_request( return CHANNEL_RC_NO_MEMORY; } - rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, - IRP_MJ_SET_INFORMATION, 0); - Stream_Write_UINT32(s, - FileRenameInformation); /* FsInformationClass (4 bytes) */ - Stream_Write_UINT32(s, pathLength + 6); /* Length (4 bytes) */ - Stream_Zero(s, 24); /* Padding (24 bytes) */ + rdpdr_server_write_device_iorequest(s, deviceId, fileId, completionId, IRP_MJ_SET_INFORMATION, + 0); + Stream_Write_UINT32(s, FileRenameInformation); /* FsInformationClass (4 bytes) */ + Stream_Write_UINT32(s, pathLength + 6); /* Length (4 bytes) */ + Stream_Zero(s, 24); /* Padding (24 bytes) */ /* RDP_FILE_RENAME_INFORMATION */ - Stream_Write_UINT8(s, 0); /* ReplaceIfExists (1 byte) */ - Stream_Write_UINT8(s, 0); /* RootDirectory (1 byte) */ + Stream_Write_UINT8(s, 0); /* ReplaceIfExists (1 byte) */ + Stream_Write_UINT8(s, 0); /* RootDirectory (1 byte) */ Stream_Write_UINT32(s, pathLength); /* FileNameLength (4 bytes) */ /* Convert the path to Unicode. */ if (pathLength > 0) { - MultiByteToWideChar(CP_ACP, 0, path, -1, (LPWSTR) Stream_Pointer(s), - pathLength); + MultiByteToWideChar(CP_ACP, 0, path, -1, (LPWSTR)Stream_Pointer(s), pathLength); Stream_Seek(s, pathLength); } Stream_SealLength(s); - status = WTSVirtualChannelWrite(context->priv->ChannelHandle, - (PCHAR) Stream_Buffer(s), Stream_Length(s), &written); + status = WTSVirtualChannelWrite(context->priv->ChannelHandle, (PCHAR)Stream_Buffer(s), + Stream_Length(s), &written); Stream_Free(s, TRUE); return status ? CHANNEL_RC_OK : ERROR_INTERNAL_ERROR; } @@ -1655,12 +1622,13 @@ static void rdpdr_server_convert_slashes(char* path, int size) * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_create_directory_callback2( - RdpdrServerContext* context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, - UINT32 completionId, UINT32 ioStatus) +static UINT rdpdr_server_drive_create_directory_callback2(RdpdrServerContext* context, wStream* s, + RDPDR_IRP* irp, UINT32 deviceId, + UINT32 completionId, UINT32 ioStatus) { WLog_DBG(TAG, - "RdpdrServerDriveCreateDirectoryCallback2: deviceId=%"PRIu32", completionId=%"PRIu32", ioStatus=0x%"PRIx32"", + "RdpdrServerDriveCreateDirectoryCallback2: deviceId=%" PRIu32 ", completionId=%" PRIu32 + ", ioStatus=0x%" PRIx32 "", deviceId, completionId, ioStatus); /* Invoke the create directory completion routine. */ context->OnDriveCreateDirectoryComplete(context, irp->CallbackData, ioStatus); @@ -1674,14 +1642,15 @@ static UINT rdpdr_server_drive_create_directory_callback2( * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_create_directory_callback1( - RdpdrServerContext* context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, - UINT32 completionId, UINT32 ioStatus) +static UINT rdpdr_server_drive_create_directory_callback1(RdpdrServerContext* context, wStream* s, + RDPDR_IRP* irp, UINT32 deviceId, + UINT32 completionId, UINT32 ioStatus) { UINT32 fileId; UINT8 information; WLog_DBG(TAG, - "RdpdrServerDriveCreateDirectoryCallback1: deviceId=%"PRIu32", completionId=%"PRIu32", ioStatus=0x%"PRIx32"", + "RdpdrServerDriveCreateDirectoryCallback1: deviceId=%" PRIu32 ", completionId=%" PRIu32 + ", ioStatus=0x%" PRIx32 "", deviceId, completionId, ioStatus); if (ioStatus != STATUS_SUCCESS) @@ -1699,7 +1668,7 @@ static UINT rdpdr_server_drive_create_directory_callback1( return ERROR_INVALID_DATA; } - Stream_Read_UINT32(s, fileId); /* FileId (4 bytes) */ + Stream_Read_UINT32(s, fileId); /* FileId (4 bytes) */ Stream_Read_UINT8(s, information); /* Information (1 byte) */ /* Setup the IRP. */ irp->CompletionId = context->priv->NextCompletionId++; @@ -1715,8 +1684,7 @@ static UINT rdpdr_server_drive_create_directory_callback1( } /* Send a request to close the file */ - return rdpdr_server_send_device_close_request(context, deviceId, fileId, - irp->CompletionId); + return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId); } /** @@ -1724,8 +1692,8 @@ static UINT rdpdr_server_drive_create_directory_callback1( * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_create_directory(RdpdrServerContext* context, - void* callbackData, UINT32 deviceId, const char* path) +static UINT rdpdr_server_drive_create_directory(RdpdrServerContext* context, void* callbackData, + UINT32 deviceId, const char* path) { RDPDR_IRP* irp; irp = rdpdr_server_irp_new(); @@ -1751,10 +1719,9 @@ static UINT rdpdr_server_drive_create_directory(RdpdrServerContext* context, } /* Send a request to open the file. */ - return rdpdr_server_send_device_create_request(context, deviceId, - irp->CompletionId, irp->PathName, - FILE_READ_DATA | SYNCHRONIZE, - FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_CREATE); + return rdpdr_server_send_device_create_request( + context, deviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_CREATE); } /************************************************* @@ -1766,12 +1733,13 @@ static UINT rdpdr_server_drive_create_directory(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_delete_directory_callback2( - RdpdrServerContext* context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, - UINT32 completionId, UINT32 ioStatus) +static UINT rdpdr_server_drive_delete_directory_callback2(RdpdrServerContext* context, wStream* s, + RDPDR_IRP* irp, UINT32 deviceId, + UINT32 completionId, UINT32 ioStatus) { WLog_DBG(TAG, - "RdpdrServerDriveDeleteDirectoryCallback2: deviceId=%"PRIu32", completionId=%"PRIu32", ioStatus=0x%"PRIx32"", + "RdpdrServerDriveDeleteDirectoryCallback2: deviceId=%" PRIu32 ", completionId=%" PRIu32 + ", ioStatus=0x%" PRIx32 "", deviceId, completionId, ioStatus); /* Invoke the delete directory completion routine. */ context->OnDriveDeleteDirectoryComplete(context, irp->CallbackData, ioStatus); @@ -1785,14 +1753,15 @@ static UINT rdpdr_server_drive_delete_directory_callback2( * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_delete_directory_callback1( - RdpdrServerContext* context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, - UINT32 completionId, UINT32 ioStatus) +static UINT rdpdr_server_drive_delete_directory_callback1(RdpdrServerContext* context, wStream* s, + RDPDR_IRP* irp, UINT32 deviceId, + UINT32 completionId, UINT32 ioStatus) { UINT32 fileId; UINT8 information; WLog_DBG(TAG, - "RdpdrServerDriveDeleteDirectoryCallback1: deviceId=%"PRIu32", completionId=%"PRIu32", ioStatus=0x%"PRIx32"", + "RdpdrServerDriveDeleteDirectoryCallback1: deviceId=%" PRIu32 ", completionId=%" PRIu32 + ", ioStatus=0x%" PRIx32 "", deviceId, completionId, ioStatus); if (ioStatus != STATUS_SUCCESS) @@ -1810,7 +1779,7 @@ static UINT rdpdr_server_drive_delete_directory_callback1( return ERROR_INVALID_DATA; } - Stream_Read_UINT32(s, fileId); /* FileId (4 bytes) */ + Stream_Read_UINT32(s, fileId); /* FileId (4 bytes) */ Stream_Read_UINT8(s, information); /* Information (1 byte) */ /* Setup the IRP. */ irp->CompletionId = context->priv->NextCompletionId++; @@ -1826,8 +1795,7 @@ static UINT rdpdr_server_drive_delete_directory_callback1( } /* Send a request to close the file */ - return rdpdr_server_send_device_close_request(context, deviceId, fileId, - irp->CompletionId); + return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId); } /** @@ -1835,8 +1803,8 @@ static UINT rdpdr_server_drive_delete_directory_callback1( * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_delete_directory(RdpdrServerContext* context, - void* callbackData, UINT32 deviceId, const char* path) +static UINT rdpdr_server_drive_delete_directory(RdpdrServerContext* context, void* callbackData, + UINT32 deviceId, const char* path) { RDPDR_IRP* irp; irp = rdpdr_server_irp_new(); @@ -1862,10 +1830,9 @@ static UINT rdpdr_server_drive_delete_directory(RdpdrServerContext* context, } /* Send a request to open the file. */ - return rdpdr_server_send_device_create_request(context, deviceId, - irp->CompletionId, irp->PathName, - DELETE | SYNCHRONIZE, FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE | - FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN); + return rdpdr_server_send_device_create_request( + context, deviceId, irp->CompletionId, irp->PathName, DELETE | SYNCHRONIZE, + FILE_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN); } /************************************************* @@ -1877,15 +1844,16 @@ static UINT rdpdr_server_drive_delete_directory(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_query_directory_callback2( - RdpdrServerContext* context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, - UINT32 completionId, UINT32 ioStatus) +static UINT rdpdr_server_drive_query_directory_callback2(RdpdrServerContext* context, wStream* s, + RDPDR_IRP* irp, UINT32 deviceId, + UINT32 completionId, UINT32 ioStatus) { UINT error; UINT32 length; FILE_DIRECTORY_INFORMATION fdi; WLog_DBG(TAG, - "RdpdrServerDriveQueryDirectoryCallback2: deviceId=%"PRIu32", completionId=%"PRIu32", ioStatus=0x%"PRIx32"", + "RdpdrServerDriveQueryDirectoryCallback2: deviceId=%" PRIu32 ", completionId=%" PRIu32 + ", ioStatus=0x%" PRIx32 "", deviceId, completionId, ioStatus); if (Stream_GetRemainingLength(s) < 4) @@ -1901,7 +1869,8 @@ static UINT rdpdr_server_drive_query_directory_callback2( if ((error = rdpdr_server_read_file_directory_information(s, &fdi))) { WLog_ERR(TAG, - "rdpdr_server_read_file_directory_information failed with error %"PRIu32"!", error); + "rdpdr_server_read_file_directory_information failed with error %" PRIu32 "!", + error); return error; } } @@ -1933,14 +1902,13 @@ static UINT rdpdr_server_drive_query_directory_callback2( } /* Send a request to query the directory. */ - return rdpdr_server_send_device_query_directory_request(context, irp->DeviceId, - irp->FileId, irp->CompletionId, NULL); + return rdpdr_server_send_device_query_directory_request(context, irp->DeviceId, irp->FileId, + irp->CompletionId, NULL); } else { /* Invoke the query directory completion routine. */ - context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus, - NULL); + context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus, NULL); /* Destroy the IRP. */ rdpdr_server_irp_free(irp); } @@ -1953,20 +1921,20 @@ static UINT rdpdr_server_drive_query_directory_callback2( * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_query_directory_callback1( - RdpdrServerContext* context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, - UINT32 completionId, UINT32 ioStatus) +static UINT rdpdr_server_drive_query_directory_callback1(RdpdrServerContext* context, wStream* s, + RDPDR_IRP* irp, UINT32 deviceId, + UINT32 completionId, UINT32 ioStatus) { UINT32 fileId; WLog_DBG(TAG, - "RdpdrServerDriveQueryDirectoryCallback1: deviceId=%"PRIu32", completionId=%"PRIu32", ioStatus=0x%"PRIx32"", + "RdpdrServerDriveQueryDirectoryCallback1: deviceId=%" PRIu32 ", completionId=%" PRIu32 + ", ioStatus=0x%" PRIx32 "", deviceId, completionId, ioStatus); if (ioStatus != STATUS_SUCCESS) { /* Invoke the query directory completion routine. */ - context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus, - NULL); + context->OnDriveQueryDirectoryComplete(context, irp->CallbackData, ioStatus, NULL); /* Destroy the IRP. */ rdpdr_server_irp_free(irp); return CHANNEL_RC_OK; @@ -1994,8 +1962,8 @@ static UINT rdpdr_server_drive_query_directory_callback1( } /* Send a request to query the directory. */ - return rdpdr_server_send_device_query_directory_request(context, deviceId, - fileId, irp->CompletionId, irp->PathName); + return rdpdr_server_send_device_query_directory_request(context, deviceId, fileId, + irp->CompletionId, irp->PathName); } /** @@ -2003,8 +1971,8 @@ static UINT rdpdr_server_drive_query_directory_callback1( * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_query_directory(RdpdrServerContext* context, - void* callbackData, UINT32 deviceId, const char* path) +static UINT rdpdr_server_drive_query_directory(RdpdrServerContext* context, void* callbackData, + UINT32 deviceId, const char* path) { RDPDR_IRP* irp; irp = rdpdr_server_irp_new(); @@ -2030,10 +1998,9 @@ static UINT rdpdr_server_drive_query_directory(RdpdrServerContext* context, } /* Send a request to open the directory. */ - return rdpdr_server_send_device_create_request(context, deviceId, - irp->CompletionId, irp->PathName, - FILE_READ_DATA | SYNCHRONIZE, - FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN); + return rdpdr_server_send_device_create_request( + context, deviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE, + FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN); } /************************************************* @@ -2045,14 +2012,15 @@ static UINT rdpdr_server_drive_query_directory(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_open_file_callback(RdpdrServerContext* context, - wStream* s, RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, - UINT32 ioStatus) +static UINT rdpdr_server_drive_open_file_callback(RdpdrServerContext* context, wStream* s, + RDPDR_IRP* irp, UINT32 deviceId, + UINT32 completionId, UINT32 ioStatus) { UINT32 fileId; UINT8 information; WLog_DBG(TAG, - "RdpdrServerDriveOpenFileCallback: deviceId=%"PRIu32", completionId=%"PRIu32", ioStatus=0x%"PRIx32"", + "RdpdrServerDriveOpenFileCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32 + ", ioStatus=0x%" PRIx32 "", deviceId, completionId, ioStatus); if (Stream_GetRemainingLength(s) < 5) @@ -2061,11 +2029,10 @@ static UINT rdpdr_server_drive_open_file_callback(RdpdrServerContext* context, return ERROR_INVALID_DATA; } - Stream_Read_UINT32(s, fileId); /* FileId (4 bytes) */ + Stream_Read_UINT32(s, fileId); /* FileId (4 bytes) */ Stream_Read_UINT8(s, information); /* Information (1 byte) */ /* Invoke the open file completion routine. */ - context->OnDriveOpenFileComplete(context, irp->CallbackData, ioStatus, deviceId, - fileId); + context->OnDriveOpenFileComplete(context, irp->CallbackData, ioStatus, deviceId, fileId); /* Destroy the IRP. */ rdpdr_server_irp_free(irp); return CHANNEL_RC_OK; @@ -2076,9 +2043,9 @@ static UINT rdpdr_server_drive_open_file_callback(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_open_file(RdpdrServerContext* context, - void* callbackData, UINT32 deviceId, const char* path, UINT32 desiredAccess, - UINT32 createDisposition) +static UINT rdpdr_server_drive_open_file(RdpdrServerContext* context, void* callbackData, + UINT32 deviceId, const char* path, UINT32 desiredAccess, + UINT32 createDisposition) { RDPDR_IRP* irp; irp = rdpdr_server_irp_new(); @@ -2104,9 +2071,9 @@ static UINT rdpdr_server_drive_open_file(RdpdrServerContext* context, } /* Send a request to open the file. */ - return rdpdr_server_send_device_create_request(context, deviceId, - irp->CompletionId, irp->PathName, - desiredAccess | SYNCHRONIZE, FILE_SYNCHRONOUS_IO_NONALERT, createDisposition); + return rdpdr_server_send_device_create_request(context, deviceId, irp->CompletionId, + irp->PathName, desiredAccess | SYNCHRONIZE, + FILE_SYNCHRONOUS_IO_NONALERT, createDisposition); } /************************************************* @@ -2118,14 +2085,15 @@ static UINT rdpdr_server_drive_open_file(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_read_file_callback(RdpdrServerContext* context, - wStream* s, RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, - UINT32 ioStatus) +static UINT rdpdr_server_drive_read_file_callback(RdpdrServerContext* context, wStream* s, + RDPDR_IRP* irp, UINT32 deviceId, + UINT32 completionId, UINT32 ioStatus) { UINT32 length; char* buffer = NULL; WLog_DBG(TAG, - "RdpdrServerDriveReadFileCallback: deviceId=%"PRIu32", completionId=%"PRIu32", ioStatus=0x%"PRIx32"", + "RdpdrServerDriveReadFileCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32 + ", ioStatus=0x%" PRIx32 "", deviceId, completionId, ioStatus); if (Stream_GetRemainingLength(s) < 4) @@ -2144,13 +2112,12 @@ static UINT rdpdr_server_drive_read_file_callback(RdpdrServerContext* context, if (length > 0) { - buffer = (char*) Stream_Pointer(s); + buffer = (char*)Stream_Pointer(s); Stream_Seek(s, length); } /* Invoke the read file completion routine. */ - context->OnDriveReadFileComplete(context, irp->CallbackData, ioStatus, buffer, - length); + context->OnDriveReadFileComplete(context, irp->CallbackData, ioStatus, buffer, length); /* Destroy the IRP. */ rdpdr_server_irp_free(irp); return CHANNEL_RC_OK; @@ -2161,9 +2128,9 @@ static UINT rdpdr_server_drive_read_file_callback(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_read_file(RdpdrServerContext* context, - void* callbackData, UINT32 deviceId, UINT32 fileId, UINT32 length, - UINT32 offset) +static UINT rdpdr_server_drive_read_file(RdpdrServerContext* context, void* callbackData, + UINT32 deviceId, UINT32 fileId, UINT32 length, + UINT32 offset) { RDPDR_IRP* irp; irp = rdpdr_server_irp_new(); @@ -2188,8 +2155,8 @@ static UINT rdpdr_server_drive_read_file(RdpdrServerContext* context, } /* Send a request to open the directory. */ - return rdpdr_server_send_device_read_request(context, deviceId, fileId, - irp->CompletionId, length, offset); + return rdpdr_server_send_device_read_request(context, deviceId, fileId, irp->CompletionId, + length, offset); } /************************************************* @@ -2201,13 +2168,14 @@ static UINT rdpdr_server_drive_read_file(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_write_file_callback(RdpdrServerContext* context, - wStream* s, RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, - UINT32 ioStatus) +static UINT rdpdr_server_drive_write_file_callback(RdpdrServerContext* context, wStream* s, + RDPDR_IRP* irp, UINT32 deviceId, + UINT32 completionId, UINT32 ioStatus) { UINT32 length; WLog_DBG(TAG, - "RdpdrServerDriveWriteFileCallback: deviceId=%"PRIu32", completionId=%"PRIu32", ioStatus=0x%"PRIx32"", + "RdpdrServerDriveWriteFileCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32 + ", ioStatus=0x%" PRIx32 "", deviceId, completionId, ioStatus); if (Stream_GetRemainingLength(s) < 5) @@ -2217,7 +2185,7 @@ static UINT rdpdr_server_drive_write_file_callback(RdpdrServerContext* context, } Stream_Read_UINT32(s, length); /* Length (4 bytes) */ - Stream_Seek(s, 1); /* Padding (1 byte) */ + Stream_Seek(s, 1); /* Padding (1 byte) */ if (Stream_GetRemainingLength(s) < length) { @@ -2237,9 +2205,9 @@ static UINT rdpdr_server_drive_write_file_callback(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_write_file(RdpdrServerContext* context, - void* callbackData, UINT32 deviceId, UINT32 fileId, const char* buffer, - UINT32 length, UINT32 offset) +static UINT rdpdr_server_drive_write_file(RdpdrServerContext* context, void* callbackData, + UINT32 deviceId, UINT32 fileId, const char* buffer, + UINT32 length, UINT32 offset) { RDPDR_IRP* irp; irp = rdpdr_server_irp_new(); @@ -2264,8 +2232,8 @@ static UINT rdpdr_server_drive_write_file(RdpdrServerContext* context, } /* Send a request to open the directory. */ - return rdpdr_server_send_device_write_request(context, deviceId, fileId, - irp->CompletionId, buffer, length, offset); + return rdpdr_server_send_device_write_request(context, deviceId, fileId, irp->CompletionId, + buffer, length, offset); } /************************************************* @@ -2277,12 +2245,13 @@ static UINT rdpdr_server_drive_write_file(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_close_file_callback(RdpdrServerContext* context, - wStream* s, RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, - UINT32 ioStatus) +static UINT rdpdr_server_drive_close_file_callback(RdpdrServerContext* context, wStream* s, + RDPDR_IRP* irp, UINT32 deviceId, + UINT32 completionId, UINT32 ioStatus) { WLog_DBG(TAG, - "RdpdrServerDriveCloseFileCallback: deviceId=%"PRIu32", completionId=%"PRIu32", ioStatus=0x%"PRIx32"", + "RdpdrServerDriveCloseFileCallback: deviceId=%" PRIu32 ", completionId=%" PRIu32 + ", ioStatus=0x%" PRIx32 "", deviceId, completionId, ioStatus); /* Invoke the close file completion routine. */ context->OnDriveCloseFileComplete(context, irp->CallbackData, ioStatus); @@ -2296,8 +2265,8 @@ static UINT rdpdr_server_drive_close_file_callback(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_close_file(RdpdrServerContext* context, - void* callbackData, UINT32 deviceId, UINT32 fileId) +static UINT rdpdr_server_drive_close_file(RdpdrServerContext* context, void* callbackData, + UINT32 deviceId, UINT32 fileId) { RDPDR_IRP* irp; irp = rdpdr_server_irp_new(); @@ -2322,8 +2291,7 @@ static UINT rdpdr_server_drive_close_file(RdpdrServerContext* context, } /* Send a request to open the directory. */ - return rdpdr_server_send_device_close_request(context, deviceId, fileId, - irp->CompletionId); + return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId); } /************************************************* @@ -2335,12 +2303,13 @@ static UINT rdpdr_server_drive_close_file(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_delete_file_callback2(RdpdrServerContext* - context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, - UINT32 ioStatus) +static UINT rdpdr_server_drive_delete_file_callback2(RdpdrServerContext* context, wStream* s, + RDPDR_IRP* irp, UINT32 deviceId, + UINT32 completionId, UINT32 ioStatus) { WLog_DBG(TAG, - "RdpdrServerDriveDeleteFileCallback2: deviceId=%"PRIu32", completionId=%"PRIu32", ioStatus=0x%"PRIx32"", + "RdpdrServerDriveDeleteFileCallback2: deviceId=%" PRIu32 ", completionId=%" PRIu32 + ", ioStatus=0x%" PRIx32 "", deviceId, completionId, ioStatus); /* Invoke the delete file completion routine. */ context->OnDriveDeleteFileComplete(context, irp->CallbackData, ioStatus); @@ -2354,14 +2323,15 @@ static UINT rdpdr_server_drive_delete_file_callback2(RdpdrServerContext* * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_delete_file_callback1(RdpdrServerContext* - context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, - UINT32 ioStatus) +static UINT rdpdr_server_drive_delete_file_callback1(RdpdrServerContext* context, wStream* s, + RDPDR_IRP* irp, UINT32 deviceId, + UINT32 completionId, UINT32 ioStatus) { UINT32 fileId; UINT8 information; WLog_DBG(TAG, - "RdpdrServerDriveDeleteFileCallback1: deviceId=%"PRIu32", completionId=%"PRIu32", ioStatus=0x%"PRIx32"", + "RdpdrServerDriveDeleteFileCallback1: deviceId=%" PRIu32 ", completionId=%" PRIu32 + ", ioStatus=0x%" PRIx32 "", deviceId, completionId, ioStatus); if (ioStatus != STATUS_SUCCESS) @@ -2379,7 +2349,7 @@ static UINT rdpdr_server_drive_delete_file_callback1(RdpdrServerContext* return ERROR_INVALID_DATA; } - Stream_Read_UINT32(s, fileId); /* FileId (4 bytes) */ + Stream_Read_UINT32(s, fileId); /* FileId (4 bytes) */ Stream_Read_UINT8(s, information); /* Information (1 byte) */ /* Setup the IRP. */ irp->CompletionId = context->priv->NextCompletionId++; @@ -2395,8 +2365,7 @@ static UINT rdpdr_server_drive_delete_file_callback1(RdpdrServerContext* } /* Send a request to close the file */ - return rdpdr_server_send_device_close_request(context, deviceId, fileId, - irp->CompletionId); + return rdpdr_server_send_device_close_request(context, deviceId, fileId, irp->CompletionId); } /** @@ -2404,8 +2373,8 @@ static UINT rdpdr_server_drive_delete_file_callback1(RdpdrServerContext* * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_delete_file(RdpdrServerContext* context, - void* callbackData, UINT32 deviceId, const char* path) +static UINT rdpdr_server_drive_delete_file(RdpdrServerContext* context, void* callbackData, + UINT32 deviceId, const char* path) { RDPDR_IRP* irp; irp = rdpdr_server_irp_new(); @@ -2431,10 +2400,9 @@ static UINT rdpdr_server_drive_delete_file(RdpdrServerContext* context, } /* Send a request to open the file. */ - return rdpdr_server_send_device_create_request(context, deviceId, - irp->CompletionId, irp->PathName, - FILE_READ_DATA | SYNCHRONIZE, - FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN); + return rdpdr_server_send_device_create_request( + context, deviceId, irp->CompletionId, irp->PathName, FILE_READ_DATA | SYNCHRONIZE, + FILE_DELETE_ON_CLOSE | FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN); } /************************************************* @@ -2446,12 +2414,13 @@ static UINT rdpdr_server_drive_delete_file(RdpdrServerContext* context, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_rename_file_callback3(RdpdrServerContext* - context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, - UINT32 ioStatus) +static UINT rdpdr_server_drive_rename_file_callback3(RdpdrServerContext* context, wStream* s, + RDPDR_IRP* irp, UINT32 deviceId, + UINT32 completionId, UINT32 ioStatus) { WLog_DBG(TAG, - "RdpdrServerDriveRenameFileCallback3: deviceId=%"PRIu32", completionId=%"PRIu32", ioStatus=0x%"PRIx32"", + "RdpdrServerDriveRenameFileCallback3: deviceId=%" PRIu32 ", completionId=%" PRIu32 + ", ioStatus=0x%" PRIx32 "", deviceId, completionId, ioStatus); /* Destroy the IRP. */ rdpdr_server_irp_free(irp); @@ -2463,13 +2432,14 @@ static UINT rdpdr_server_drive_rename_file_callback3(RdpdrServerContext* * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* - context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, - UINT32 ioStatus) +static UINT rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* context, wStream* s, + RDPDR_IRP* irp, UINT32 deviceId, + UINT32 completionId, UINT32 ioStatus) { UINT32 length; WLog_DBG(TAG, - "RdpdrServerDriveRenameFileCallback2: deviceId=%"PRIu32", completionId=%"PRIu32", ioStatus=0x%"PRIx32"", + "RdpdrServerDriveRenameFileCallback2: deviceId=%" PRIu32 ", completionId=%" PRIu32 + ", ioStatus=0x%" PRIx32 "", deviceId, completionId, ioStatus); if (Stream_GetRemainingLength(s) < 5) @@ -2479,7 +2449,7 @@ static UINT rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* } Stream_Read_UINT32(s, length); /* Length (4 bytes) */ - Stream_Seek(s, 1); /* Padding (1 byte) */ + Stream_Seek(s, 1); /* Padding (1 byte) */ /* Invoke the rename file completion routine. */ context->OnDriveRenameFileComplete(context, irp->CallbackData, ioStatus); /* Setup the IRP. */ @@ -2496,7 +2466,7 @@ static UINT rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* /* Send a request to close the file */ return rdpdr_server_send_device_close_request(context, deviceId, irp->FileId, - irp->CompletionId); + irp->CompletionId); } /** @@ -2504,14 +2474,15 @@ static UINT rdpdr_server_drive_rename_file_callback2(RdpdrServerContext* * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_rename_file_callback1(RdpdrServerContext* - context, wStream* s, RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, - UINT32 ioStatus) +static UINT rdpdr_server_drive_rename_file_callback1(RdpdrServerContext* context, wStream* s, + RDPDR_IRP* irp, UINT32 deviceId, + UINT32 completionId, UINT32 ioStatus) { UINT32 fileId; UINT8 information; WLog_DBG(TAG, - "RdpdrServerDriveRenameFileCallback1: deviceId=%"PRIu32", completionId=%"PRIu32", ioStatus=0x%"PRIx32"", + "RdpdrServerDriveRenameFileCallback1: deviceId=%" PRIu32 ", completionId=%" PRIu32 + ", ioStatus=0x%" PRIx32 "", deviceId, completionId, ioStatus); if (ioStatus != STATUS_SUCCESS) @@ -2529,7 +2500,7 @@ static UINT rdpdr_server_drive_rename_file_callback1(RdpdrServerContext* return ERROR_INVALID_DATA; } - Stream_Read_UINT32(s, fileId); /* FileId (4 bytes) */ + Stream_Read_UINT32(s, fileId); /* FileId (4 bytes) */ Stream_Read_UINT8(s, information); /* Information (1 byte) */ /* Setup the IRP. */ irp->CompletionId = context->priv->NextCompletionId++; @@ -2546,7 +2517,7 @@ static UINT rdpdr_server_drive_rename_file_callback1(RdpdrServerContext* /* Send a request to rename the file */ return rdpdr_server_send_device_file_rename_request(context, deviceId, fileId, - irp->CompletionId, irp->ExtraBuffer); + irp->CompletionId, irp->ExtraBuffer); } /** @@ -2554,8 +2525,9 @@ static UINT rdpdr_server_drive_rename_file_callback1(RdpdrServerContext* * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpdr_server_drive_rename_file(RdpdrServerContext* context, - void* callbackData, UINT32 deviceId, const char* oldPath, const char* newPath) +static UINT rdpdr_server_drive_rename_file(RdpdrServerContext* context, void* callbackData, + UINT32 deviceId, const char* oldPath, + const char* newPath) { RDPDR_IRP* irp; irp = rdpdr_server_irp_new(); @@ -2583,15 +2555,15 @@ static UINT rdpdr_server_drive_rename_file(RdpdrServerContext* context, } /* Send a request to open the file. */ - return rdpdr_server_send_device_create_request(context, deviceId, - irp->CompletionId, irp->PathName, - FILE_READ_DATA | SYNCHRONIZE, FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN); + return rdpdr_server_send_device_create_request(context, deviceId, irp->CompletionId, + irp->PathName, FILE_READ_DATA | SYNCHRONIZE, + FILE_SYNCHRONOUS_IO_NONALERT, FILE_OPEN); } RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm) { RdpdrServerContext* context; - context = (RdpdrServerContext*) calloc(1, sizeof(RdpdrServerContext)); + context = (RdpdrServerContext*)calloc(1, sizeof(RdpdrServerContext)); if (context) { @@ -2607,7 +2579,7 @@ RdpdrServerContext* rdpdr_server_context_new(HANDLE vcm) context->DriveCloseFile = rdpdr_server_drive_close_file; context->DriveDeleteFile = rdpdr_server_drive_delete_file; context->DriveRenameFile = rdpdr_server_drive_rename_file; - context->priv = (RdpdrServerPrivate*) calloc(1, sizeof(RdpdrServerPrivate)); + context->priv = (RdpdrServerPrivate*)calloc(1, sizeof(RdpdrServerPrivate)); if (!context->priv) { @@ -2652,4 +2624,3 @@ void rdpdr_server_context_free(RdpdrServerContext* context) free(context); } } - diff --git a/channels/rdpdr/server/rdpdr_main.h b/channels/rdpdr/server/rdpdr_main.h index 035ff7d..f3f54cc 100644 --- a/channels/rdpdr/server/rdpdr_main.h +++ b/channels/rdpdr/server/rdpdr_main.h @@ -48,7 +48,7 @@ struct _rdpdr_server_private UINT32 NextCompletionId; }; -#define RDPDR_HEADER_LENGTH 4 +#define RDPDR_HEADER_LENGTH 4 struct _RDPDR_HEADER { @@ -57,14 +57,14 @@ struct _RDPDR_HEADER }; typedef struct _RDPDR_HEADER RDPDR_HEADER; -#define RDPDR_VERSION_MAJOR 0x0001 +#define RDPDR_VERSION_MAJOR 0x0001 -#define RDPDR_VERSION_MINOR_RDP50 0x0002 -#define RDPDR_VERSION_MINOR_RDP51 0x0005 -#define RDPDR_VERSION_MINOR_RDP52 0x000A -#define RDPDR_VERSION_MINOR_RDP6X 0x000C +#define RDPDR_VERSION_MINOR_RDP50 0x0002 +#define RDPDR_VERSION_MINOR_RDP51 0x0005 +#define RDPDR_VERSION_MINOR_RDP52 0x000A +#define RDPDR_VERSION_MINOR_RDP6X 0x000C -#define RDPDR_CAPABILITY_HEADER_LENGTH 8 +#define RDPDR_CAPABILITY_HEADER_LENGTH 8 struct _RDPDR_CAPABILITY_HEADER { @@ -81,8 +81,10 @@ struct _RDPDR_IRP UINT32 FileId; char PathName[256]; char ExtraBuffer[256]; - void *CallbackData; - UINT (*Callback)(RdpdrServerContext* context, wStream* s, struct _RDPDR_IRP* irp, UINT32 deviceId, UINT32 completionId, UINT32 ioStatus); + void* CallbackData; + UINT(*Callback) + (RdpdrServerContext* context, wStream* s, struct _RDPDR_IRP* irp, UINT32 deviceId, + UINT32 completionId, UINT32 ioStatus); }; typedef struct _RDPDR_IRP RDPDR_IRP; diff --git a/channels/rdpei/client/rdpei_main.c b/channels/rdpei/client/rdpei_main.c index f668159..0a0cfef 100644 --- a/channels/rdpei/client/rdpei_main.c +++ b/channels/rdpei/client/rdpei_main.c @@ -62,7 +62,7 @@ * http://msdn.microsoft.com/en-us/library/hh454910/ */ -#define MAX_CONTACTS 512 +#define MAX_CONTACTS 512 struct _RDPEI_CHANNEL_CALLBACK { @@ -101,11 +101,6 @@ struct _RDPEI_PLUGIN RDPINPUT_CONTACT_DATA contacts[MAX_CONTACTS]; RDPINPUT_CONTACT_POINT* contactPoints; - HANDLE event; - HANDLE stopEvent; - HANDLE thread; - - CRITICAL_SECTION lock; rdpContext* rdpcontext; }; typedef struct _RDPEI_PLUGIN RDPEI_PLUGIN; @@ -115,34 +110,46 @@ typedef struct _RDPEI_PLUGIN RDPEI_PLUGIN; * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_send_frame(RdpeiClientContext* context); +static UINT rdpei_send_frame(RdpeiClientContext* context); -const char* RDPEI_EVENTID_STRINGS[] = +#ifdef WITH_DEBUG_RDPEI +static const char* rdpei_eventid_string(UINT16 event) { - "", - "EVENTID_SC_READY", - "EVENTID_CS_READY", - "EVENTID_TOUCH", - "EVENTID_SUSPEND_TOUCH", - "EVENTID_RESUME_TOUCH", - "EVENTID_DISMISS_HOVERING_CONTACT" -}; + switch (event) + { + case EVENTID_SC_READY: + return "EVENTID_SC_READY"; + case EVENTID_CS_READY: + return "EVENTID_CS_READY"; + case EVENTID_TOUCH: + return "EVENTID_TOUCH"; + case EVENTID_SUSPEND_TOUCH: + return "EVENTID_SUSPEND_TOUCH"; + case EVENTID_RESUME_TOUCH: + return "EVENTID_RESUME_TOUCH"; + case EVENTID_DISMISS_HOVERING_CONTACT: + return "EVENTID_DISMISS_HOVERING_CONTACT"; + default: + return "EVENTID_UNKNOWN"; + } +} +#endif /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_add_frame(RdpeiClientContext* context) +static UINT rdpei_add_frame(RdpeiClientContext* context) { int i; RDPINPUT_CONTACT_DATA* contact; - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle; + RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)context->handle; rdpei->frame.contactCount = 0; for (i = 0; i < rdpei->maxTouchContacts; i++) { - contact = (RDPINPUT_CONTACT_DATA*) & (rdpei->contactPoints[i].data); + contact = (RDPINPUT_CONTACT_DATA*)&(rdpei->contactPoints[i].data); if (rdpei->contactPoints[i].dirty) { @@ -169,91 +176,25 @@ UINT rdpei_add_frame(RdpeiClientContext* context) return CHANNEL_RC_OK; } -static DWORD WINAPI rdpei_schedule_thread(LPVOID arg) -{ - DWORD status; - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) arg; - RdpeiClientContext* context = (RdpeiClientContext*) rdpei->iface.pInterface; - HANDLE hdl[] = {rdpei->event, rdpei->stopEvent}; - UINT error = CHANNEL_RC_OK; - - if (!rdpei) - { - error = ERROR_INVALID_PARAMETER; - goto out; - } - - if (!context) - { - error = ERROR_INVALID_PARAMETER; - goto out; - } - - while (1) - { - status = WaitForMultipleObjects(2, hdl, FALSE, 20); - - if (status == WAIT_FAILED) - { - error = GetLastError(); - WLog_ERR(TAG, "WaitForMultipleObjects failed with error %"PRIu32"!", error); - break; - } - - if (status == WAIT_OBJECT_0 + 1) - break; - - EnterCriticalSection(&rdpei->lock); - - if ((error = rdpei_add_frame(context))) - { - WLog_ERR(TAG, "rdpei_add_frame failed with error %"PRIu32"!", error); - break; - } - - if (rdpei->frame.contactCount > 0) - { - if ((error = rdpei_send_frame(context))) - { - WLog_ERR(TAG, "rdpei_send_frame failed with error %"PRIu32"!", error); - break; - } - } - - if (status == WAIT_OBJECT_0) - ResetEvent(rdpei->event); - - LeaveCriticalSection(&rdpei->lock); - } - -out: - - if (error && rdpei && rdpei->rdpcontext) - setChannelError(rdpei->rdpcontext, error, - "rdpei_schedule_thread reported an error"); - - ExitThread(error); - return error; -} - /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_send_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s, - UINT16 eventId, UINT32 pduLength) +static UINT rdpei_send_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s, UINT16 eventId, + UINT32 pduLength) { UINT status; Stream_SetPosition(s, 0); - Stream_Write_UINT16(s, eventId); /* eventId (2 bytes) */ + Stream_Write_UINT16(s, eventId); /* eventId (2 bytes) */ Stream_Write_UINT32(s, pduLength); /* pduLength (4 bytes) */ Stream_SetPosition(s, Stream_Length(s)); - status = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), - Stream_Buffer(s), NULL); + status = callback->channel->Write(callback->channel, (UINT32)Stream_Length(s), Stream_Buffer(s), + NULL); #ifdef WITH_DEBUG_RDPEI - WLog_DBG(TAG, "rdpei_send_pdu: eventId: %"PRIu16" (%s) length: %"PRIu32" status: %"PRIu32"", - eventId, RDPEI_EVENTID_STRINGS[eventId], pduLength, status); + WLog_DBG(TAG, + "rdpei_send_pdu: eventId: %" PRIu16 " (%s) length: %" PRIu32 " status: %" PRIu32 "", + eventId, rdpei_eventid_string(eventId), pduLength, status); #endif return status; } @@ -263,16 +204,16 @@ UINT rdpei_send_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s, * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_send_cs_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback) +static UINT rdpei_send_cs_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback) { UINT status; wStream* s; UINT32 flags; UINT32 pduLength; - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) callback->plugin; + RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)callback->plugin; flags = 0; flags |= READY_FLAGS_SHOW_TOUCH_VISUALS; - //flags |= READY_FLAGS_DISABLE_TIMESTAMP_INJECTION; + // flags |= READY_FLAGS_DISABLE_TIMESTAMP_INJECTION; pduLength = RDPINPUT_HEADER_LENGTH + 10; s = Stream_New(NULL, pduLength); @@ -283,17 +224,16 @@ UINT rdpei_send_cs_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback) } Stream_Seek(s, RDPINPUT_HEADER_LENGTH); - Stream_Write_UINT32(s, flags); /* flags (4 bytes) */ - Stream_Write_UINT32(s, RDPINPUT_PROTOCOL_V10); /* protocolVersion (4 bytes) */ - Stream_Write_UINT16(s, - rdpei->maxTouchContacts); /* maxTouchContacts (2 bytes) */ + Stream_Write_UINT32(s, flags); /* flags (4 bytes) */ + Stream_Write_UINT32(s, RDPINPUT_PROTOCOL_V10); /* protocolVersion (4 bytes) */ + Stream_Write_UINT16(s, rdpei->maxTouchContacts); /* maxTouchContacts (2 bytes) */ Stream_SealLength(s); status = rdpei_send_pdu(callback, s, EVENTID_CS_READY, pduLength); Stream_Free(s, TRUE); return status; } -void rdpei_print_contact_flags(UINT32 contactFlags) +static void rdpei_print_contact_flags(UINT32 contactFlags) { if (contactFlags & CONTACT_FLAG_DOWN) WLog_DBG(TAG, " CONTACT_FLAG_DOWN"); @@ -319,14 +259,14 @@ void rdpei_print_contact_flags(UINT32 contactFlags) * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame) +static UINT rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame) { UINT32 index; int rectSize = 2; RDPINPUT_CONTACT_DATA* contact; #ifdef WITH_DEBUG_RDPEI - WLog_DBG(TAG, "contactCount: %"PRIu32"", frame->contactCount); - WLog_DBG(TAG, "frameOffset: 0x%016"PRIX64"", frame->frameOffset); + WLog_DBG(TAG, "contactCount: %" PRIu32 "", frame->contactCount); + WLog_DBG(TAG, "frameOffset: 0x%016" PRIX64 "", frame->frameOffset); #endif rdpei_write_2byte_unsigned(s, frame->contactCount); /* contactCount (TWO_BYTE_UNSIGNED_INTEGER) */ @@ -334,10 +274,10 @@ UINT rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame) * the time offset from the previous frame (in microseconds). * If this is the first frame being transmitted then this field MUST be set to zero. */ - rdpei_write_8byte_unsigned(s, - frame->frameOffset * 1000); /* frameOffset (EIGHT_BYTE_UNSIGNED_INTEGER) */ + rdpei_write_8byte_unsigned(s, frame->frameOffset * + 1000); /* frameOffset (EIGHT_BYTE_UNSIGNED_INTEGER) */ - if (!Stream_EnsureRemainingCapacity(s, (size_t) frame->contactCount * 64)) + if (!Stream_EnsureRemainingCapacity(s, (size_t)frame->contactCount * 64)) { WLog_ERR(TAG, "Stream_EnsureRemainingCapacity failed!"); return CHANNEL_RC_NO_MEMORY; @@ -352,11 +292,13 @@ UINT rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame) contact->contactRectRight = contact->x + rectSize; contact->contactRectBottom = contact->y + rectSize; #ifdef WITH_DEBUG_RDPEI - WLog_DBG(TAG, "contact[%"PRIu32"].contactId: %"PRIu32"", index, contact->contactId); - WLog_DBG(TAG, "contact[%"PRIu32"].fieldsPresent: %"PRIu32"", index, contact->fieldsPresent); - WLog_DBG(TAG, "contact[%"PRIu32"].x: %"PRId32"", index, contact->x); - WLog_DBG(TAG, "contact[%"PRIu32"].y: %"PRId32"", index, contact->y); - WLog_DBG(TAG, "contact[%"PRIu32"].contactFlags: 0x%08"PRIX32"", index, contact->contactFlags); + WLog_DBG(TAG, "contact[%" PRIu32 "].contactId: %" PRIu32 "", index, contact->contactId); + WLog_DBG(TAG, "contact[%" PRIu32 "].fieldsPresent: %" PRIu32 "", index, + contact->fieldsPresent); + WLog_DBG(TAG, "contact[%" PRIu32 "].x: %" PRId32 "", index, contact->x); + WLog_DBG(TAG, "contact[%" PRIu32 "].y: %" PRId32 "", index, contact->y); + WLog_DBG(TAG, "contact[%" PRIu32 "].contactFlags: 0x%08" PRIX32 "", index, + contact->contactFlags); rdpei_print_contact_flags(contact->contactFlags); #endif Stream_Write_UINT8(s, contact->contactId); /* contactId (1 byte) */ @@ -400,8 +342,8 @@ UINT rdpei_write_touch_frame(wStream* s, RDPINPUT_TOUCH_FRAME* frame) * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, - RDPINPUT_TOUCH_FRAME* frame) +static UINT rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, + RDPINPUT_TOUCH_FRAME* frame) { UINT status; wStream* s; @@ -420,13 +362,13 @@ UINT rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, * the time that has elapsed (in milliseconds) from when the oldest touch frame * was generated to when it was encoded for transmission by the client. */ - rdpei_write_4byte_unsigned(s, - (UINT32) frame->frameOffset); /* encodeTime (FOUR_BYTE_UNSIGNED_INTEGER) */ - rdpei_write_2byte_unsigned(s, 1); /* (frameCount) TWO_BYTE_UNSIGNED_INTEGER */ + rdpei_write_4byte_unsigned( + s, (UINT32)frame->frameOffset); /* encodeTime (FOUR_BYTE_UNSIGNED_INTEGER) */ + rdpei_write_2byte_unsigned(s, 1); /* (frameCount) TWO_BYTE_UNSIGNED_INTEGER */ if ((status = rdpei_write_touch_frame(s, frame))) { - WLog_ERR(TAG, "rdpei_write_touch_frame failed with error %"PRIu32"!", status); + WLog_ERR(TAG, "rdpei_write_touch_frame failed with error %" PRIu32 "!", status); Stream_Free(s, TRUE); return status; } @@ -443,7 +385,7 @@ UINT rdpei_send_touch_event_pdu(RDPEI_CHANNEL_CALLBACK* callback, * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_recv_sc_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) +static UINT rdpei_recv_sc_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) { UINT32 protocolVersion; Stream_Read_UINT32(s, protocolVersion); /* protocolVersion (4 bytes) */ @@ -464,14 +406,14 @@ UINT rdpei_recv_sc_ready_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_recv_suspend_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) +static UINT rdpei_recv_suspend_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) { - RdpeiClientContext* rdpei = (RdpeiClientContext*) callback->plugin->pInterface; + RdpeiClientContext* rdpei = (RdpeiClientContext*)callback->plugin->pInterface; UINT error = CHANNEL_RC_OK; IFCALLRET(rdpei->SuspendTouch, error, rdpei); if (error) - WLog_ERR(TAG, "rdpei->SuspendTouch failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rdpei->SuspendTouch failed with error %" PRIu32 "!", error); return error; } @@ -481,14 +423,14 @@ UINT rdpei_recv_suspend_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_recv_resume_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) +static UINT rdpei_recv_resume_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) { - RdpeiClientContext* rdpei = (RdpeiClientContext*) callback->plugin->pInterface; + RdpeiClientContext* rdpei = (RdpeiClientContext*)callback->plugin->pInterface; UINT error = CHANNEL_RC_OK; IFCALLRET(rdpei->ResumeTouch, error, rdpei); if (error) - WLog_ERR(TAG, "rdpei->ResumeTouch failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rdpei->ResumeTouch failed with error %" PRIu32 "!", error); return error; } @@ -498,16 +440,19 @@ UINT rdpei_recv_resume_touch_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) +static UINT rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) { UINT16 eventId; UINT32 pduLength; UINT error; - Stream_Read_UINT16(s, eventId); /* eventId (2 bytes) */ + if (Stream_GetRemainingLength(s) < 6) + return ERROR_INVALID_DATA; + + Stream_Read_UINT16(s, eventId); /* eventId (2 bytes) */ Stream_Read_UINT32(s, pduLength); /* pduLength (4 bytes) */ #ifdef WITH_DEBUG_RDPEI - WLog_DBG(TAG, "rdpei_recv_pdu: eventId: %"PRIu16" (%s) length: %"PRIu32"", - eventId, RDPEI_EVENTID_STRINGS[eventId], pduLength); + WLog_DBG(TAG, "rdpei_recv_pdu: eventId: %" PRIu16 " (%s) length: %" PRIu32 "", eventId, + rdpei_eventid_string(eventId), pduLength); #endif switch (eventId) @@ -515,13 +460,13 @@ UINT rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) case EVENTID_SC_READY: if ((error = rdpei_recv_sc_ready_pdu(callback, s))) { - WLog_ERR(TAG, "rdpei_recv_sc_ready_pdu failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rdpei_recv_sc_ready_pdu failed with error %" PRIu32 "!", error); return error; } if ((error = rdpei_send_cs_ready_pdu(callback))) { - WLog_ERR(TAG, "rdpei_send_cs_ready_pdu failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rdpei_send_cs_ready_pdu failed with error %" PRIu32 "!", error); return error; } @@ -530,7 +475,7 @@ UINT rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) case EVENTID_SUSPEND_TOUCH: if ((error = rdpei_recv_suspend_touch_pdu(callback, s))) { - WLog_ERR(TAG, "rdpei_recv_suspend_touch_pdu failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rdpei_recv_suspend_touch_pdu failed with error %" PRIu32 "!", error); return error; } @@ -539,7 +484,7 @@ UINT rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) case EVENTID_RESUME_TOUCH: if ((error = rdpei_recv_resume_touch_pdu(callback, s))) { - WLog_ERR(TAG, "rdpei_recv_resume_touch_pdu failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rdpei_recv_resume_touch_pdu failed with error %" PRIu32 "!", error); return error; } @@ -557,11 +502,10 @@ UINT rdpei_recv_pdu(RDPEI_CHANNEL_CALLBACK* callback, wStream* s) * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, - wStream* data) +static UINT rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, wStream* data) { - RDPEI_CHANNEL_CALLBACK* callback = (RDPEI_CHANNEL_CALLBACK*) pChannelCallback; - return rdpei_recv_pdu(callback, data); + RDPEI_CHANNEL_CALLBACK* callback = (RDPEI_CHANNEL_CALLBACK*)pChannelCallback; + return rdpei_recv_pdu(callback, data); } /** @@ -571,7 +515,7 @@ static UINT rdpei_on_data_received(IWTSVirtualChannelCallback* pChannelCallback, */ static UINT rdpei_on_close(IWTSVirtualChannelCallback* pChannelCallback) { - RDPEI_CHANNEL_CALLBACK* callback = (RDPEI_CHANNEL_CALLBACK*) pChannelCallback; + RDPEI_CHANNEL_CALLBACK* callback = (RDPEI_CHANNEL_CALLBACK*)pChannelCallback; free(callback); return CHANNEL_RC_OK; } @@ -581,15 +525,13 @@ static UINT rdpei_on_close(IWTSVirtualChannelCallback* pChannelCallback) * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpei_on_new_channel_connection(IWTSListenerCallback* - pListenerCallback, - IWTSVirtualChannel* pChannel, BYTE* Data, BOOL* pbAccept, - IWTSVirtualChannelCallback** ppCallback) +static UINT rdpei_on_new_channel_connection(IWTSListenerCallback* pListenerCallback, + IWTSVirtualChannel* pChannel, BYTE* Data, + BOOL* pbAccept, IWTSVirtualChannelCallback** ppCallback) { RDPEI_CHANNEL_CALLBACK* callback; - RDPEI_LISTENER_CALLBACK* listener_callback = (RDPEI_LISTENER_CALLBACK*) - pListenerCallback; - callback = (RDPEI_CHANNEL_CALLBACK*) calloc(1, sizeof(RDPEI_CHANNEL_CALLBACK)); + RDPEI_LISTENER_CALLBACK* listener_callback = (RDPEI_LISTENER_CALLBACK*)pListenerCallback; + callback = (RDPEI_CHANNEL_CALLBACK*)calloc(1, sizeof(RDPEI_CHANNEL_CALLBACK)); if (!callback) { @@ -603,7 +545,7 @@ static UINT rdpei_on_new_channel_connection(IWTSListenerCallback* callback->channel_mgr = listener_callback->channel_mgr; callback->channel = pChannel; listener_callback->channel_callback = callback; - *ppCallback = (IWTSVirtualChannelCallback*) callback; + *ppCallback = (IWTSVirtualChannelCallback*)callback; return CHANNEL_RC_OK; } @@ -612,13 +554,11 @@ static UINT rdpei_on_new_channel_connection(IWTSListenerCallback* * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpei_plugin_initialize(IWTSPlugin* pPlugin, - IWTSVirtualChannelManager* pChannelMgr) +static UINT rdpei_plugin_initialize(IWTSPlugin* pPlugin, IWTSVirtualChannelManager* pChannelMgr) { UINT error; - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) pPlugin; - rdpei->listener_callback = (RDPEI_LISTENER_CALLBACK*) calloc(1 , - sizeof(RDPEI_LISTENER_CALLBACK)); + RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)pPlugin; + rdpei->listener_callback = (RDPEI_LISTENER_CALLBACK*)calloc(1, sizeof(RDPEI_LISTENER_CALLBACK)); if (!rdpei->listener_callback) { @@ -626,44 +566,21 @@ static UINT rdpei_plugin_initialize(IWTSPlugin* pPlugin, return CHANNEL_RC_NO_MEMORY; } - rdpei->listener_callback->iface.OnNewChannelConnection = - rdpei_on_new_channel_connection; + rdpei->listener_callback->iface.OnNewChannelConnection = rdpei_on_new_channel_connection; rdpei->listener_callback->plugin = pPlugin; rdpei->listener_callback->channel_mgr = pChannelMgr; if ((error = pChannelMgr->CreateListener(pChannelMgr, RDPEI_DVC_CHANNEL_NAME, 0, - (IWTSListenerCallback*) rdpei->listener_callback, &(rdpei->listener)))) + &rdpei->listener_callback->iface, &(rdpei->listener)))) { - WLog_ERR(TAG, "ChannelMgr->CreateListener failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "ChannelMgr->CreateListener failed with error %" PRIu32 "!", error); goto error_out; } rdpei->listener->pInterface = rdpei->iface.pInterface; - InitializeCriticalSection(&rdpei->lock); - - if (!(rdpei->event = CreateEvent(NULL, TRUE, FALSE, NULL))) - { - WLog_ERR(TAG, "CreateEvent failed!"); - goto error_out; - } - - if (!(rdpei->stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL))) - { - WLog_ERR(TAG, "CreateEvent failed!"); - goto error_out; - } - - if (!(rdpei->thread = CreateThread(NULL, 0, - rdpei_schedule_thread, (void*) rdpei, 0, NULL))) - { - WLog_ERR(TAG, "CreateThread failed!"); - goto error_out; - } return error; error_out: - CloseHandle(rdpei->stopEvent); - CloseHandle(rdpei->event); free(rdpei->listener_callback); return error; } @@ -675,26 +592,17 @@ error_out: */ static UINT rdpei_plugin_terminated(IWTSPlugin* pPlugin) { - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) pPlugin; - UINT error; + RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)pPlugin; if (!pPlugin) return ERROR_INVALID_PARAMETER; - SetEvent(rdpei->stopEvent); - EnterCriticalSection(&rdpei->lock); - - if (WaitForSingleObject(rdpei->thread, INFINITE) == WAIT_FAILED) + if (rdpei && rdpei->listener_callback) { - error = GetLastError(); - WLog_ERR(TAG, "WaitForSingleObject failed with error %"PRIu32"!", error); - return error; + IWTSVirtualChannelManager* mgr = rdpei->listener_callback->channel_mgr; + if (mgr) + IFCALL(mgr->DestroyListener, mgr, rdpei->listener); } - - CloseHandle(rdpei->stopEvent); - CloseHandle(rdpei->event); - CloseHandle(rdpei->thread); - DeleteCriticalSection(&rdpei->lock); free(rdpei->listener_callback); free(rdpei->context); free(rdpei); @@ -705,9 +613,9 @@ static UINT rdpei_plugin_terminated(IWTSPlugin* pPlugin) * Channel Client Interface */ -int rdpei_get_version(RdpeiClientContext* context) +static int rdpei_get_version(RdpeiClientContext* context) { - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle; + RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)context->handle; return rdpei->version; } @@ -719,7 +627,7 @@ int rdpei_get_version(RdpeiClientContext* context) UINT rdpei_send_frame(RdpeiClientContext* context) { UINT64 currentTime; - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle; + RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)context->handle; RDPEI_CHANNEL_CALLBACK* callback = rdpei->listener_callback->channel_callback; UINT error; currentTime = GetTickCount64(); @@ -737,7 +645,7 @@ UINT rdpei_send_frame(RdpeiClientContext* context) if ((error = rdpei_send_touch_event_pdu(callback, &rdpei->frame))) { - WLog_ERR(TAG, "rdpei_send_touch_event_pdu failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rdpei_send_touch_event_pdu failed with error %" PRIu32 "!", error); return error; } @@ -751,18 +659,32 @@ UINT rdpei_send_frame(RdpeiClientContext* context) * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_add_contact(RdpeiClientContext* context, - RDPINPUT_CONTACT_DATA* contact) +static UINT rdpei_add_contact(RdpeiClientContext* context, const RDPINPUT_CONTACT_DATA* contact) { + UINT error; RDPINPUT_CONTACT_POINT* contactPoint; - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle; - EnterCriticalSection(&rdpei->lock); - contactPoint = (RDPINPUT_CONTACT_POINT*) - &rdpei->contactPoints[contact->contactId]; + RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)context->handle; + + contactPoint = (RDPINPUT_CONTACT_POINT*)&rdpei->contactPoints[contact->contactId]; CopyMemory(&(contactPoint->data), contact, sizeof(RDPINPUT_CONTACT_DATA)); contactPoint->dirty = TRUE; - SetEvent(rdpei->event); - LeaveCriticalSection(&rdpei->lock); + + error = rdpei_add_frame(context); + if (error != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "rdpei_add_frame failed with error %" PRIu32 "!", error); + return error; + } + + if (rdpei->frame.contactCount > 0) + { + error = rdpei_send_frame(context); + if (error != CHANNEL_RC_OK) + { + WLog_ERR(TAG, "rdpei_send_frame failed with error %" PRIu32 "!", error); + return error; + } + } return CHANNEL_RC_OK; } @@ -771,21 +693,21 @@ UINT rdpei_add_contact(RdpeiClientContext* context, * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x, - int y, int* contactId) +static UINT rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x, int y, + int* contactId) { unsigned int i; - int contactIdlocal = -1; + INT64 contactIdlocal = -1; RDPINPUT_CONTACT_DATA contact; RDPINPUT_CONTACT_POINT* contactPoint = NULL; - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle; - UINT error = CHANNEL_RC_OK; + RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)context->handle; + UINT error = CHANNEL_RC_OK; /* Create a new contact point in an empty slot */ for (i = 0; i < rdpei->maxTouchContacts; i++) { - contactPoint = (RDPINPUT_CONTACT_POINT*) &rdpei->contactPoints[i]; + contactPoint = (RDPINPUT_CONTACT_POINT*)&rdpei->contactPoints[i]; if (!contactPoint->active) { @@ -805,7 +727,7 @@ UINT rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x, contactPoint->lastY = y; contact.x = x; contact.y = y; - contact.contactId = (UINT32) contactIdlocal; + contact.contactId = (UINT32)contactIdlocal; contact.contactFlags |= CONTACT_FLAG_DOWN; contact.contactFlags |= CONTACT_FLAG_INRANGE; contact.contactFlags |= CONTACT_FLAG_INCONTACT; @@ -821,19 +743,19 @@ UINT rdpei_touch_begin(RdpeiClientContext* context, int externalId, int x, * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_touch_update(RdpeiClientContext* context, int externalId, int x, - int y, int* contactId) +static UINT rdpei_touch_update(RdpeiClientContext* context, int externalId, int x, int y, + int* contactId) { unsigned int i; int contactIdlocal = -1; RDPINPUT_CONTACT_DATA contact; RDPINPUT_CONTACT_POINT* contactPoint = NULL; - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle; + RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)context->handle; UINT error = CHANNEL_RC_OK; for (i = 0; i < rdpei->maxTouchContacts; i++) { - contactPoint = (RDPINPUT_CONTACT_POINT*) &rdpei->contactPoints[i]; + contactPoint = (RDPINPUT_CONTACT_POINT*)&rdpei->contactPoints[i]; if (!contactPoint->active) continue; @@ -852,7 +774,7 @@ UINT rdpei_touch_update(RdpeiClientContext* context, int externalId, int x, contactPoint->lastY = y; contact.x = x; contact.y = y; - contact.contactId = (UINT32) contactIdlocal; + contact.contactId = (UINT32)contactIdlocal; contact.contactFlags |= CONTACT_FLAG_UPDATE; contact.contactFlags |= CONTACT_FLAG_INRANGE; contact.contactFlags |= CONTACT_FLAG_INCONTACT; @@ -868,20 +790,20 @@ UINT rdpei_touch_update(RdpeiClientContext* context, int externalId, int x, * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y, - int* contactId) +static UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y, + int* contactId) { unsigned int i; int contactIdlocal = -1; int tempvalue; RDPINPUT_CONTACT_DATA contact; RDPINPUT_CONTACT_POINT* contactPoint = NULL; - RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*) context->handle; + RDPEI_PLUGIN* rdpei = (RDPEI_PLUGIN*)context->handle; UINT error; for (i = 0; i < rdpei->maxTouchContacts; i++) { - contactPoint = (RDPINPUT_CONTACT_POINT*) &rdpei->contactPoints[i]; + contactPoint = (RDPINPUT_CONTACT_POINT*)&rdpei->contactPoints[i]; if (!contactPoint->active) continue; @@ -901,19 +823,19 @@ UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y, { if ((error = context->TouchUpdate(context, externalId, x, y, &tempvalue))) { - WLog_ERR(TAG, "context->TouchUpdate failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "context->TouchUpdate failed with error %" PRIu32 "!", error); return error; } } contact.x = x; contact.y = y; - contact.contactId = (UINT32) contactIdlocal; + contact.contactId = (UINT32)contactIdlocal; contact.contactFlags |= CONTACT_FLAG_UP; if ((error = context->AddContact(context, &contact))) { - WLog_ERR(TAG, "context->AddContact failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "context->AddContact failed with error %" PRIu32 "!", error); return error; } @@ -929,9 +851,9 @@ UINT rdpei_touch_end(RdpeiClientContext* context, int externalId, int x, int y, } #ifdef BUILTIN_CHANNELS -#define DVCPluginEntry rdpei_DVCPluginEntry +#define DVCPluginEntry rdpei_DVCPluginEntry #else -#define DVCPluginEntry FREERDP_API DVCPluginEntry +#define DVCPluginEntry FREERDP_API DVCPluginEntry #endif /** @@ -944,12 +866,12 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) UINT error; RDPEI_PLUGIN* rdpei = NULL; RdpeiClientContext* context = NULL; - rdpei = (RDPEI_PLUGIN*) pEntryPoints->GetPlugin(pEntryPoints, "rdpei"); + rdpei = (RDPEI_PLUGIN*)pEntryPoints->GetPlugin(pEntryPoints, "rdpei"); if (!rdpei) { size_t size; - rdpei = (RDPEI_PLUGIN*) calloc(1, sizeof(RDPEI_PLUGIN)); + rdpei = (RDPEI_PLUGIN*)calloc(1, sizeof(RDPEI_PLUGIN)); if (!rdpei) { @@ -964,12 +886,13 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) rdpei->version = 1; rdpei->currentFrameTime = 0; rdpei->previousFrameTime = 0; - rdpei->frame.contacts = (RDPINPUT_CONTACT_DATA*) rdpei->contacts; + rdpei->frame.contacts = (RDPINPUT_CONTACT_DATA*)rdpei->contacts; rdpei->maxTouchContacts = 10; size = rdpei->maxTouchContacts * sizeof(RDPINPUT_CONTACT_POINT); - rdpei->contactPoints = (RDPINPUT_CONTACT_POINT*) calloc(1, size); - rdpei->rdpcontext = ((freerdp*)((rdpSettings*) pEntryPoints->GetRdpSettings( - pEntryPoints))->instance)->context; + rdpei->contactPoints = (RDPINPUT_CONTACT_POINT*)calloc(1, size); + rdpei->rdpcontext = + ((freerdp*)((rdpSettings*)pEntryPoints->GetRdpSettings(pEntryPoints))->instance) + ->context; if (!rdpei->contactPoints) { @@ -978,7 +901,7 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) goto error_out; } - context = (RdpeiClientContext*) calloc(1, sizeof(RdpeiClientContext)); + context = (RdpeiClientContext*)calloc(1, sizeof(RdpeiClientContext)); if (!context) { @@ -987,18 +910,17 @@ UINT DVCPluginEntry(IDRDYNVC_ENTRY_POINTS* pEntryPoints) goto error_out; } - context->handle = (void*) rdpei; + context->handle = (void*)rdpei; context->GetVersion = rdpei_get_version; context->AddContact = rdpei_add_contact; context->TouchBegin = rdpei_touch_begin; context->TouchUpdate = rdpei_touch_update; context->TouchEnd = rdpei_touch_end; - rdpei->iface.pInterface = (void*) context; + rdpei->iface.pInterface = (void*)context; - if ((error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpei", - (IWTSPlugin*) rdpei))) + if ((error = pEntryPoints->RegisterPlugin(pEntryPoints, "rdpei", (IWTSPlugin*)rdpei))) { - WLog_ERR(TAG, "EntryPoints->RegisterPlugin failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "EntryPoints->RegisterPlugin failed with error %" PRIu32 "!", error); error = CHANNEL_RC_NO_MEMORY; goto error_out; } diff --git a/channels/rdpei/client/rdpei_main.h b/channels/rdpei/client/rdpei_main.h index 4dc4998..ed557b2 100644 --- a/channels/rdpei/client/rdpei_main.h +++ b/channels/rdpei/client/rdpei_main.h @@ -34,10 +34,10 @@ #define TAG CHANNELS_TAG("rdpei.client") -#define RDPINPUT_CONTACT_STATE_INITIAL 0x0000 -#define RDPINPUT_CONTACT_STATE_ENGAGED 0x0001 -#define RDPINPUT_CONTACT_STATE_HOVERING 0x0002 -#define RDPINPUT_CONTACT_STATE_OUT_OF_RANGE 0x0003 +#define RDPINPUT_CONTACT_STATE_INITIAL 0x0000 +#define RDPINPUT_CONTACT_STATE_ENGAGED 0x0001 +#define RDPINPUT_CONTACT_STATE_HOVERING 0x0002 +#define RDPINPUT_CONTACT_STATE_OUT_OF_RANGE 0x0003 /** * Touch Contact State Transitions @@ -84,8 +84,10 @@ typedef struct _RDPINPUT_CONTACT_POINT RDPINPUT_CONTACT_POINT; #ifdef WITH_DEBUG_DVC #define DEBUG_DVC(...) WLog_DBG(TAG, __VA_ARGS__) #else -#define DEBUG_DVC(...) do { } while (0) +#define DEBUG_DVC(...) \ + do \ + { \ + } while (0) #endif #endif /* FREERDP_CHANNEL_RDPEI_CLIENT_MAIN_H */ - diff --git a/channels/rdpei/rdpei_common.c b/channels/rdpei/rdpei_common.c index 41a2ec3..f01d4dd 100644 --- a/channels/rdpei/rdpei_common.c +++ b/channels/rdpei/rdpei_common.c @@ -199,18 +199,18 @@ BOOL rdpei_write_4byte_unsigned(wStream* s, UINT32 value) { BYTE byte; - if (value <= 0x3F) + if (value <= 0x3FUL) { Stream_Write_UINT8(s, value); } - else if (value <= 0x3FFF) + else if (value <= 0x3FFFUL) { byte = (value >> 8) & 0x3F; Stream_Write_UINT8(s, byte | 0x40); byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x3FFFFF) + else if (value <= 0x3FFFFFUL) { byte = (value >> 16) & 0x3F; Stream_Write_UINT8(s, byte | 0x80); @@ -219,7 +219,7 @@ BOOL rdpei_write_4byte_unsigned(wStream* s, UINT32 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x3FFFFF) + else if (value <= 0x3FFFFFFFUL) { byte = (value >> 24) & 0x3F; Stream_Write_UINT8(s, byte | 0xC0); @@ -306,7 +306,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value) value *= -1; } - if (value <= 0x1F) + if (value <= 0x1FUL) { byte = value & 0x1F; @@ -315,7 +315,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value) Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFF) + else if (value <= 0x1FFFUL) { byte = (value >> 8) & 0x1F; @@ -326,7 +326,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFF) + else if (value <= 0x1FFFFFUL) { byte = (value >> 16) & 0x1F; @@ -339,7 +339,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFF) + else if (value <= 0x1FFFFFFFUL) { byte = (value >> 24) & 0x1F; @@ -408,7 +408,7 @@ BOOL rdpei_read_8byte_unsigned(wStream* s, UINT64* value) break; case 4: - *value = ((UINT64) (byte & 0x1F)) << 32; + *value = ((UINT64)(byte & 0x1F)) << 32; Stream_Read_UINT8(s, byte); *value |= (byte << 24); Stream_Read_UINT8(s, byte); @@ -420,9 +420,9 @@ BOOL rdpei_read_8byte_unsigned(wStream* s, UINT64* value) break; case 5: - *value = ((UINT64) (byte & 0x1F)) << 40; + *value = ((UINT64)(byte & 0x1F)) << 40; Stream_Read_UINT8(s, byte); - *value |= (((UINT64) byte) << 32); + *value |= (((UINT64)byte) << 32); Stream_Read_UINT8(s, byte); *value |= (byte << 24); Stream_Read_UINT8(s, byte); @@ -434,11 +434,11 @@ BOOL rdpei_read_8byte_unsigned(wStream* s, UINT64* value) break; case 6: - *value = ((UINT64) (byte & 0x1F)) << 48; + *value = ((UINT64)(byte & 0x1F)) << 48; Stream_Read_UINT8(s, byte); - *value |= (((UINT64) byte) << 40); + *value |= (((UINT64)byte) << 40); Stream_Read_UINT8(s, byte); - *value |= (((UINT64) byte) << 32); + *value |= (((UINT64)byte) << 32); Stream_Read_UINT8(s, byte); *value |= (byte << 24); Stream_Read_UINT8(s, byte); @@ -450,13 +450,13 @@ BOOL rdpei_read_8byte_unsigned(wStream* s, UINT64* value) break; case 7: - *value = ((UINT64) (byte & 0x1F)) << 56; + *value = ((UINT64)(byte & 0x1F)) << 56; Stream_Read_UINT8(s, byte); - *value |= (((UINT64) byte) << 48); + *value |= (((UINT64)byte) << 48); Stream_Read_UINT8(s, byte); - *value |= (((UINT64) byte) << 40); + *value |= (((UINT64)byte) << 40); Stream_Read_UINT8(s, byte); - *value |= (((UINT64) byte) << 32); + *value |= (((UINT64)byte) << 32); Stream_Read_UINT8(s, byte); *value |= (byte << 24); Stream_Read_UINT8(s, byte); @@ -478,12 +478,12 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value) { BYTE byte; - if (value <= 0x1F) + if (value <= 0x1FULL) { byte = value & 0x1F; Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFF) + else if (value <= 0x1FFFULL) { byte = (value >> 8) & 0x1F; byte |= (1 << 5); @@ -491,7 +491,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFF) + else if (value <= 0x1FFFFFULL) { byte = (value >> 16) & 0x1F; byte |= (2 << 5); @@ -501,7 +501,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFF) + else if (value <= 0x1FFFFFULL) { byte = (value >> 24) & 0x1F; byte |= (3 << 5); @@ -513,7 +513,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFFFF) + else if (value <= 0x1FFFFFFFULL) { byte = (value >> 32) & 0x1F; byte |= (4 << 5); @@ -527,7 +527,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFFFFFF) + else if (value <= 0x1FFFFFFFFFULL) { byte = (value >> 40) & 0x1F; byte |= (5 << 5); @@ -543,7 +543,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFFFFFFFF) + else if (value <= 0x1FFFFFFFFFFFULL) { byte = (value >> 48) & 0x1F; byte |= (6 << 5); @@ -561,7 +561,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value) byte = (value & 0xFF); Stream_Write_UINT8(s, byte); } - else if (value <= 0x1FFFFFFFFFFFFF) + else if (value <= 0x1FFFFFFFFFFFFFFFULL) { byte = (value >> 56) & 0x1F; byte |= (7 << 5); @@ -589,7 +589,7 @@ BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value) return TRUE; } -void touch_event_reset(RDPINPUT_TOUCH_EVENT *event) +void touch_event_reset(RDPINPUT_TOUCH_EVENT* event) { int i; @@ -601,8 +601,7 @@ void touch_event_reset(RDPINPUT_TOUCH_EVENT *event) event->frameCount = 0; } - -void touch_frame_reset(RDPINPUT_TOUCH_FRAME *frame) +void touch_frame_reset(RDPINPUT_TOUCH_FRAME* frame) { free(frame->contacts); frame->contacts = NULL; diff --git a/channels/rdpei/rdpei_common.h b/channels/rdpei/rdpei_common.h index 34d1edd..610767a 100644 --- a/channels/rdpei/rdpei_common.h +++ b/channels/rdpei/rdpei_common.h @@ -26,7 +26,8 @@ #include /** @brief input event ids */ -enum { +enum +{ EVENTID_SC_READY = 0x0001, EVENTID_CS_READY = 0x0002, EVENTID_TOUCH = 0x0003, @@ -46,8 +47,7 @@ BOOL rdpei_write_4byte_signed(wStream* s, INT32 value); BOOL rdpei_read_8byte_unsigned(wStream* s, UINT64* value); BOOL rdpei_write_8byte_unsigned(wStream* s, UINT64 value); -void touch_event_reset(RDPINPUT_TOUCH_EVENT *event); -void touch_frame_reset(RDPINPUT_TOUCH_FRAME *frame); +void touch_event_reset(RDPINPUT_TOUCH_EVENT* event); +void touch_frame_reset(RDPINPUT_TOUCH_FRAME* frame); #endif /* FREERDP_CHANNEL_RDPEI_COMMON_H */ - diff --git a/channels/rdpei/server/rdpei_main.c b/channels/rdpei/server/rdpei_main.c index a475584..81b93ce 100644 --- a/channels/rdpei/server/rdpei_main.c +++ b/channels/rdpei/server/rdpei_main.c @@ -34,7 +34,8 @@ #include /** @brief */ -enum RdpEiState { +enum RdpEiState +{ STATE_INITIAL, STATE_WAITING_CLIENT_READY, STATE_WAITING_FRAME, @@ -48,8 +49,8 @@ struct _rdpei_server_private UINT32 expectedBytes; BOOL waitingHeaders; - wStream *inputStream; - wStream *outputStream; + wStream* inputStream; + wStream* outputStream; UINT16 currentMsgType; @@ -58,11 +59,10 @@ struct _rdpei_server_private enum RdpEiState automataState; }; - RdpeiServerContext* rdpei_server_context_new(HANDLE vcm) { - RdpeiServerContext *ret = calloc(1, sizeof(*ret)); - RdpeiServerPrivate *priv; + RdpeiServerContext* ret = calloc(1, sizeof(*ret)); + RdpeiServerPrivate* priv; if (!ret) return NULL; @@ -97,22 +97,27 @@ out_free: * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_server_init(RdpeiServerContext *context) +UINT rdpei_server_init(RdpeiServerContext* context) { - void *buffer = NULL; + void* buffer = NULL; DWORD bytesReturned; - RdpeiServerPrivate *priv = context->priv; + RdpeiServerPrivate* priv = context->priv; - priv->channelHandle = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, RDPEI_DVC_CHANNEL_NAME, WTS_CHANNEL_OPTION_DYNAMIC); + priv->channelHandle = WTSVirtualChannelOpenEx(WTS_CURRENT_SESSION, RDPEI_DVC_CHANNEL_NAME, + WTS_CHANNEL_OPTION_DYNAMIC); if (!priv->channelHandle) { WLog_ERR(TAG, "WTSVirtualChannelOpenEx failed!"); return CHANNEL_RC_INITIALIZATION_ERROR; } - if (!WTSVirtualChannelQuery(priv->channelHandle, WTSVirtualEventHandle, &buffer, &bytesReturned) || (bytesReturned != sizeof(HANDLE))) + if (!WTSVirtualChannelQuery(priv->channelHandle, WTSVirtualEventHandle, &buffer, + &bytesReturned) || + (bytesReturned != sizeof(HANDLE))) { - WLog_ERR(TAG, "WTSVirtualChannelQuery failed or invalid invalid returned size(%"PRIu32")!", bytesReturned); + WLog_ERR(TAG, + "WTSVirtualChannelQuery failed or invalid invalid returned size(%" PRIu32 ")!", + bytesReturned); if (buffer) WTSFreeMemory(buffer); goto out_close; @@ -127,10 +132,9 @@ out_close: return CHANNEL_RC_INITIALIZATION_ERROR; } - -void rdpei_server_context_reset(RdpeiServerContext *context) +void rdpei_server_context_reset(RdpeiServerContext* context) { - RdpeiServerPrivate *priv = context->priv; + RdpeiServerPrivate* priv = context->priv; priv->channelHandle = INVALID_HANDLE_VALUE; priv->expectedBytes = RDPINPUT_HEADER_LENGTH; @@ -141,7 +145,7 @@ void rdpei_server_context_reset(RdpeiServerContext *context) void rdpei_server_context_free(RdpeiServerContext* context) { - RdpeiServerPrivate *priv = context->priv; + RdpeiServerPrivate* priv = context->priv; if (priv->channelHandle != INVALID_HANDLE_VALUE) WTSVirtualChannelClose(priv->channelHandle); Stream_Free(priv->inputStream, TRUE); @@ -149,18 +153,17 @@ void rdpei_server_context_free(RdpeiServerContext* context) free(context); } -HANDLE rdpei_server_get_event_handle(RdpeiServerContext *context) +HANDLE rdpei_server_get_event_handle(RdpeiServerContext* context) { return context->priv->eventHandle; } - /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -static UINT read_cs_ready_message(RdpeiServerContext *context, wStream *s) +static UINT read_cs_ready_message(RdpeiServerContext* context, wStream* s) { UINT error = CHANNEL_RC_OK; if (Stream_GetRemainingLength(s) < 10) @@ -175,17 +178,17 @@ static UINT read_cs_ready_message(RdpeiServerContext *context, wStream *s) switch (context->clientVersion) { - case RDPINPUT_PROTOCOL_V10: - case RDPINPUT_PROTOCOL_V101: - break; - default: - WLog_ERR(TAG, "unhandled RPDEI protocol version 0x%"PRIx32"", context->clientVersion); - break; + case RDPINPUT_PROTOCOL_V10: + case RDPINPUT_PROTOCOL_V101: + break; + default: + WLog_ERR(TAG, "unhandled RPDEI protocol version 0x%" PRIx32 "", context->clientVersion); + break; } IFCALLRET(context->onClientReady, error, context); if (error) - WLog_ERR(TAG, "context->onClientReady failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context->onClientReady failed with error %" PRIu32 "", error); return error; } @@ -195,7 +198,8 @@ static UINT read_cs_ready_message(RdpeiServerContext *context, wStream *s) * * @return 0 on success, otherwise a Win32 error code */ -static UINT read_touch_contact_data(RdpeiServerContext *context, wStream *s, RDPINPUT_CONTACT_DATA *contactData) +static UINT read_touch_contact_data(RdpeiServerContext* context, wStream* s, + RDPINPUT_CONTACT_DATA* contactData) { if (Stream_GetRemainingLength(s) < 1) { @@ -205,9 +209,9 @@ static UINT read_touch_contact_data(RdpeiServerContext *context, wStream *s, RDP Stream_Read_UINT8(s, contactData->contactId); if (!rdpei_read_2byte_unsigned(s, &contactData->fieldsPresent) || - !rdpei_read_4byte_signed(s, &contactData->x) || - !rdpei_read_4byte_signed(s, &contactData->y) || - !rdpei_read_4byte_unsigned(s, &contactData->contactFlags)) + !rdpei_read_4byte_signed(s, &contactData->x) || + !rdpei_read_4byte_signed(s, &contactData->y) || + !rdpei_read_4byte_unsigned(s, &contactData->contactFlags)) { WLog_ERR(TAG, "rdpei_read_ failed!"); return ERROR_INTERNAL_ERROR; @@ -216,9 +220,9 @@ static UINT read_touch_contact_data(RdpeiServerContext *context, wStream *s, RDP if (contactData->fieldsPresent & CONTACT_DATA_CONTACTRECT_PRESENT) { if (!rdpei_read_2byte_signed(s, &contactData->contactRectLeft) || - !rdpei_read_2byte_signed(s, &contactData->contactRectTop) || - !rdpei_read_2byte_signed(s, &contactData->contactRectRight) || - !rdpei_read_2byte_signed(s, &contactData->contactRectBottom)) + !rdpei_read_2byte_signed(s, &contactData->contactRectTop) || + !rdpei_read_2byte_signed(s, &contactData->contactRectRight) || + !rdpei_read_2byte_signed(s, &contactData->contactRectBottom)) { WLog_ERR(TAG, "rdpei_read_ failed!"); return ERROR_INTERNAL_ERROR; @@ -226,15 +230,14 @@ static UINT read_touch_contact_data(RdpeiServerContext *context, wStream *s, RDP } if ((contactData->fieldsPresent & CONTACT_DATA_ORIENTATION_PRESENT) && - !rdpei_read_4byte_unsigned(s, &contactData->orientation)) + !rdpei_read_4byte_unsigned(s, &contactData->orientation)) { WLog_ERR(TAG, "rdpei_read_ failed!"); return ERROR_INTERNAL_ERROR; } - if ((contactData->fieldsPresent & CONTACT_DATA_PRESSURE_PRESENT) && - !rdpei_read_4byte_unsigned(s, &contactData->pressure)) + !rdpei_read_4byte_unsigned(s, &contactData->pressure)) { WLog_ERR(TAG, "rdpei_read_ failed!"); return ERROR_INTERNAL_ERROR; @@ -248,13 +251,14 @@ static UINT read_touch_contact_data(RdpeiServerContext *context, wStream *s, RDP * * @return 0 on success, otherwise a Win32 error code */ -static UINT read_touch_frame(RdpeiServerContext *context, wStream *s, RDPINPUT_TOUCH_FRAME *frame) +static UINT read_touch_frame(RdpeiServerContext* context, wStream* s, RDPINPUT_TOUCH_FRAME* frame) { - int i; - RDPINPUT_CONTACT_DATA *contact; + UINT32 i; + RDPINPUT_CONTACT_DATA* contact; UINT error; - if (!rdpei_read_2byte_unsigned(s, &frame->contactCount) || !rdpei_read_8byte_unsigned(s, &frame->frameOffset)) + if (!rdpei_read_2byte_unsigned(s, &frame->contactCount) || + !rdpei_read_8byte_unsigned(s, &frame->frameOffset)) { WLog_ERR(TAG, "rdpei_read_ failed!"); return ERROR_INTERNAL_ERROR; @@ -271,7 +275,7 @@ static UINT read_touch_frame(RdpeiServerContext *context, wStream *s, RDPINPUT_T { if ((error = read_touch_contact_data(context, s, contact))) { - WLog_ERR(TAG, "read_touch_contact_data failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "read_touch_contact_data failed with error %" PRIu32 "!", error); frame->contactCount = i; touch_frame_reset(frame); return error; @@ -285,15 +289,16 @@ static UINT read_touch_frame(RdpeiServerContext *context, wStream *s, RDPINPUT_T * * @return 0 on success, otherwise a Win32 error code */ -static UINT read_touch_event(RdpeiServerContext *context, wStream *s) +static UINT read_touch_event(RdpeiServerContext* context, wStream* s) { UINT32 frameCount; - int i; - RDPINPUT_TOUCH_EVENT *event = &context->priv->touchEvent; - RDPINPUT_TOUCH_FRAME *frame; + UINT32 i; + RDPINPUT_TOUCH_EVENT* event = &context->priv->touchEvent; + RDPINPUT_TOUCH_FRAME* frame; UINT error = CHANNEL_RC_OK; - if (!rdpei_read_4byte_unsigned(s, &event->encodeTime) || !rdpei_read_2byte_unsigned(s, &frameCount)) + if (!rdpei_read_4byte_unsigned(s, &event->encodeTime) || + !rdpei_read_2byte_unsigned(s, &frameCount)) { WLog_ERR(TAG, "rdpei_read_ failed!"); return ERROR_INTERNAL_ERROR; @@ -311,29 +316,28 @@ static UINT read_touch_event(RdpeiServerContext *context, wStream *s) { if ((error = read_touch_frame(context, s, frame))) { - WLog_ERR(TAG, "read_touch_contact_data failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "read_touch_contact_data failed with error %" PRIu32 "!", error); event->frameCount = i; goto out_cleanup; } } - IFCALLRET(context->onTouchEvent, error, context, event); if (error) - WLog_ERR(TAG, "context->onTouchEvent failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context->onTouchEvent failed with error %" PRIu32 "", error); out_cleanup: touch_event_reset(event); return error; } - /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -static UINT read_dismiss_hovering_contact(RdpeiServerContext *context, wStream *s) { +static UINT read_dismiss_hovering_contact(RdpeiServerContext* context, wStream* s) +{ BYTE contactId; UINT error = CHANNEL_RC_OK; @@ -347,24 +351,25 @@ static UINT read_dismiss_hovering_contact(RdpeiServerContext *context, wStream * IFCALLRET(context->onTouchReleased, error, context, contactId); if (error) - WLog_ERR(TAG, "context->onTouchReleased failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context->onTouchReleased failed with error %" PRIu32 "", error); return error; } - /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_server_handle_messages(RdpeiServerContext *context) { +UINT rdpei_server_handle_messages(RdpeiServerContext* context) +{ DWORD bytesReturned; - RdpeiServerPrivate *priv = context->priv; - wStream *s = priv->inputStream; + RdpeiServerPrivate* priv = context->priv; + wStream* s = priv->inputStream; UINT error = CHANNEL_RC_OK; - if (!WTSVirtualChannelRead(priv->channelHandle, 0, (PCHAR)Stream_Pointer(s), priv->expectedBytes, &bytesReturned)) + if (!WTSVirtualChannelRead(priv->channelHandle, 0, (PCHAR)Stream_Pointer(s), + priv->expectedBytes, &bytesReturned)) { if (GetLastError() == ERROR_NO_DATA) return ERROR_READ_FAULT; @@ -391,7 +396,7 @@ UINT rdpei_server_handle_messages(RdpeiServerContext *context) { if (pduLen < RDPINPUT_HEADER_LENGTH) { - WLog_ERR(TAG, "invalid pduLength %"PRIu32"", pduLen); + WLog_ERR(TAG, "invalid pduLength %" PRIu32 "", pduLen); return ERROR_INVALID_DATA; } priv->expectedBytes = pduLen - RDPINPUT_HEADER_LENGTH; @@ -411,36 +416,37 @@ UINT rdpei_server_handle_messages(RdpeiServerContext *context) { /* when here we have the header + the body */ switch (priv->currentMsgType) { - case EVENTID_CS_READY: - if (priv->automataState != STATE_WAITING_CLIENT_READY) - { - WLog_ERR(TAG, "not expecting a CS_READY packet in this state(%d)", priv->automataState); - return ERROR_INVALID_STATE; - } + case EVENTID_CS_READY: + if (priv->automataState != STATE_WAITING_CLIENT_READY) + { + WLog_ERR(TAG, "not expecting a CS_READY packet in this state(%d)", + priv->automataState); + return ERROR_INVALID_STATE; + } - if ((error = read_cs_ready_message(context, s))) - { - WLog_ERR(TAG, "read_cs_ready_message failed with error %"PRIu32"", error); - return error; - } - break; + if ((error = read_cs_ready_message(context, s))) + { + WLog_ERR(TAG, "read_cs_ready_message failed with error %" PRIu32 "", error); + return error; + } + break; - case EVENTID_TOUCH: - if ((error = read_touch_event(context, s))) - { - WLog_ERR(TAG, "read_touch_event failed with error %"PRIu32"", error); - return error; - } - break; - case EVENTID_DISMISS_HOVERING_CONTACT: - if ((error = read_dismiss_hovering_contact(context, s))) - { - WLog_ERR(TAG, "read_dismiss_hovering_contact failed with error %"PRIu32"", error); - return error; - } - break; - default: - WLog_ERR(TAG, "unexpected message type 0x%"PRIx16"", priv->currentMsgType); + case EVENTID_TOUCH: + if ((error = read_touch_event(context, s))) + { + WLog_ERR(TAG, "read_touch_event failed with error %" PRIu32 "", error); + return error; + } + break; + case EVENTID_DISMISS_HOVERING_CONTACT: + if ((error = read_dismiss_hovering_contact(context, s))) + { + WLog_ERR(TAG, "read_dismiss_hovering_contact failed with error %" PRIu32 "", error); + return error; + } + break; + default: + WLog_ERR(TAG, "unexpected message type 0x%" PRIx16 "", priv->currentMsgType); } Stream_SetPosition(s, 0); @@ -449,16 +455,15 @@ UINT rdpei_server_handle_messages(RdpeiServerContext *context) { return error; } - /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_server_send_sc_ready(RdpeiServerContext *context, UINT32 version) +UINT rdpei_server_send_sc_ready(RdpeiServerContext* context, UINT32 version) { ULONG written; - RdpeiServerPrivate *priv = context->priv; + RdpeiServerPrivate* priv = context->priv; if (priv->automataState != STATE_INITIAL) { @@ -479,7 +484,7 @@ UINT rdpei_server_send_sc_ready(RdpeiServerContext *context, UINT32 version) Stream_Write_UINT32(priv->outputStream, version); if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream), - Stream_GetPosition(priv->outputStream), &written)) + Stream_GetPosition(priv->outputStream), &written)) { WLog_ERR(TAG, "WTSVirtualChannelWrite failed!"); return ERROR_INTERNAL_ERROR; @@ -494,21 +499,21 @@ UINT rdpei_server_send_sc_ready(RdpeiServerContext *context, UINT32 version) * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_server_suspend(RdpeiServerContext *context) +UINT rdpei_server_suspend(RdpeiServerContext* context) { ULONG written; - RdpeiServerPrivate *priv = context->priv; + RdpeiServerPrivate* priv = context->priv; switch (priv->automataState) { - case STATE_SUSPENDED: - WLog_ERR(TAG, "already suspended"); - return CHANNEL_RC_OK; - case STATE_WAITING_FRAME: - break; - default: - WLog_ERR(TAG, "called from unexpected state %d", priv->automataState); - return ERROR_INVALID_STATE; + case STATE_SUSPENDED: + WLog_ERR(TAG, "already suspended"); + return CHANNEL_RC_OK; + case STATE_WAITING_FRAME: + break; + default: + WLog_ERR(TAG, "called from unexpected state %d", priv->automataState); + return ERROR_INVALID_STATE; } Stream_SetPosition(priv->outputStream, 0); @@ -522,7 +527,7 @@ UINT rdpei_server_suspend(RdpeiServerContext *context) Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH); if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream), - Stream_GetPosition(priv->outputStream), &written)) + Stream_GetPosition(priv->outputStream), &written)) { WLog_ERR(TAG, "WTSVirtualChannelWrite failed!"); return ERROR_INTERNAL_ERROR; @@ -532,27 +537,26 @@ UINT rdpei_server_suspend(RdpeiServerContext *context) return CHANNEL_RC_OK; } - /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -UINT rdpei_server_resume(RdpeiServerContext *context) +UINT rdpei_server_resume(RdpeiServerContext* context) { ULONG written; - RdpeiServerPrivate *priv = context->priv; + RdpeiServerPrivate* priv = context->priv; switch (priv->automataState) { - case STATE_WAITING_FRAME: - WLog_ERR(TAG, "not suspended"); - return CHANNEL_RC_OK; - case STATE_SUSPENDED: - break; - default: - WLog_ERR(TAG, "called from unexpected state %d", priv->automataState); - return ERROR_INVALID_STATE; + case STATE_WAITING_FRAME: + WLog_ERR(TAG, "not suspended"); + return CHANNEL_RC_OK; + case STATE_SUSPENDED: + break; + default: + WLog_ERR(TAG, "called from unexpected state %d", priv->automataState); + return ERROR_INVALID_STATE; } Stream_SetPosition(priv->outputStream, 0); @@ -566,7 +570,7 @@ UINT rdpei_server_resume(RdpeiServerContext *context) Stream_Write_UINT32(priv->outputStream, RDPINPUT_HEADER_LENGTH); if (!WTSVirtualChannelWrite(priv->channelHandle, (PCHAR)Stream_Buffer(priv->outputStream), - Stream_GetPosition(priv->outputStream), &written)) + Stream_GetPosition(priv->outputStream), &written)) { WLog_ERR(TAG, "WTSVirtualChannelWrite failed!"); return ERROR_INTERNAL_ERROR; @@ -575,4 +579,3 @@ UINT rdpei_server_resume(RdpeiServerContext *context) priv->automataState = STATE_WAITING_FRAME; return CHANNEL_RC_OK; } - diff --git a/channels/rdpei/server/rdpei_main.h b/channels/rdpei/server/rdpei_main.h index f6505f5..cf3e3cb 100644 --- a/channels/rdpei/server/rdpei_main.h +++ b/channels/rdpei/server/rdpei_main.h @@ -29,7 +29,4 @@ #define TAG CHANNELS_TAG("rdpei.server") - - #endif /* FREERDP_CHANNEL_RDPEI_SERVER_MAIN_H */ - diff --git a/channels/rdpgfx/client/rdpgfx_codec.c b/channels/rdpgfx/client/rdpgfx_codec.c index d2dfbb3..d89278c 100644 --- a/channels/rdpgfx/client/rdpgfx_codec.c +++ b/channels/rdpgfx/client/rdpgfx_codec.c @@ -39,8 +39,7 @@ * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, - RDPGFX_H264_METABLOCK* meta) +static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, RDPGFX_H264_METABLOCK* meta) { UINT32 index; RECTANGLE_16* regionRect; @@ -63,7 +62,7 @@ static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, goto error_out; } - meta->regionRects = (RECTANGLE_16*) calloc(meta->numRegionRects, sizeof(RECTANGLE_16)); + meta->regionRects = (RECTANGLE_16*)calloc(meta->numRegionRects, sizeof(RECTANGLE_16)); if (!meta->regionRects) { @@ -72,8 +71,8 @@ static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, goto error_out; } - meta->quantQualityVals = (RDPGFX_H264_QUANT_QUALITY*) calloc(meta->numRegionRects, sizeof( - RDPGFX_H264_QUANT_QUALITY)); + meta->quantQualityVals = + (RDPGFX_H264_QUANT_QUALITY*)calloc(meta->numRegionRects, sizeof(RDPGFX_H264_QUANT_QUALITY)); if (!meta->quantQualityVals) { @@ -82,7 +81,7 @@ static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, goto error_out; } - WLog_DBG(TAG, "H264_METABLOCK: numRegionRects: %"PRIu32"", meta->numRegionRects); + WLog_DBG(TAG, "H264_METABLOCK: numRegionRects: %" PRIu32 "", meta->numRegionRects); for (index = 0; index < meta->numRegionRects; index++) { @@ -90,12 +89,13 @@ static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, if ((error = rdpgfx_read_rect16(s, regionRect))) { - WLog_ERR(TAG, "rdpgfx_read_rect16 failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rdpgfx_read_rect16 failed with error %" PRIu32 "!", error); goto error_out; } WLog_DBG(TAG, - "regionRects[%"PRIu32"]: left: %"PRIu16" top: %"PRIu16" right: %"PRIu16" bottom: %"PRIu16"", + "regionRects[%" PRIu32 "]: left: %" PRIu16 " top: %" PRIu16 " right: %" PRIu16 + " bottom: %" PRIu16 "", index, regionRect->left, regionRect->top, regionRect->right, regionRect->bottom); } @@ -109,14 +109,16 @@ static UINT rdpgfx_read_h264_metablock(RDPGFX_PLUGIN* gfx, wStream* s, for (index = 0; index < meta->numRegionRects; index++) { quantQualityVal = &(meta->quantQualityVals[index]); - Stream_Read_UINT8(s, quantQualityVal->qpVal); /* qpVal (1 byte) */ + Stream_Read_UINT8(s, quantQualityVal->qpVal); /* qpVal (1 byte) */ Stream_Read_UINT8(s, quantQualityVal->qualityVal); /* qualityVal (1 byte) */ quantQualityVal->qp = quantQualityVal->qpVal & 0x3F; quantQualityVal->r = (quantQualityVal->qpVal >> 6) & 1; quantQualityVal->p = (quantQualityVal->qpVal >> 7) & 1; WLog_DBG(TAG, - "quantQualityVals[%"PRIu32"]: qp: %"PRIu8" r: %"PRIu8" p: %"PRIu8" qualityVal: %"PRIu8"", - index, quantQualityVal->qp, quantQualityVal->r, quantQualityVal->p, quantQualityVal->qualityVal); + "quantQualityVals[%" PRIu32 "]: qp: %" PRIu8 " r: %" PRIu8 " p: %" PRIu8 + " qualityVal: %" PRIu8 "", + index, quantQualityVal->qp, quantQualityVal->r, quantQualityVal->p, + quantQualityVal->qualityVal); } return CHANNEL_RC_OK; @@ -138,7 +140,7 @@ static UINT rdpgfx_decode_AVC420(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd UINT error; wStream* s; RDPGFX_AVC420_BITMAP_STREAM h264; - RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; s = Stream_New(cmd->data, cmd->length); if (!s) @@ -150,21 +152,21 @@ static UINT rdpgfx_decode_AVC420(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.meta)))) { Stream_Free(s, FALSE); - WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %" PRIu32 "!", error); return error; } h264.data = Stream_Pointer(s); - h264.length = (UINT32) Stream_GetRemainingLength(s); + h264.length = (UINT32)Stream_GetRemainingLength(s); Stream_Free(s, FALSE); - cmd->extra = (void*) &h264; + cmd->extra = (void*)&h264; if (context) { IFCALLRET(context->SurfaceCommand, error, context, cmd); if (error) - WLog_ERR(TAG, "context->SurfaceCommand failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context->SurfaceCommand failed with error %" PRIu32 "", error); } free(h264.meta.regionRects); @@ -184,7 +186,7 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd size_t pos1, pos2; wStream* s; RDPGFX_AVC444_BITMAP_STREAM h264 = { 0 }; - RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; s = Stream_New(cmd->data, cmd->length); if (!s) @@ -213,7 +215,7 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.bitstream[0].meta)))) { - WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %" PRIu32 "!", error); goto fail; } @@ -235,7 +237,7 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd if ((error = rdpgfx_read_h264_metablock(gfx, s, &(h264.bitstream[1].meta)))) { - WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %"PRIu32"!", error); + WLog_ERR(TAG, "rdpgfx_read_h264_metablock failed with error %" PRIu32 "!", error); goto fail; } @@ -243,19 +245,16 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd h264.bitstream[1].length = Stream_GetRemainingLength(s); } else - { h264.bitstream[0].length = Stream_GetRemainingLength(s); - memset(&h264.bitstream[1], 0, sizeof(h264.bitstream[1])); - } - cmd->extra = (void*) &h264; + cmd->extra = (void*)&h264; if (context) { IFCALLRET(context->SurfaceCommand, error, context, cmd); if (error) - WLog_ERR(TAG, "context->SurfaceCommand failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context->SurfaceCommand failed with error %" PRIu32 "", error); } fail: @@ -275,21 +274,21 @@ fail: UINT rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) { UINT error = CHANNEL_RC_OK; - RdpgfxClientContext* context = (RdpgfxClientContext*) gfx->iface.pInterface; + RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; PROFILER_ENTER(context->SurfaceProfiler) switch (cmd->codecId) { case RDPGFX_CODECID_AVC420: if ((error = rdpgfx_decode_AVC420(gfx, cmd))) - WLog_ERR(TAG, "rdpgfx_decode_AVC420 failed with error %"PRIu32"", error); + WLog_ERR(TAG, "rdpgfx_decode_AVC420 failed with error %" PRIu32 "", error); break; case RDPGFX_CODECID_AVC444: case RDPGFX_CODECID_AVC444v2: if ((error = rdpgfx_decode_AVC444(gfx, cmd))) - WLog_ERR(TAG, "rdpgfx_decode_AVC444 failed with error %"PRIu32"", error); + WLog_ERR(TAG, "rdpgfx_decode_AVC444 failed with error %" PRIu32 "", error); break; @@ -299,7 +298,7 @@ UINT rdpgfx_decode(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd) IFCALLRET(context->SurfaceCommand, error, context, cmd); if (error) - WLog_ERR(TAG, "context->SurfaceCommand failed with error %"PRIu32"", error); + WLog_ERR(TAG, "context->SurfaceCommand failed with error %" PRIu32 "", error); } break; diff --git a/channels/rdpgfx/client/rdpgfx_main.c b/channels/rdpgfx/client/rdpgfx_main.c index 0090db0..6ca75bd 100644 --- a/channels/rdpgfx/client/rdpgfx_main.c +++ b/channels/rdpgfx/client/rdpgfx_main.c @@ -47,106 +47,285 @@ #define TAG CHANNELS_TAG("rdpgfx.client") +static void free_surfaces(RdpgfxClientContext* context, wHashTable* SurfaceTable) +{ + UINT error = 0; + ULONG_PTR* pKeys = NULL; + int count; + int index; + + count = HashTable_GetKeys(SurfaceTable, &pKeys); + + for (index = 0; index < count; index++) + { + RDPGFX_DELETE_SURFACE_PDU pdu; + pdu.surfaceId = ((UINT16)pKeys[index]) - 1; + + if (context) + { + IFCALLRET(context->DeleteSurface, error, context, &pdu); + + if (error) + { + WLog_ERR(TAG, "context->DeleteSurface failed with error %" PRIu32 "", error); + } + } + } + + free(pKeys); +} + +static void evict_cache_slots(RdpgfxClientContext* context, UINT16 MaxCacheSlots, void** CacheSlots) +{ + UINT16 index; + + for (index = 0; index < MaxCacheSlots; index++) + { + if (CacheSlots[index]) + { + RDPGFX_EVICT_CACHE_ENTRY_PDU pdu; + pdu.cacheSlot = (UINT16)index + 1; + + if (context && context->EvictCacheEntry) + { + context->EvictCacheEntry(context, &pdu); + } + + CacheSlots[index] = NULL; + } + } +} + /** * Function description * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpgfx_send_caps_advertise_pdu(RDPGFX_CHANNEL_CALLBACK* callback) +static UINT rdpgfx_send_caps_advertise_pdu(RdpgfxClientContext* context, + const RDPGFX_CAPS_ADVERTISE_PDU* pdu) { - UINT error; - wStream* s; + UINT error = CHANNEL_RC_OK; UINT16 index; - RDPGFX_PLUGIN* gfx; RDPGFX_HEADER header; RDPGFX_CAPSET* capsSet; - RDPGFX_CAPSET capsSets[RDPGFX_NUMBER_CAPSETS]; - RDPGFX_CAPS_ADVERTISE_PDU pdu; - gfx = (RDPGFX_PLUGIN*) callback->plugin; + RDPGFX_PLUGIN* gfx; + RDPGFX_CHANNEL_CALLBACK* callback; + wStream* s; + gfx = (RDPGFX_PLUGIN*)context->handle; + + if (!gfx || !gfx->listener_callback) + return ERROR_BAD_ARGUMENTS; + + callback = gfx->listener_callback->channel_callback; + header.flags = 0; header.cmdId = RDPGFX_CMDID_CAPSADVERTISE; + header.pduLength = RDPGFX_HEADER_SIZE + 2; + + for (index = 0; index < pdu->capsSetCount; index++) + { + capsSet = &(pdu->capsSets[index]); + header.pduLength += RDPGFX_CAPSET_BASE_SIZE + capsSet->length; + } + + DEBUG_RDPGFX(gfx->log, "SendCapsAdvertisePdu %" PRIu16 "", pdu->capsSetCount); + s = Stream_New(NULL, header.pduLength); + + if (!s) + { + WLog_ERR(TAG, "Stream_New failed!"); + return CHANNEL_RC_NO_MEMORY; + } + + if ((error = rdpgfx_write_header(s, &header))) + goto fail; + + /* RDPGFX_CAPS_ADVERTISE_PDU */ + Stream_Write_UINT16(s, pdu->capsSetCount); /* capsSetCount (2 bytes) */ + + for (index = 0; index < pdu->capsSetCount; index++) + { + capsSet = &(pdu->capsSets[index]); + Stream_Write_UINT32(s, capsSet->version); /* version (4 bytes) */ + Stream_Write_UINT32(s, capsSet->length); /* capsDataLength (4 bytes) */ + Stream_Write_UINT32(s, capsSet->flags); /* capsData (4 bytes) */ + Stream_Zero(s, capsSet->length - 4); + } + + Stream_SealLength(s); + error = callback->channel->Write(callback->channel, (UINT32)Stream_Length(s), Stream_Buffer(s), + NULL); +fail: + Stream_Free(s, TRUE); + return error; +} + +static BOOL rdpgfx_is_capability_filtered(RDPGFX_PLUGIN* gfx, UINT32 caps) +{ + const UINT32 filter = gfx->capsFilter; + const UINT32 capList[] = { + RDPGFX_CAPVERSION_8, RDPGFX_CAPVERSION_81, RDPGFX_CAPVERSION_10, + RDPGFX_CAPVERSION_101, RDPGFX_CAPVERSION_102, RDPGFX_CAPVERSION_103, + RDPGFX_CAPVERSION_104, RDPGFX_CAPVERSION_105, RDPGFX_CAPVERSION_106 + }; + UINT32 x; + + for (x = 0; x < ARRAYSIZE(capList); x++) + { + if (caps == capList[x]) + return (filter & (1 << x)) != 0; + } + + return TRUE; +} + +/** + * Function description + * + * @return 0 on success, otherwise a Win32 error code + */ +static UINT rdpgfx_send_supported_caps(RDPGFX_CHANNEL_CALLBACK* callback) +{ + RDPGFX_PLUGIN* gfx; + RdpgfxClientContext* context; + RDPGFX_CAPSET* capsSet; + RDPGFX_CAPSET capsSets[RDPGFX_NUMBER_CAPSETS] = { 0 }; + RDPGFX_CAPS_ADVERTISE_PDU pdu; + + if (!callback) + return ERROR_BAD_ARGUMENTS; + + gfx = (RDPGFX_PLUGIN*)callback->plugin; + + if (!gfx) + return ERROR_BAD_CONFIGURATION; + + context = (RdpgfxClientContext*)gfx->iface.pInterface; + + if (!context) + return ERROR_BAD_CONFIGURATION; + pdu.capsSetCount = 0; - pdu.capsSets = (RDPGFX_CAPSET*) capsSets; - capsSet = &capsSets[pdu.capsSetCount++]; - capsSet->version = RDPGFX_CAPVERSION_8; - capsSet->flags = 0; + pdu.capsSets = (RDPGFX_CAPSET*)capsSets; - if (gfx->ThinClient) - capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT; + if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_8)) + { + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_8; + capsSet->length = 4; + capsSet->flags = 0; - /* in CAPVERSION_8 the spec says that we should not have both - * thinclient and smallcache (and thinclient implies a small cache) - */ - if (gfx->SmallCache && !gfx->ThinClient) - capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; + if (gfx->ThinClient) + capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT; - capsSet = &capsSets[pdu.capsSetCount++]; - capsSet->version = RDPGFX_CAPVERSION_81; - capsSet->flags = 0; + /* in CAPVERSION_8 the spec says that we should not have both + * thinclient and smallcache (and thinclient implies a small cache) + */ + if (gfx->SmallCache && !gfx->ThinClient) + capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; + } - if (gfx->ThinClient) - capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT; + if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_81)) + { + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_81; + capsSet->length = 4; + capsSet->flags = 0; + + if (gfx->ThinClient) + capsSet->flags |= RDPGFX_CAPS_FLAG_THINCLIENT; - if (gfx->SmallCache) - capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; + if (gfx->SmallCache) + capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; #ifdef WITH_GFX_H264 - if (gfx->H264) - capsSet->flags |= RDPGFX_CAPS_FLAG_AVC420_ENABLED; + + if (gfx->H264) + capsSet->flags |= RDPGFX_CAPS_FLAG_AVC420_ENABLED; + #endif + } if (!gfx->H264 || gfx->AVC444) { - capsSet = &capsSets[pdu.capsSetCount++]; - capsSet->version = RDPGFX_CAPVERSION_10; - capsSet->flags = 0; + UINT32 caps10Flags = 0; if (gfx->SmallCache) - capsSet->flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; + caps10Flags |= RDPGFX_CAPS_FLAG_SMALL_CACHE; #ifdef WITH_GFX_H264 + if (!gfx->AVC444) - capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; + caps10Flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; + #else - capsSet->flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; + caps10Flags |= RDPGFX_CAPS_FLAG_AVC_DISABLED; #endif - capsSets[pdu.capsSetCount] = *capsSet; - capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_102; - capsSets[pdu.capsSetCount] = *capsSet; - capsSets[pdu.capsSetCount++].version = RDPGFX_CAPVERSION_103; - } + if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_10)) + { + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_10; + capsSet->length = 4; + capsSet->flags = caps10Flags; + } - header.pduLength = RDPGFX_HEADER_SIZE + 2 + (pdu.capsSetCount * RDPGFX_CAPSET_SIZE); - WLog_Print(gfx->log, WLOG_DEBUG, "SendCapsAdvertisePdu %"PRIu16"", pdu.capsSetCount); - s = Stream_New(NULL, header.pduLength); + if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_101)) + { + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_101; + capsSet->length = 0x10; + capsSet->flags = 0; + } - if (!s) - { - WLog_ERR(TAG, "Stream_New failed!"); - return CHANNEL_RC_NO_MEMORY; - } + if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_102)) + { + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_102; + capsSet->length = 0x4; + capsSet->flags = caps10Flags; + } - if ((error = rdpgfx_write_header(s, &header))) - goto fail; + if (gfx->ThinClient) + { + if ((caps10Flags & RDPGFX_CAPS_FLAG_AVC_DISABLED) == 0) + caps10Flags |= RDPGFX_CAPS_FLAG_AVC_THINCLIENT; + } - /* RDPGFX_CAPS_ADVERTISE_PDU */ - Stream_Write_UINT16(s, pdu.capsSetCount); /* capsSetCount (2 bytes) */ + if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_103)) + { + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_103; + capsSet->length = 0x4; + capsSet->flags = caps10Flags & ~RDPGFX_CAPS_FLAG_SMALL_CACHE; + } - for (index = 0; index < pdu.capsSetCount; index++) - { - capsSet = &(pdu.capsSets[index]); - Stream_Write_UINT32(s, capsSet->version); /* version (4 bytes) */ - Stream_Write_UINT32(s, 4); /* capsDataLength (4 bytes) */ - Stream_Write_UINT32(s, capsSet->flags); /* capsData (4 bytes) */ + if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_104)) + { + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_104; + capsSet->length = 0x4; + capsSet->flags = caps10Flags; + } + + if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_105)) + { + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_105; + capsSet->length = 0x4; + capsSet->flags = caps10Flags; + } + + if (!rdpgfx_is_capability_filtered(gfx, RDPGFX_CAPVERSION_106)) + { + capsSet = &capsSets[pdu.capsSetCount++]; + capsSet->version = RDPGFX_CAPVERSION_106; + capsSet->length = 0x4; + capsSet->flags = caps10Flags; + } } - Stream_SealLength(s); - error = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), - Stream_Buffer(s), NULL); -fail: - Stream_Free(s, TRUE); - return error; + return IFCALLRESULT(ERROR_BAD_CONFIGURATION, context->CapsAdvertise, context, &pdu); } /** @@ -154,14 +333,12 @@ fail: * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback, - wStream* s) +static UINT rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback, wStream* s) { RDPGFX_CAPSET capsSet; - UINT32 capsDataLength; RDPGFX_CAPS_CONFIRM_PDU pdu; - RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; - + RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*)callback->plugin; + RdpgfxClientContext* context = (RdpgfxClientContext*)gfx->iface.pInterface; pdu.capsSet = &capsSet; if (Stream_GetRemainingLength(s) < 12) @@ -171,14 +348,16 @@ static UINT rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback, } Stream_Read_UINT32(s, capsSet.version); /* version (4 bytes) */ - Stream_Read_UINT32(s, capsDataLength); /* capsDataLength (4 bytes) */ - Stream_Read_UINT32(s, capsSet.flags); /* capsData (4 bytes) */ - + Stream_Read_UINT32(s, capsSet.length); /* capsDataLength (4 bytes) */ + Stream_Read_UINT32(s, capsSet.flags); /* capsData (4 bytes) */ gfx->ConnectionCaps = capsSet; + DEBUG_RDPGFX(gfx->log, "RecvCapsConfirmPdu: version: 0x%08" PRIX32 " flags: 0x%08" PRIX32 "", + capsSet.version, capsSet.flags); - WLog_Print(gfx->log, WLOG_DEBUG, "RecvCapsConfirmPdu: version: 0x%08"PRIX32" flags: 0x%08"PRIX32"", - capsSet.version, capsSet.flags); - return CHANNEL_RC_OK; + if (!context) + return ERROR_BAD_CONFIGURATION; + + return IFCALLRESULT(CHANNEL_RC_OK, context->CapsConfirm, context, &pdu); } /** @@ -186,20 +365,34 @@ static UINT rdpgfx_recv_caps_confirm_pdu(RDPGFX_CHANNEL_CALLBACK* callback, * * @return 0 on success, otherwise a Win32 error code */ -static UINT rdpgfx_send_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callback, - RDPGFX_FRAME_ACKNOWLEDGE_PDU* pdu) +static UINT rdpgfx_send_frame_acknowledge_pdu(RdpgfxClientContext* context, + const RDPGFX_FRAME_ACKNOWLEDGE_PDU* pdu) { UINT error; wStream* s; RDPGFX_HEADER header; - RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; + RDPGFX_PLUGIN* gfx; + RDPGFX_CHANNEL_CALLBACK* callback; + + if (!context || !pdu) + return ERROR_BAD_ARGUMENTS; + + gfx = (RDPGFX_PLUGIN*)context->handle; + + if (!gfx || !gfx->listener_callback) + return ERROR_BAD_CONFIGURATION; + + callback = gfx->listener_callback->channel_callback; + + if (!callback) + return ERROR_BAD_CONFIGURATION; header.flags = 0; header.cmdId = RDPGFX_CMDID_FRAMEACKNOWLEDGE; header.pduLength = RDPGFX_HEADER_SIZE + 12; - WLog_Print(gfx->log, WLOG_DEBUG, "SendFrameAcknowledgePdu: %"PRIu32"", pdu->frameId); - + DEBUG_RDPGFX(gfx->log, "SendFrameAcknowledgePdu: %" PRIu32 "", pdu->frameId); s = Stream_New(NULL, header.pduLength); + if (!s) { WLog_ERR(TAG, "Stream_New failed!"); @@ -210,31 +403,48 @@ static UINT rdpgfx_send_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callback, goto fail; /* RDPGFX_FRAME_ACKNOWLEDGE_PDU */ - Stream_Write_UINT32(s, pdu->queueDepth); /* queueDepth (4 bytes) */ - Stream_Write_UINT32(s, pdu->frameId); /* frameId (4 bytes) */ - Stream_Write_UINT32(s, - pdu->totalFramesDecoded); /* totalFramesDecoded (4 bytes) */ - error = callback->channel->Write(callback->channel, (UINT32) Stream_Length(s), - Stream_Buffer(s), NULL); + Stream_Write_UINT32(s, pdu->queueDepth); /* queueDepth (4 bytes) */ + Stream_Write_UINT32(s, pdu->frameId); /* frameId (4 bytes) */ + Stream_Write_UINT32(s, pdu->totalFramesDecoded); /* totalFramesDecoded (4 bytes) */ + error = callback->channel->Write(callback->channel, (UINT32)Stream_Length(s), Stream_Buffer(s), + NULL); + + if (error == CHANNEL_RC_OK) /* frame successfully acked */ + gfx->UnacknowledgedFrames--; + fail: Stream_Free(s, TRUE); return error; } -static UINT rdpgfx_send_qoe_frame_acknowledge_pdu(RDPGFX_CHANNEL_CALLBACK* callback, +static UINT rdpgfx_send_qoe_frame_acknowledge_pdu(RdpgfxClientContext* context, const RDPGFX_QOE_FRAME_ACKNOWLEDGE_PDU* pdu) { UINT error; wStream* s; RDPGFX_HEADER header; - RDPGFX_PLUGIN* gfx = (RDPGFX_PLUGIN*) callback->plugin; - + RDPGFX_CHANNEL_CALLBACK* callback; + RDPGFX_PLUGIN* gfx; header.flags = 0; header.cmdId = RDPGFX_CMDID_QOEFRAMEACKNOWLEDGE; header.pduLength = RDPGFX_HEADER_SIZE + 12; - WLog_Print(gfx->log, WLOG_DEBUG, "SendQoeFrameAcknowledgePdu: %"PRIu32"", pdu->frameId); + if (!context || !pdu) + return ERROR_BAD_ARGUMENTS; + + gfx = (RDPGFX_PLUGIN*)context->handle; + + if (!gfx || !gfx->listener_callback) + return ERROR_BAD_CONFIGURATION; + + callback = gfx->listener_callback->channel_callback; + + if (!callback) + return ERR