New upstream version 2.1.1+dfsg1

This commit is contained in:
Mike Gabriel 2020-05-28 00:16:30 +02:00
parent 29326a1671
commit 912dda7d3e
1356 changed files with 146510 additions and 176613 deletions

125
.clang-format Normal file
View File

@ -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
...

25
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,25 @@
## Found a bug? - We would like to help you and smash the bug away.
1. __Please don't "report" questions as bugs.__
* We are reachable via IRC _#freerdp on freenode_
* We are reachable via mailing list <freerdp-devel@lists.sourceforge.net>
* Try our mailing list for discussions/questions
1. Before reporting a bug have a look into our issue tracker to see if the bug was already reported and you can add some additional information.
1. If it's a __new__ bug - create a new issue.
1. For more details see https://github.com/FreeRDP/FreeRDP/wiki/BugReporting
## To save time and help us identify the issue a bug report should at least contain the following:
* a useful description of the bug - "It's not working" isn't good enough - you must try harder ;)
* the steps to reproduce the bug
* command line you have used
* to what system did you connect to? (win8, 2008, ..)
* what did you expect to happen?
* what actually happened?
* freerdp version (e.g. xfreerdp --version) or package version or git commit
* freerdp configuration (e.g. xfreerdp --buildconfig)
* operating System, architecture, distribution e.g. linux, amd64, debian
* if you built it yourself add some notes which branch you have used, also your cmake parameters can help
* extra information helping us to find the bug
## Please remove this text before submitting your issue!
_Thank you for reporting a bug!_

56
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,56 @@
---
name: Bug report
about: Create a report to help us improve
---
**Found a bug? - We would like to help you and smash the bug away.**
1. __Please don't "report" questions as bugs. For these (questions/build instructions/...) please use one of the following means of contact:__
* We are reachable via IRC _#freerdp on freenode_
* We are reachable via mailing list <freerdp-devel@lists.sourceforge.net>
* Try our mailing list for discussions/questions
1. Before reporting a bug have a look into our issue tracker to see if the bug was already reported and you can add some additional information.
1. If it's a __new__ bug - create a new issue.
1. For more details see https://github.com/FreeRDP/FreeRDP/wiki/BugReporting
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Application details**
* Version of FreeRDP
* Command line used
* output of `/buildconfig`
* OS version connecting to
* If available the log output from a run with `/log-level:trace`
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.
** Please remove this text before submitting your issue!
_Thank you for reporting a bug!_

View File

@ -0,0 +1,17 @@
---
name: Feature request
about: Suggest an idea for this project
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

25
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,25 @@
## This is how are pull requests handled by FreeRDP
1. Every new pull request needs to build and pass the unit tests at https://ci.freerdp.com
1. At least 1 (better two) people need to review and test a pull request and agree to accept
## 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 _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
## To ease accepting your contribution
* Give the pull request a proper name so people looking at it have an basic idea what it is for
* Add at least a brief description what it does (or should do :) and what it's good for
* Give instructions on how to test your changes
* Ideally add unit tests if adding new features
## What you should be prepared for
* fix issues found during the review phase
* Joining IRC _#freerdp_ to talk to other developers or help them test your pull might accelerate acceptance
* Joining our mailing list <freerdp-devel@lists.sourceforge.net> may be helpful too.
## Please remove this text before submitting your pull!

154
.gitignore vendored Normal file
View File

