Compare commits
39 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc34c2b4c8 | ||
|
|
a48ea06e9b | ||
|
|
04da549942 | ||
|
|
68f6113430 | ||
|
|
84fd2a510b | ||
|
|
01d3dedfdf | ||
|
|
8e08066bc8 | ||
|
|
ac67abe9b6 | ||
|
|
02c265c5a5 | ||
|
|
fb2a863d12 | ||
|
|
19b4905018 | ||
|
|
c5e6c4e117 | ||
|
|
9985737e9b | ||
|
|
790834a947 | ||
|
|
7700fcb1dc | ||
|
|
d6cf81a4da | ||
|
|
ab2430ac76 | ||
|
|
72d30061b0 | ||
|
|
a7115cced2 | ||
|
|
83f9d4ec17 | ||
|
|
d0edde791e | ||
|
|
99cf0e19f7 | ||
|
|
9b33d299d0 | ||
|
|
c3cb8554b6 | ||
|
|
12ff5d4814 | ||
|
|
8a1e6f74f7 | ||
|
|
d769b402bc | ||
|
|
ab698c3d58 | ||
|
|
355a71fe6d | ||
|
|
ee37eb2803 | ||
|
|
74c2f7c4a7 | ||
|
|
66a8e93f3c | ||
|
|
9f422cc306 | ||
|
|
dc6ac9758b | ||
|
|
bfecd1887b | ||
|
|
b0a30a3581 | ||
|
|
1917b9c747 | ||
|
|
e00236193f | ||
|
|
6272ae6018 |
10
.github/workflows/build.yml
vendored
10
.github/workflows/build.yml
vendored
@ -132,7 +132,7 @@ jobs:
|
||||
echo "PKG_CONFIG_PATH=$PKG_CONFIG_PATH_${{ matrix.arch }}" >> $GITHUB_ENV
|
||||
echo "CFLAGS=$CFLAGS_${{ matrix.arch }}" >> $GITHUB_ENV
|
||||
echo "LDFLAGS=$LDFLAGS_${{ matrix.arch }}" >> $GITHUB_ENV
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: "Install Dependencies"
|
||||
# See https://github.com/actions/runner-images/issues/7192
|
||||
run: |
|
||||
@ -173,9 +173,9 @@ jobs:
|
||||
id: os
|
||||
run: echo "image=$ImageOS" >>$GITHUB_OUTPUT
|
||||
shell: bash
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Cache cppcheck
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
env:
|
||||
cache-name: cache-cppcheck
|
||||
with:
|
||||
@ -202,9 +202,9 @@ jobs:
|
||||
id: os
|
||||
run: echo "image=$ImageOS" >>$GITHUB_OUTPUT
|
||||
shell: bash
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Cache astyle
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
env:
|
||||
cache-name: cache-astyle
|
||||
with:
|
||||
|
||||
813
NEWS.md
813
NEWS.md
@ -1,651 +1,210 @@
|
||||
# Release notes for xrdp v0.9.19 (2022/03/17)
|
||||
# Release notes for xrdp v0.10.0 (2024/03/dd)
|
||||
|
||||
This section notes changes since the [v0.10 branch](#branch-v010) was created.
|
||||
|
||||
## General announcements
|
||||
* Running xrdp and xrdp-sesman on separate hosts is still supported by this release, but is now deprecated. This is not secure. A future release will replace the TCP socket used between these processes with a Unix Domain Socket, and then cross-host running will not be possible.
|
||||
The biggest news of this release is that [Graphic Pipeline Extension](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpegfx/da5c75f9-cd99-450c-98c4-014a496942b0) also called GFX in short has been supported. xrdp v0.10 with GFX achieves more frame rates and less bandwidth compared to v0.9. There is a significant performance improvement especially if the client is Windows 11's mstsc.exe or Microsoft Remote Desktop for Mac. GFX H.264/AVC 444 mode and hardware-accelerated encoding are not supported in this version yet.
|
||||
|
||||
## New features
|
||||
* Both inbound and outbound clipboards can now be restricted for text, files or images [Sponsored by @CyberTrust @clear-code and @kenhys] (#2087)
|
||||
GFX implementation in xrdp is sponsored by an enterprise sponsor. We very much appreciate the sponsorship. It helped us to accelerate xrdp development and land GFX earlier!
|
||||
|
||||
## Bug fixes
|
||||
* [CVE-2022-23613](https://www.cve.org/CVERecord?id=CVE-2022-23613): Privilege escalation on xrdp-sesman (This fix is also in the out-of-band v0.9.18.1 release)
|
||||
* The versions of imlib2 used on RHEL 7 and 8 are now detected correctly (#2118)
|
||||
* Some situations where zombie processes could exist have been resolved (#2146, #2151, #2168)
|
||||
* Some null-pointer exceptions which can happen in the logging module have been addressed (#2149)
|
||||
* Some minor logging errors have been corrected (#2152)
|
||||
* The signal handling in sesman has been reworked to prevent race conditions when a child exits. This has also made it possible to reliably reload the sesman configuration with SIGHUP (#1729, #2168)
|
||||
Please consider sponsoring or making a donation to the project if you like xrdp. We accept financial contributions via [Open Collective](https://opencollective.com/xrdp-project). Direct donations to each developer via GitHub Sponsors are also welcomed.
|
||||
|
||||
## Internal changes
|
||||
* Versions 0.13 and later of checklib can undefine the pre-processor symbol `HAVE_STDINT_H`. The xrdp tests now build successfully against these versions (#2124)
|
||||
* OpenSSL packaging changes (#2130):-
|
||||
- The OpenSSL 3 EVP interface is now fully supported
|
||||
- When building against OpenSSL 3, an internal implementation of the RC4 cipher is used instead of the implementation from the OpenSSL legacy provider
|
||||
- The wrapping of the OpenSSL library has been improved which should make it simpler to provide an alternative cryptographic provider in the future, if required
|
||||
- The logging of TLS/non-TLS security negotiation has been improved
|
||||
* cppcheck version used for CI bumped to 2.7 (#2140)
|
||||
* The `s_check()` macro which is easily mis-used has been removed (#2144)
|
||||
* Status values for the DRDYNVC channel are now available in `libxrdp/xrdp_channel.h`
|
||||
## Highlights
|
||||
This section describes the most user-visible new or changed features in xrdp since v0.9.19. See [Branch v0.10](#branch-v010) for all changes relative to v0.9.19.
|
||||
|
||||
## Changes for packagers or developers
|
||||
* On OpenSSL 3 systems, there is now no need to build with the `-Wno-error=deprecated-declarations` flag
|
||||
* Added GFX support with multi-monitor support (including monitor hot plug/unplug) (#2256 #2338 #2595 #2879 #2891 #2911 #2929 #2933)
|
||||
* Touchpad inertial scrolling (#2364, #2424). Thanks to new contributor @seflerZ
|
||||
* New look of login screen (#2366)
|
||||
* Scaled login screen on higher DPI monitors (#2341, #2427, #2435)
|
||||
* This feature works automatically when monitor DPI information is sent by the client (i.e. a full-screen session)
|
||||
* Native platform tools are now provided to manipulate .fv1 format font files.
|
||||
* The format of the date and time in the log file has been changed to ISO 8601 with milliseconds (#2386 #2541)
|
||||
* xrdp-sesman now supports a `--reload` switch to allow for the configuration to be changed when sessions are active (#2416)
|
||||
|
||||
## Known issues
|
||||
|
||||
* On-the-fly resolution change requires the Microsoft Store version of Remote Desktop client but sometimes crashes on connect (#1869)
|
||||
* xrdp's login dialog is not relocated at the center of the new resolution after on-the-fly resolution change happens (#1867)
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.18.1 (2022/02/08)
|
||||
|
||||
This is a security fix release that includes fixes for the following privilege escalation vulnerability.
|
||||
|
||||
* [CVE-2022-23613: Privilege escalation on xrdp-sesman](https://www.cve.org/CVERecord?id=CVE-2022-23613)
|
||||
|
||||
Users who uses xrdp v0.9.17 or v0.9.18 are recommended to update to this version.
|
||||
|
||||
## Special thanks
|
||||
|
||||
Thanks to [Gilad Kleinman](https://github.com/giladkl) reporting the vulnerability and reviewing fix.
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.18 (2022/01/10)
|
||||
|
||||
## General announcements
|
||||
* Running xrdp and xrdp-sesman on separate hosts is still supported by this release, but is now deprecated. This is not secure. A future release will replace the TCP socket used between these processes with a Unix Domain Socket, and then cross-host running will not be possible.
|
||||
* Special thanks for @trishume for contributing code to the RFX codec
|
||||
|
||||
## New features
|
||||
* Backgrounds and logos on the login screen can now be zoomed and scaled (#1962)
|
||||
* Small change for Alpine Linux support (#2005)
|
||||
* loongarch support (#2057)
|
||||
* Improved Fail2ban support (#1976)
|
||||
|
||||
## Bug fixes
|
||||
* Logging is improved for security protocol level decisions (#1974, #1975)
|
||||
* An unnecessary log error message which is always generated when running neutrinordp has been removed (#2016)
|
||||
* An incorrect development log message has been fixed (#2074)
|
||||
* Some informational and error messages written to the console on stdout have been removed or replaced with log messages (#2078 #2080)
|
||||
* Failure to attach to the memory area shared with xorgxrdp is now logged (#2065)
|
||||
* A regression in the VNC module logging which might cause a connection to drop out has been identified and fixed (#1989)
|
||||
* Remote drive redirection now works if printer redirection is also requested by the client (#327)
|
||||
* Some file names could not be copied from the client to the server over the clipboard. This is now fixed (#1992, #1995)
|
||||
* A config value has been added which allows copy-pasting of files to work with Nautilus for GNOME 3 versions >= 3.29.92 (#1994, #1996)
|
||||
* Clipboard now works properly when files can't be read (#1997 #2001)
|
||||
* (xorgxrdp v0.2.18) The screen is fully refreshed after initialising shared memory which should fix black screen problems like #1964
|
||||
* An incorrect initialisation reported by @qarmin has been fixed (#1909)
|
||||
* Some minor memory leaks have been fixed (#2014 #2028)
|
||||
* A hard hang in chansrv when copying files from the remote system has been addressed (#2032)
|
||||
* Users can now capitalise username and password on the login screen if required (#2061)
|
||||
* Some failed size checks in the fastpath code with `--enable-devel-streamcheck` have been addressed (#2066,#2070)
|
||||
* Log level for clipboard restriction has been promoted from DEVEL DEBUG to INFO (#2088)
|
||||
* A buffer overflow in the RFX codec associated with large screens has been fixed (#2087)
|
||||
|
||||
## Internal changes
|
||||
* Some 64-bit packages are removed during the 32-bit CI build process in an attempt to make this more robust (#1985)
|
||||
* Minor improvements to error checking and logging for file copy-paste (#1996)
|
||||
* Now uses cppcheck 2.6 for CI builds (#2008)
|
||||
* Generated systemd unit files now ignored by git (#2006)
|
||||
* More internal tests (#2015)
|
||||
* Some unnecessary files have been removed from the distribution (#2030)
|
||||
* The `which` command in shell scripts has been replaced with `command -v` (#2067)
|
||||
* Additional unit tests added for `g_file_get_size()` (#1988)
|
||||
* A compiler warning with -O3 on gcc 11.1 has been addressed (#2105)
|
||||
* An unused declaration for xrdp_wm_drdynvc_up has been removed (#2098)
|
||||
* The SCP V0 code has been unified, which will make it easier to update and replace (#2011)
|
||||
* Monitor processing unit tests for existing xrdp_sec function have been added (#1932)
|
||||
* The librfxcodec has been updated as part of #2087, and also to add stack frames to assemble code to assist debugging
|
||||
|
||||
## Changes for packagers or developers
|
||||
* The `--with-imlib2` option has been added. If xrdp is built with imlib2, the login screen supports more image formats for the background and logo, and better quality zooming and scaling (#1962)
|
||||
|
||||
## Known issues
|
||||
|
||||
* On-the-fly resolution change requires the Microsoft Store version of Remote Desktop client but sometimes crashes on connect (#1869)
|
||||
* xrdp's login dialog is not relocated at the center of the new resolution after on-the-fly resolution change happens (#1867)
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.17 (2021/08/31)
|
||||
|
||||
## General announcements
|
||||
* Running xrdp and xrdp-sesman on separate hosts is still supported by this release, but is now deprecated. This is not secure. A future release will replace the TCP socket used between these processes with a Unix Domain Socket, and then cross-host running will not be possible.
|
||||
|
||||
## New features
|
||||
* The IP address, port, and user name of NeutrinoRDP Proxy connection are logged in xrdp.log - these connections may not have a sesman log to use (#1873)
|
||||
* The performance settings for NeutrinoRDP can be now configured (#1903)
|
||||
* Support for Alpine Linux in startwm.sh (#1965)
|
||||
* clipboard: log file transfer for the purpose of audit (#1954)
|
||||
* Client's Keyboard layout now can be overridden by xrdp configuration for debugging purposes (#1952)
|
||||
|
||||
## Bug fixes
|
||||
* PAM_USER environment variable is not set when using pam_exec module (#1882)
|
||||
* Allow common channel settings to be overridden for modules as well as chansrv (#1899)
|
||||
* The text only-copy/paste interface for the VNC module (used only when chansrv is not active) has been improved (#1900)
|
||||
* The unsupported `tcutils` utility has been removed (#1943)
|
||||
* The quality of TLS logging has been improved (#1926)
|
||||
* Keyboard information is now passed correctly through NeuutrinoRDP, and can be overridden if required (#1934)
|
||||
* A message is now logged in the sesman log for unsuccessful login attempts detailing the user used (#1947)
|
||||
|
||||
|
||||
## Internal changes
|
||||
* astyle formatting is now checked during CI builds (#1879)
|
||||
* Generalise development build options, and add --enable-devel-streamcheck (#1887)
|
||||
* Now uses cppcheck 2.5 for CI builds (#1938)
|
||||
* The SCP protocol is now using a standard `struct trans` for messaging rather than its own thing (#1925)
|
||||
|
||||
## Changes for packagers or developers
|
||||
* The `--enable-xrdpdebug` developer option has been replaced with finer-grained `--enable-devel-*` options. Consequently, specifying `--enable-xrdpdebug` is now an error (#1913)
|
||||
|
||||
## Known issues
|
||||
|
||||
* On-the-fly resolution change requires the Microsoft Store version of Remote Desktop client but sometimes crashes on connect (#1869)
|
||||
* xrdp's login dialog is not relocated at the center of the new resolution after on-the-fly resolution change happens (#1867)
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.16 (2021/04/30)
|
||||
|
||||
## New features
|
||||
* On-the-fly resolution change now supported for Xvnc and Xorg (#448, #1820) - thanks to @Nexarian for this significant first contribution. See the following YouTube video for a demo.
|
||||
* [Windows] https://youtu.be/cZ0ebieZHeA
|
||||
* [Mac] https://youtu.be/6kfAkyLUgFY
|
||||
* xrdp can now use key algorithms other than RSA for TLS (#1776)
|
||||
* Do not spit on the console 2nd stage (inspired by Debian) #1762
|
||||
* Unified and improved logging (#1742, #1767, #1802, #1806, #1807, #1826, #1843) - thanks to @aquesnel for this detailed work.
|
||||
* Other logging level fixes (#1864)
|
||||
* chansrv can now work on `DISPLAY=:0` so it can be used with x11vnc/Vino/etc sessions (#1849)
|
||||
|
||||
## Bug fixes
|
||||
* Fix some regressions in sesman auth modules (#1769)
|
||||
* Minor manpage fixes (#1787)
|
||||
* Fix TS_PLAY_SOUND_PDU_DATA to set the correct frequency and duration (#1793)
|
||||
* Fix password leakage to logs in NeutrinoRDP module (#1872) - thanks to @TOMATO-ONE for reporting.
|
||||
|
||||
## Internal changes
|
||||
* cppcheck version for CI bumped to 2.4 (#1771, #1836)
|
||||
* FreeBSD version for CI bumped to 12-2 (#1804)
|
||||
* Support for check unit test framework added (#1843, #1860)
|
||||
* FreeBSD FUSE module now compiles under CI but needs additional work (#1856)
|
||||
* Compilation support added for additional Debian platforms (#1818)
|
||||
* Refactoring:-
|
||||
* Confusing preprocessor macro USE_NOPAM replaced with USE_PAM (#1800)
|
||||
* Window manager states in xrdp executable now use symbolic constants instead of numbers (#1803)
|
||||
* Documentation improvements
|
||||
* KRDC added to client list (#1817)
|
||||
* Platform support tier added (#1822)
|
||||
* README file revised (#1863)
|
||||
* Don't install test+development executables by default (#1858)
|
||||
|
||||
## Changes for packagers
|
||||
These changes are likely to impact operating system package builders and those building xrdp from source.
|
||||
* (#1843, #1860) This release introduces an additional optional compile-time dependency on the `check` unit test framework. The dependency is recommended when packaging for compile-time tests.
|
||||
* (#1858) The executables `memtest` and `tcp_proxy` are no longer copied to the sbin directory on a package install.
|
||||
|
||||
## Known issues
|
||||
|
||||
* On-the-fly resolution change requires the Microsoft Store version of Remote Desktop client but sometimes crashes on connect (#1869)
|
||||
* xrdp's login dialog is not relocated at the center of the new resolution after on-the-fly resolution change happens (#1867)
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.15 (2020/12/28)
|
||||
|
||||
## New features
|
||||
* Allow token sign in without autologon for SSO (#1667 #1668)
|
||||
* Norwegian keyboard support (#1675)
|
||||
* Improved config support for chansrv (#1635)
|
||||
* Unified chansrv, sesman and libxrdp logging (#1633 #1708 #1738) - thanks to @aquesnel
|
||||
* Support SUSE move to /usr/etc (#1702)
|
||||
* Parameters may now be specified for user-specified shell (#1270 #1695)
|
||||
* xrdp executables now allow alternative config files to be specified with -c (#1588 #1650 #1651)
|
||||
* sesrun improvements (#1741)
|
||||
* Drive redirection location can now be specified (#1048)
|
||||
* Now compiles on RISC-V (#1761)
|
||||
|
||||
## Bug fixes
|
||||
* Additional buffer overflow checks (#1662)
|
||||
* FUSE support now builds on 32-bit platforms (#1682)
|
||||
* genkeymap array size conflict fixed (#1691)
|
||||
* Buffering issue with neutrinordp over a slow link fixed (#1608 1634)
|
||||
* Various documentation fixes (#1704 #1741 #1755 #1759)
|
||||
* Prevent PAM info message from causing authentication failure (#1727)
|
||||
* Cosmetic fixes for minor issues (#1751 #1755 #1749)
|
||||
* Try harder to clean up socket files on session exit (#1740 #1756)
|
||||
* xrdp-chansrv become defunct in docker while file copy (#1658)
|
||||
|
||||
## Internal changes
|
||||
* Compilation warnings with newer compilers (#1659 #1680)
|
||||
* Continuation Integration checks on 32-bit platforms now include FUSE support (#1682)
|
||||
* Continuation Integration builds now default to the Ubuntu Focal platform (#1666)
|
||||
* FUSE type tidy-ups (#1686)
|
||||
* Switch from Travis CI to GitHub Actions (#1728 #1732)
|
||||
* Easier to set up console logging for utilities (#1711)
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.14 (2020/08/31)
|
||||
|
||||
## New features
|
||||
* VNC multi-monitor support if you are using a suitable Xvnc server #1343
|
||||
* VNC sessions now resize by default on reconnection if you are using a suitable Xvnc server #1343
|
||||
* Support Slackware for PAM #1558 #1560
|
||||
* Support Programmer Dvorak Keyboard #1663
|
||||
|
||||
**[HEADS UP]** The VNC changes are significant. They described in more detail on the following wiki page.
|
||||
* [Xvnc backend : Multi monitor and resize support](https://github.com/neutrinolabs/xrdp/wiki/Xvnc-backend-:-Multi-monitor-and-resize-support)
|
||||
|
||||
## Bug fixes
|
||||
* Fix odd shift key behavior (workaround) #397 #1522
|
||||
* Fix Xorg path in the document for Arch Linux #1448 #1529
|
||||
* Fix Xorg path in the document for CentOS 8 #1646 #1647
|
||||
* Fix internal username/password buffer is smaller than RDP protocol specification #1648 #1653
|
||||
* Fix possible memory out-of-bounds accesses #1549
|
||||
* Fix memory allocation overflow #1557
|
||||
* Prevent chansrv input channels being scanned during a server reset #1595
|
||||
* Ignore TS_MULTIFRAGMENTUPDATE_CAPABILITYSET from client if fp disabled #1593
|
||||
* Minor manpage fixes #1611
|
||||
|
||||
## Other changes
|
||||
* CI error fixes
|
||||
* Introduce cppcheck
|
||||
|
||||
## Known issues
|
||||
* FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to
|
||||
xrdp's bad-mannered behaviour, add `+glyph-cache` option to FreeRDP to connect #1266
|
||||
* Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
|
||||
|
||||
# Release notes for xrdp v0.9.13.1 (2020/06/30)
|
||||
|
||||
This is a security fix release that includes fixes for the following local buffer overflow vulnerability.
|
||||
|
||||
* [CVE-2020-4044: Local users can perform a buffer overflow attack against the xrdp-sesman service and then impersonate it](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-4044)
|
||||
|
||||
This update is recommended for all xrdp users.
|
||||
|
||||
## Special thanks
|
||||
|
||||
Thanks to [Ashley Newson](https://github.com/ashleynewson) reporting the vulnerability and reviewing fix.
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.13 (2020/03/11)
|
||||
|
||||
This release is an intermediate bugfix release. The previous version v0.9.12 has some regressions on drive redirection.
|
||||
|
||||
## Bug fixes (drive redirection related)
|
||||
* Fix chansrv crashes with segmentation fault (regression in #1449) #1487
|
||||
* Drive redirection now supports Guacamole client #1505 #1507
|
||||
* Prevent a coredump in the event of a corrupted file system #1507
|
||||
* Resolve double-free in `chansrv_fuse` #1469
|
||||
|
||||
## Bug fixes (other)
|
||||
* Fix the issue `xrdp --version | less` will show empty output #1471 #1472
|
||||
* Fix some warnings found by cppcheck #1479 #1481 #1484 #1485
|
||||
|
||||
## Other changes
|
||||
* Add FreeBSD CI test #1466
|
||||
* Move Microsoft-defined constants into separate includes #1470
|
||||
* Perform cppcheck during CI test #1493
|
||||
* Support mousex button 8/9 #1478
|
||||
|
||||
## Known issues
|
||||
* FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to
|
||||
xrdp's bad-mannered behaviour, add `+glyph-cache` option to FreeRDP to connect #1266
|
||||
* Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.12 (2019/12/28)
|
||||
|
||||
## Bug fixes
|
||||
* Fix "The log reference is NULL" error when sesman startup #1425
|
||||
* Fix behavior when shmem_id changes #1439
|
||||
* Make vsock config accept -1 for cid and port #1441
|
||||
* Cleanup refresh rect and check stream bounds #1437
|
||||
* Significant improvements in drive redirection #1449
|
||||
* Fix build on macOS Catalina #1462
|
||||
|
||||
## Other changes
|
||||
* Proprietary microphone redirection via rdpsnd is now default off
|
||||
RDP compatible microphone redirection is on instead #1427
|
||||
* Skip connecting to chansrv when no channels enabled #1393
|
||||
* Add openSUSE's pam rules #1442
|
||||
* Do not terminate xrdp daemon when caught SIGHUP #1319
|
||||
|
||||
## Known issues
|
||||
* FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to
|
||||
xrdp's bad-mannered behaviour, add `+glyph-cache` option to FreeRDP to connect #1266
|
||||
* Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
|
||||
|
||||
# Release notes for xrdp v0.9.11 (2019/08/19)
|
||||
|
||||
## New features
|
||||
* Suppress output (do not draw screen when client window is minimized) #1330
|
||||
* Audio input (microphone) redirection compatible with [MS-RDPEAI](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeai/d04ffa42-5a0f-4f80-abb1-cc26f71c9452) #1369
|
||||
* Now xrdp can listen on more than one port #1124 #1366
|
||||
|
||||
## Bug fixes
|
||||
* Fix the issue audio redirection sometimes sounds with long delay #1363
|
||||
* Check term event for more responsive shutdown #1372
|
||||
|
||||
## Known issues
|
||||
* FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to
|
||||
xrdp's bad-mannered behaviour, add `+glyph-cache` option to FreeRDP to connect #1266
|
||||
* Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.11 (2019/08/19)
|
||||
|
||||
## New features
|
||||
* Suppress output (do not draw screen when client window is minimized) #1330
|
||||
* Audio input (microphone) redirection compatible with [MS-RDPEAI](https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-rdpeai/d04ffa42-5a0f-4f80-abb1-cc26f71c9452) #1369
|
||||
* Now xrdp can listen on more than one port #1124 #1366
|
||||
|
||||
## Bug fixes
|
||||
* Fix the issue audio redirection sometimes sounds with long delay #1363
|
||||
* Check term event for more responsive shutdown #1372
|
||||
|
||||
## Known issues
|
||||
* FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to
|
||||
xrdp's bad-mannered behaviour, add `+glyph-cache` option to FreeRDP to connect #1266
|
||||
* Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.10 (2019/04/18)
|
||||
|
||||
## Special thanks
|
||||
Thank you for matt335672 contributing to lots of improvements in drive redirection!
|
||||
|
||||
## New features
|
||||
* Restrict outbound (server->client) clipboard transfer, configured in `sesman.ini` #1298
|
||||
|
||||
## Bug fixes
|
||||
* Fix the issue libscp v1 not setting width but height twice #1293
|
||||
* Fix the issue reconnecting to session causes duplicate drive entries in fuse fs #1299
|
||||
* Fix default_wm and reconnect_sh refer wrong path after sesman caught SIGUP #1315 #1331
|
||||
* Shutdown xrdp more responsively #1325
|
||||
* Improve remote file lookup in drive redirection #996 #1327
|
||||
* Overwriting & appending to existing files is are now supported #1327
|
||||
|
||||
## Other changes
|
||||
* Add Danish Keyboard #1290
|
||||
* Put xrdp- prefix to some executables appear in man page #1313
|
||||
* Replace some URLs from SF.net to xrdp.org #1313
|
||||
|
||||
## Known issues
|
||||
* FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to
|
||||
xrdp's bad-mannered behaviour, add `+glyph-cache` option to FreeRDP to connect #1266
|
||||
* Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.9 (2018/12/25)
|
||||
|
||||
## Release cycle
|
||||
From the next release, release cycle will be changed from quarterly to every
|
||||
4 months. xrdp will be released in April, August, December.
|
||||
|
||||
## New features
|
||||
* Disconnection by idle timeout (requires xorgxrdp v0.2.9 or later) #1227
|
||||
* Glyph cache v2 (fixes no font issue on iOS/macOS/Android client) #367 #1235
|
||||
|
||||
## Bug fixes
|
||||
* Fix xrdp-chansrv crashes caused in drive redirection #1202 #1225
|
||||
* Fix build with FDK AAC v2 #1257
|
||||
* Do not enable RemoteApp if the INFO_RAIL flag is not set (RDP-RDP proxy) #1253
|
||||
|
||||
## Other changes
|
||||
* Add Spanish Latin Amarican keyboard #1237 #1240 #1244
|
||||
* Dynamic channel improvements #1222 #1224
|
||||
* Remove some deprecated sesman session types #1232
|
||||
* Refactoring and cleanups
|
||||
|
||||
## Known issues
|
||||
* FreeRDP 2.0.0-rc4 or later might not able to connect to xrdp due to
|
||||
xrdp's bad-mannered behaviour, add `+glyph-cache` option to FreeRDP to connect #1266
|
||||
* Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.8 (2018/09/25)
|
||||
|
||||
## Deprecation notice
|
||||
We removed TLSv1 and TLSv1.1 from the default config. The current default is TLSv1.2
|
||||
and TLSv1.3. Users can whenever re-enable these early TLS versions by editing xrdp.
|
||||
To use TLSv1.3, OpenSSL or LibreSSL must support TLSv1.3. You can know the OpenSSL
|
||||
or LibreSSL version by `xrdp --version` command that compiled with xrdp.
|
||||
|
||||
## Other topics
|
||||
|
||||
Pulseaudio modules has been removed from xrdp source tree since it is actually
|
||||
independent and not part of xrdp. The repository has been moved to:
|
||||
https://github.com/neutrinolabs/pulseaudio-module-xrdp
|
||||
|
||||
If you want to use audio redirection, make sure install the module separately.
|
||||
|
||||
## New features
|
||||
* Add TLSv1.3 support #1193
|
||||
|
||||
## Bug fixes
|
||||
* Ensure unmount redirected drive on fatal X error #1140
|
||||
|
||||
## Other changes
|
||||
* Show more helpful message if xrdp-dis failed #1206
|
||||
* Pass pulse socket name via environment variable #1198
|
||||
* Fix xrdp's log path in man page #1168
|
||||
|
||||
# Release notes for xrdp v0.9.7 (2018/06/29)
|
||||
|
||||
## Deprecation notice
|
||||
x11rdp has been removed from xrdp reposiory and stored in the separate repository.
|
||||
Checkout [x11rdp repository](https://github.com/neutrionlabs/x11rdp) if you still need x11rdp.
|
||||
In most cases, [xorgxrdp](https://github.com/neutrinolabs/xorgxrdp) can replace x11rdp.
|
||||
|
||||
## Bug fixes
|
||||
* Fix endianness detection on ppc64el #1082
|
||||
* Fix a bug xrdp file copy slow #1112 #1132
|
||||
* Copy the PAM session environment for the reconnect script #1120
|
||||
* Accept fullpath for DefaultWindowManager, ReconnectScript #1147
|
||||
|
||||
## Other changes
|
||||
* Add PAM support for Arch Linux #1078
|
||||
* Show OpenSSL version to '--version' CLI option #1096
|
||||
* Separate x11rdp from xrdp repository #1104
|
||||
* Support sesrun start xorgxrdp sessions #1108
|
||||
* Show configure summary when configure is done #1126 #1134 #1137
|
||||
* Less spit on the console when sesman starts #1142
|
||||
* Fix memory leaks #1146
|
||||
* Separate rc script for FreeBSD into xrdp and xrdp-sesman #1153
|
||||
* Improve documents and helps
|
||||
|
||||
## Known issues
|
||||
* Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.6 (2018/03/26)
|
||||
|
||||
## Compatibility notice
|
||||
Exclamation mark (`!`) has been removed from comment out symbol of config files.
|
||||
Use number sign (`#`) or semicolon (`;`) instead. As a result of this change, now
|
||||
you can use exclamation mark as config value such as in `tls_ciphers`.
|
||||
|
||||
```
|
||||
tls_ciphers=HIGH:!aNULL:!eNULL:!EXPORT:!RC4
|
||||
```
|
||||
|
||||
See also: #1033
|
||||
|
||||
## macOS supports
|
||||
Please note that xrdp still doesn't support macOS officially so far.
|
||||
However, a volunteer is working on macOS compatibility.
|
||||
|
||||
* Generate dylibs for macOS #1015
|
||||
* Add PAM support for macOS #1021
|
||||
|
||||
## Bug fixes
|
||||
* Make listen check before daemon fork #988
|
||||
* Fix xrdp sometimes become zombie processes #1000
|
||||
* Include hostname in sesman password file name #1006 #1007 #1076
|
||||
* Fix default startwm.sh to use bash explicitly #1009 #1049
|
||||
* Fix the issue FreeBSD doesn't acknowledge terminated sessions #1016 #1030
|
||||
|
||||
## Other changes
|
||||
* Add Swiss French keyboard #1053
|
||||
* Improve perfect forward secrecy, explicitly enable ECDHE/DHE #1024 #1052 #1063
|
||||
* Lots of leak fixes, cleanups and refactoring
|
||||
|
||||
## Known issues
|
||||
* Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.5 (2017/12/27)
|
||||
|
||||
## Security fixes
|
||||
* Fix local denial of service [CVE-2017-16927](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-16927) #958 #979
|
||||
None
|
||||
|
||||
## New features
|
||||
* Add a new log level TRACE more verbose than DEBUG #835 #944
|
||||
* SSH agent forwarding via RDP #867 #868 FreeRDP/FreeRDP#4122
|
||||
* Support horizontal wheel properly #928
|
||||
* If the client announces support for the RemoteFX codec it is logged (back-port of #2946)
|
||||
|
||||
## Bug fixes
|
||||
* Fix some monitor hotplug issues (#2951)
|
||||
* GFX: Fix disconnect on resize of busy windows (#2962 #2957)
|
||||
* Fall back to IPv4 if IPv6 capable but don't have an IPv6 address set (#2967 #2957)
|
||||
* Remove tcutils channel from xrdp.ini (#2970 #2957)
|
||||
|
||||
* Avoid use of hard-coded sesman port #895
|
||||
* Workaround for corrupted display with Windows Server 2008 using NeutrinoRDP #869
|
||||
* Fix glitch in audio redirection by AAC #910 #936
|
||||
* Implement vsock support #930 #935 #948
|
||||
* Avoid 100% CPU usage on SSL accept #956
|
||||
|
||||
## Other changes
|
||||
* Add US Dvorak keyboard #929
|
||||
* Suppress some misleading logs #964
|
||||
* Add Finnish keyboard #972
|
||||
* Add more user-friendlier description about Xorg config #974
|
||||
* Renew pulseaudio document #984 #985
|
||||
* Lots of cleanups and refactoring
|
||||
## Internal changes
|
||||
* Adjust log level not too verbose (#2954 #2972 #2957)
|
||||
* Migrate GitHub actions to Node 20 (#2955 #2957)
|
||||
* Bump copyright year and make easier to bump (#2956 #2957)
|
||||
* Remove duplicate DEBUG output (#2976 #2977)
|
||||
* Add script to make release tarball (#2983)
|
||||
|
||||
## Known issues
|
||||
* Audio redirection by MP3 codec doesn't sound with some client, use AAC instead #965
|
||||
* On-the-fly resolution change with the Microsoft Store version of Remote Desktop client sometimes crashes on connect (#1869)
|
||||
* xrdp's login dialog is not relocated at the center of the new resolution after on-the-fly resolution change happens (#1867)
|
||||
|
||||
## Changes for packagers or developers
|
||||
* If moving from v0.9.x, read the '[Significant changes for packagers or developers section](#significant-changes-for-packagers-or-developers)' for the v0.10 branch below.
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.4 (2017/09/28)
|
||||
# Branch v0.10
|
||||
|
||||
This branch was forked from development on 2024-02-08 in preparation for testing and release of v0.10.1.
|
||||
|
||||
The changes in this section are relative to version v0.9.19 of xrdp.
|
||||
|
||||
## General announcements
|
||||
* The [x11rdp](/neutrinolabs/x11rdp) X server is no longer supported. Users will need to move to xorgxrdp (#2489)
|
||||
* Running xrdp and xrdp-sesman on separate hosts is no longer supported.
|
||||
* There are some changes to `xrdp.ini` and `sesman.ini` which break backwards compatibility. In particular:-
|
||||
* `sesman.ini/Globals/ListenAddress` is not longer used. A warning message is generated if this is found in the configuration, but the configuration will continue to work.
|
||||
* `sesman.ini/Globals/ListenPort` is now a path to a socket, or an unqualified socket in a default directory. If the old default value `3350` is found, a warning is generated and a default value is used instead. The configuration will continue to work.
|
||||
* The `ip` and `pamsessionmng` parameters are no longer required in sections in `xrdp.ini` to locate the sesman port. Unnecessary usages of this parameter now generate warnings. The configuration will continue to work.
|
||||
* The 'C' field for the session allocation policy has been replaced with `Policy=Separate`. This field is has a very specific specialist purpose, and will not be used by the vast majority of users. The renaming makes it much clearer what is happening (#2251 #2239). Any uses of the 'C' field will generate warnings, **and the configuration will require updating**
|
||||
* The format of the date and time in the log file has been changed to ISO 8601 with milliseconds (#2386 #2541)
|
||||
|
||||
Users are urged to heed any generated configuration warnings and update their configurations. Later major versions of xrdp may remove these warnings, or introduce other behaviours for the affected parameters.
|
||||
|
||||
## Security fixes
|
||||
|
||||
This branch provides following important security fixes reported by [Team BT5 (BoB 11th)](https://github.com/Team-BT5). We appreciate their great help with making and reviewing patches for them.
|
||||
|
||||
* [CVE-2022-23468](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23468)
|
||||
* [CVE-2022-23477](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23477)
|
||||
* [CVE-2022-23478](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23478)
|
||||
* [CVE-2022-23479](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23479)
|
||||
* [CVE-2022-23480](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23480)
|
||||
* [CVE-2022-23481](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23481)
|
||||
* [CVE-2022-23483](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23483)
|
||||
* [CVE-2022-23482](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23482)
|
||||
* [CVE-2022-23484](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23484)
|
||||
* [CVE-2022-23493](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23493)
|
||||
|
||||
The following issue was reported by [@gafusss](https://github.com/gafusss)
|
||||
* [CVE-2023-40184](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-40184)
|
||||
|
||||
Other security fixes:-
|
||||
* [CVE-2023-42822: Unchecked access to font glyph info](https://www.cve.org/CVERecord?id=CVE-2023-42822)
|
||||
|
||||
## New features
|
||||
* Accept prefill credentials in base64 form #153 #811
|
||||
* Indroduce AAC encoder to audio redirection (requires Windows 10 client)
|
||||
* Added GFX support with multi-monitor support (including monitor hot plug/unplug) (#2256 #2338 #2595 #2879 #2891 #2911 #2929 #2933)
|
||||
* Add Ulalaca that enables remote access to macOS's native screen (developed by [team unstablers](https://unstabler.pl/))
|
||||
* Ulalaca is still heavy in development, not suitable for production use yet
|
||||
* `sessionbroker` and `sessionprojector` are also required, see also [README](https://github.com/unstabler/ulalaca)
|
||||
* Scaled login screen on higher DPI monitors (#2341, #2427, #2435)
|
||||
* This feature works automatically when monitor DPI information is sent by the client (i.e. a full-screen session)
|
||||
* Native platform tools are now provided to manipulate .fv1 format font files.
|
||||
* Touchpad inertial scrolling (#2364, #2424). Thanks to new contributor @seflerZ
|
||||
* New look of login screen (#2366)
|
||||
* Record codec GUID to identify unknown codc (#2401)
|
||||
* OpenSuSE Tumbleweed move to /usr/lib/pam.d is now supported in the installation scripts (#2413)
|
||||
* xrdp-sesman now supports a `--reload` switch to allow for the configuration to be changed when sessions are active (#2416)
|
||||
* VNC backend session now supports extra mouse buttons 6, 7 and 8 (#2426)
|
||||
* `LogFile=<stdout>` redirects log to stdout, which is useful for debugging (#2407)
|
||||
* xrdp-sesrun and xrdp-sesadmin can now authenticate automatically as the logged-in user without a password (#2472)
|
||||
* Empty passwords are no longer automatically passed though to sesman for authentication (#2487)
|
||||
* BSD setusercontext() is now supported (#2225, #2473)
|
||||
* The FUSE mount path can now be qualified with the display name or display string (#2528)
|
||||
* Debian: use startup command from /usr/share/xsession if DISPLAY_SESSION is set (#2522)
|
||||
* The directory where PAM configuration files is installed can now be set with `--with-pamconfdir` (#2552 #2557)
|
||||
* Some classes of 'blue screen' failures have been addressed:-
|
||||
* X server failures are now reported as a separate error from window manager (#2592)
|
||||
* sesman failures are reported immediately (#2640)
|
||||
* Allow longer UserWindowManager strings (#2651)
|
||||
* Some changes have been made to made it easier to implement AppArmor support in the future (#2265):-
|
||||
* `g_file_open()` has been replaced with `g_file_open_ro()` and `g_file_open_rw()` calls
|
||||
* the starting of the X server with no-new-privileges can now be disabled by the administrator
|
||||
* On systemd-based systems, system call filtering is used to restrict the system calls that the xrdp process can make (#2697 #2719)
|
||||
* GNOME and KDE keyrings should now be supported out-of-the-box on Debian and Arch (#2776)
|
||||
* Implement vsock support for FreeBSD #2798
|
||||
* Side buttons on some mice are now supported by NeutrinoRDP (#2864). Thanks to new contributor @naruhito for this patch.
|
||||
* Support for the Elbrus E2K architecture (#2872). Thanks to new contributor @r-a-sattarov for this patch.
|
||||
* Just log Image RemoteFX codec (#2946)
|
||||
|
||||
## Bugfixes
|
||||
* Fix ocasional SEGV in drive redirection #838
|
||||
* Fix client's IP addresses in xrdp-sesman.log are always logged as `0.0.0.0` #878 #882
|
||||
* Fix `ls_background_image` didn't accept full path #776 #853
|
||||
* Fix misuse of hidelogwindow #414 #876
|
||||
* Fix WTSVirtualChannelWrite return code #859
|
||||
* Fix no longer needed socket files remained in the socket dir #812 #831
|
||||
* Make creating socket path a bit more robust #823
|
||||
## Bug fixes
|
||||
* A missing directive to link libxrdpapi with libcommon has been added (#2185)
|
||||
* Some sesman config warning messages could be lost. This has now been fixed (#2198)
|
||||
* Moving sesman to a Unix domain socket fixes a number of issues related to firewalls and Ipv4/v6 connectivity issues (#1596 #1805 #1855)
|
||||
* Secondary groups are now added correctly on Linux from /etc/security/group.conf (#1978).
|
||||
* The `--disable-static` switch for `configure` now works (#1467 #2257)
|
||||
* Windows RDS compatibility has been improved, so some old clients (e.g. Wyse Sx0) can now be used again with xrdp in non-TLS mode (#2166)
|
||||
* PAM_RHOST is now set for the PAM stack (#2251, #392)
|
||||
* A minor spacing issue in a sesman log message has been fixed (#2282)
|
||||
* MSTSC crashes when resolution is changed by maximizing on a different monitor (#2291 #2300)
|
||||
* Fix swapped `require_credentials`/`enable_token_login` config options in xrdp.ini manpage (#2391)
|
||||
* Passwords are no longer left on the heap in sesman (#1599 #2438)
|
||||
* Set permissions on pcsc socket dir to owner only (#2454 #2459)
|
||||
* The Kerberos authentication module has been reworked and tested (#2453)
|
||||
* Minor documentation fixes (#2481 #2581)
|
||||
* The correct message is now generated when the session limit is reached (#642)
|
||||
* sesman now returns better information to xrdp when session creation fails (#909, #1921)
|
||||
* MaxLoginRetry limit for sesman now works (#1739)
|
||||
* On systems where the same user can have multiple names, the correct session is now reconnected (#1823)
|
||||
* On FreeBSD, the correct peer is now logged for xorgxrdp connections (#146)
|
||||
* In some situations, xrdp sessions can be bootstrapped on system startup (#1303)
|
||||
* Don't try to listen on the scard socket if it isn't there (#2504)
|
||||
* Fix some noise of MP3/AAC audio redirection and add some parameters to tweak sounds (#2519 #2608)
|
||||
* Memory management fixes to list module (#2536 #2575)
|
||||
* Session is not now started until X server is fully active (#2492)
|
||||
* Fix potential NULL dereferences in chansrv (#2573)
|
||||
* An erroneous free in the smartcard handling code has been removed (#2607)
|
||||
* An unnecessary 'check.h' include was removed which prevented compilation on Arch systems (#2649)
|
||||
* No user session created with xrdp and pam_systemd_home account module (#1684)
|
||||
* Homedir gets not correctly created at first login (#350)
|
||||
* pam_setcred never returns xrdp-sesman is hung (#1323)
|
||||
* chansrv should no longer hang occasionally in developer builds on session exit (#2145)
|
||||
* Environment variables set by PAM modules are no longer restricted to around 250 characters (#2711)
|
||||
* Checking group membership should now work better on systems using directory services (#2806 #2815)
|
||||
* Pasting more than 32K characters of text to the clipboard now succeeds (#1839 #2810)
|
||||
* An incompatibility with FreeRDP 2.11.2 in the drive redirector has been fixed (#2834 #2838)
|
||||
* Unicode bugs have been fixed (#942 #2603)
|
||||
|
||||
## Other changes
|
||||
* Add Belgian keyboard #858
|
||||
* Add a PAM file for FreeBSD #824
|
||||
* Several refactorings and cosmetic changes
|
||||
## Internal changes
|
||||
* SCP (Sesman Control Protocol) has been refactored from separate V0 and V1 protocols to a simplified V2 protocol running on top of a new library 'libipm' (#2163).
|
||||
* libipm provides a way to pass file descriptors between processes (#2494)
|
||||
* SCP connections are now only supported on top of Unix Domain Sockets (#2207 #2235 #2247)
|
||||
* Monitor processing logic, which was in two places, has now been unified (#1895 #2301)
|
||||
* Simplifications to transport connect logic (#2204)
|
||||
* The fields in `struct trans` and `struct xrdp_client_info` used for storing client addressing information have been simplified (#2251)
|
||||
* A couple of string utility functions have been added to parse character strings like the one used for the session allocation policy (#2251)
|
||||
* cppcheck version used for CI bumped to 2.13.0 (#2520 #2737 #2785 #2886). Note that #2785 greatly increases cppcheck scan times.
|
||||
* cppcheck install script no longer installs z3 for cppcheck >= 2.8 (#2782)
|
||||
* The physical desktop size information sent from the client is now recorded in more situations (#2310)
|
||||
* Simple maintenance improvements (#2354)
|
||||
* An opaque type is now used for the auth_info handle used by the sesman auth module (#2362)
|
||||
* CI updates to cope with github upgrades (#2394)
|
||||
* GUIDs created for new sessions are now compliant with RFC4122 random UUIDs (#2420)
|
||||
* Some 'magic numbers' have been replaced with constants (#2421)
|
||||
* FreeBSD CI now runs a 'make check' (#2490)
|
||||
* FreeBSD CI now runs on FreeBSD 13.2 (#2621 #2896)
|
||||
* Some logging improvements on audio redirection (#2537)
|
||||
* Extra executables : waitforx (#2492 #2591 #2586) xrdp-sesexec (#2644)
|
||||
* The poll() system call now replaces select() for monitoring file descriptors (#2497 #2568)
|
||||
* sigaction() now replaces signal() for increased portability (#2813)
|
||||
* Other portability changes (#2909)
|
||||
* Some extra convenience functions were added for handling lists of strings (#2576)
|
||||
* `g_malloc`, `g_free`, `g_memset`, `g_memcpy`, and `g_memmove` are now macros. These should not be used in new code (#2609)
|
||||
* config_ac.h is now used consistently (#2667)
|
||||
* as mentioned above, `g_file_open()` has been replaced with `g_file_open_ro()` and `g_file_open_rw()` calls
|
||||
* The separate fifo packages in the common directory and chansrv have now been merged (#2686)
|
||||
* Unicode conversions are now provided by explicit functions rather than relying on C library `mbstowcs()`/`wcstombs()` functions (#2794)
|
||||
* Some test timeouts have been increased for slow CI machines (#2901)
|
||||
* `g_obj_wait()` can now take a zero timeout (#2904)
|
||||
* POSIX shared memory is now used to communicate with `xorgxrdp` rather than System-V shared memory (#2709 #2786 #2889)
|
||||
|
||||
## Known issues
|
||||
* Windows 10 (1703) shows black blank screen in RemoteFX mode
|
||||
* This issue is already fixed at Insider Preview build 16273
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.3.1 (2017/08/16)
|
||||
|
||||
This release fixes a trivial packaging issue #848 occurred in v0.9.3. The issue only affects systemd systems. This release is principally for distro packagers or users who compile & install xrdp from source.
|
||||
|
||||
Users who running xrdp on these systems don't need to upgrade from v0.9.3 to v0.9.3.1.
|
||||
|
||||
* Linux systems without systemd
|
||||
* non-Linux systems such as BSD operating systems
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.3 (2017/07/15)
|
||||
|
||||
## New features
|
||||
* Log user-friendly messages when certificate/privkey is inaccessible
|
||||
|
||||
## Bugfixes
|
||||
* Now sesman sets mandatory LOGNAME environment variable #725
|
||||
* Now sesman ensures socket directory present #801
|
||||
* Exit with failure status if port already in use #644
|
||||
* Eliminate some hard coded paths
|
||||
* Fix glitches with IPv4 struct initialization #803
|
||||
* Fix some keyboard layout integration (UK, Spanish)
|
||||
* Fix handle OS when IPv6 disabled #714
|
||||
* Fix issues around systemd session #778
|
||||
* Fix protocol error when 32 bit color and non RemoteFX session #737 #804
|
||||
* Fix sesadmin shows error when no sessions #797
|
||||
* Fix TLS spins 100% CPU #728
|
||||
* Fix Xvnc backend disconnects when some data copied to clipboard #755
|
||||
* Pick up the first section if given section(domain) doesn't match anything #750
|
||||
|
||||
## Other changes
|
||||
* Change xrdp-chansrv log path to include display number
|
||||
* Optimize startwm.sh for SUSE
|
||||
* Several cleanups and optimizations
|
||||
|
||||
## Known issues
|
||||
* Windows 10 (1703) shows black blank screen in RemoteFX mode
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.2 (2017/03/30)
|
||||
## New features
|
||||
* RemoteFX codec support is now enabled by default.
|
||||
* Bitmap updates support is now enabled by default.
|
||||
* TLS ciphers suites and version is now logged.
|
||||
* Connected computer name is now logged.
|
||||
* Switched to Xorg (xorgxrdp) as the default backend now.
|
||||
* Miscellaneous RemoteFX codec mode improvements.
|
||||
* Socket directory is configurable at the compile time.
|
||||
|
||||
## Bugfixes
|
||||
* Parallels client for MacOS / iOS can now connect (audio redirection must be disabled on client or xrdp server though).
|
||||
* MS RDP client for iOS can now connect using TLS security layer.
|
||||
* MS RDP client for Android can now connect to xrdp.
|
||||
* Large resolutions (4K) can be used with RemoteFX graphics.
|
||||
* Multiple RemoteApps can be opened throguh NeutrinoRDP proxy.
|
||||
* tls_ciphers in xrdp.ini is not limited to 63 chars anymore, it's variable-length.
|
||||
* Fixed an issue where tls_ciphers were ignored and rdp security layer could be used instead.
|
||||
* Kill disconnected sessions feature is working with Xorg (xorgxrdp) backend.
|
||||
* Miscellaneous code cleanup and memory issues fixes.
|
||||
|
||||
-----------------------
|
||||
|
||||
# Release notes for xrdp v0.9.1 (2016/12/21)
|
||||
## New features
|
||||
* New xorgxrdp backend using existing Xorg with additional modules
|
||||
* Improvements to X11rdp backend
|
||||
* Support for IPv6 (disabled by default)
|
||||
* Initial support for RemoteFX Codec (disabled by default)
|
||||
* Support for TLS security layer (preferred over RDP layer if supported by the client)
|
||||
* Support for disabling deprecated SSLv3 protocol and for selecting custom cipher suites in xrdp.ini
|
||||
* Support for bidirectional fastpath (enabled in both directions by default)
|
||||
* Support clients that don't support drawing orders, such as MS RDP client for Android, ChromeRDP (disabled by default)
|
||||
* More configurable login screen
|
||||
* Support for new virtual channels:
|
||||
* rdpdr: device redirection
|
||||
* rdpsnd: audio output
|
||||
* cliprdr: clipboard
|
||||
* xrdpvr: xrdp video redirection channel (can be used along with NeutrinoRDP client)
|
||||
* Support for disabling virtual channels globally or by session type
|
||||
* Allow to specify the path for backends (Xorg, X11rdp, Xvnc)
|
||||
* Added files for systemd support
|
||||
* Multi-monitor support
|
||||
* xrdp-chansrv stroes logs in `${XDG_DATA_HOME}/xrdp` now
|
||||
|
||||
## Security fixes
|
||||
* User's password could be recovered from the Xvnc password file
|
||||
* X11 authentication was not used
|
||||
## Significant changes for packagers or developers
|
||||
* The libscp.so shared library is replaced with libipm.so
|
||||
* A new shared library libsesman.so contains shared code for sesman and related executables (#2601)
|
||||
* The default setting for `--with-socketdir` is now `/var/run/xrdp` rather than `/tmp/.xrdp`. The new setting works for installations where `/tmp` is polyinstantiated ( see #1482 for more details)
|
||||
* The layout of the socketdir has changed to remove the use of the sticky bit and allow the sesman socket to be stored in it. UNIX socket files used by users are now stored in a per-UID directory (#2731)
|
||||
* Passing `--disable-static` to `configure` prevents unused static libraries being installed by `make install`.
|
||||
* The `simple.c` example xrdpapi program has been updated to work with logging changes, and is now built as part of the CI (#2276)
|
||||
* If the `xrdp-mkfv1` utility is to be built, the switch `--with-freetype2` must be passed to `./configure`.
|
||||
* Minimum supported autoconf version is now 2.69 (#2408)
|
||||
* Add xrdp-sesman.system to distributed files (#2466 #2467)
|
||||
* A developer-only utility to exercise the auth module selected at configure time has been provided (#2453)
|
||||
* Extra executables have been added to this release in pkglibexecdir
|
||||
* The default systemd unit files have been changed to no longer fork (#2672)
|
||||
@ -74,6 +74,7 @@
|
||||
|
||||
/* Client Core Data: earlyCapabilityFlags (2.2.1.3.2) */
|
||||
#define RNS_UD_CS_WANT_32BPP_SESSION 0x0002
|
||||
#define RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU 0x0040
|
||||
#define RNS_UD_CS_SUPPORT_DYNVC_GFX_PROTOCOL 0x0100
|
||||
|
||||
/* Client Core Data: connectionType (2.2.1.3.2) */
|
||||
@ -448,6 +449,7 @@
|
||||
#define RDP_DATA_PDU_LOGON 38
|
||||
#define RDP_DATA_PDU_FONT2 39
|
||||
#define RDP_DATA_PDU_DISCONNECT 47
|
||||
#define PDUTYPE2_MONITOR_LAYOUT_PDU 55
|
||||
|
||||
/* TS_SECURITY_HEADER: flags (2.2.8.1.1.2.1) */
|
||||
/* TODO: to be renamed */
|
||||
|
||||
@ -378,6 +378,7 @@ g_tcp_socket(void)
|
||||
{
|
||||
switch (errno)
|
||||
{
|
||||
case EPROTONOSUPPORT: /* if IPv6 is supported, but don't have an IPv6 address */
|
||||
case EAFNOSUPPORT: /* if IPv6 not supported, retry IPv4 */
|
||||
LOG(LOG_LEVEL_INFO, "IPv6 not supported, falling back to IPv4");
|
||||
rv = (int)socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
@ -67,6 +67,13 @@ struct display_size_description
|
||||
unsigned int session_height;
|
||||
};
|
||||
|
||||
enum client_resize_mode
|
||||
{
|
||||
CRMODE_NONE,
|
||||
CRMODE_SINGLE_SCREEN,
|
||||
CRMODE_MULTI_SCREEN
|
||||
};
|
||||
|
||||
/**
|
||||
* Information about the xrdp client
|
||||
*
|
||||
@ -218,6 +225,9 @@ struct xrdp_client_info
|
||||
|
||||
int large_pointer_support_flags;
|
||||
int gfx;
|
||||
|
||||
// Can we resize the desktop by using a Deactivation-Reactivation Sequence?
|
||||
enum client_resize_mode client_resize_mode;
|
||||
};
|
||||
|
||||
enum xrdp_encoder_flags
|
||||
|
||||
@ -1,7 +1,8 @@
|
||||
# Process this file with autoconf to produce a configure script
|
||||
|
||||
AC_PREREQ([2.69])
|
||||
AC_INIT([xrdp], [0.9.80], [xrdp-devel@googlegroups.com])
|
||||
AC_INIT([xrdp], [0.10.0-beta.2], [xrdp-devel@googlegroups.com])
|
||||
AC_DEFINE([VERSION_YEAR], 2024, [Copyright year])
|
||||
AC_CONFIG_HEADERS(config_ac.h:config_ac-h.in)
|
||||
AM_INIT_AUTOMAKE([1.7.2 foreign])
|
||||
AC_CONFIG_MACRO_DIR([m4])
|
||||
|
||||
@ -1136,43 +1136,10 @@ libxrdp_orders_send_font(struct xrdp_session *session,
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Note : if this is called on a multimon setup, the client is resized
|
||||
* to a single monitor */
|
||||
int EXPORT_CC
|
||||
libxrdp_reset(struct xrdp_session *session,
|
||||
unsigned int width, unsigned int height, int bpp)
|
||||
libxrdp_reset(struct xrdp_session *session)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_reset:");
|
||||
if (session->client_info != 0)
|
||||
{
|
||||
struct xrdp_client_info *client_info = session->client_info;
|
||||
|
||||
/* older client can't resize */
|
||||
if (client_info->build <= 419)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if same (and only one monitor on client) don't need to do anything */
|
||||
if (client_info->display_sizes.session_width == width &&
|
||||
client_info->display_sizes.session_height == height &&
|
||||
client_info->bpp == bpp &&
|
||||
(client_info->display_sizes.monitorCount == 0 || client_info->multimon == 0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
client_info->display_sizes.session_width = width;
|
||||
client_info->display_sizes.session_height = height;
|
||||
client_info->display_sizes.monitorCount = 0;
|
||||
client_info->bpp = bpp;
|
||||
client_info->multimon = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_reset: session->client_info is NULL");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* this will send any lingering orders */
|
||||
if (xrdp_orders_reset((struct xrdp_orders *)session->orders) != 0)
|
||||
@ -1439,6 +1406,23 @@ libxrdp_disable_channel(struct xrdp_session *session, int channel_id,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
libxrdp_drdynvc_start(struct xrdp_session *session)
|
||||
{
|
||||
struct xrdp_rdp *rdp;
|
||||
struct xrdp_sec *sec;
|
||||
struct xrdp_channel *chan;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_drdynvc_start:");
|
||||
|
||||
rdp = (struct xrdp_rdp *) (session->rdp);
|
||||
sec = rdp->sec_layer;
|
||||
chan = sec->chan_layer;
|
||||
return xrdp_channel_drdynvc_start(chan);
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
libxrdp_drdynvc_open(struct xrdp_session *session, const char *name,
|
||||
@ -1801,6 +1785,19 @@ libxrdp_send_session_info(struct xrdp_session *session, const char *data,
|
||||
static void
|
||||
sanitise_extended_monitor_attributes(struct monitor_info *monitor_layout)
|
||||
{
|
||||
if (monitor_layout->physical_width == 0
|
||||
&& monitor_layout->physical_width == 0
|
||||
&& monitor_layout->orientation == 0
|
||||
&& monitor_layout->desktop_scale_factor == 0
|
||||
&& monitor_layout->device_scale_factor == 0)
|
||||
{
|
||||
/* Module expects us to provide defaults */
|
||||
monitor_layout->orientation = ORIENTATION_LANDSCAPE;
|
||||
monitor_layout->desktop_scale_factor = 100;
|
||||
monitor_layout->device_scale_factor = 100;
|
||||
return;
|
||||
}
|
||||
|
||||
/* if EITHER physical_width or physical_height are
|
||||
* out of range, BOTH must be ignored.
|
||||
*/
|
||||
@ -1891,16 +1888,16 @@ libxrdp_process_monitor_stream(struct stream *s,
|
||||
{
|
||||
uint32_t num_monitor;
|
||||
uint32_t monitor_index;
|
||||
struct monitor_info monitors[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS];
|
||||
struct monitor_info *monitor_layout;
|
||||
struct xrdp_rect all_monitors_encompassing_bounds = {0};
|
||||
int got_primary = 0;
|
||||
int monitor_struct_stream_check_bytes;
|
||||
const char *monitor_struct_stream_check_message;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "libxrdp_process_monitor_stream:");
|
||||
if (description == NULL)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR, "libxrdp_process_monitor_stream: description was"
|
||||
LOG_DEVEL(LOG_LEVEL_ERROR,
|
||||
"libxrdp_process_monitor_stream: description was"
|
||||
" null. Valid pointer to allocated description expected.");
|
||||
return SEC_PROCESS_MONITORS_ERR;
|
||||
}
|
||||
@ -1948,7 +1945,7 @@ libxrdp_process_monitor_stream(struct stream *s,
|
||||
" from [MS-RDPEDISP] 2.2.2.2.1 DISPLAYCONTROL_MONITOR_LAYOUT.";
|
||||
}
|
||||
|
||||
description->monitorCount = num_monitor;
|
||||
memset(monitors, 0, sizeof(monitors[0]) * num_monitor);
|
||||
|
||||
for (monitor_index = 0; monitor_index < num_monitor; ++monitor_index)
|
||||
{
|
||||
@ -1960,7 +1957,8 @@ libxrdp_process_monitor_stream(struct stream *s,
|
||||
return SEC_PROCESS_MONITORS_ERR;
|
||||
}
|
||||
|
||||
monitor_layout = description->minfo + monitor_index;
|
||||
monitor_layout = &monitors[monitor_index];
|
||||
|
||||
if (full_parameters != 0)
|
||||
{
|
||||
in_uint32_le(s, monitor_layout->flags);
|
||||
@ -2026,8 +2024,6 @@ libxrdp_process_monitor_stream(struct stream *s,
|
||||
in_uint32_le(s, monitor_layout->desktop_scale_factor);
|
||||
in_uint32_le(s, monitor_layout->device_scale_factor);
|
||||
|
||||
sanitise_extended_monitor_attributes(monitor_layout);
|
||||
|
||||
/*
|
||||
* 2.2.2.2.1 DISPLAYCONTROL_MONITOR_LAYOUT
|
||||
*/
|
||||
@ -2056,130 +2052,10 @@ libxrdp_process_monitor_stream(struct stream *s,
|
||||
monitor_layout->is_primary = TS_MONITOR_PRIMARY;
|
||||
}
|
||||
}
|
||||
|
||||
if (monitor_index == 0)
|
||||
{
|
||||
all_monitors_encompassing_bounds.left = monitor_layout->left;
|
||||
all_monitors_encompassing_bounds.top = monitor_layout->top;
|
||||
all_monitors_encompassing_bounds.right = monitor_layout->right;
|
||||
all_monitors_encompassing_bounds.bottom = monitor_layout->bottom;
|
||||
}
|
||||
else
|
||||
{
|
||||
all_monitors_encompassing_bounds.left =
|
||||
MIN(monitor_layout->left,
|
||||
all_monitors_encompassing_bounds.left);
|
||||
all_monitors_encompassing_bounds.top =
|
||||
MIN(monitor_layout->top,
|
||||
all_monitors_encompassing_bounds.top);
|
||||
all_monitors_encompassing_bounds.right =
|
||||
MAX(all_monitors_encompassing_bounds.right,
|
||||
monitor_layout->right);
|
||||
all_monitors_encompassing_bounds.bottom =
|
||||
MAX(all_monitors_encompassing_bounds.bottom,
|
||||
monitor_layout->bottom);
|
||||
}
|
||||
|
||||
if (monitor_layout->is_primary == TS_MONITOR_PRIMARY)
|
||||
{
|
||||
got_primary = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (!got_primary)
|
||||
{
|
||||
/* no primary monitor was set,
|
||||
* choose the leftmost monitor as primary.
|
||||
*/
|
||||
for (monitor_index = 0; monitor_index < num_monitor; ++monitor_index)
|
||||
{
|
||||
monitor_layout = description->minfo + monitor_index;
|
||||
if (monitor_layout->left
|
||||
== all_monitors_encompassing_bounds.left
|
||||
&& monitor_layout->top
|
||||
== all_monitors_encompassing_bounds.top)
|
||||
{
|
||||
monitor_layout->is_primary = TS_MONITOR_PRIMARY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set wm geometry if the encompassing area is well formed.
|
||||
Otherwise, log and return an error.
|
||||
*/
|
||||
if (all_monitors_encompassing_bounds.right
|
||||
> all_monitors_encompassing_bounds.left
|
||||
&& all_monitors_encompassing_bounds.bottom
|
||||
> all_monitors_encompassing_bounds.top)
|
||||
{
|
||||
description->session_width =
|
||||
all_monitors_encompassing_bounds.right
|
||||
- all_monitors_encompassing_bounds.left + 1;
|
||||
description->session_height =
|
||||
all_monitors_encompassing_bounds.bottom
|
||||
- all_monitors_encompassing_bounds.top + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_process_monitor_stream:"
|
||||
" The area encompassing the monitors is not a"
|
||||
" well-formed rectangle. Received"
|
||||
" (top: %d, left: %d, right: %d, bottom: %d)."
|
||||
" This will prevent initialization.",
|
||||
all_monitors_encompassing_bounds.top,
|
||||
all_monitors_encompassing_bounds.left,
|
||||
all_monitors_encompassing_bounds.right,
|
||||
all_monitors_encompassing_bounds.bottom);
|
||||
return SEC_PROCESS_MONITORS_ERR_INVALID_DESKTOP;
|
||||
}
|
||||
|
||||
/* Make sure virtual desktop size is OK
|
||||
* 2.2.1.3.6 Client Monitor Data (TS_UD_CS_MONITOR)
|
||||
*/
|
||||
if (description->session_width
|
||||
> CLIENT_MONITOR_DATA_MAXIMUM_VIRTUAL_DESKTOP_WIDTH
|
||||
|| description->session_width
|
||||
< CLIENT_MONITOR_DATA_MINIMUM_VIRTUAL_DESKTOP_WIDTH
|
||||
|| description->session_height
|
||||
> CLIENT_MONITOR_DATA_MAXIMUM_VIRTUAL_DESKTOP_HEIGHT
|
||||
|| description->session_height
|
||||
< CLIENT_MONITOR_DATA_MINIMUM_VIRTUAL_DESKTOP_HEIGHT)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"libxrdp_process_monitor_stream: Client supplied virtual"
|
||||
" desktop width or height is invalid."
|
||||
" Allowed width range: min %d, max %d. Width received: %d."
|
||||
" Allowed height range: min %d, max %d. Height received: %d",
|
||||
CLIENT_MONITOR_DATA_MINIMUM_VIRTUAL_DESKTOP_WIDTH,
|
||||
CLIENT_MONITOR_DATA_MAXIMUM_VIRTUAL_DESKTOP_WIDTH,
|
||||
description->session_width,
|
||||
CLIENT_MONITOR_DATA_MINIMUM_VIRTUAL_DESKTOP_HEIGHT,
|
||||
CLIENT_MONITOR_DATA_MAXIMUM_VIRTUAL_DESKTOP_HEIGHT,
|
||||
description->session_width);
|
||||
return SEC_PROCESS_MONITORS_ERR_INVALID_DESKTOP;
|
||||
}
|
||||
|
||||
/* keep a copy of non negative monitor info values for xrdp_wm usage */
|
||||
for (monitor_index = 0; monitor_index < num_monitor; ++monitor_index)
|
||||
{
|
||||
monitor_layout = description->minfo_wm + monitor_index;
|
||||
|
||||
g_memcpy(monitor_layout,
|
||||
description->minfo + monitor_index,
|
||||
sizeof(struct monitor_info));
|
||||
|
||||
monitor_layout->left =
|
||||
monitor_layout->left - all_monitors_encompassing_bounds.left;
|
||||
monitor_layout->top =
|
||||
monitor_layout->top - all_monitors_encompassing_bounds.top;
|
||||
monitor_layout->right =
|
||||
monitor_layout->right - all_monitors_encompassing_bounds.left;
|
||||
monitor_layout->bottom =
|
||||
monitor_layout->bottom - all_monitors_encompassing_bounds.top;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return libxrdp_init_display_size_description(
|
||||
num_monitor, monitors, description);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -2283,6 +2159,163 @@ libxrdp_process_monitor_ex_stream(struct stream *s,
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
libxrdp_init_display_size_description(
|
||||
unsigned int num_monitor,
|
||||
const struct monitor_info *monitors,
|
||||
struct display_size_description *description)
|
||||
{
|
||||
unsigned int monitor_index;
|
||||
struct monitor_info *monitor_layout;
|
||||
struct xrdp_rect all_monitors_encompassing_bounds = {0};
|
||||
int got_primary = 0;
|
||||
|
||||
/* Caller should have checked this, so don't log an error */
|
||||
if (num_monitor > CLIENT_MONITOR_DATA_MAXIMUM_MONITORS)
|
||||
{
|
||||
return SEC_PROCESS_MONITORS_ERR_TOO_MANY_MONITORS;
|
||||
}
|
||||
|
||||
description->monitorCount = num_monitor;
|
||||
for (monitor_index = 0 ; monitor_index < num_monitor; ++monitor_index)
|
||||
{
|
||||
monitor_layout = &description->minfo[monitor_index];
|
||||
*monitor_layout = monitors[monitor_index];
|
||||
sanitise_extended_monitor_attributes(monitor_layout);
|
||||
|
||||
if (monitor_index == 0)
|
||||
{
|
||||
all_monitors_encompassing_bounds.left = monitor_layout->left;
|
||||
all_monitors_encompassing_bounds.top = monitor_layout->top;
|
||||
all_monitors_encompassing_bounds.right = monitor_layout->right;
|
||||
all_monitors_encompassing_bounds.bottom = monitor_layout->bottom;
|
||||
}
|
||||
else
|
||||
{
|
||||
all_monitors_encompassing_bounds.left =
|
||||
MIN(monitor_layout->left,
|
||||
all_monitors_encompassing_bounds.left);
|
||||
all_monitors_encompassing_bounds.top =
|
||||
MIN(monitor_layout->top,
|
||||
all_monitors_encompassing_bounds.top);
|
||||
all_monitors_encompassing_bounds.right =
|
||||
MAX(all_monitors_encompassing_bounds.right,
|
||||
monitor_layout->right);
|
||||
all_monitors_encompassing_bounds.bottom =
|
||||
MAX(all_monitors_encompassing_bounds.bottom,
|
||||
monitor_layout->bottom);
|
||||
}
|
||||
|
||||
if (monitor_layout->is_primary == TS_MONITOR_PRIMARY)
|
||||
{
|
||||
if (got_primary)
|
||||
{
|
||||
// Already got one - don't have two
|
||||
monitor_layout->is_primary = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
got_primary = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!got_primary)
|
||||
{
|
||||
/* no primary monitor was set,
|
||||
* choose the leftmost monitor as primary.
|
||||
*/
|
||||
for (monitor_index = 0; monitor_index < num_monitor; ++monitor_index)
|
||||
{
|
||||
monitor_layout = description->minfo + monitor_index;
|
||||
if (monitor_layout->left
|
||||
== all_monitors_encompassing_bounds.left
|
||||
&& monitor_layout->top
|
||||
== all_monitors_encompassing_bounds.top)
|
||||
{
|
||||
monitor_layout->is_primary = TS_MONITOR_PRIMARY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* set wm geometry if the encompassing area is well formed.
|
||||
Otherwise, log and return an error.
|
||||
*/
|
||||
if (all_monitors_encompassing_bounds.right
|
||||
> all_monitors_encompassing_bounds.left
|
||||
&& all_monitors_encompassing_bounds.bottom
|
||||
> all_monitors_encompassing_bounds.top)
|
||||
{
|
||||
description->session_width =
|
||||
all_monitors_encompassing_bounds.right
|
||||
- all_monitors_encompassing_bounds.left + 1;
|
||||
description->session_height =
|
||||
all_monitors_encompassing_bounds.bottom
|
||||
- all_monitors_encompassing_bounds.top + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "libxrdp_init_display_size_description:"
|
||||
" The area encompassing the monitors is not a"
|
||||
" well-formed rectangle. Received"
|
||||
" (top: %d, left: %d, right: %d, bottom: %d)."
|
||||
" This will prevent initialization.",
|
||||
all_monitors_encompassing_bounds.top,
|
||||
all_monitors_encompassing_bounds.left,
|
||||
all_monitors_encompassing_bounds.right,
|
||||
all_monitors_encompassing_bounds.bottom);
|
||||
return SEC_PROCESS_MONITORS_ERR_INVALID_DESKTOP;
|
||||
}
|
||||
|
||||
/* Make sure virtual desktop size is OK
|
||||
* 2.2.1.3.6 Client Monitor Data (TS_UD_CS_MONITOR)
|
||||
*/
|
||||
if (description->session_width
|
||||
> CLIENT_MONITOR_DATA_MAXIMUM_VIRTUAL_DESKTOP_WIDTH
|
||||
|| description->session_width
|
||||
< CLIENT_MONITOR_DATA_MINIMUM_VIRTUAL_DESKTOP_WIDTH
|
||||
|| description->session_height
|
||||
> CLIENT_MONITOR_DATA_MAXIMUM_VIRTUAL_DESKTOP_HEIGHT
|
||||
|| description->session_height
|
||||
< CLIENT_MONITOR_DATA_MINIMUM_VIRTUAL_DESKTOP_HEIGHT)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"libxrdp_init_display_size_description: Calculated virtual"
|
||||
" desktop width or height is invalid."
|
||||
" Allowed width range: min %d, max %d. Width received: %d."
|
||||
" Allowed height range: min %d, max %d. Height received: %d",
|
||||
CLIENT_MONITOR_DATA_MINIMUM_VIRTUAL_DESKTOP_WIDTH,
|
||||
CLIENT_MONITOR_DATA_MAXIMUM_VIRTUAL_DESKTOP_WIDTH,
|
||||
description->session_width,
|
||||
CLIENT_MONITOR_DATA_MINIMUM_VIRTUAL_DESKTOP_HEIGHT,
|
||||
CLIENT_MONITOR_DATA_MAXIMUM_VIRTUAL_DESKTOP_HEIGHT,
|
||||
description->session_width);
|
||||
return SEC_PROCESS_MONITORS_ERR_INVALID_DESKTOP;
|
||||
}
|
||||
|
||||
/* keep a copy of non negative monitor info values for xrdp_wm usage */
|
||||
for (monitor_index = 0; monitor_index < num_monitor; ++monitor_index)
|
||||
{
|
||||
monitor_layout = description->minfo_wm + monitor_index;
|
||||
|
||||
*monitor_layout = description->minfo[monitor_index];
|
||||
|
||||
monitor_layout->left =
|
||||
monitor_layout->left - all_monitors_encompassing_bounds.left;
|
||||
monitor_layout->top =
|
||||
monitor_layout->top - all_monitors_encompassing_bounds.top;
|
||||
monitor_layout->right =
|
||||
monitor_layout->right - all_monitors_encompassing_bounds.left;
|
||||
monitor_layout->bottom =
|
||||
monitor_layout->bottom - all_monitors_encompassing_bounds.top;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int EXPORT_CC
|
||||
libxrdp_planar_compress(char *in_data, int width, int height,
|
||||
|
||||
@ -437,6 +437,10 @@ int
|
||||
xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s,
|
||||
int data_pdu_type);
|
||||
int
|
||||
xrdp_rdp_send_data_from_channel(struct xrdp_rdp *self, struct stream *s,
|
||||
int data_pdu_type, int channel_id,
|
||||
int compress);
|
||||
int
|
||||
xrdp_rdp_send_fastpath(struct xrdp_rdp *self, struct stream *s,
|
||||
int data_pdu_type);
|
||||
int
|
||||
|
||||
@ -24,6 +24,7 @@
|
||||
#include "xrdp_rail.h"
|
||||
|
||||
struct list;
|
||||
struct monitor_info;
|
||||
|
||||
/* struct xrdp_client_info moved to xrdp_client_info.h */
|
||||
|
||||
@ -195,8 +196,7 @@ libxrdp_orders_send_font(struct xrdp_session *session,
|
||||
struct xrdp_font_char *font_char,
|
||||
int font_index, int char_index);
|
||||
int
|
||||
libxrdp_reset(struct xrdp_session *session,
|
||||
unsigned int width, unsigned int height, int bpp);
|
||||
libxrdp_reset(struct xrdp_session *session);
|
||||
int
|
||||
libxrdp_orders_send_raw_bitmap2(struct xrdp_session *session,
|
||||
int width, int height, int bpp, char *data,
|
||||
@ -241,6 +241,8 @@ int
|
||||
libxrdp_disable_channel(struct xrdp_session *session, int channel_id,
|
||||
int is_disabled);
|
||||
int
|
||||
libxrdp_drdynvc_start(struct xrdp_session *session);
|
||||
int
|
||||
libxrdp_drdynvc_open(struct xrdp_session *session, const char *name,
|
||||
int flags, struct xrdp_drdynvc_procs *procs,
|
||||
int *chan_id);
|
||||
@ -346,4 +348,21 @@ int EXPORT_CC
|
||||
libxrdp_process_monitor_ex_stream(struct stream *s,
|
||||
struct display_size_description *description);
|
||||
|
||||
/**
|
||||
* Convert a list of monitors into a full description
|
||||
*
|
||||
* Monitor data is sanitised during the conversion
|
||||
*
|
||||
* @param num_monitor Monitor count (> 0)
|
||||
* @param monitors List of monitors
|
||||
* @param[out] description Display size description
|
||||
*
|
||||
* @return 0 if the data is processed, non-zero if there is an error.
|
||||
*/
|
||||
int
|
||||
libxrdp_init_display_size_description(
|
||||
unsigned int num_monitor,
|
||||
const struct monitor_info *monitors,
|
||||
struct display_size_description *description);
|
||||
|
||||
#endif
|
||||
|
||||
@ -48,6 +48,7 @@ xrdp_caps_send_monitorlayout(struct xrdp_rdp *self)
|
||||
struct stream *s;
|
||||
uint32_t i;
|
||||
struct display_size_description *description;
|
||||
int rv = 0;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
@ -74,14 +75,13 @@ xrdp_caps_send_monitorlayout(struct xrdp_rdp *self)
|
||||
|
||||
s_mark_end(s);
|
||||
|
||||
if (xrdp_rdp_send_data(self, s, 0x37) != 0)
|
||||
{
|
||||
free_stream(s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// [MS-RDPBCGR]
|
||||
// - 2.2.12.1 - ...the pduSource field MUST be set to zero.
|
||||
// - 3.3.5.12.1 - The contents of this PDU SHOULD NOT be compressed
|
||||
rv = xrdp_rdp_send_data_from_channel(self, s,
|
||||
PDUTYPE2_MONITOR_LAYOUT_PDU, 0, 0);
|
||||
free_stream(s);
|
||||
return 0;
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
@ -120,6 +120,45 @@ xrdp_caps_process_general(struct xrdp_rdp *self, struct stream *s,
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdp_caps_process_bitmap(struct xrdp_rdp *self, struct stream *s,
|
||||
int len)
|
||||
{
|
||||
/* [MS-RDPBCGR] 2.2.7.1.2 */
|
||||
int desktopResizeFlag;
|
||||
if (len < 14 + 2)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Not enough bytes in the stream: "
|
||||
"len 16, remaining %d", len);
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_uint8s(s, 14);
|
||||
in_uint16_le(s, desktopResizeFlag);
|
||||
|
||||
/* Work out what kind of client resizing we can do from the server */
|
||||
int early_cap_flags = self->client_info.mcs_early_capability_flags;
|
||||
if (desktopResizeFlag == 0)
|
||||
{
|
||||
self->client_info.client_resize_mode = CRMODE_NONE;
|
||||
LOG(LOG_LEVEL_INFO, "Client cannot be resized by xrdp");
|
||||
}
|
||||
else if ((early_cap_flags & RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU) == 0)
|
||||
{
|
||||
self->client_info.client_resize_mode = CRMODE_SINGLE_SCREEN;
|
||||
LOG(LOG_LEVEL_INFO, "Client supports single-screen resizes by xrdp");
|
||||
}
|
||||
else
|
||||
{
|
||||
self->client_info.client_resize_mode = CRMODE_MULTI_SCREEN;
|
||||
LOG(LOG_LEVEL_INFO, "Client supports multi-screen resizes by xrdp");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/*
|
||||
* Process [MS-RDPBCGR] TS_ORDER_CAPABILITYSET (2.2.7.1.3) message.
|
||||
@ -603,6 +642,12 @@ xrdp_caps_process_codecs(struct xrdp_rdp *self, struct stream *s, int len)
|
||||
g_memcpy(self->client_info.h264_prop, s->p, i1);
|
||||
self->client_info.h264_prop_len = i1;
|
||||
}
|
||||
/* other known codec but not supported yet */
|
||||
else if (g_memcmp(codec_guid, XR_CODEC_GUID_IMAGE_REMOTEFX, 16) == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO, "xrdp_caps_process_codecs: Image RemoteFX(%s), codec id [%d], properties len [%d]",
|
||||
codec_guid_str, codec_id, codec_properties_length);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "xrdp_caps_process_codecs: unknown(%s), codec id [%d], properties len [%d]",
|
||||
@ -760,7 +805,8 @@ xrdp_caps_process_confirm_active(struct xrdp_rdp *self, struct stream *s)
|
||||
break;
|
||||
case CAPSTYPE_BITMAP:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
"capabilitySetType = CAPSTYPE_BITMAP - Ignored");
|
||||
"capabilitySetType = CAPSTYPE_BITMAP");
|
||||
xrdp_caps_process_bitmap(self, s, len);
|
||||
break;
|
||||
case CAPSTYPE_ORDER:
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Received [MS-RDPBCGR] TS_CONFIRM_ACTIVE_PDU - TS_CAPS_SET "
|
||||
@ -1331,8 +1377,11 @@ xrdp_caps_send_demand_active(struct xrdp_rdp *self)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* send Monitor Layout PDU for dual monitor */
|
||||
if (self->client_info.display_sizes.monitorCount > 0 &&
|
||||
/* send Monitor Layout PDU for multi-monitor */
|
||||
int early_cap_flags = self->client_info.mcs_early_capability_flags;
|
||||
|
||||
if ((early_cap_flags & RNS_UD_CS_SUPPORT_MONITOR_LAYOUT_PDU) != 0 &&
|
||||
self->client_info.display_sizes.monitorCount > 0 &&
|
||||
self->client_info.multimon == 1)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "xrdp_caps_send_demand_active: sending monitor layout pdu");
|
||||
|
||||
@ -752,46 +752,63 @@ xrdp_channel_drdynvc_send_capability_request(struct xrdp_channel *self)
|
||||
int
|
||||
xrdp_channel_drdynvc_start(struct xrdp_channel *self)
|
||||
{
|
||||
int index;
|
||||
int count;
|
||||
struct mcs_channel_item *ci;
|
||||
struct mcs_channel_item *dci;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_channel_drdynvc_start: drdynvc_channel_id %d", self->drdynvc_channel_id);
|
||||
int rv = 0;
|
||||
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||
"xrdp_channel_drdynvc_start: drdynvc_channel_id %d",
|
||||
self->drdynvc_channel_id);
|
||||
if (self->drdynvc_channel_id != -1)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "xrdp_channel_drdynvc_start: already started");
|
||||
return 0;
|
||||
}
|
||||
dci = NULL;
|
||||
count = self->mcs_layer->channel_list->count;
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
ci = (struct mcs_channel_item *)
|
||||
list_get_item(self->mcs_layer->channel_list, index);
|
||||
if (ci != NULL)
|
||||
{
|
||||
if (g_strcasecmp(ci->name, "drdynvc") == 0)
|
||||
{
|
||||
dci = ci;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dci != NULL)
|
||||
{
|
||||
self->drdynvc_channel_id = (dci->chanid - MCS_GLOBAL_CHANNEL) - 1;
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG,
|
||||
"Initializing Dynamic Virtual Channel with channel id %d",
|
||||
self->drdynvc_channel_id);
|
||||
xrdp_channel_drdynvc_send_capability_request(self);
|
||||
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||
"xrdp_channel_drdynvc_start: already started");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Dynamic Virtual Channel named 'drdynvc' not found, "
|
||||
"channel not initialized");
|
||||
int index;
|
||||
int count;
|
||||
struct mcs_channel_item *ci;
|
||||
struct mcs_channel_item *dci;
|
||||
dci = NULL;
|
||||
count = self->mcs_layer->channel_list->count;
|
||||
for (index = 0; index < count; index++)
|
||||
{
|
||||
ci = (struct mcs_channel_item *)
|
||||
list_get_item(self->mcs_layer->channel_list, index);
|
||||
if (ci != NULL)
|
||||
{
|
||||
if (g_strcasecmp(ci->name, DRDYNVC_SVC_CHANNEL_NAME) == 0)
|
||||
{
|
||||
dci = ci;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dci == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "Static channel '%s' not found.",
|
||||
DRDYNVC_SVC_CHANNEL_NAME);
|
||||
rv = -1;
|
||||
}
|
||||
else if (dci->disabled)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "Static channel '%s' is disabled.",
|
||||
DRDYNVC_SVC_CHANNEL_NAME);
|
||||
rv = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->drdynvc_channel_id = (dci->chanid - MCS_GLOBAL_CHANNEL) - 1;
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, DRDYNVC_SVC_CHANNEL_NAME
|
||||
"Initializing Dynamic Virtual Channel with channel id %d",
|
||||
self->drdynvc_channel_id);
|
||||
xrdp_channel_drdynvc_send_capability_request(self);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
|
||||
if (rv != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "Dynamic channels will not be available");
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
@ -585,11 +585,13 @@ xrdp_rdp_send(struct xrdp_rdp *self, struct stream *s, int pdu_type)
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Send a [MS-RDPBCGR] Data PDU with for the given pduType2 with the headers
|
||||
/* Send a [MS-RDPBCGR] Data PDU for the given pduType2 from
|
||||
* the specified source with the headers
|
||||
added and data compressed */
|
||||
int
|
||||
xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s,
|
||||
int data_pdu_type)
|
||||
xrdp_rdp_send_data_from_channel(struct xrdp_rdp *self, struct stream *s,
|
||||
int data_pdu_type, int channel_id,
|
||||
int compress)
|
||||
{
|
||||
int len;
|
||||
int ctype;
|
||||
@ -614,7 +616,8 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s,
|
||||
clen = len;
|
||||
tocomplen = pdulen - 18;
|
||||
|
||||
if (self->client_info.rdp_compression && self->session->up_and_running)
|
||||
if (compress && self->client_info.rdp_compression &&
|
||||
self->session->up_and_running)
|
||||
{
|
||||
mppc_enc = self->mppc_enc;
|
||||
if (compress_rdp(mppc_enc, (tui8 *)(s->p + 18), tocomplen))
|
||||
@ -643,7 +646,8 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s,
|
||||
else
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE,
|
||||
"xrdp_rdp_send_data: compress_rdp failed, sending "
|
||||
"xrdp_rdp_send_data_from_channel: "
|
||||
"compress_rdp failed, sending "
|
||||
"uncompressed data. type %d, flags %d",
|
||||
mppc_enc->protocol_type, mppc_enc->flags);
|
||||
}
|
||||
@ -652,11 +656,11 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s,
|
||||
/* TS_SHARECONTROLHEADER */
|
||||
out_uint16_le(s, pdulen); /* totalLength */
|
||||
out_uint16_le(s, pdutype); /* pduType */
|
||||
out_uint16_le(s, self->mcs_channel); /* pduSource */
|
||||
out_uint16_le(s, channel_id); /* pduSource */
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "Adding header [MS-RDPBCGR] TS_SHARECONTROLHEADER "
|
||||
"totalLength %d, pduType.type %s (%d), pduType.PDUVersion %d, "
|
||||
"pduSource %d", pdulen, PDUTYPE_TO_STR(pdutype & 0xf),
|
||||
pdutype & 0xf, ((pdutype & 0xfff0) >> 4), self->mcs_channel);
|
||||
pdutype & 0xf, ((pdutype & 0xfff0) >> 4), channel_id);
|
||||
|
||||
/* TS_SHAREDATAHEADER */
|
||||
out_uint32_le(s, self->share_id);
|
||||
@ -673,13 +677,26 @@ xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s,
|
||||
|
||||
if (xrdp_sec_send(self->sec_layer, s, MCS_GLOBAL_CHANNEL) != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_rdp_send_data: xrdp_sec_send failed");
|
||||
LOG(LOG_LEVEL_ERROR, "xrdp_rdp_send_data_from_channel: "
|
||||
"xrdp_sec_send failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*****************************************************************************/
|
||||
/* Send a [MS-RDPBCGR] Data PDU on the MCS channel for the given pduType2
|
||||
* with the headers added and data compressed */
|
||||
int
|
||||
xrdp_rdp_send_data(struct xrdp_rdp *self, struct stream *s,
|
||||
int data_pdu_type)
|
||||
{
|
||||
return xrdp_rdp_send_data_from_channel(self, s, data_pdu_type,
|
||||
self->mcs_channel, 1);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
/* returns the fastpath rdp byte count */
|
||||
int
|
||||
@ -1306,7 +1323,6 @@ xrdp_rdp_process_data_font(struct xrdp_rdp *self, struct stream *s)
|
||||
self->session->callback(self->session->id, 0x555a, 0, 0,
|
||||
0, 0);
|
||||
}
|
||||
xrdp_channel_drdynvc_start(self->sec_layer->chan_layer);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
10
mc/mc.h
10
mc/mc.h
@ -31,6 +31,9 @@
|
||||
|
||||
struct source_info;
|
||||
|
||||
/* Defined in xrdp_client_info.h */
|
||||
struct monitor_info;
|
||||
|
||||
struct mod
|
||||
{
|
||||
int size; /* size of this struct */
|
||||
@ -81,7 +84,10 @@ struct mod
|
||||
int box_left, int box_top,
|
||||
int box_right, int box_bottom,
|
||||
int x, int y, char *data, int data_len);
|
||||
int (*server_reset)(struct mod *v, int width, int height, int bpp);
|
||||
int (*client_monitor_resize)(struct mod *v, int width, int height,
|
||||
int num_monitors,
|
||||
const struct monitor_info *monitors);
|
||||
int (*server_monitor_resize_done)(struct mod *v);
|
||||
int (*server_get_channel_count)(struct mod *v);
|
||||
int (*server_query_channel)(struct mod *v, int index,
|
||||
char *channel_name,
|
||||
@ -92,7 +98,7 @@ struct mod
|
||||
int total_data_len, int flags);
|
||||
int (*server_bell_trigger)(struct mod *v);
|
||||
int (*server_chansrv_in_use)(struct mod *v);
|
||||
tintptr server_dumby[100 - 27]; /* align, 100 minus the number of server
|
||||
tintptr server_dumby[100 - 28]; /* align, 100 minus the number of server
|
||||
functions above */
|
||||
/* common */
|
||||
tintptr handle; /* pointer to self as long */
|
||||
|
||||
@ -877,8 +877,12 @@ lxrdp_server_version_message(struct mod *mod)
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
lxrdp_server_monitor_resize(struct mod *mod, int width, int height)
|
||||
lxrdp_server_monitor_resize(struct mod *mod, int width, int height,
|
||||
int num_monitors,
|
||||
const struct monitor_info *monitors,
|
||||
int *in_progress)
|
||||
{
|
||||
*in_progress = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -88,7 +88,10 @@ struct mod
|
||||
int (*mod_suppress_output)(struct mod *mod, int suppress,
|
||||
int left, int top, int right, int bottom);
|
||||
int (*mod_server_monitor_resize)(struct mod *mod,
|
||||
int width, int height);
|
||||
int width, int height,
|
||||
int num_monitors,
|
||||
const struct monitor_info *monitors,
|
||||
int *in_progress);
|
||||
int (*mod_server_monitor_full_invalidate)(struct mod *mod,
|
||||
int width, int height);
|
||||
int (*mod_server_version_message)(struct mod *mod);
|
||||
@ -126,7 +129,10 @@ struct mod
|
||||
int box_left, int box_top,
|
||||
int box_right, int box_bottom,
|
||||
int x, int y, char *data, int data_len);
|
||||
int (*server_reset)(struct mod *v, int width, int height, int bpp);
|
||||
int (*client_monitor_resize)(struct mod *v, int width, int height,
|
||||
int num_monitors,
|
||||
const struct monitor_info *monitors);
|
||||
int (*server_monitor_resize_done)(struct mod *v);
|
||||
int (*server_get_channel_count)(struct mod *v);
|
||||
int (*server_query_channel)(struct mod *v, int index,
|
||||
char *channel_name,
|
||||
@ -191,7 +197,7 @@ struct mod
|
||||
int flags, int frame_id);
|
||||
int (*server_session_info)(struct mod *v, const char *data,
|
||||
int data_bytes);
|
||||
tintptr server_dumby[100 - 46]; /* align, 100 minus the number of server
|
||||
tintptr server_dumby[100 - 47]; /* align, 100 minus the number of server
|
||||
functions above */
|
||||
/* common */
|
||||
tintptr handle; /* pointer to self as long */
|
||||
|
||||
65
scripts/make_release_tarball.sh
Executable file
65
scripts/make_release_tarball.sh
Executable file
@ -0,0 +1,65 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Script to generate release tarball
|
||||
#
|
||||
# This script will generate release tarball. If the repository HEAD is not
|
||||
# tagged, the script will be aborted. Target GitHub repository, branch can be
|
||||
# customized by GH_* envirnment variable.
|
||||
#
|
||||
# Usage:
|
||||
# Just execute the script. This script is intended to be run by maintainers
|
||||
# so build dependencies are not taken care of.
|
||||
#
|
||||
# $ ./scripts/make_release_tarball.sh
|
||||
# (snip)
|
||||
# ===============================================
|
||||
# Release tarball has been generated at:
|
||||
# /tmp/tmp.q8kme7m7/xrdp-0.9.22.1.tar.gz
|
||||
#
|
||||
# CHECKSUM:
|
||||
# 3ca220d6941ca6dab6a8bd1b50fcffffcf386ce01fbbc350099fdc83684380e0 xrdp-0.9.22.1.tar.gz
|
||||
#
|
||||
# Copy tarball to /home/meta/github/metalefty/xrdp? [y/N] y
|
||||
#
|
||||
# If the script is executed with BATCH=yes, the full path of the release
|
||||
# tarball will be printed on the last line. Clip it using tail command.
|
||||
#
|
||||
# $ BATCH=yes ./scripts/make_release_tarball.sh | tail -n1
|
||||
|
||||
set -e
|
||||
|
||||
: ${GH_ACCOUNT:=neutrinolabs}
|
||||
: ${GH_PROJECT:=xrdp}
|
||||
: ${GH_BRANCH:=v0.10}
|
||||
: ${BATCH:=""}
|
||||
|
||||
WRKDIR=$(mktemp -d)
|
||||
|
||||
# clean checkout
|
||||
git clone --recursive --branch "${GH_BRANCH}" "https://github.com/${GH_ACCOUNT}/${GH_PROJECT}.git" "${WRKDIR}"
|
||||
|
||||
cd "${WRKDIR}"
|
||||
git diff --no-ext-diff --quiet --exit-code # check if there's no changes on working tree
|
||||
RELVER=$(git describe --tags --exact-match HEAD) # check if working HEAD refs a release tag
|
||||
./bootstrap
|
||||
./configure
|
||||
make distcheck
|
||||
|
||||
echo
|
||||
echo ===============================================
|
||||
echo Release tarball has been generated at:
|
||||
echo ${WRKDIR}/xrdp-${RELVER#v}.tar.gz
|
||||
echo
|
||||
echo CHECKSUM:
|
||||
sha256sum xrdp-${RELVER#v}.tar.gz
|
||||
echo
|
||||
|
||||
if [ -z "${BATCH}" ]; then
|
||||
echo -n "Copy tarball to ${OLDPWD}? [y/N] "
|
||||
read -t 60 copy_tarball
|
||||
case "${copy_tarball}" in
|
||||
[Yy]*) cp -i xrdp-${RELVER#v}.tar.gz "${OLDPWD}"; exit ;;
|
||||
esac
|
||||
else
|
||||
echo ${WRKDIR}/xrdp-${RELVER#v}.tar.gz
|
||||
fi
|
||||
@ -579,8 +579,9 @@ print_version(void)
|
||||
{
|
||||
g_writeln("xrdp-sesman %s", PACKAGE_VERSION);
|
||||
g_writeln(" The xrdp session manager");
|
||||
g_writeln(" Copyright (C) 2004-2023 Jay Sorg, "
|
||||
"Neutrino Labs, and all contributors.");
|
||||
g_writeln(" Copyright (C) 2004-%d Jay Sorg, "
|
||||
"Neutrino Labs, and all contributors.",
|
||||
VERSION_YEAR);
|
||||
g_writeln(" See https://github.com/neutrinolabs/xrdp for more information.");
|
||||
g_writeln("%s", "");
|
||||
|
||||
|
||||
@ -108,6 +108,9 @@ START_TEST(test_g_signal_child_stop_1)
|
||||
pid = g_fork();
|
||||
if (pid == 0)
|
||||
{
|
||||
// Before raising the signal, change directory to a non-writeable
|
||||
// one to avoid generating a corefile.
|
||||
g_set_current_dir("/");
|
||||
raise(SIGSEGV);
|
||||
}
|
||||
ck_assert_int_ne(pid, 0);
|
||||
|
||||
431
vnc/vnc.c
431
vnc/vnc.c
@ -149,17 +149,13 @@ log_screen_layout(const enum logLevels lvl, const char *source,
|
||||
* @param a First structure
|
||||
* @param b Second structure
|
||||
*
|
||||
* @return Suitable for sorting structures with ID as the primary key
|
||||
* @return Suitable for sorting structures on (x, y, width, height)
|
||||
*/
|
||||
static int cmp_vnc_screen(const struct vnc_screen *a,
|
||||
const struct vnc_screen *b)
|
||||
{
|
||||
int result = 0;
|
||||
if (a->id != b->id)
|
||||
{
|
||||
result = a->id - b->id;
|
||||
}
|
||||
else if (a->x != b->x)
|
||||
if (a->x != b->x)
|
||||
{
|
||||
result = a->x - b->x;
|
||||
}
|
||||
@ -211,9 +207,7 @@ static int vnc_screen_layouts_equal(const struct vnc_screen_layout *a,
|
||||
* @return != 0 for error
|
||||
*
|
||||
* @pre The next octet read from v->trans is the number of screens
|
||||
* @pre layout is not already allocated
|
||||
*
|
||||
* @post if call is successful, layout->s must be freed after use.
|
||||
* @post Returned structure is in increasing ID order
|
||||
* @post layout->total_width is untouched
|
||||
* @post layout->total_height is untouched
|
||||
@ -225,10 +219,8 @@ read_extended_desktop_size_rect(struct vnc *v,
|
||||
struct stream *s;
|
||||
int error;
|
||||
unsigned int count;
|
||||
struct vnc_screen *screens;
|
||||
|
||||
layout->count = 0;
|
||||
layout->s = NULL;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
@ -239,46 +231,41 @@ read_extended_desktop_size_rect(struct vnc *v,
|
||||
{
|
||||
/* Get the number of screens */
|
||||
in_uint8(s, count);
|
||||
in_uint8s(s, 3);
|
||||
|
||||
error = trans_force_read_s(v->trans, s, 16 * count);
|
||||
if (error == 0)
|
||||
if (count <= 0 || count > CLIENT_MONITOR_DATA_MAXIMUM_MONITORS)
|
||||
{
|
||||
screens = g_new(struct vnc_screen, count);
|
||||
if (screens == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"VNC : Can't alloc for %d screens", count);
|
||||
error = 1;
|
||||
}
|
||||
else
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"Bad monitor count %d in ExtendedDesktopSize rectangle",
|
||||
count);
|
||||
error = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
in_uint8s(s, 3);
|
||||
|
||||
error = trans_force_read_s(v->trans, s, 16 * count);
|
||||
if (error == 0)
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0 ; i < count ; ++i)
|
||||
{
|
||||
in_uint32_be(s, screens[i].id);
|
||||
in_uint16_be(s, screens[i].x);
|
||||
in_uint16_be(s, screens[i].y);
|
||||
in_uint16_be(s, screens[i].width);
|
||||
in_uint16_be(s, screens[i].height);
|
||||
in_uint32_be(s, screens[i].flags);
|
||||
in_uint32_be(s, layout->s[i].id);
|
||||
in_uint16_be(s, layout->s[i].x);
|
||||
in_uint16_be(s, layout->s[i].y);
|
||||
in_uint16_be(s, layout->s[i].width);
|
||||
in_uint16_be(s, layout->s[i].height);
|
||||
in_uint32_be(s, layout->s[i].flags);
|
||||
}
|
||||
|
||||
/* sort monitors in increasing ID order */
|
||||
qsort(screens, count, sizeof(screens[0]),
|
||||
/* sort monitors in increasing (x,y) order */
|
||||
qsort(layout->s, count, sizeof(layout->s[0]),
|
||||
(int (*)(const void *, const void *))cmp_vnc_screen);
|
||||
layout->count = count;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free_stream(s);
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
layout->count = count;
|
||||
layout->s = screens;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -326,88 +313,76 @@ send_set_desktop_size(struct vnc *v, const struct vnc_screen_layout *layout)
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Sets up a single-screen vnc_screen_layout structure
|
||||
*
|
||||
* @param layout Structure to set up
|
||||
* @param width New client width
|
||||
* @param height New client height
|
||||
*
|
||||
* @pre layout->count must be valid
|
||||
* @pre layout->s must be valid
|
||||
* Initialises a vnc_screen_layout as a single screen
|
||||
* @param[in] width Screen Width
|
||||
* @param[in] height Screen Height
|
||||
* @param[out] layout Layout to initialise
|
||||
*/
|
||||
static void
|
||||
set_single_screen_layout(struct vnc_screen_layout *layout,
|
||||
int width, int height)
|
||||
init_single_screen_layout(int width, int height,
|
||||
struct vnc_screen_layout *layout)
|
||||
{
|
||||
int id = 0;
|
||||
int flags = 0;
|
||||
|
||||
layout->total_width = width;
|
||||
layout->total_height = height;
|
||||
|
||||
if (layout->count == 0)
|
||||
{
|
||||
/* No previous layout */
|
||||
layout->s = g_new(struct vnc_screen, 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Keep the ID and flags from the previous first screen */
|
||||
id = layout->s[0].id;
|
||||
flags = layout->s[0].flags;
|
||||
|
||||
if (layout->count > 1)
|
||||
{
|
||||
g_free(layout->s);
|
||||
layout->s = g_new(struct vnc_screen, 1);
|
||||
}
|
||||
}
|
||||
layout->count = 1;
|
||||
layout->s[0].id = id;
|
||||
layout->s[0].id = 0;
|
||||
layout->s[0].x = 0;
|
||||
layout->s[0].y = 0;
|
||||
layout->s[0].width = width;
|
||||
layout->s[0].height = height;
|
||||
layout->s[0].flags = flags;
|
||||
layout->s[0].flags = 0;
|
||||
}
|
||||
|
||||
/**************************************************************************//**
|
||||
* Resize the client as a single screen
|
||||
* Resize the client to match the server_layout
|
||||
*
|
||||
* @param v VNC object
|
||||
* @param update_in_progress True if there's a painter update in progress
|
||||
* @param width New client width
|
||||
* @param height New client height
|
||||
* @return != 0 for error
|
||||
*
|
||||
* The new client layout is recorded in v->client_layout. If the client was
|
||||
* multi-screen before this call, it won't be afterwards.
|
||||
* The new client layout is recorded in v->client_layout.
|
||||
*/
|
||||
static int
|
||||
resize_client(struct vnc *v, int update_in_progress, int width, int height)
|
||||
resize_client_to_server(struct vnc *v, int update_in_progress)
|
||||
{
|
||||
int error = 0;
|
||||
unsigned int i;
|
||||
const struct vnc_screen_layout *sl = &v->server_layout;
|
||||
struct monitor_info client_mons[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS] = {0};
|
||||
|
||||
if (v->client_layout.count != 1 ||
|
||||
v->client_layout.total_width != width ||
|
||||
v->client_layout.total_height != height)
|
||||
if (sl->count <= 0 ||
|
||||
sl->count > CLIENT_MONITOR_DATA_MAXIMUM_MONITORS)
|
||||
{
|
||||
if (update_in_progress)
|
||||
{
|
||||
error = v->server_end_update(v);
|
||||
}
|
||||
LOG(LOG_LEVEL_ERROR, "%s: Programming error. Bad monitors %d",
|
||||
__func__, sl->count);
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Convert the server monitors into client monitors
|
||||
for (i = 0; i < sl->count; ++i)
|
||||
{
|
||||
client_mons[i].left = sl->s[i].x;
|
||||
client_mons[i].top = sl->s[i].y;
|
||||
client_mons[i].right = sl->s[i].x + sl->s[i].width - 1;
|
||||
client_mons[i].bottom = sl->s[i].y + sl->s[i].height - 1;
|
||||
}
|
||||
|
||||
if (update_in_progress && v->server_end_update(v) != 0)
|
||||
{
|
||||
error = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = v->client_monitor_resize(v, sl->total_width, sl->total_height,
|
||||
sl->count, client_mons);
|
||||
if (error == 0)
|
||||
{
|
||||
error = v->server_reset(v, width, height, v->server_bpp);
|
||||
if (error == 0)
|
||||
{
|
||||
set_single_screen_layout(&v->client_layout, width, height);
|
||||
if (update_in_progress)
|
||||
{
|
||||
error = v->server_begin_update(v);
|
||||
}
|
||||
}
|
||||
v->client_layout = *sl;
|
||||
}
|
||||
|
||||
if (update_in_progress && v->server_begin_update(v) != 0)
|
||||
{
|
||||
error = 1;
|
||||
}
|
||||
}
|
||||
|
||||
@ -416,50 +391,53 @@ resize_client(struct vnc *v, int update_in_progress, int width, int height)
|
||||
|
||||
|
||||
/**************************************************************************//**
|
||||
* Resize the attached client from a layout
|
||||
* Resize the server to the client layout
|
||||
*
|
||||
* @param v VNC object
|
||||
* @param update_in_progress True if there's a painter update in progress
|
||||
* @param layout Desired layout from server
|
||||
* @return != 0 for error
|
||||
*
|
||||
* This has some limitations. We have no way to move multiple screens about
|
||||
* on a connected client, and so we are not able to change the client unless
|
||||
* we're changing to a single screen layout.
|
||||
* The new client layout is recorded in v->client_layout.
|
||||
*/
|
||||
static int
|
||||
resize_client_from_layout(struct vnc *v,
|
||||
int update_in_progress,
|
||||
const struct vnc_screen_layout *layout)
|
||||
resize_server_to_client_layout(struct vnc *v)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
if (!vnc_screen_layouts_equal(&v->client_layout, layout))
|
||||
if (v->resize_supported != VRSS_SUPPORTED)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "%s: Asked to resize server, but not possible",
|
||||
__func__);
|
||||
error = 1;
|
||||
}
|
||||
else if (vnc_screen_layouts_equal(&v->server_layout, &v->client_layout))
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Server layout is the same "
|
||||
"as the client layout");
|
||||
v->resize_status = VRS_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
* we don't have the capability to resize to anything other
|
||||
* than a single screen.
|
||||
* If we've only got one screen, and the other side has
|
||||
* only got one screen, we will preserve their screen ID
|
||||
* and any flags. This may prevent us sending an unwanted
|
||||
* SetDesktopSize message if the screen dimensions are
|
||||
* a match. We can't do this with more than one screen,
|
||||
* as we have no way to map different IDs
|
||||
*/
|
||||
if (layout->count != 1)
|
||||
if (v->server_layout.count == 1 && v->client_layout.count == 1)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR,
|
||||
"VNC Resize to %d screen(s) from %d screen(s) "
|
||||
"not implemented",
|
||||
v->client_layout.count, layout->count);
|
||||
LOG(LOG_LEVEL_DEBUG, "VNC "
|
||||
"setting screen id to %d from server",
|
||||
v->server_layout.s[0].id);
|
||||
|
||||
/* Dump some useful info, in case we get here when we don't
|
||||
* need to */
|
||||
log_screen_layout(LOG_LEVEL_ERROR, "OldLayout", &v->client_layout);
|
||||
log_screen_layout(LOG_LEVEL_ERROR, "NewLayout", layout);
|
||||
error = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = resize_client(v,
|
||||
update_in_progress,
|
||||
layout->total_width,
|
||||
layout->total_height);
|
||||
v->client_layout.s[0].id = v->server_layout.s[0].id;
|
||||
v->client_layout.s[0].flags = v->server_layout.s[0].flags;
|
||||
}
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "Changing server layout");
|
||||
error = send_set_desktop_size(v, &v->client_layout);
|
||||
v->resize_status = VRS_WAITING_FOR_RESIZE_CONFIRM;
|
||||
}
|
||||
|
||||
return error;
|
||||
@ -927,7 +905,6 @@ skip_encoding(struct vnc *v, int x, int y, int cx, int cy,
|
||||
"x=%d, y=%d geom=%dx%d",
|
||||
x, y, cx, cy);
|
||||
error = read_extended_desktop_size_rect(v, &layout);
|
||||
g_free(layout.s);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -944,7 +921,7 @@ skip_encoding(struct vnc *v, int x, int y, int cx, int cy,
|
||||
* Parses an entire framebuffer update message from the wire, and returns the
|
||||
* first matching ExtendedDesktopSize encoding if found.
|
||||
*
|
||||
* Caller can check for a match by examining match_layout.s after the call
|
||||
* Caller can check for a match by examining match_layout.count after the call
|
||||
*
|
||||
* @param v VNC object
|
||||
* @param match Function to call to check for a match
|
||||
@ -952,8 +929,6 @@ skip_encoding(struct vnc *v, int x, int y, int cx, int cy,
|
||||
* @param [out] match_y Matching y parameter for an encoding (if needed)
|
||||
* @param [out] match_layout Returned layout for the encoding
|
||||
* @return != 0 for error
|
||||
*
|
||||
* @post After a successful call, match_layout.s must be free'd
|
||||
*/
|
||||
static int
|
||||
find_matching_extended_rect(struct vnc *v,
|
||||
@ -971,8 +946,7 @@ find_matching_extended_rect(struct vnc *v,
|
||||
int cx;
|
||||
int cy;
|
||||
encoding_type encoding;
|
||||
|
||||
match_layout->s = NULL;
|
||||
int found = 0;
|
||||
|
||||
make_stream(s);
|
||||
init_stream(s, 8192);
|
||||
@ -1002,14 +976,14 @@ find_matching_extended_rect(struct vnc *v,
|
||||
in_uint32_be(s, encoding);
|
||||
|
||||
if (encoding == RFB_ENC_EXTENDED_DESKTOP_SIZE &&
|
||||
match_layout->s == NULL &&
|
||||
!found &&
|
||||
match(x, y, cx, cy))
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG,
|
||||
"VNC matched ExtendedDesktopSize rectangle "
|
||||
"x=%d, y=%d geom=%dx%d",
|
||||
x, y, cx, cy);
|
||||
|
||||
found = 1;
|
||||
error = read_extended_desktop_size_rect(v, match_layout);
|
||||
if (match_x)
|
||||
{
|
||||
@ -1065,6 +1039,7 @@ send_update_request_for_resize_status(struct vnc *v)
|
||||
switch (v->resize_status)
|
||||
{
|
||||
case VRS_WAITING_FOR_FIRST_UPDATE:
|
||||
case VRS_WAITING_FOR_RESIZE_CONFIRM:
|
||||
/*
|
||||
* Ask for an immediate, minimal update.
|
||||
*/
|
||||
@ -1078,20 +1053,6 @@ send_update_request_for_resize_status(struct vnc *v)
|
||||
error = lib_send_copy(v, s);
|
||||
break;
|
||||
|
||||
case VRS_WAITING_FOR_RESIZE_CONFIRM:
|
||||
/*
|
||||
* Ask for a deferred minimal update.
|
||||
*/
|
||||
out_uint8(s, RFB_C2S_FRAMEBUFFER_UPDATE_REQUEST);
|
||||
out_uint8(s, 1); /* incremental == 1 : Changes only */
|
||||
out_uint16_be(s, 0);
|
||||
out_uint16_be(s, 0);
|
||||
out_uint16_be(s, 1);
|
||||
out_uint16_be(s, 1);
|
||||
s_mark_end(s);
|
||||
error = lib_send_copy(v, s);
|
||||
break;
|
||||
|
||||
default:
|
||||
/*
|
||||
* Ask for a full update from the server
|
||||
@ -1102,8 +1063,8 @@ send_update_request_for_resize_status(struct vnc *v)
|
||||
out_uint8(s, 0); /* incremental == 0 : Full update */
|
||||
out_uint16_be(s, 0);
|
||||
out_uint16_be(s, 0);
|
||||
out_uint16_be(s, v->server_width);
|
||||
out_uint16_be(s, v->server_height);
|
||||
out_uint16_be(s, v->server_layout.total_width);
|
||||
out_uint16_be(s, v->server_layout.total_height);
|
||||
s_mark_end(s);
|
||||
error = lib_send_copy(v, s);
|
||||
}
|
||||
@ -1159,12 +1120,15 @@ lib_framebuffer_first_update(struct vnc *v)
|
||||
&layout);
|
||||
if (error == 0)
|
||||
{
|
||||
if (layout.s != NULL)
|
||||
if (layout.count > 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "VNC server supports resizing");
|
||||
v->resize_supported = VRSS_SUPPORTED;
|
||||
v->server_layout = layout;
|
||||
|
||||
/* Force the client geometry over to the server */
|
||||
log_screen_layout(LOG_LEVEL_INFO, "OldLayout", &layout);
|
||||
log_screen_layout(LOG_LEVEL_INFO, "ClientLayout", &v->client_layout);
|
||||
log_screen_layout(LOG_LEVEL_INFO, "OldServerLayout", &layout);
|
||||
|
||||
/*
|
||||
* If we've only got one screen, and the other side has
|
||||
@ -1184,32 +1148,19 @@ lib_framebuffer_first_update(struct vnc *v)
|
||||
v->client_layout.s[0].flags = layout.s[0].flags;
|
||||
}
|
||||
|
||||
if (vnc_screen_layouts_equal(&layout, &v->client_layout))
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Server layout is the same "
|
||||
"as the client layout");
|
||||
v->resize_status = VRS_DONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "Server layout differs from "
|
||||
"the client layout. Changing server layout");
|
||||
error = send_set_desktop_size(v, &v->client_layout);
|
||||
v->resize_status = VRS_WAITING_FOR_RESIZE_CONFIRM;
|
||||
}
|
||||
resize_server_to_client_layout(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "VNC server does not support resizing");
|
||||
v->resize_supported = VRSS_NOT_SUPPORTED;
|
||||
|
||||
/* Force client to same size as server */
|
||||
LOG(LOG_LEVEL_DEBUG, "Resizing client to server %dx%d",
|
||||
v->server_width, v->server_height);
|
||||
error = resize_client(v, 0, v->server_width, v->server_height);
|
||||
v->server_layout.total_width, v->server_layout.total_height);
|
||||
error = resize_client_to_server(v, 0);
|
||||
v->resize_status = VRS_DONE;
|
||||
}
|
||||
|
||||
g_free(layout.s);
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
@ -1224,7 +1175,7 @@ lib_framebuffer_first_update(struct vnc *v)
|
||||
* Looks for a resize confirm in a framebuffer update request
|
||||
*
|
||||
* If the server supports resizes from us, this is used to find the
|
||||
* reply to our initial resize request. See The RFB community wiki for details.
|
||||
* reply to our resize request. See The RFB community wiki for details.
|
||||
*
|
||||
* @param v VNC object
|
||||
* @return != 0 for error
|
||||
@ -1243,18 +1194,17 @@ lib_framebuffer_waiting_for_resize_confirm(struct vnc *v)
|
||||
&layout);
|
||||
if (error == 0)
|
||||
{
|
||||
if (layout.s != NULL)
|
||||
if (layout.count > 0)
|
||||
{
|
||||
if (response_code == 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "VNC server successfully resized");
|
||||
log_screen_layout(LOG_LEVEL_INFO, "NewLayout", &layout);
|
||||
v->server_layout = layout;
|
||||
// If this resize was requested by the client mid-session
|
||||
// (dynamic resize), we need to tell xrdp_mm that
|
||||
// it's OK to continue with the resize state machine.
|
||||
// We do this by sending a reset with bpp == 0
|
||||
error = v->server_reset(v, v->server_width,
|
||||
v->server_height, 0);
|
||||
error = v->server_monitor_resize_done(v);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1263,14 +1213,11 @@ lib_framebuffer_waiting_for_resize_confirm(struct vnc *v)
|
||||
response_code,
|
||||
rfb_get_eds_status_msg(response_code));
|
||||
/* Force client to same size as server */
|
||||
LOG(LOG_LEVEL_WARNING, "Resizing client to server %dx%d",
|
||||
v->server_width, v->server_height);
|
||||
error = resize_client(v, 0, v->server_width, v->server_height);
|
||||
LOG(LOG_LEVEL_WARNING, "Resizing client to server");
|
||||
error = resize_client_to_server(v, 0);
|
||||
}
|
||||
v->resize_status = VRS_DONE;
|
||||
}
|
||||
|
||||
g_free(layout.s);
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
@ -1415,9 +1362,8 @@ lib_framebuffer_update(struct vnc *v)
|
||||
else if (encoding == RFB_ENC_DESKTOP_SIZE)
|
||||
{
|
||||
/* Server end has resized */
|
||||
v->server_width = cx;
|
||||
v->server_height = cy;
|
||||
error = resize_client(v, 1, cx, cy);
|
||||
init_single_screen_layout(cx, cy, &v->server_layout);
|
||||
error = resize_client_to_server(v, 1);
|
||||
}
|
||||
else if (encoding == RFB_ENC_EXTENDED_DESKTOP_SIZE)
|
||||
{
|
||||
@ -1427,11 +1373,14 @@ lib_framebuffer_update(struct vnc *v)
|
||||
/* If this is a reply to a request from us, x == 1 */
|
||||
if (error == 0 && x != 1)
|
||||
{
|
||||
v->server_width = layout.total_width;
|
||||
v->server_height = layout.total_height;
|
||||
error = resize_client_from_layout(v, 1, &layout);
|
||||
if (!vnc_screen_layouts_equal(&v->server_layout, &layout))
|
||||
{
|
||||
v->server_layout = layout;
|
||||
log_screen_layout(LOG_LEVEL_INFO, "NewServerLayout",
|
||||
&v->server_layout);
|
||||
error = resize_client_to_server(v, 1);
|
||||
}
|
||||
}
|
||||
g_free(layout.s);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1456,8 +1405,8 @@ lib_framebuffer_update(struct vnc *v)
|
||||
out_uint8(s, 1); /* incremental == 1 : Changes only */
|
||||
out_uint16_be(s, 0);
|
||||
out_uint16_be(s, 0);
|
||||
out_uint16_be(s, v->server_width);
|
||||
out_uint16_be(s, v->server_height);
|
||||
out_uint16_be(s, v->server_layout.total_width);
|
||||
out_uint16_be(s, v->server_layout.total_height);
|
||||
s_mark_end(s);
|
||||
error = lib_send_copy(v, s);
|
||||
}
|
||||
@ -1831,8 +1780,11 @@ lib_mod_connect(struct vnc *v)
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
in_uint16_be(s, v->server_width);
|
||||
in_uint16_be(s, v->server_height);
|
||||
int width;
|
||||
int height;
|
||||
in_uint16_be(s, width);
|
||||
in_uint16_be(s, height);
|
||||
init_single_screen_layout(width, height, &v->server_layout);
|
||||
|
||||
init_stream(pixel_format, 8192);
|
||||
v->server_msg(v, "VNC receiving pixel format", 0);
|
||||
@ -2000,6 +1952,7 @@ lib_mod_connect(struct vnc *v)
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
v->resize_supported = VRSS_UNKNOWN;
|
||||
v->resize_status = VRS_WAITING_FOR_FIRST_UPDATE;
|
||||
error = send_update_request_for_resize_status(v);
|
||||
}
|
||||
@ -2061,33 +2014,40 @@ lib_mod_end(struct vnc *v)
|
||||
/**************************************************************************//**
|
||||
* Initialises the client layout from the Windows monitor definition.
|
||||
*
|
||||
* @param [out] layout Our layout
|
||||
* @param [in] client_info WM info
|
||||
* @param v VNC module
|
||||
* @param [in] width session width
|
||||
* @param [in] height session height
|
||||
* @param [in] num_monitors (can be 0, meaning one monitor)
|
||||
* @param [in] monitors Monitor definitions for num_monitors > 0
|
||||
* @param [in] multimon_configured Whether multimon is configured
|
||||
*/
|
||||
static void
|
||||
init_client_layout(struct vnc_screen_layout *layout,
|
||||
const struct xrdp_client_info *client_info)
|
||||
init_client_layout(struct vnc *v,
|
||||
int width, int height,
|
||||
int num_monitors,
|
||||
const struct monitor_info *monitors)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
layout->total_width = client_info->display_sizes.session_width;
|
||||
layout->total_height = client_info->display_sizes.session_height;
|
||||
|
||||
layout->count = client_info->display_sizes.monitorCount;
|
||||
layout->s = g_new(struct vnc_screen, layout->count);
|
||||
|
||||
for (i = 0 ; i < client_info->display_sizes.monitorCount ; ++i)
|
||||
struct vnc_screen_layout *layout = &v->client_layout;
|
||||
if (!v->multimon_configured || num_monitors < 1)
|
||||
{
|
||||
/* Use minfo_wm, as this is normalised for a top-left of (0,0)
|
||||
* as required by RFC6143 */
|
||||
layout->s[i].id = i;
|
||||
layout->s[i].x = client_info->display_sizes.minfo_wm[i].left;
|
||||
layout->s[i].y = client_info->display_sizes.minfo_wm[i].top;
|
||||
layout->s[i].width = client_info->display_sizes.minfo_wm[i].right -
|
||||
client_info->display_sizes.minfo_wm[i].left + 1;
|
||||
layout->s[i].height = client_info->display_sizes.minfo_wm[i].bottom -
|
||||
client_info->display_sizes.minfo_wm[i].top + 1;
|
||||
layout->s[i].flags = 0;
|
||||
init_single_screen_layout(width, height, layout);
|
||||
}
|
||||
else
|
||||
{
|
||||
layout->total_width = width;
|
||||
layout->total_height = height;
|
||||
layout->count = num_monitors;
|
||||
|
||||
unsigned int i;
|
||||
for (i = 0 ; i < layout->count; ++i)
|
||||
{
|
||||
layout->s[i].id = i;
|
||||
layout->s[i].x = monitors[i].left;
|
||||
layout->s[i].y = monitors[i].top;
|
||||
layout->s[i].width = monitors[i].right - monitors[i].left + 1;
|
||||
layout->s[i].height = monitors[i].bottom - monitors[i].top + 1;
|
||||
layout->s[i].flags = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2132,19 +2092,16 @@ lib_mod_set_param(struct vnc *v, const char *name, const char *value)
|
||||
const struct xrdp_client_info *client_info =
|
||||
(const struct xrdp_client_info *) value;
|
||||
|
||||
g_free(v->client_layout.s);
|
||||
v->multimon_configured = client_info->multimon;
|
||||
|
||||
/* Save monitor information from the client */
|
||||
if (!client_info->multimon || client_info->display_sizes.monitorCount < 1)
|
||||
{
|
||||
set_single_screen_layout(&v->client_layout,
|
||||
client_info->display_sizes.session_width,
|
||||
client_info->display_sizes.session_height);
|
||||
}
|
||||
else
|
||||
{
|
||||
init_client_layout(&v->client_layout, client_info);
|
||||
}
|
||||
/* Save monitor information from the client
|
||||
* Use minfo_wm, as this is normalised for a top-left of (0,0)
|
||||
* as required by RFC6143 */
|
||||
init_client_layout(v,
|
||||
client_info->display_sizes.session_width,
|
||||
client_info->display_sizes.session_height,
|
||||
client_info->display_sizes.monitorCount,
|
||||
client_info->display_sizes.minfo_wm);
|
||||
log_screen_layout(LOG_LEVEL_DEBUG, "client_info", &v->client_layout);
|
||||
}
|
||||
|
||||
@ -2185,6 +2142,10 @@ lib_mod_check_wait_objs(struct vnc *v)
|
||||
if (v->trans != 0)
|
||||
{
|
||||
rv = trans_check_wait_objs(v->trans);
|
||||
if (rv != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "VNC server closed connection");
|
||||
}
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
@ -2217,8 +2178,8 @@ lib_mod_suppress_output(struct vnc *v, int suppress,
|
||||
out_uint8(s, 0); /* incremental == 0 : Full contents */
|
||||
out_uint16_be(s, 0);
|
||||
out_uint16_be(s, 0);
|
||||
out_uint16_be(s, v->server_width);
|
||||
out_uint16_be(s, v->server_height);
|
||||
out_uint16_be(s, v->server_layout.total_width);
|
||||
out_uint16_be(s, v->server_layout.total_height);
|
||||
s_mark_end(s);
|
||||
error = lib_send_copy(v, s);
|
||||
free_stream(s);
|
||||
@ -2237,12 +2198,29 @@ lib_mod_server_version_message(struct vnc *v)
|
||||
/******************************************************************************/
|
||||
/* return error */
|
||||
int
|
||||
lib_mod_server_monitor_resize(struct vnc *v, int width, int height)
|
||||
lib_mod_server_monitor_resize(struct vnc *v, int width, int height,
|
||||
int num_monitors,
|
||||
const struct monitor_info *monitors,
|
||||
int *in_progress)
|
||||
{
|
||||
int error = 0;
|
||||
set_single_screen_layout(&v->client_layout, width, height);
|
||||
v->resize_status = VRS_WAITING_FOR_FIRST_UPDATE;
|
||||
error = send_update_request_for_resize_status(v);
|
||||
int error;
|
||||
*in_progress = 0;
|
||||
init_client_layout(v, width, height, num_monitors, monitors);
|
||||
|
||||
if ((error = resize_server_to_client_layout(v)) == 0)
|
||||
{
|
||||
// If we're waiting for a confirmation, send an update request.
|
||||
// According to the spec this should not be needed, but
|
||||
// it works around a buggy VNC server not sending an
|
||||
// ExtendedDesktopSize rectangle if the desktop change is
|
||||
// small (eg. same dimensions, but 2 monitors -> 1 monitor)
|
||||
if (v->resize_status == VRS_WAITING_FOR_RESIZE_CONFIRM &&
|
||||
(error = send_update_request_for_resize_status(v)) == 0)
|
||||
{
|
||||
*in_progress = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -2298,7 +2276,6 @@ mod_exit(tintptr handle)
|
||||
return 0;
|
||||
}
|
||||
trans_delete(v->trans);
|
||||
g_free(v->client_layout.s);
|
||||
vnc_clip_exit(v);
|
||||
g_free(v);
|
||||
return 0;
|
||||
|
||||
32
vnc/vnc.h
32
vnc/vnc.h
@ -27,6 +27,7 @@
|
||||
#include "os_calls.h"
|
||||
#include "defines.h"
|
||||
#include "guid.h"
|
||||
#include "ms-rdpbcgr.h"
|
||||
|
||||
#define CURRENT_MOD_VER 4
|
||||
|
||||
@ -46,8 +47,8 @@ struct vnc_screen_layout
|
||||
int total_width;
|
||||
int total_height;
|
||||
unsigned int count;
|
||||
/* For comparison, screens are sorted in increasing order of ID */
|
||||
struct vnc_screen *s;
|
||||
/* For comparison, screens are sorted in x, y, width, height) order */
|
||||
struct vnc_screen s[CLIENT_MONITOR_DATA_MAXIMUM_MONITORS];
|
||||
};
|
||||
|
||||
/**
|
||||
@ -60,11 +61,21 @@ enum vnc_resize_status
|
||||
VRS_DONE
|
||||
};
|
||||
|
||||
enum vnc_resize_support_status
|
||||
{
|
||||
VRSS_NOT_SUPPORTED,
|
||||
VRSS_SUPPORTED,
|
||||
VRSS_UNKNOWN
|
||||
};
|
||||
|
||||
struct source_info;
|
||||
|
||||
/* Defined in vnc_clip.c */
|
||||
struct vnc_clipboard_data;
|
||||
|
||||
/* Defined in xrdp_client_info.h */
|
||||
struct monitor_info;
|
||||
|
||||
struct vnc
|
||||
{
|
||||
int size; /* size of this struct */
|
||||
@ -85,7 +96,10 @@ struct vnc
|
||||
int (*mod_suppress_output)(struct vnc *v, int suppress,
|
||||
int left, int top, int right, int bottom);
|
||||
int (*mod_server_monitor_resize)(struct vnc *v,
|
||||
int width, int height);
|
||||
int width, int height,
|
||||
int num_monitors,
|
||||
const struct monitor_info *monitors,
|
||||
int *in_progress);
|
||||
int (*mod_server_monitor_full_invalidate)(struct vnc *v,
|
||||
int width, int height);
|
||||
int (*mod_server_version_message)(struct vnc *v);
|
||||
@ -123,7 +137,10 @@ struct vnc
|
||||
int box_left, int box_top,
|
||||
int box_right, int box_bottom,
|
||||
int x, int y, char *data, int data_len);
|
||||
int (*server_reset)(struct vnc *v, int width, int height, int bpp);
|
||||
int (*client_monitor_resize)(struct vnc *v, int width, int height,
|
||||
int num_monitors,
|
||||
const struct monitor_info *monitors);
|
||||
int (*server_monitor_resize_done)(struct vnc *v);
|
||||
int (*server_get_channel_count)(struct vnc *v);
|
||||
int (*server_query_channel)(struct vnc *v, int index,
|
||||
char *channel_name,
|
||||
@ -134,7 +151,7 @@ struct vnc
|
||||
int total_data_len, int flags);
|
||||
int (*server_bell_trigger)(struct vnc *v);
|
||||
int (*server_chansrv_in_use)(struct vnc *v);
|
||||
tintptr server_dumby[100 - 27]; /* align, 100 minus the number of server
|
||||
tintptr server_dumby[100 - 28]; /* align, 100 minus the number of server
|
||||
functions above */
|
||||
/* common */
|
||||
tintptr handle; /* pointer to self as long */
|
||||
@ -142,8 +159,6 @@ struct vnc
|
||||
tintptr painter;
|
||||
struct source_info *si;
|
||||
/* mod data */
|
||||
int server_width;
|
||||
int server_height;
|
||||
int server_bpp;
|
||||
char mod_name[256];
|
||||
int mod_mouse_state;
|
||||
@ -164,8 +179,11 @@ struct vnc
|
||||
int suppress_output;
|
||||
unsigned int enabled_encodings_mask;
|
||||
/* Resizeable support */
|
||||
int multimon_configured;
|
||||
struct vnc_screen_layout client_layout;
|
||||
struct vnc_screen_layout server_layout;
|
||||
enum vnc_resize_status resize_status;
|
||||
enum vnc_resize_support_status resize_supported;
|
||||
};
|
||||
|
||||
/*
|
||||
|
||||
@ -53,8 +53,9 @@ print_version(void)
|
||||
{
|
||||
g_writeln("xrdp %s", PACKAGE_VERSION);
|
||||
g_writeln(" A Remote Desktop Protocol Server.");
|
||||
g_writeln(" Copyright (C) 2004-2020 Jay Sorg, "
|
||||
"Neutrino Labs, and all contributors.");
|
||||
g_writeln(" Copyright (C) 2004-%d Jay Sorg, "
|
||||
"Neutrino Labs, and all contributors.",
|
||||
VERSION_YEAR);
|
||||
g_writeln(" See https://github.com/neutrinolabs/xrdp for more information.");
|
||||
g_writeln("%s", "");
|
||||
|
||||
|
||||
@ -502,6 +502,9 @@ int
|
||||
xrdp_mm_check_wait_objs(struct xrdp_mm *self);
|
||||
int
|
||||
xrdp_mm_frame_ack(struct xrdp_mm *self, int frame_id);
|
||||
void
|
||||
xrdp_mm_efgx_add_dirty_region_to_planar_list(struct xrdp_mm *self,
|
||||
struct xrdp_region *dirty_region);
|
||||
int
|
||||
xrdp_mm_egfx_send_planar_bitmap(struct xrdp_mm *self,
|
||||
struct xrdp_bitmap *bitmap,
|
||||
@ -591,7 +594,10 @@ server_draw_text(struct xrdp_mod *mod, int font,
|
||||
int box_right, int box_bottom,
|
||||
int x, int y, char *data, int data_len);
|
||||
int
|
||||
server_reset(struct xrdp_mod *mod, int width, int height, int bpp);
|
||||
client_monitor_resize(struct xrdp_mod *mod, int width, int height,
|
||||
int num_monitors, const struct monitor_info *monitors);
|
||||
int
|
||||
server_monitor_resize_done(struct xrdp_mod *mod);
|
||||
int
|
||||
is_channel_allowed(struct xrdp_wm *wm, int channel_id);
|
||||
int
|
||||
|
||||
@ -219,7 +219,6 @@ drdynvc=true
|
||||
cliprdr=true
|
||||
rail=true
|
||||
xrdpvr=true
|
||||
tcutils=true
|
||||
|
||||
; for debugging xrdp, in section xrdp1, change port=-1 to this:
|
||||
#port=/tmp/.xrdp/xrdp_display_10
|
||||
|
||||
@ -301,8 +301,6 @@ xrdp_bitmap_resize(struct xrdp_bitmap *self, int width, int height)
|
||||
return 1;
|
||||
}
|
||||
|
||||
self->width = width;
|
||||
self->height = height;
|
||||
Bpp = 4;
|
||||
|
||||
switch (self->bpp)
|
||||
@ -318,8 +316,28 @@ xrdp_bitmap_resize(struct xrdp_bitmap *self, int width, int height)
|
||||
break;
|
||||
}
|
||||
|
||||
g_free(self->data);
|
||||
self->data = (char *)g_malloc(width * height * Bpp, 0);
|
||||
/* To prevent valgrind errors (particularly on a screen resize),
|
||||
clear extra memory */
|
||||
unsigned long old_size = self->width * self->height * Bpp;
|
||||
unsigned long new_size = width * height * Bpp;
|
||||
|
||||
char *new_data = (char *)realloc(self->data, new_size);
|
||||
if (new_data == NULL)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
self->width = width;
|
||||
self->height = height;
|
||||
if (new_data != self->data)
|
||||
{
|
||||
self->data = new_data;
|
||||
memset(self->data, 0, new_size);
|
||||
}
|
||||
else if (new_size > old_size)
|
||||
{
|
||||
memset(self->data + old_size, 0, new_size - old_size);
|
||||
}
|
||||
self->line_size = width * Bpp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -392,8 +392,11 @@ xrdp_egfx_send_frame_start(struct xrdp_egfx *egfx, int frame_id, int timestamp)
|
||||
LOG(LOG_LEVEL_TRACE, "xrdp_egfx_send_frame_start:");
|
||||
s = xrdp_egfx_frame_start(egfx->bulk, frame_id, timestamp);
|
||||
error = xrdp_egfx_send_s(egfx, s);
|
||||
LOG(LOG_LEVEL_DEBUG, "xrdp_egfx_send_frame_start: xrdp_egfx_send_s "
|
||||
"error %d", error);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "xrdp_egfx_send_frame_start: xrdp_egfx_send_s "
|
||||
"error %d", error);
|
||||
}
|
||||
free_stream(s);
|
||||
return error;
|
||||
}
|
||||
@ -434,8 +437,11 @@ xrdp_egfx_send_frame_end(struct xrdp_egfx *egfx, int frame_id)
|
||||
LOG(LOG_LEVEL_TRACE, "xrdp_egfx_send_frame_end:");
|
||||
s = xrdp_egfx_frame_end(egfx->bulk, frame_id);
|
||||
error = xrdp_egfx_send_s(egfx, s);
|
||||
LOG(LOG_LEVEL_DEBUG, "xrdp_egfx_send_frame_end: xrdp_egfx_send_s "
|
||||
"error %d", error);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_DEBUG, "xrdp_egfx_send_frame_end: xrdp_egfx_send_s "
|
||||
"error %d", error);
|
||||
}
|
||||
free_stream(s);
|
||||
return error;
|
||||
}
|
||||
@ -769,7 +775,7 @@ xrdp_egfx_process_frame_ack(struct xrdp_egfx *egfx, struct stream *s)
|
||||
in_uint32_le(s, queueDepth);
|
||||
in_uint32_le(s, intframeId);
|
||||
in_uint32_le(s, totalFramesDecoded);
|
||||
LOG(LOG_LEVEL_DEBUG, "xrdp_egfx_process_frame_ack: queueDepth %d"
|
||||
LOG(LOG_LEVEL_TRACE, "xrdp_egfx_process_frame_ack: queueDepth %d"
|
||||
" intframeId %d totalFramesDecoded %d",
|
||||
queueDepth, intframeId, totalFramesDecoded);
|
||||
if (egfx->frame_ack != NULL)
|
||||
@ -869,7 +875,7 @@ xrdp_egfx_process(struct xrdp_egfx *egfx, struct stream *s)
|
||||
in_uint16_le(s, flags);
|
||||
in_uint32_le(s, pduLength);
|
||||
s->end = holdp + pduLength;
|
||||
LOG(LOG_LEVEL_DEBUG, "xrdp_egfx_process: cmdId 0x%x flags %d"
|
||||
LOG(LOG_LEVEL_TRACE, "xrdp_egfx_process: cmdId 0x%x flags %d"
|
||||
" pduLength %d", cmdId, flags, pduLength);
|
||||
if (pduLength < 8)
|
||||
{
|
||||
@ -1121,6 +1127,10 @@ xrdp_egfx_shutdown_close_connection(struct xrdp_egfx *egfx)
|
||||
return error;
|
||||
}
|
||||
|
||||
// Ignore any messages we haven't processed yet
|
||||
egfx->caps_advertise = NULL;
|
||||
egfx->frame_ack = NULL;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
@ -85,6 +85,40 @@ xrdp_enc_data_done_destructor(void *item, void *closure)
|
||||
g_free(enc_done);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static unsigned int
|
||||
get_largest_monitor_pixels(struct xrdp_mm *mm)
|
||||
{
|
||||
unsigned int max_pixels;
|
||||
|
||||
struct xrdp_client_info *client_info = mm->wm->client_info;
|
||||
struct display_size_description *display_sizes;
|
||||
display_sizes = &client_info->display_sizes;
|
||||
|
||||
if (display_sizes->monitorCount < 1)
|
||||
{
|
||||
max_pixels = display_sizes->session_width *
|
||||
display_sizes->session_height;
|
||||
}
|
||||
else
|
||||
{
|
||||
max_pixels = 0;
|
||||
struct monitor_info *minfo = display_sizes->minfo;
|
||||
unsigned int i;
|
||||
for (i = 0 ; i < display_sizes->monitorCount; ++i)
|
||||
{
|
||||
unsigned int pixels = (minfo[i].right + 1) - minfo[i].left;
|
||||
pixels *= (minfo[i].bottom + 1) - minfo[i].top;
|
||||
if (pixels > max_pixels)
|
||||
{
|
||||
max_pixels = pixels;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return max_pixels;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_encoder *
|
||||
xrdp_encoder_create(struct xrdp_mm *mm)
|
||||
@ -189,9 +223,12 @@ xrdp_encoder_create(struct xrdp_mm *mm)
|
||||
self->xrdp_encoder_term = g_create_wait_obj(buf);
|
||||
if (client_info->gfx)
|
||||
{
|
||||
// Magic numbers... Why?
|
||||
// Assume compressor needs to cope with largest monitor with
|
||||
// ineffective compression
|
||||
self->frames_in_flight = 2;
|
||||
self->max_compressed_bytes = 3145728;
|
||||
self->max_compressed_bytes = get_largest_monitor_pixels(mm) * 4;
|
||||
LOG_DEVEL(LOG_LEVEL_INFO, "Using %d max_compressed_bytes for encoder",
|
||||
self->max_compressed_bytes);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -1458,8 +1458,6 @@ load_xrdp_config(struct xrdp_config *config, const char *xrdp_ini, int bpp)
|
||||
LOG(LOG_LEVEL_DEBUG, "tcp_keepalive: %d", globals->tcp_keepalive);
|
||||
LOG(LOG_LEVEL_DEBUG, "tcp_send_buffer_bytes: %d", globals->tcp_send_buffer_bytes);
|
||||
LOG(LOG_LEVEL_DEBUG, "tcp_recv_buffer_bytes: %d", globals->tcp_recv_buffer_bytes);
|
||||
LOG(LOG_LEVEL_DEBUG, "new_cursors: %d", globals->new_cursors);
|
||||
LOG(LOG_LEVEL_DEBUG, "allow_multimon: %d", globals->allow_multimon);
|
||||
|
||||
LOG(LOG_LEVEL_DEBUG, "grey: %d", globals->grey);
|
||||
LOG(LOG_LEVEL_DEBUG, "black: %d", globals->black);
|
||||
|
||||
260
xrdp/xrdp_mm.c
260
xrdp/xrdp_mm.c
@ -396,7 +396,8 @@ xrdp_mm_setup_mod1(struct xrdp_mm *self)
|
||||
self->mod->server_draw_line = server_draw_line;
|
||||
self->mod->server_add_char = server_add_char;
|
||||
self->mod->server_draw_text = server_draw_text;
|
||||
self->mod->server_reset = server_reset;
|
||||
self->mod->client_monitor_resize = client_monitor_resize;
|
||||
self->mod->server_monitor_resize_done = server_monitor_resize_done;
|
||||
self->mod->server_get_channel_count = server_get_channel_count;
|
||||
self->mod->server_query_channel = server_query_channel;
|
||||
self->mod->server_get_channel_id = server_get_channel_id;
|
||||
@ -1094,25 +1095,32 @@ cleanup:
|
||||
|
||||
/******************************************************************************/
|
||||
static int
|
||||
xrdp_mm_egfx_invalidate_all(struct xrdp_mm *self)
|
||||
xrdp_mm_egfx_invalidate_wm_screen(struct xrdp_mm *self)
|
||||
{
|
||||
struct xrdp_rect xr_rect;
|
||||
struct xrdp_bitmap *screen;
|
||||
int error;
|
||||
int error = 0;
|
||||
|
||||
LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_invalidate_all:");
|
||||
LOG(LOG_LEVEL_INFO, "xrdp_mm_egfx_invalidate_wm_screen:");
|
||||
|
||||
screen = self->wm->screen;
|
||||
|
||||
xr_rect.left = 0;
|
||||
xr_rect.top = 0;
|
||||
xr_rect.right = screen->width;
|
||||
xr_rect.bottom = screen->height;
|
||||
if (self->wm->screen_dirty_region == NULL)
|
||||
// Only invalidate the WM screen if the module is using the WM screen,
|
||||
// or we haven't loaded the module yet.
|
||||
//
|
||||
// Otherwise we may send client updates which conflict with the
|
||||
// updates sent directly from the module via the encoder.
|
||||
if (self->mod_uses_wm_screen_for_gfx || self->mod_handle == 0)
|
||||
{
|
||||
self->wm->screen_dirty_region = xrdp_region_create(self->wm);
|
||||
struct xrdp_bitmap *screen = self->wm->screen;
|
||||
struct xrdp_rect xr_rect;
|
||||
|
||||
xr_rect.left = 0;
|
||||
xr_rect.top = 0;
|
||||
xr_rect.right = screen->width;
|
||||
xr_rect.bottom = screen->height;
|
||||
if (self->wm->screen_dirty_region == NULL)
|
||||
{
|
||||
self->wm->screen_dirty_region = xrdp_region_create(self->wm);
|
||||
}
|
||||
error = xrdp_region_add_rect(self->wm->screen_dirty_region, &xr_rect);
|
||||
}
|
||||
error = xrdp_region_add_rect(self->wm->screen_dirty_region, &xr_rect);
|
||||
return error;
|
||||
}
|
||||
|
||||
@ -1369,7 +1377,7 @@ xrdp_mm_egfx_caps_advertise(void *user, int caps_count,
|
||||
self->egfx_up = 1;
|
||||
xrdp_mm_egfx_create_surfaces(self);
|
||||
self->encoder = xrdp_encoder_create(self);
|
||||
xrdp_mm_egfx_invalidate_all(self);
|
||||
xrdp_mm_egfx_invalidate_wm_screen(self);
|
||||
|
||||
if (self->resize_data != NULL
|
||||
&& self->resize_data->state == WMRZ_EGFX_INITALIZING)
|
||||
@ -1635,6 +1643,7 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm)
|
||||
struct xrdp_rdp *rdp;
|
||||
struct xrdp_sec *sec;
|
||||
struct xrdp_channel *chan;
|
||||
int in_progress;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "process_display_control_monitor_layout_data:");
|
||||
|
||||
@ -1697,6 +1706,7 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm)
|
||||
if (error == 0 && module != 0)
|
||||
{
|
||||
xrdp_egfx_shutdown_close_connection(wm->mm->egfx);
|
||||
mm->egfx_up = 0;
|
||||
}
|
||||
advance_resize_state_machine(mm, WMRZ_EGFX_CONN_CLOSING);
|
||||
break;
|
||||
@ -1725,13 +1735,15 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm)
|
||||
{
|
||||
xrdp_egfx_shutdown_delete(wm->mm->egfx);
|
||||
mm->egfx = NULL;
|
||||
mm->egfx_up = 0;
|
||||
}
|
||||
advance_resize_state_machine(mm, WMRZ_SERVER_MONITOR_RESIZE);
|
||||
break;
|
||||
case WMRZ_SERVER_MONITOR_RESIZE:
|
||||
error = module->mod_server_monitor_resize(
|
||||
module, desc_width, desc_height);
|
||||
module, desc_width, desc_height,
|
||||
description->description.monitorCount,
|
||||
description->description.minfo,
|
||||
&in_progress);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||
@ -1739,30 +1751,27 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm)
|
||||
" mod_server_monitor_resize failed %d", error);
|
||||
return advance_error(error, mm);
|
||||
}
|
||||
advance_resize_state_machine(
|
||||
mm, WMRZ_SERVER_VERSION_MESSAGE_START);
|
||||
break;
|
||||
case WMRZ_SERVER_VERSION_MESSAGE_START:
|
||||
error = module->mod_server_version_message(module);
|
||||
if (error != 0)
|
||||
else if (in_progress)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||
"process_display_control_monitor_layout_data:"
|
||||
" mod_server_version_message failed %d", error);
|
||||
return advance_error(error, mm);
|
||||
// Call is proceeding asynchronously
|
||||
advance_resize_state_machine(
|
||||
mm, WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Call is done
|
||||
advance_resize_state_machine(
|
||||
mm, WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED);
|
||||
}
|
||||
advance_resize_state_machine(
|
||||
mm, WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING);
|
||||
break;
|
||||
// Not processed here. Processed in server_reset
|
||||
// Not processed here. Processed in client_monitor_resize
|
||||
// case WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING:
|
||||
case WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED:
|
||||
advance_resize_state_machine(mm, WMRZ_XRDP_CORE_RESET);
|
||||
break;
|
||||
case WMRZ_XRDP_CORE_RESET:
|
||||
// TODO: Unify this logic with server_reset
|
||||
error = libxrdp_reset(
|
||||
wm->session, desc_width, desc_height, wm->screen->bpp);
|
||||
sync_dynamic_monitor_data(wm, &(description->description));
|
||||
error = libxrdp_reset(wm->session);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||
@ -1813,7 +1822,6 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm)
|
||||
" xrdp_bitmap_resize failed %d", error);
|
||||
return advance_error(error, mm);
|
||||
}
|
||||
sync_dynamic_monitor_data(wm, &(description->description));
|
||||
advance_resize_state_machine(mm, WMRZ_EGFX_INITIALIZE);
|
||||
break;
|
||||
case WMRZ_EGFX_INITIALIZE:
|
||||
@ -1845,20 +1853,13 @@ process_display_control_monitor_layout_data(struct xrdp_wm *wm)
|
||||
// Ack all frames to speed up resize.
|
||||
module->mod_frame_ack(module, 0, INT_MAX);
|
||||
}
|
||||
// Restart module output
|
||||
// Restart module output after invalidating
|
||||
// the screen. This causes an automatic redraw.
|
||||
xrdp_bitmap_invalidate(wm->screen, 0);
|
||||
rdp = (struct xrdp_rdp *) (wm->session->rdp);
|
||||
xrdp_rdp_suppress_output(rdp,
|
||||
0, XSO_REASON_DYNAMIC_RESIZE,
|
||||
0, 0, desc_width, desc_height);
|
||||
/* redraw */
|
||||
error = xrdp_bitmap_invalidate(wm->screen, 0);
|
||||
if (error != 0)
|
||||
{
|
||||
LOG_DEVEL(LOG_LEVEL_INFO,
|
||||
"process_display_control_monitor_layout_data:"
|
||||
" xrdp_bitmap_invalidate failed %d", error);
|
||||
return advance_error(error, mm);
|
||||
}
|
||||
advance_resize_state_machine(mm, WMRZ_COMPLETE);
|
||||
break;
|
||||
default:
|
||||
@ -3534,6 +3535,39 @@ xrdp_mm_process_enc_done(struct xrdp_mm *self)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
void
|
||||
xrdp_mm_efgx_add_dirty_region_to_planar_list(struct xrdp_mm *self,
|
||||
struct xrdp_region *dirty_region)
|
||||
{
|
||||
int jndex = 0;
|
||||
struct xrdp_rect rect;
|
||||
|
||||
int error = xrdp_region_get_rect(dirty_region, jndex, &rect);
|
||||
if (error == 0)
|
||||
{
|
||||
if (self->wm->screen_dirty_region == NULL)
|
||||
{
|
||||
self->wm->screen_dirty_region = xrdp_region_create(self->wm);
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
xrdp_region_add_rect(self->wm->screen_dirty_region, &rect);
|
||||
jndex++;
|
||||
error = xrdp_region_get_rect(dirty_region, jndex, &rect);
|
||||
}
|
||||
while (error == 0);
|
||||
|
||||
if (self->mod_handle != 0)
|
||||
{
|
||||
// Module has been writing to WM screen using GFX
|
||||
self->mod_uses_wm_screen_for_gfx = 1;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
static int
|
||||
xrdp_mm_draw_dirty(struct xrdp_mm *self)
|
||||
@ -4116,11 +4150,13 @@ server_egfx_cmd(struct xrdp_mod *mod,
|
||||
mm = wm->mm;
|
||||
if (mm->encoder == NULL)
|
||||
{
|
||||
// This can happen when we are in the resize state machine, if
|
||||
// there are messages queued up by the X server
|
||||
if (data != NULL)
|
||||
{
|
||||
g_munmap(data, data_bytes);
|
||||
}
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
enc = g_new0(struct xrdp_enc_data, 1);
|
||||
if (enc == NULL)
|
||||
@ -4432,17 +4468,70 @@ server_draw_text(struct xrdp_mod *mod, int font,
|
||||
x, y, data, data_len);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
int
|
||||
client_monitor_resize(struct xrdp_mod *mod, int width, int height,
|
||||
int num_monitors, const struct monitor_info *monitors)
|
||||
{
|
||||
int error = 0;
|
||||
struct xrdp_wm *wm;
|
||||
struct display_size_description *display_size_data;
|
||||
|
||||
LOG_DEVEL(LOG_LEVEL_TRACE, "client_monitor_resize:");
|
||||
wm = (struct xrdp_wm *)(mod->wm);
|
||||
if (wm == 0 || wm->mm == 0 || wm->client_info == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (wm->client_info->client_resize_mode == CRMODE_NONE)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "Server is not allowed to resize this client");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (wm->client_info->client_resize_mode == CRMODE_SINGLE_SCREEN &&
|
||||
num_monitors > 1)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING,
|
||||
"Server cannot resize this client with multiple monitors");
|
||||
return 1;
|
||||
}
|
||||
|
||||
display_size_data = g_new0(struct display_size_description, 1);
|
||||
if (display_size_data == NULL)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "client_monitor_resize: Out of memory");
|
||||
return 1;
|
||||
}
|
||||
error = libxrdp_init_display_size_description(num_monitors,
|
||||
monitors,
|
||||
display_size_data);
|
||||
if (error)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "client_monitor_resize:"
|
||||
" libxrdp_init_display_size_description"
|
||||
" failed with error %d.", error);
|
||||
free(display_size_data);
|
||||
return error;
|
||||
}
|
||||
list_add_item(wm->mm->resize_queue, (tintptr)display_size_data);
|
||||
g_set_wait_obj(wm->mm->resize_ready);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
/* Note : if this is called on a multimon setup, the client is resized
|
||||
* to a single monitor */
|
||||
int
|
||||
server_reset(struct xrdp_mod *mod, int width, int height, int bpp)
|
||||
server_monitor_resize_done(struct xrdp_mod *mod)
|
||||
{
|
||||
struct xrdp_wm *wm;
|
||||
struct xrdp_mm *mm;
|
||||
|
||||
LOG(LOG_LEVEL_TRACE, "server_reset:");
|
||||
LOG(LOG_LEVEL_TRACE, "server_monitor_resize_done:");
|
||||
|
||||
wm = (struct xrdp_wm *)(mod->wm);
|
||||
if (wm == 0)
|
||||
@ -4450,78 +4539,25 @@ server_reset(struct xrdp_mod *mod, int width, int height, int bpp)
|
||||
return 1;
|
||||
}
|
||||
mm = wm->mm;
|
||||
if (mm == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (wm->client_info == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* older client can't resize */
|
||||
if (wm->client_info->build <= 419)
|
||||
if (mm->resize_data != NULL
|
||||
&& mm->resize_data->state
|
||||
== WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING)
|
||||
{
|
||||
return 0;
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"server_monitor_resize_done: Advancing server monitor resized.");
|
||||
advance_resize_state_machine(
|
||||
mm, WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED);
|
||||
}
|
||||
|
||||
// bpp of zero is impossible.
|
||||
// This is a signal from xup that
|
||||
// It is finished resizing.
|
||||
if (bpp == 0)
|
||||
{
|
||||
if (mm == 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (!xrdp_wm_can_resize(wm))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (mm->resize_data == NULL)
|
||||
{
|
||||
mm->mod->mod_server_monitor_full_invalidate(mm->mod, width, height);
|
||||
return 0;
|
||||
}
|
||||
if (mm->resize_data != NULL
|
||||
&& mm->resize_data->state
|
||||
== WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING)
|
||||
{
|
||||
LOG(LOG_LEVEL_INFO,
|
||||
"server_reset: Advancing server monitor resized.");
|
||||
advance_resize_state_machine(
|
||||
mm, WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED);
|
||||
}
|
||||
else if (mm->resize_data != NULL
|
||||
&& mm->resize_data->description.session_height == 0
|
||||
&& mm->resize_data->description.session_width == 0)
|
||||
{
|
||||
mm->mod->mod_server_monitor_full_invalidate(mm->mod, width, height);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* if same (and only one monitor on client) don't need to do anything */
|
||||
if (wm->client_info->display_sizes.session_width == (uint32_t)width &&
|
||||
wm->client_info->display_sizes.session_height == (uint32_t)height &&
|
||||
wm->client_info->bpp == bpp &&
|
||||
(wm->client_info->display_sizes.monitorCount == 0 ||
|
||||
wm->client_info->multimon == 0))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* reset lib, client_info gets updated in libxrdp_reset */
|
||||
if (libxrdp_reset(wm->session, width, height, bpp) != 0)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* reset cache */
|
||||
xrdp_cache_reset(wm->cache, wm->client_info);
|
||||
/* resize the main window */
|
||||
xrdp_bitmap_resize(wm->screen, wm->client_info->display_sizes.session_width,
|
||||
wm->client_info->display_sizes.session_height);
|
||||
/* load some stuff */
|
||||
xrdp_wm_load_static_colors_plus(wm, 0);
|
||||
xrdp_wm_load_static_pointers(wm);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -95,18 +95,8 @@ xrdp_painter_send_dirty(struct xrdp_painter *self)
|
||||
|
||||
if (self->session->client_info->gfx)
|
||||
{
|
||||
if (self->wm->screen_dirty_region == NULL)
|
||||
{
|
||||
self->wm->screen_dirty_region = xrdp_region_create(self->wm);
|
||||
}
|
||||
jndex = 0;
|
||||
error = xrdp_region_get_rect(self->dirty_region, jndex, &rect);
|
||||
while (error == 0)
|
||||
{
|
||||
xrdp_region_add_rect(self->wm->screen_dirty_region, &rect);
|
||||
jndex++;
|
||||
error = xrdp_region_get_rect(self->dirty_region, jndex, &rect);
|
||||
}
|
||||
xrdp_mm_efgx_add_dirty_region_to_planar_list(self->wm->mm,
|
||||
self->dirty_region);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -64,7 +64,10 @@ struct xrdp_mod
|
||||
int (*mod_suppress_output)(struct xrdp_mod *v, int suppress,
|
||||
int left, int top, int right, int bottom);
|
||||
int (*mod_server_monitor_resize)(struct xrdp_mod *v,
|
||||
int width, int height);
|
||||
int width, int height,
|
||||
int num_monitors,
|
||||
const struct monitor_info *monitors,
|
||||
int *in_progress);
|
||||
int (*mod_server_monitor_full_invalidate)(struct xrdp_mod *v,
|
||||
int width, int height);
|
||||
int (*mod_server_version_message)(struct xrdp_mod *v);
|
||||
@ -106,7 +109,10 @@ struct xrdp_mod
|
||||
int box_left, int box_top,
|
||||
int box_right, int box_bottom,
|
||||
int x, int y, char *data, int data_len);
|
||||
int (*server_reset)(struct xrdp_mod *v, int width, int height, int bpp);
|
||||
int (*client_monitor_resize)(struct xrdp_mod *v, int width, int height,
|
||||
int num_monitors,
|
||||
const struct monitor_info *monitors);
|
||||
int (*server_monitor_resize_done)(struct xrdp_mod *v);
|
||||
int (*server_get_channel_count)(struct xrdp_mod *v);
|
||||
int (*server_query_channel)(struct xrdp_mod *v, int index,
|
||||
char *channel_name,
|
||||
@ -185,7 +191,7 @@ struct xrdp_mod
|
||||
int (*server_egfx_cmd)(struct xrdp_mod *v,
|
||||
char *cmd, int cmd_bytes,
|
||||
char *data, int data_bytes);
|
||||
tintptr server_dumby[100 - 49]; /* align, 100 minus the number of server
|
||||
tintptr server_dumby[100 - 50]; /* align, 100 minus the number of server
|
||||
functions above */
|
||||
/* common */
|
||||
tintptr handle; /* pointer to self as int */
|
||||
@ -347,7 +353,6 @@ enum display_resize_state
|
||||
WMRZ_EGFX_CONN_CLOSED,
|
||||
WRMZ_EGFX_DELETE,
|
||||
WMRZ_SERVER_MONITOR_RESIZE,
|
||||
WMRZ_SERVER_VERSION_MESSAGE_START,
|
||||
WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING,
|
||||
WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED,
|
||||
WMRZ_XRDP_CORE_RESET,
|
||||
@ -370,8 +375,6 @@ enum display_resize_state
|
||||
(status) == WMRZ_EGFX_CONN_CLOSED ? "WMRZ_EGFX_CONN_CLOSED" : \
|
||||
(status) == WRMZ_EGFX_DELETE ? "WMRZ_EGFX_DELETE" : \
|
||||
(status) == WMRZ_SERVER_MONITOR_RESIZE ? "WMRZ_SERVER_MONITOR_RESIZE" : \
|
||||
(status) == WMRZ_SERVER_VERSION_MESSAGE_START ? \
|
||||
"WMRZ_SERVER_VERSION_MESSAGE_START" : \
|
||||
(status) == WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING ? \
|
||||
"WMRZ_SERVER_MONITOR_MESSAGE_PROCESSING" : \
|
||||
(status) == WMRZ_SERVER_MONITOR_MESSAGE_PROCESSED ? \
|
||||
@ -436,6 +439,7 @@ struct xrdp_mm
|
||||
int egfx_up;
|
||||
enum xrdp_egfx_flags egfx_flags;
|
||||
int gfx_delay_autologin;
|
||||
int mod_uses_wm_screen_for_gfx;
|
||||
/* Resize on-the-fly control */
|
||||
struct display_control_monitor_layout_data *resize_data;
|
||||
struct list *resize_queue;
|
||||
|
||||
121
xrdp/xrdp_wm.c
121
xrdp/xrdp_wm.c
@ -29,6 +29,54 @@
|
||||
#include "log.h"
|
||||
#include "string_calls.h"
|
||||
|
||||
/*****************************************************************************/
|
||||
static void
|
||||
xrdp_wm_load_channel_config(struct xrdp_wm *self)
|
||||
{
|
||||
struct list *names = list_create();
|
||||
names->auto_free = 1;
|
||||
struct list *values = list_create();
|
||||
values->auto_free = 1;
|
||||
|
||||
if (file_by_name_read_section(self->session->xrdp_ini,
|
||||
"Channels", names, values) == 0)
|
||||
{
|
||||
int chan_id;
|
||||
int chan_count = libxrdp_get_channel_count(self->session);
|
||||
const char *disabled_str = NULL;
|
||||
|
||||
for (chan_id = 0 ; chan_id < chan_count ; ++chan_id)
|
||||
{
|
||||
char chan_name[16];
|
||||
if (libxrdp_query_channel(self->session, chan_id, chan_name,
|
||||
NULL) == 0)
|
||||
{
|
||||
int disabled = 1; /* Channels disabled if not found */
|
||||
int index;
|
||||
|
||||
for (index = 0; index < names->count; index++)
|
||||
{
|
||||
const char *q = (const char *)list_get_item(names, index);
|
||||
const char *r = (const char *)list_get_item(values, index);
|
||||
if (g_strcasecmp(q, chan_name) == 0)
|
||||
{
|
||||
disabled = !g_text2bool(r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
disabled_str = (disabled) ? "disabled" : "enabled";
|
||||
LOG(LOG_LEVEL_DEBUG, "xrdp_wm_load_channel_config: "
|
||||
"channel %s channel id %d is %s",
|
||||
chan_name, chan_id, disabled_str);
|
||||
|
||||
libxrdp_disable_channel(self->session, chan_id, disabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
list_delete(names);
|
||||
list_delete(values);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
struct xrdp_wm *
|
||||
xrdp_wm_create(struct xrdp_process *owner,
|
||||
@ -69,6 +117,23 @@ xrdp_wm_create(struct xrdp_process *owner,
|
||||
/* to store configuration from xrdp.ini */
|
||||
self->xrdp_config = g_new0(struct xrdp_config, 1);
|
||||
|
||||
/* Load the channel config so libxrdp can check whether
|
||||
drdynvc is enabled or not */
|
||||
xrdp_wm_load_channel_config(self);
|
||||
|
||||
// Start drdynvc if available.
|
||||
if (libxrdp_drdynvc_start(self->session) == 0)
|
||||
{
|
||||
// drdynvc is started. callback() will
|
||||
// be notified when capabilities are received.
|
||||
}
|
||||
else if (self->client_info->gfx)
|
||||
{
|
||||
LOG(LOG_LEVEL_WARNING, "Disabling GFX as '"
|
||||
DRDYNVC_SVC_CHANNEL_NAME "' isn't available");
|
||||
self->client_info->gfx = 0;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -564,9 +629,7 @@ xrdp_wm_init(struct xrdp_wm *self)
|
||||
{
|
||||
int fd;
|
||||
int index;
|
||||
struct list *names;
|
||||
struct list *values;
|
||||
char *q;
|
||||
const char *q;
|
||||
const char *r;
|
||||
char param[256];
|
||||
char default_section_name[256];
|
||||
@ -590,48 +653,6 @@ xrdp_wm_init(struct xrdp_wm *self)
|
||||
/* Scale the login screen values */
|
||||
xrdp_login_wnd_scale_config_values(self);
|
||||
|
||||
/* global channels allow */
|
||||
names = list_create();
|
||||
names->auto_free = 1;
|
||||
values = list_create();
|
||||
values->auto_free = 1;
|
||||
if (file_by_name_read_section(self->session->xrdp_ini,
|
||||
"Channels", names, values) == 0)
|
||||
{
|
||||
int chan_id;
|
||||
int chan_count = libxrdp_get_channel_count(self->session);
|
||||
const char *disabled_str = NULL;
|
||||
|
||||
for (chan_id = 0 ; chan_id < chan_count ; ++chan_id)
|
||||
{
|
||||
char chan_name[16];
|
||||
if (libxrdp_query_channel(self->session, chan_id, chan_name,
|
||||
NULL) == 0)
|
||||
{
|
||||
int disabled = 1; /* Channels disabled if not found */
|
||||
|
||||
for (index = 0; index < names->count; index++)
|
||||
{
|
||||
q = (char *) list_get_item(names, index);
|
||||
if (g_strcasecmp(q, chan_name) == 0)
|
||||
{
|
||||
r = (const char *) list_get_item(values, index);
|
||||
disabled = !g_text2bool(r);
|
||||
break;
|
||||
}
|
||||
}
|
||||
disabled_str = (disabled) ? "disabled" : "enabled";
|
||||
LOG(LOG_LEVEL_DEBUG, "xrdp_wm_init: "
|
||||
"channel %s channel id %d is %s",
|
||||
chan_name, chan_id, disabled_str);
|
||||
|
||||
libxrdp_disable_channel(self->session, chan_id, disabled);
|
||||
}
|
||||
}
|
||||
}
|
||||
list_delete(names);
|
||||
list_delete(values);
|
||||
|
||||
xrdp_wm_load_static_colors_plus(self, autorun_name);
|
||||
xrdp_wm_load_static_pointers(self);
|
||||
self->screen->bg_color = self->xrdp_config->cfg_globals.ls_top_window_bg_color;
|
||||
@ -645,9 +666,9 @@ xrdp_wm_init(struct xrdp_wm *self)
|
||||
fd = g_file_open_ro(self->session->xrdp_ini);
|
||||
if (fd != -1)
|
||||
{
|
||||
names = list_create();
|
||||
struct list *names = list_create();
|
||||
names->auto_free = 1;
|
||||
values = list_create();
|
||||
struct list *values = list_create();
|
||||
values->auto_free = 1;
|
||||
|
||||
/* pick up the first section name except for 'globals', 'Logging', 'channels'
|
||||
@ -656,7 +677,7 @@ xrdp_wm_init(struct xrdp_wm *self)
|
||||
default_section_name[0] = '\0';
|
||||
for (index = 0; index < names->count; index++)
|
||||
{
|
||||
q = (char *)list_get_item(names, index);
|
||||
q = (const char *)list_get_item(names, index);
|
||||
if ((g_strncasecmp("globals", q, 8) != 0) &&
|
||||
(g_strncasecmp("Logging", q, 8) != 0) &&
|
||||
(g_strncasecmp("LoggingPerLogger", q, 17) != 0) &&
|
||||
@ -714,8 +735,8 @@ xrdp_wm_init(struct xrdp_wm *self)
|
||||
{
|
||||
for (index = 0; index < names->count; index++)
|
||||
{
|
||||
q = (char *)list_get_item(names, index);
|
||||
r = (char *)list_get_item(values, index);
|
||||
q = (const char *)list_get_item(names, index);
|
||||
r = (const char *)list_get_item(values, index);
|
||||
|
||||
if (g_strncasecmp("password", q, 255) == 0)
|
||||
{
|
||||
|
||||
56
xup/xup.c
56
xup/xup.c
@ -28,8 +28,10 @@
|
||||
#include "string_calls.h"
|
||||
|
||||
static int
|
||||
send_server_monitor_resize(
|
||||
struct mod *mod, struct stream *s, int width, int height, int bpp);
|
||||
send_server_monitor_update(struct mod *v, struct stream *s,
|
||||
int width, int height,
|
||||
int num_monitors,
|
||||
const struct monitor_info *monitors);
|
||||
|
||||
static int
|
||||
send_server_monitor_full_invalidate(
|
||||
@ -224,13 +226,6 @@ lib_mod_connect(struct mod *mod)
|
||||
error = send_server_version_message(mod, s);
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
/* send screen size message */
|
||||
error = send_server_monitor_resize(
|
||||
mod, s, mod->width, mod->height, mod->bpp);
|
||||
}
|
||||
|
||||
if (error == 0)
|
||||
{
|
||||
error = send_server_monitor_full_invalidate(
|
||||
@ -1466,33 +1461,30 @@ send_server_version_message(struct mod *mod, struct stream *s)
|
||||
/******************************************************************************/
|
||||
/* return error */
|
||||
static int
|
||||
send_server_monitor_resize(
|
||||
struct mod *mod, struct stream *s, int width, int height, int bpp)
|
||||
send_server_monitor_update(struct mod *mod, struct stream *s,
|
||||
int width, int height,
|
||||
int num_monitors,
|
||||
const struct monitor_info *monitors)
|
||||
{
|
||||
/* send screen size message */
|
||||
/* send monitor update message */
|
||||
init_stream(s, 8192);
|
||||
s_push_layer(s, iso_hdr, 4);
|
||||
out_uint16_le(s, 103);
|
||||
out_uint32_le(s, 300);
|
||||
out_uint32_le(s, 302);
|
||||
out_uint32_le(s, width);
|
||||
out_uint32_le(s, height);
|
||||
/*
|
||||
TODO: The bpp here is only necessary for initial creation. We should
|
||||
modify XUP to require this only on server initialization, but not on
|
||||
resize. Microsoft's RDP protocol does not support changing
|
||||
the bpp on resize.
|
||||
*/
|
||||
out_uint32_le(s, bpp);
|
||||
out_uint32_le(s, num_monitors);
|
||||
out_uint32_le(s, 0);
|
||||
out_uint8a(s, monitors, sizeof(monitors[0]) * num_monitors);
|
||||
s_mark_end(s);
|
||||
int len = (int)(s->end - s->data);
|
||||
s_pop_layer(s, iso_hdr);
|
||||
out_uint32_le(s, len);
|
||||
int rv = lib_send_copy(mod, s);
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "send_server_monitor_resize:"
|
||||
" sent resize message with following properties to"
|
||||
" xorgxrdp backend width=%d, height=%d, bpp=%d, return value=%d",
|
||||
width, height, bpp, rv);
|
||||
LOG_DEVEL(LOG_LEVEL_DEBUG, "send_server_monitor_update:"
|
||||
" sent monitor updsate message with following properties to"
|
||||
" xorgxrdp backend width=%d, height=%d, num=%d, return value=%d",
|
||||
width, height, num_monitors, rv);
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -1542,12 +1534,16 @@ lib_send_server_version_message(struct mod *mod)
|
||||
/******************************************************************************/
|
||||
/* return error */
|
||||
static int
|
||||
lib_send_server_monitor_resize(struct mod *mod, int width, int height)
|
||||
lib_send_server_monitor_resize(struct mod *mod, int width, int height,
|
||||
int num_monitors,
|
||||
const struct monitor_info *monitors,
|
||||
int *in_progress)
|
||||
{
|
||||
/* send screen size message */
|
||||
struct stream *s;
|
||||
make_stream(s);
|
||||
int rv = send_server_monitor_resize(mod, s, width, height, mod->bpp);
|
||||
int rv = send_server_monitor_update(mod, s, width, height,
|
||||
num_monitors, monitors);
|
||||
*in_progress = (rv == 0);
|
||||
free_stream(s);
|
||||
return rv;
|
||||
}
|
||||
@ -1802,7 +1798,7 @@ lib_mod_process_message(struct mod *mod, struct stream *s)
|
||||
LOG(LOG_LEVEL_INFO, "Received memory_allocation_complete"
|
||||
" command. width: %d, height: %d",
|
||||
width, height);
|
||||
rv = mod->server_reset(mod, width, height, 0);
|
||||
rv = mod->server_monitor_resize_done(mod);
|
||||
break;
|
||||
}
|
||||
s->p = phold + len;
|
||||
@ -1897,6 +1893,10 @@ lib_mod_check_wait_objs(struct mod *mod)
|
||||
if (mod->trans != 0)
|
||||
{
|
||||
rv = trans_check_wait_objs(mod->trans);
|
||||
if (rv != 0)
|
||||
{
|
||||
LOG(LOG_LEVEL_ERROR, "Xorg server closed connection");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
12
xup/xup.h
12
xup/xup.h
@ -55,7 +55,10 @@ struct mod
|
||||
int (*mod_suppress_output)(struct mod *v, int suppress,
|
||||
int left, int top, int right, int bottom);
|
||||
int (*mod_server_monitor_resize)(struct mod *v,
|
||||
int width, int height);
|
||||
int width, int height,
|
||||
int num_monitors,
|
||||
const struct monitor_info *monitors,
|
||||
int *in_progress);
|
||||
int (*mod_server_monitor_full_invalidate)(struct mod *v,
|
||||
int width, int height);
|
||||
int (*mod_server_version_message)(struct mod *v);
|
||||
@ -94,7 +97,10 @@ struct mod
|
||||
int box_left, int box_top,
|
||||
int box_right, int box_bottom,
|
||||
int x, int y, char *data, int data_len);
|
||||
int (*server_reset)(struct mod *v, int width, int height, int bpp);
|
||||
int (*client_monitor_resize)(struct mod *v, int width, int height,
|
||||
int num_monitors,
|
||||
const struct monitor_info *monitors);
|
||||
int (*server_monitor_resize_done)(struct mod *v);
|
||||
int (*server_get_channel_count)(struct mod *v);
|
||||
int (*server_query_channel)(struct mod *v, int index,
|
||||
char *channel_name,
|
||||
@ -170,7 +176,7 @@ struct mod
|
||||
int (*server_egfx_cmd)(struct mod *v,
|
||||
char *cmd, int cmd_bytes,
|
||||
char *data, int data_bytes);
|
||||
tintptr server_dumby[100 - 49]; /* align, 100 minus the number of server
|
||||
tintptr server_dumby[100 - 50]; /* align, 100 minus the number of server
|
||||
functions above */
|
||||
/* common */
|
||||
tintptr handle; /* pointer to self as long */
|
||||
|
||||
Loading…
Reference in New Issue
Block a user