@ -0,0 +1,154 @@
#ninja
.ninja_deps
.ninja_log
build.ninja
rules.ninja
# CMake
CMakeFiles/
CMakeScripts/
CMakeCache.txt
config.h
install_manifest*.txt
CTestTestfile.cmake
*.pc
Makefile
Testing
cmake_install.cmake
CPackConfig.cmake
CPackSourceConfig.cmake
DartConfiguration.tcl
CMakeCPackOptions.cmake
_CPack_Packages
LICENSE.txt
/external/*
!external/README
*Config.cmake
*ConfigVersion.cmake
include/freerdp/version.h
include/freerdp/build-config.h
buildflags.h
*.a.objlist.cmake
*.a.objlist
*.a.objdir
*_dummy.c
*_dummy.c.base
# Eclipse
*.project
*.cproject
*.settings
nbproject/
compile_commands.json
# .rdp files
*.rdp
*.RDP
# Documentation
docs/api
client/X11/xfreerdp.1
client/X11/xfreerdp.1.xml
# Mac OS X
.DS_Store
*.xcodeproj/
DerivedData/
# iOS
FreeRDP.build
Debug-*
Release-*
# Windows
*.vcxproj
*.vcxproj.*
*.vcproj
*.vcproj.*
*.aps
*.sdf
*.sln
*.suo
*.ncb
*.opensdf
Thumbs.db
ipch
Debug
RelWithDebInfo
*.lib
*.exp
*.pdb
*.dll
*.ilk
*.resource.txt
*.embed.manifest*
*.intermediate.manifest*
version.rc
*.VC.db
*.VC.opendb
# Binaries
*.a
*.o
*.so
*.so.*
*.dylib
bin
libs
cunit/test_freerdp
client/X11/xfreerdp
client/Mac/xcode
client/Sample/sfreerdp
client/Wayland/wlfreerdp
server/Sample/sfreerdp-server
server/X11/xfreerdp-server
server/proxy/freerdp-proxy
xcode
libfreerdp/codec/test/TestOpenH264ASM
# Other
*~
*.dir
Release
Win32
build*/
*.orig
*.msrcIncident
default.log
*Amplifier XE*
*Inspector XE*
*.cbp
*.txt.user
*.autosave
# etags
TAGS
# generated packages
*.zip
*.exe
#*.sh
*.deb
*.rpm
*.dmg
*.tar.Z
*.tar.gz
# packaging related files
!packaging/**.sh
packaging/deb/freerdp-nightly/freerdp-nightly
packaging/deb/freerdp-nightly/freerdp-nightly-dev
packaging/deb/freerdp-nightly/freerdp-nightly-dbg
.source_version
#
.idea
# VisualStudio Code
.vscode
cache/

View File

@ -1 +0,0 @@
2693389a+debian

View File

@ -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-dev5")
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)
@ -493,7 +497,7 @@ if(WIN32)
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")
@ -510,7 +514,7 @@ if(WIN32)
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}")
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})
@ -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 )
@ -706,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")
@ -726,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")
@ -750,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")
@ -785,15 +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(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")
@ -803,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()
@ -834,8 +829,6 @@ 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()
@ -856,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})
@ -871,7 +862,7 @@ 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)
set(WITH_OPENH264_LOADING OFF)
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)
@ -945,10 +936,6 @@ 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()
@ -957,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)

54294
ChangeLog

File diff suppressed because it is too large Load Diff

View File

@ -1,25 +1,22 @@
FreeRDP: A Remote Desktop Protocol Implementation
=================================================
# 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
---------
## 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/
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
IRC channel: #freerdp @ irc.freenode.net
Mailing list: https://lists.sourceforge.net/lists/listinfo/freerdp-devel
Microsoft Open Specifications
-----------------------------
## Microsoft Open Specifications
Information regarding the Microsoft Open Specifications can be found at:
http://www.microsoft.com/openspecifications/
@ -27,8 +24,7 @@ http://www.microsoft.com/openspecifications/
A list of reference documentation is maintained here:
https://github.com/FreeRDP/FreeRDP/wiki/Reference-Documentation
Compilation
-----------
## Compilation
Instructions on how to get started compiling FreeRDP can be found on the wiki:
https://github.com/FreeRDP/FreeRDP/wiki/Compilation

View File

@ -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})

View File

@ -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, "<device>", 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, "<device>",
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;
}

View File

@ -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; x<ARRAYSIZE(samplerates); x++)
for (x = 0; x < ARRAYSIZE(samplerates); x++)
{
format.nSamplesPerSec = samplerates[x];
test = IFCALLRESULT(FALSE, audin->device->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, "<subsystem>", NULL, NULL, -1, NULL, "subsystem" },
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "device" },
{ "format", COMMAND_LINE_VALUE_REQUIRED, "<format>", NULL, NULL, -1, NULL, "format" },
{ "rate", COMMAND_LINE_VALUE_REQUIRED, "<rate>", NULL, NULL, -1, NULL, "rate" },
{ "channel", COMMAND_LINE_VALUE_REQUIRED, "<channel>", 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, "<subsystem>", NULL, NULL, -1, NULL, "subsystem" },
{ "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>", NULL, NULL, -1, NULL, "device" },
{ "format", COMMAND_LINE_VALUE_REQUIRED, "<format>", NULL, NULL, -1, NULL, "format" },
{ "rate", COMMAND_LINE_VALUE_REQUIRED, "<rate>", NULL, NULL, -1, NULL, "rate" },
{ "channel", COMMAND_LINE_VALUE_REQUIRED, "<channel>", 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.");
{
/* 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;
}
error = pEntryPoints->RegisterPlugin(pEntryPoints, "audin", (IWTSPlugin*)audin);
if (error == CHANNEL_RC_OK)
return error;
error = pEntryPoints->RegisterPlugin(pEntryPoints, "audin", (IWTSPlugin*) audin);
out:
if (error != CHANNEL_RC_OK)
audin_plugin_terminated((IWTSPlugin*)audin);
audin_plugin_terminated((IWTSPlugin*)audin);
return error;
}

View File

@ -33,4 +33,3 @@
#define TAG CHANNELS_TAG("audin.client")
#endif /* FREERDP_CHANNEL_AUDIN_CLIENT_MAIN_H */

View File

@ -34,7 +34,11 @@
#include <winpr/cmdline.h>
#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 <CoreAudio/CoreAudioTypes.h>
#include <CoreAudio/CoreAudio.h>
@ -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, "<device>", 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, "<device>",
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;
}

View File

@ -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,34 +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);
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))
{
@ -123,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;
}
@ -137,16 +134,16 @@ 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);
opensles->format = *format;
@ -177,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;
}
@ -193,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;
@ -234,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;
@ -247,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, "<device>",
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, "<device>", 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;
@ -283,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);
@ -295,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
/**
@ -314,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)
{
@ -340,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;
}

View File

@ -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 <organization> 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 <organization> 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);
}

View File

@ -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 <organization> 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 <organization> 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 <stdlib.h>
#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
};

View File

@ -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,33 +242,34 @@ 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;
}
}
@ -280,8 +277,7 @@ static DWORD WINAPI audin_oss_thread_func(LPVOID arg)
err_out:
if (error && oss && oss->rdpcontext)
setChannelError(oss->rdpcontext, error,
"audin_oss_thread_func reported an error");
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, "<device>", 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, "<device>",
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;
}

View File

@ -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, "<device>", 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, "<device>",
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;
}

View File

@ -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, "<device>", 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, "<device>",
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;
}

View File

@ -39,13 +39,13 @@
#include <freerdp/channels/log.h>
#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;

View File

@ -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)

View File

@ -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 (strcmp(CLIENT_STATIC_ADDIN_TABLE[i].name, pszName) == 0)
if (dwFlags & FREERDP_ADDIN_CHANNEL_ENTRYEX)
type = "VirtualChannelEntryEx";
else
type = "VirtualChannelEntry";
}
for (; table->name != NULL; table++)
{
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;
}
}
}

View File

@ -16,5 +16,3 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/

View File

@ -19,6 +19,7 @@
* limitations under the License.
*/
#include <freerdp/channels/rdpdr.h>
#include "tables.h"
${CLIENT_STATIC_TYPEDEFS}

View File

@ -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;

View File

@ -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")

View File

@ -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 ((error = cliprdr_read_format_list(s, &formatList, cliprdr->useLongFormatNames)))
goto error_out;
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 (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]);
}

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -0,0 +1,578 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Cliprdr common
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <freerdp/channels/log.h>
#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;
}
}

View File

@ -0,0 +1,61 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Cliprdr common
*
* Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CHANNEL_RDPECLIP_COMMON_H
#define FREERDP_CHANNEL_RDPECLIP_COMMON_H
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <freerdp/channels/cliprdr.h>
#include <freerdp/api.h>
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 */

View File

@ -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")

File diff suppressed because it is too large Load Diff

View File

@ -30,7 +30,7 @@
#define TAG CHANNELS_TAG("cliprdr.server")
#define CLIPRDR_HEADER_LENGTH 8
#define CLIPRDR_HEADER_LENGTH 8
struct _cliprdr_server_private
{

View File

@ -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()

View File

@ -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(..)

176
channels/disp/client/disp_main.c Executable file → Normal file
View File

@ -40,6 +40,7 @@
#include <freerdp/addin.h>
#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
{

View File

@ -33,10 +33,6 @@
#include <freerdp/client/disp.h>
#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 */

View File

@ -0,0 +1,60 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* RDPEDISP Virtual Channel Extension
*
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <freerdp/channels/log.h>
#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;
}

View File

@ -0,0 +1,32 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* RDPEDISP Virtual Channel Extension
*
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CHANNEL_DISP_COMMON_H
#define FREERDP_CHANNEL_DISP_COMMON_H
#include <winpr/crt.h>
#include <winpr/stream.h>
#include <freerdp/channels/disp.h>
#include <freerdp/api.h>
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 */

View File

@ -0,0 +1,32 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
define_channel_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")

View File

@ -0,0 +1,581 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* RDPEDISP Virtual Channel Extension
*
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "disp_main.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/stream.h>
#include <winpr/sysinfo.h>
#include <freerdp/channels/wtsvc.h>
#include <freerdp/channels/log.h>
#include <freerdp/server/disp.h>
#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);
}

View File

@ -0,0 +1,37 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* RDPEDISP Virtual Channel Extension
*
* Copyright 2019 Kobi Mizrachi <kmizrachi18@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CHANNEL_DISP_SERVER_MAIN_H
#define FREERDP_CHANNEL_DISP_SERVER_MAIN_H
#include <freerdp/server/disp.h>
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 */

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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)
{

View File

@ -46,9 +46,19 @@
#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)
@ -79,12 +89,12 @@ static void drive_file_fix_path(WCHAR* path)
}
static WCHAR* drive_file_combine_fullpath(const WCHAR* base_path, const WCHAR* path,
size_t PathLength)
size_t PathLength)
{
WCHAR* fullpath;
size_t base_path_length;
if (!base_path || !path)
if (!base_path || (!path && (PathLength > 0)))
return NULL;
base_path_length = _wcslen(base_path) * 2;
@ -97,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;
}
@ -140,8 +151,8 @@ static BOOL drive_file_remove_dir(const WCHAR* path)
{
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;
}
@ -162,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);
@ -238,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)
{
@ -255,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;
@ -286,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. */
@ -298,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)
{
@ -343,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;
}
@ -461,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;
@ -479,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;
@ -497,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:
@ -556,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:
@ -611,8 +644,8 @@ 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;
}
@ -620,7 +653,8 @@ BOOL drive_file_set_information(DRIVE_FILE* file, UINT32 FsInformationClass, UIN
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;
}
@ -628,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;
}
@ -699,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;
@ -762,22 +798,30 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
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, 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, (UINT32)length); /* FileNameLength */
Stream_Write_UINT32(output, (UINT32)length); /* FileNameLength */
Stream_Write(output, file->find_data.cFileName, length);
break;
@ -791,23 +835,31 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
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, 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, (UINT32)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;
@ -821,24 +873,32 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
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, 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, (UINT32)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);
@ -854,14 +914,14 @@ BOOL drive_file_query_directory(DRIVE_FILE* file, UINT32 FsInformationClass, BYT
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_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);
WLog_ERR(TAG, "unhandled FsInformationClass %" PRIu32, FsInformationClass);
/* Unhandled FsInformationClass */
goto out_fail;
}
@ -869,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;
}

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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 */

View File

@ -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);
}

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -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);
}

View File

@ -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;
}

View File

@ -29,6 +29,4 @@
#include <freerdp/addin.h>
#include <freerdp/client/geometry.h>
#endif /* FREERDP_CHANNEL_GEOMETRY_CLIENT_MAIN_H */

View File

@ -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;

View File

@ -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()

View File

@ -0,0 +1,31 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2019 Armin Novak <armin.novak@thincast.com>
# 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})

View File

@ -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 <martin.haimberger@thincast.com>
* Copyright 2016 Armin Novak <armin.novak@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <cups/cups.h>
#include <winpr/crt.h>
#include <winpr/string.h>
#include <freerdp/channels/rdpdr.h>
#include <freerdp/client/printer.h>
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;
}

View File

@ -1,331 +0,0 @@
/**
* 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 <martin.haimberger@thincast.com>
* Copyright 2016 Armin Novak <armin.novak@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <cups/cups.h>
#include <winpr/crt.h>
#include <winpr/string.h>
#include <freerdp/channels/rdpdr.h>
#include "printer_main.h"
#include "printer_cups.h"
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;
};
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, int size)
{
time_t tt;
struct tm* t;
tt = time(NULL);
t = localtime(&tt);
sprintf_s(buf, size - 1, "FreeRDP Print Job %d%02d%02d%02d%02d%02d",
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
}
/**
* 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));
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];
cups_printjob->printjob_object = httpConnectEncrypt(cupsServer(), ippPort(), HTTP_ENCRYPT_IF_REQUESTED);
if (!cups_printjob->printjob_object)
{
free(cups_printjob);
return NULL;
}
printer_cups_get_printjob_name(buf, sizeof(buf));
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);
free(printer->name);
free(printer->driver);
free(printer);
}
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.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.Free = printer_cups_free_printer;
return (rdpPrinter*) cups_printer;
}
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)
{
printers[num_printers++] = printer_cups_new_printer((rdpCupsPrinterDriver*) driver,
dest->name, NULL, dest->is_default);
}
}
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 rdpCupsPrinterDriver* cups_driver = NULL;
rdpPrinterDriver* printer_cups_get_driver(void)
{
if (cups_driver == NULL)
{
cups_driver = (rdpCupsPrinterDriver*) calloc(1, sizeof(rdpCupsPrinterDriver));
if (!cups_driver)
return NULL;
cups_driver->driver.EnumPrinters = printer_cups_enum_printers;
cups_driver->driver.GetPrinter = printer_cups_get_printer;
cups_driver->id_sequence = 1;
}
return (rdpPrinterDriver*) cups_driver;
}

View File

@ -42,15 +42,7 @@
#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 <freerdp/client/printer.h>
#include <freerdp/channels/log.h>
@ -79,21 +71,15 @@ typedef enum
PRN_CONF_PNP = 1,
PRN_CONF_DRIVER = 2,
PRN_CONF_DATA = 3
}
prn_conf_t;
} prn_conf_t;
static const char* filemap[] =
{
"PortDosName",
"PnPName",
"DriverName",
"CachedPrinterConfigData"
};
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* bname = crypto_base64_encode((const BYTE*)name, (int)length);
char* config = GetCombinedPath(dir, bname);
if (config && !PathFileExistsA(config))
@ -121,11 +107,10 @@ static BOOL printer_write_setting(const char* path, prn_conf_t type, const void*
const char* name = filemap[type];
char* abs = GetCombinedPath(path, name);
if (!abs)
if (!abs || (length > INT32_MAX))
return FALSE;
file = CreateFileA(abs, GENERIC_WRITE, 0,
NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
file = CreateFileA(abs, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
free(abs);
if (file == INVALID_HANDLE_VALUE)
@ -138,7 +123,9 @@ static BOOL printer_write_setting(const char* path, prn_conf_t type, const void*
if (!base64)
goto fail;
b64len = strlen(base64);
/* 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)
@ -164,21 +151,20 @@ static BOOL printer_config_valid(const char* path)
return TRUE;
}
static BOOL printer_read_setting(const char* path, prn_conf_t type, void** data, size_t* length)
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;
BYTE* fdata = NULL;
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);
file = CreateFileA(abs, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
free(abs);
if (file == INVALID_HANDLE_VALUE)
@ -205,13 +191,13 @@ static BOOL printer_read_setting(const char* path, prn_conf_t type, void** data,
fail:
CloseHandle(file);
if (rc)
if (rc && (lowSize <= INT_MAX))
{
int blen = 0;
crypto_base64_decode(fdata, lowSize, data, &blen);
crypto_base64_decode(fdata, (int)lowSize, (BYTE**)data, &blen);
if (*data)
*length = blen;
if (*data && (blen > 0))
*length = (UINT32)blen;
else
{
rc = FALSE;
@ -228,9 +214,8 @@ fail:
return rc;
}
static BOOL printer_save_to_config(const rdpSettings* settings,
const char* PortDosName, size_t PortDosNameLen,
const WCHAR* PnPName, size_t PnPNameLen,
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)
@ -306,13 +291,13 @@ static BOOL printer_load_from_config(const rdpSettings* settings, rdpPrinter* pr
char* path = NULL;
int rc;
UINT32 flags = 0;
WCHAR* DriverName = NULL;
size_t DriverNameLen = 0;
WCHAR* PnPName = NULL;
size_t PnPNameLen = 0;
BYTE* CachedPrinterConfigData = NULL;
size_t CachedFieldsLen = 0;
size_t PrinterNameLen = 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;
@ -338,8 +323,8 @@ static BOOL printer_load_from_config(const rdpSettings* settings, rdpPrinter* pr
if (!printer_read_setting(path, PRN_CONF_DRIVER, &DriverName, &DriverNameLen))
{
DriverNameLen = ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, &DriverName,
0) * 2 + 1;
DriverNameLen =
ConvertToUnicode(CP_UTF8, 0, printer->driver, -1, (LPWSTR*)&DriverName, 0) * 2 + 1;
}
if (!printer_read_setting(path, PRN_CONF_DATA, &CachedPrinterConfigData, &CachedFieldsLen))
@ -352,7 +337,7 @@ static BOOL printer_load_from_config(const rdpSettings* settings, rdpPrinter* pr
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, 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);
@ -441,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)
{
@ -467,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)
{
@ -494,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)
{
@ -509,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;
}
@ -528,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);
@ -549,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;
}
@ -558,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;
}
@ -567,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;
}
@ -576,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;
}
@ -595,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)
@ -606,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;
}
@ -616,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)
{
@ -627,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;
@ -647,7 +634,7 @@ 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;
@ -656,7 +643,7 @@ static UINT printer_irp_request(DEVICE* device, IRP* irp)
static UINT printer_custom_component(DEVICE* device, UINT16 component, UINT16 packetId, wStream* s)
{
UINT32 eventID;
PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*) device;
PRINTER_DEVICE* printer_dev = (PRINTER_DEVICE*)device;
const rdpSettings* settings = printer_dev->rdpcontext->settings;
if (component != RDPDR_CTYP_PRN)
@ -673,156 +660,156 @@ static UINT printer_custom_component(DEVICE* device, UINT16 component, UINT16 pa
switch (eventID)
{
case RDPDR_ADD_PRINTER_EVENT:
{
char PortDosName[8];
UINT32 PnPNameLen, DriverNameLen, PrintNameLen, CacheFieldsLen;
const WCHAR* PnPName, *DriverName, *PrinterName;
const BYTE* CachedPrinterConfigData;
{
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;
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);
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;
if (Stream_GetRemainingLength(s) < PnPNameLen)
return ERROR_INVALID_DATA;
PnPName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, PnPNameLen);
PnPName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, PnPNameLen);
if (Stream_GetRemainingLength(s) < DriverNameLen)
return ERROR_INVALID_DATA;
if (Stream_GetRemainingLength(s) < DriverNameLen)
return ERROR_INVALID_DATA;
DriverName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, DriverNameLen);
DriverName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, DriverNameLen);
if (Stream_GetRemainingLength(s) < PrintNameLen)
return ERROR_INVALID_DATA;
if (Stream_GetRemainingLength(s) < PrintNameLen)
return ERROR_INVALID_DATA;
PrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, PrintNameLen);
PrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, PrintNameLen);
if (Stream_GetRemainingLength(s) < CacheFieldsLen)
return ERROR_INVALID_DATA;
if (Stream_GetRemainingLength(s) < CacheFieldsLen)
return ERROR_INVALID_DATA;
CachedPrinterConfigData = Stream_Pointer(s);
Stream_Seek(s, CacheFieldsLen);
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;
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;
{
UINT32 PrinterNameLen, ConfigDataLen;
const WCHAR* PrinterName;
const BYTE* ConfigData;
if (Stream_GetRemainingLength(s) < 8)
return ERROR_INVALID_DATA;
if (Stream_GetRemainingLength(s) < 8)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, PrinterNameLen);
Stream_Read_UINT32(s, ConfigDataLen);
Stream_Read_UINT32(s, PrinterNameLen);
Stream_Read_UINT32(s, ConfigDataLen);
if (Stream_GetRemainingLength(s) < PrinterNameLen)
return ERROR_INVALID_DATA;
if (Stream_GetRemainingLength(s) < PrinterNameLen)
return ERROR_INVALID_DATA;
PrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, PrinterNameLen);
PrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, PrinterNameLen);
if (Stream_GetRemainingLength(s) < ConfigDataLen)
return ERROR_INVALID_DATA;
if (Stream_GetRemainingLength(s) < ConfigDataLen)
return ERROR_INVALID_DATA;
ConfigData = Stream_Pointer(s);
Stream_Seek(s, ConfigDataLen);
ConfigData = Stream_Pointer(s);
Stream_Seek(s, ConfigDataLen);
if (!printer_update_to_config(settings, PrinterName, PrinterNameLen, ConfigData, ConfigDataLen))
return ERROR_INTERNAL_ERROR;
}
break;
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;
{
UINT32 PrinterNameLen;
const WCHAR* PrinterName;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, PrinterNameLen);
Stream_Read_UINT32(s, PrinterNameLen);
if (Stream_GetRemainingLength(s) < PrinterNameLen)
return ERROR_INVALID_DATA;
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;
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;
{
UINT32 OldPrinterNameLen, NewPrinterNameLen;
const WCHAR* OldPrinterName;
const WCHAR* NewPrinterName;
if (Stream_GetRemainingLength(s) < 8)
return ERROR_INVALID_DATA;
if (Stream_GetRemainingLength(s) < 8)
return ERROR_INVALID_DATA;
Stream_Read_UINT32(s, OldPrinterNameLen);
Stream_Read_UINT32(s, NewPrinterNameLen);
Stream_Read_UINT32(s, OldPrinterNameLen);
Stream_Read_UINT32(s, NewPrinterNameLen);
if (Stream_GetRemainingLength(s) < OldPrinterNameLen)
return ERROR_INVALID_DATA;
if (Stream_GetRemainingLength(s) < OldPrinterNameLen)
return ERROR_INVALID_DATA;
OldPrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, OldPrinterNameLen);
OldPrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, OldPrinterNameLen);
if (Stream_GetRemainingLength(s) < NewPrinterNameLen)
return ERROR_INVALID_DATA;
if (Stream_GetRemainingLength(s) < NewPrinterNameLen)
return ERROR_INVALID_DATA;
NewPrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, NewPrinterNameLen);
NewPrinterName = (const WCHAR*)Stream_Pointer(s);
Stream_Seek(s, NewPrinterNameLen);
if (!printer_move_config(settings, OldPrinterName, OldPrinterNameLen, NewPrinterName,
NewPrinterNameLen))
return ERROR_INTERNAL_ERROR;
}
break;
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);
WLog_ERR(TAG, "Unknown cache data eventID: 0x%08" PRIX32 "", eventID);
return ERROR_INVALID_DATA;
}
break;
case PAKID_PRN_USING_XPS:
{
UINT32 flags;
{
UINT32 flags;
if (Stream_GetRemainingLength(s) < 4)
return ERROR_INVALID_DATA;
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;
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);
WLog_ERR(TAG, "Unknown printing component packetID: 0x%04" PRIX16 "", packetId);
return ERROR_INVALID_DATA;
}
@ -837,14 +824,14 @@ static UINT printer_custom_component(DEVICE* device, UINT16 component, UINT16 pa
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
@ -854,7 +841,7 @@ static UINT printer_free(DEVICE* device)
#endif
}
while ((irp = (IRP*) InterlockedPopEntrySList(printer_dev->pIrpList)) != NULL)
while ((irp = (IRP*)InterlockedPopEntrySList(printer_dev->pIrpList)) != NULL)
irp->Discard(irp);
CloseHandle(printer_dev->thread);
@ -863,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);
@ -875,12 +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)
{
PRINTER_DEVICE* printer_dev;
UINT error = ERROR_INTERNAL_ERROR;
printer_dev = (PRINTER_DEVICE*) calloc(1, sizeof(PRINTER_DEVICE));
printer_dev = (PRINTER_DEVICE*)calloc(1, sizeof(PRINTER_DEVICE));
if (!printer_dev)
{
@ -893,7 +879,7 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
if (!printer_dev->device.data)
goto error_out;
sprintf_s(printer_dev->port, sizeof(printer_dev->port), "PRN%d", printer->id);
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;
@ -901,8 +887,8 @@ UINT printer_register(PDEVICE_SERVICE_ENTRY_POINTS pEntryPoints,
printer_dev->device.Free = printer_free;
printer_dev->rdpcontext = pEntryPoints->rdpcontext;
printer_dev->printer = printer;
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)
{
@ -930,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:
*
* <driver_name> ... name of a printer driver
* <driver_name>:<backend_name> ... 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)
{
@ -985,47 +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))
return CHANNEL_RC_INITIALIZATION_ERROR;
{
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;
}

View File

@ -1,341 +0,0 @@
/**
* 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 <martin.haimberger@thincast.com>
* Copyright 2016 Armin Novak <armin.novak@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/string.h>
#include <winpr/windows.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winspool.h>
#include "printer_main.h"
#include "printer_win.h"
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;
int id_sequence;
};
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 void printer_win_get_printjob_name(char* buf, int size)
{
time_t tt;
struct tm* t;
tt = time(NULL);
t = localtime(&tt);
sprintf_s(buf, size - 1, "FreeRDP Print Job %d%02d%02d%02d%02d%02d",
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec);
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT printer_win_write_printjob(rdpPrintJob* printjob, BYTE* data, int size)
{
rdpWinPrintJob* win_printjob = (rdpWinPrintJob*) printjob;
LPVOID pBuf = data;
DWORD cbBuf = size;
DWORD pcWritten;
if(!WritePrinter(((rdpWinPrinter*)printjob->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;
if (!EndPagePrinter(((rdpWinPrinter*) printjob->printer)->hPrinter))
{
}
if (!ClosePrinter(((rdpWinPrinter*) printjob->printer)->hPrinter))
{
}
((rdpWinPrinter*) printjob->printer)->printjob = NULL;
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 = L"FREERDPjob";
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);
return NULL;
}
if (!StartPagePrinter(win_printer->hPrinter))
{
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 (rdpPrintJob*) win_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);
free(printer->name);
free(printer->driver);
free(printer);
}
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.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.Free = printer_win_free_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;
}
return (rdpPrinter*)win_printer;
}
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++)
{
printers[num_printers++] = printer_win_new_printer((rdpWinPrinterDriver*)driver,
prninfo[i].pPrinterName, prninfo[i].pDriverName, 0);
}
GlobalFree(prninfo);
return printers;
}
static rdpPrinter* printer_win_get_printer(rdpPrinterDriver* driver,
const char* name, const char* driverName)
{
WCHAR* driverNameW = NULL;
rdpWinPrinterDriver* win_driver = (rdpWinPrinterDriver*)driver;
rdpPrinter *myPrinter = NULL;
if (driverName)
{
ConvertToUnicode(CP_UTF8, 0, driverName, -1, &driverNameW, 0);
if (!driverNameW)
return NULL;
}
myPrinter = printer_win_new_printer(win_driver, name, driverNameW,
win_driver->id_sequence == 1 ? TRUE : FALSE);
free(driverNameW);
return myPrinter;
}
static rdpWinPrinterDriver* win_driver = NULL;
rdpPrinterDriver* printer_win_get_driver(void)
{
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.GetPrinter = printer_win_get_printer;
win_driver->id_sequence = 1;
}
return (rdpPrinterDriver*) win_driver;
}

View File

@ -0,0 +1,29 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2019 Armin Novak <armin.novak@thincast.com>
# 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})

View File

@ -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 <martin.haimberger@thincast.com>
* Copyright 2016 Armin Novak <armin.novak@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <winpr/crt.h>
#include <winpr/string.h>
#include <winpr/windows.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <winspool.h>
#include <freerdp/client/printer.h>
#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;
}

View File

@ -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 */

View File

@ -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()

View File

@ -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;
}
}
@ -326,20 +333,6 @@ static UINT rail_client_system_param(RailClientContext* context,
return error;
}
/**
* Function description
*
* @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
*
@ -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,63 +355,17 @@ 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);
}
/**
* Function description
*
* @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
*
@ -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,38 +396,10 @@ 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);
}
/**
* Function description
*
* @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
*
@ -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,43 +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 */
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT rail_server_execute_result(RailClientContext* context,
const RAIL_EXEC_RESULT_ORDER* execResult)
{
if (!context || !execResult)
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);
}
/**
@ -566,29 +468,49 @@ static UINT rail_server_execute_result(RailClientContext* context,
* @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)
const RAIL_GET_APPID_REQ_ORDER* getAppIdReq)
{
railPlugin* rail;
if (!context || !getAppIdReq || !context->handle)
return ERROR_INVALID_PARAMETER;
rail = (railPlugin*) context->handle;
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_server_get_appid_response(RailClientContext* context,
const RAIL_GET_APPID_RESP_ORDER* getAppIdResp)
static UINT rail_client_compartment_info(RailClientContext* context,
const RAIL_COMPARTMENT_INFO_ORDER* compartmentInfo)
{
if (!context || !getAppIdResp)
railPlugin* rail;
if (!context || !compartmentInfo || !context->handle)
return ERROR_INVALID_PARAMETER;
return CHANNEL_RC_OK; /* stub - should be registered by client */
rail = (railPlugin*)context->handle;
return rail_send_client_compartment_info_order(rail, compartmentInfo);
}
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)
{
railPlugin* rail;
if (!context || !snap || !context->handle)
return ERROR_INVALID_PARAMETER;
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;
}

View File

@ -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 */

File diff suppressed because it is too large Load Diff

View File

@ -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 */

View File

@ -23,56 +23,37 @@
#include "rail_common.h"
#include <winpr/crt.h>
#include <freerdp/channels/log.h>
const char* const RAIL_ORDER_TYPE_STRINGS[] =
#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",
"",
"",
"",
"",
"",
"" };
const char* rail_get_order_type_string(BYTE orderType)
{
"",
"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;
}
unicode_string->string = (BYTE*) buffer;
unicode_string->length = (UINT16) length * sizeof(WCHAR);
return TRUE;
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;
}

View File

@ -26,25 +26,36 @@
#include <freerdp/rail.h>
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 */
#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 */
BOOL rail_string_to_unicode_string(const char* string, RAIL_UNICODE_STRING* unicode_string);
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 */

View File

@ -0,0 +1,32 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2019 Mati Shabtay <matishabtay@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
define_channel_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")

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,44 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* RAIL Virtual Channel Plugin
*
* Copyright 2019 Mati Shabtay <matishabtay@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef FREERDP_CHANNEL_RAIL_SERVER_MAIN_H
#define FREERDP_CHANNEL_RAIL_SERVER_MAIN_H
#include <freerdp/rail.h>
#include <freerdp/server/rail.h>
#include <winpr/crt.h>
#include <winpr/wlog.h>
#include <winpr/stream.h>
#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 */

View File

@ -1,7 +1,7 @@
# WinPR: Windows Portable Runtime
# libwinpr-com cmake build script
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2013 Marc-Andre Moreau <marcandre.moreau@gmail.com>
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -15,8 +15,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
winpr_module_add(com.c)
define_channel("rdp2tcp")
if(BUILD_TESTING)
add_subdirectory(test)
if(WITH_CLIENT_CHANNELS)
add_channel_client(${MODULE_PREFIX} ${CHANNEL_NAME})
endif()

View File

@ -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})

View File

@ -0,0 +1,27 @@
# FreeRDP: A Remote Desktop Protocol Implementation
# FreeRDP cmake build script
#
# Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
define_channel_client("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")

View File

@ -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 <stdio.h>
#include <assert.h>
#include <winpr/file.h>
#include <winpr/pipe.h>
#include <winpr/thread.h>
#include <freerdp/svc.h>
#define RDP2TCP_CHAN_NAME "rdp2tcp"
#include <freerdp/log.h>
#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

View File

@ -43,7 +43,7 @@
static void devman_device_free(void* obj)
{
DEVICE* device = (DEVICE*) obj;
DEVICE* device = (DEVICE*)obj;
if (!device)
return;
@ -58,21 +58,21 @@ 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;
}
@ -94,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);
@ -113,11 +113,11 @@ 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;
}
@ -127,12 +127,12 @@ static UINT devman_register_device(DEVMAN* devman, DEVICE* device)
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;
}
@ -150,7 +150,7 @@ DEVICE* devman_get_device_by_type(DEVMAN* devman, UINT32 type)
for (x = 0; x < count; x++)
{
DEVICE* cur = (DEVICE*) ListDictionary_GetItemValue(devman->devices, (void*)keys[x]);
DEVICE* cur = (DEVICE*)ListDictionary_GetItemValue(devman->devices, (void*)keys[x]);
if (!cur)
continue;
@ -167,23 +167,28 @@ DEVICE* devman_get_device_by_type(DEVMAN* devman, UINT32 type)
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;
@ -200,27 +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);
WLog_INFO(TAG, "Loading device service %s (static)", ServiceName);
entry = (PDEVICE_SERVICE_ENTRY) freerdp_load_channel_addin_entry(ServiceName, NULL,
"DeviceServiceEntry", 0);
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);
}

View File

@ -26,7 +26,7 @@
#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);

View File

@ -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;

View File

@ -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);
}

File diff suppressed because it is too large Load Diff

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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;

View File

@ -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;
}

View File

@ -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 */

View File

@ -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;

View File

@ -26,7 +26,8 @@
#include <freerdp/channels/rdpei.h>
/** @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 */

View File

@ -34,7 +34,8 @@
#include <freerdp/server/rdpei.h>
/** @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;
}

View File

@ -29,7 +29,4 @@
#define TAG CHANNELS_TAG("rdpei.server")
#endif /* FREERDP_CHANNEL_RDPEI_SERVER_MAIN_H */

View File

@ -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;
}
@ -245,14 +247,14 @@ static UINT rdpgfx_decode_AVC444(RDPGFX_PLUGIN* gfx, RDPGFX_SURFACE_COMMAND* cmd
else
h264.bitstream[0].length = Stream_GetRemainingLength(s);
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:
@ -272,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;
@ -296,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;

File diff suppressed because it is too large Load Diff

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