Fix inabillity to display secure desktop even when runnig as system account

This commit is contained in:
loki
2021-06-30 22:03:21 +02:00
parent ae04c4afbb
commit 545cca792b
6 changed files with 317 additions and 317 deletions

View File

@@ -51,6 +51,7 @@ if(WIN32)
set(PLATFORM_TARGET_FILES set(PLATFORM_TARGET_FILES
sunshine/platform/windows/publish.cpp sunshine/platform/windows/publish.cpp
sunshine/platform/windows/misc.h
sunshine/platform/windows/misc.cpp sunshine/platform/windows/misc.cpp
sunshine/platform/windows/input.cpp sunshine/platform/windows/input.cpp
sunshine/platform/windows/display.h sunshine/platform/windows/display.h

View File

@@ -1,271 +1,271 @@
# If no external IP address is given, Sunshine will attempt to automatically detect external ip-address # If no external IP address is given, Sunshine will attempt to automatically detect external ip-address
# external_ip = 123.456.789.12 # external_ip = 123.456.789.12
# Set the familly of ports used by Sunshine # Set the familly of ports used by Sunshine
# port = 47989 # port = 47989
# The private key must be 2048 bits # The private key must be 2048 bits
# pkey = /dir/pkey.pem # pkey = /dir/pkey.pem
# The certificate must be signed with a 2048 bit key # The certificate must be signed with a 2048 bit key
# cert = /dir/cert.pem # cert = /dir/cert.pem
# The name displayed by Moonlight # The name displayed by Moonlight
# If not specified, the PC's hostname is used # If not specified, the PC's hostname is used
# sunshine_name = Sunshine # sunshine_name = Sunshine
# The minimum log level printed to standard out # The minimum log level printed to standard out
# #
# none -> no logs are printed to standard out # none -> no logs are printed to standard out
# #
# verbose = [0] # verbose = [0]
# debug = [1] # debug = [1]
# info = [2] # info = [2]
# warning = [3] # warning = [3]
# error = [4] # error = [4]
# fatal = [5] # fatal = [5]
# none = [6] # none = [6]
# #
# min_log_level = info # min_log_level = info
# The origin of the remote endpoint address that is not denied for HTTP method /pin # The origin of the remote endpoint address that is not denied for HTTP method /pin
# Could be any of the following values: # Could be any of the following values:
# pc|lan|wan # pc|lan|wan
# pc: Only localhost may access /pin # pc: Only localhost may access /pin
# lan: Only those in LAN may access /pin # lan: Only those in LAN may access /pin
# wan: Anyone may access /pin # wan: Anyone may access /pin
# #
# origin_pin_allowed = pc # origin_pin_allowed = pc
# The origin of the remote endpoint address that is not denied for HTTPS Web UI # The origin of the remote endpoint address that is not denied for HTTPS Web UI
# Could be any of the following values: # Could be any of the following values:
# pc|lan|wan # pc|lan|wan
# pc: Only localhost may access the Web Manager # pc: Only localhost may access the Web Manager
# lan: Only those in LAN may access the Web Manager # lan: Only those in LAN may access the Web Manager
# wan: Anyone may access the Web Manager # wan: Anyone may access the Web Manager
# #
# origin_web_ui_allowed = lan # origin_web_ui_allowed = lan
# If UPnP is enabled, Sunshine will attempt to open ports for streaming over the internet # If UPnP is enabled, Sunshine will attempt to open ports for streaming over the internet
# To enable it, uncomment the following line: # To enable it, uncomment the following line:
# upnp = on # upnp = on
# The file where current state of Sunshine is stored # The file where current state of Sunshine is stored
# file_state = sunshine_state.json # file_state = sunshine_state.json
# The file where user credentials for the UI are stored # The file where user credentials for the UI are stored
# By default, credentials are stored in `file_state` # By default, credentials are stored in `file_state`
# credentials_file = sunshine_state.json # credentials_file = sunshine_state.json
# The display modes advertised by Sunshine # The display modes advertised by Sunshine
# #
# Some versions of Moonlight, such as Moonlight-nx (Switch), # Some versions of Moonlight, such as Moonlight-nx (Switch),
# rely on this list to ensure that the requested resolutions and fps # rely on this list to ensure that the requested resolutions and fps
# are supported. # are supported.
# #
# fps = [10, 30, 60, 90, 120] # fps = [10, 30, 60, 90, 120]
# resolutions = [ # resolutions = [
# 352x240, # 352x240,
# 480x360, # 480x360,
# 858x480, # 858x480,
# 1280x720, # 1280x720,
# 1920x1080, # 1920x1080,
# 2560x1080, # 2560x1080,
# 3440x1440, # 3440x1440,
# 1920x1200, # 1920x1200,
# 3860x2160, # 3860x2160,
# 3840x1600, # 3840x1600,
# ] # ]
# How long to wait in milliseconds for data from moonlight before shutting down the stream # How long to wait in milliseconds for data from moonlight before shutting down the stream
# ping_timeout = 2000 # ping_timeout = 2000
# The file where configuration for the different applications that Sunshine can run during a stream # The file where configuration for the different applications that Sunshine can run during a stream
# file_apps = apps.json # file_apps = apps.json
# How much error correcting packets must be send for every video # How much error correcting packets must be send for every video
# This is just some random number, don't know the optimal value # This is just some random number, don't know the optimal value
# The higher fec_percentage, the lower space for the actual data to send per frame there is # The higher fec_percentage, the lower space for the actual data to send per frame there is
# #
# The value must be greater than 0 and lower than or equal to 100 # The value must be greater than 0 and lower than or equal to 100
# fec_percentage = 10 # fec_percentage = 10
# When multicasting, it could be usefull to have different configurations for each connected Client. # When multicasting, it could be usefull to have different configurations for each connected Client.
# For example: # For example:
# Clients connected through WAN and LAN have different bitrate contstraints. # Clients connected through WAN and LAN have different bitrate contstraints.
# Decoders may require different settings for color # Decoders may require different settings for color
# #
# Unlike simply broadcasting to multiple Client, this will generate distinct video streams. # Unlike simply broadcasting to multiple Client, this will generate distinct video streams.
# Note, CPU usage increases for each distinct video stream generated # Note, CPU usage increases for each distinct video stream generated
# channels = 1 # channels = 1
# The back/select button on the controller # The back/select button on the controller
# On the Shield, the home and powerbutton are not passed to Moonlight # On the Shield, the home and powerbutton are not passed to Moonlight
# If, after the timeout, the back button is still pressed down, Home/Guide button press is emulated. # If, after the timeout, the back button is still pressed down, Home/Guide button press is emulated.
# If back_button_timeout < 0, then the Home/Guide button will not be emulated # If back_button_timeout < 0, then the Home/Guide button will not be emulated
# back_button_timeout = 2000 # back_button_timeout = 2000
# !! Windows only !! # !! Windows only !!
# Control how fast keys will repeat themselves # Control how fast keys will repeat themselves
# The initial delay in milliseconds before repeating keys # The initial delay in milliseconds before repeating keys
# key_repeat_delay = 500 # key_repeat_delay = 500
# #
# How often keys repeat every second # How often keys repeat every second
# This configurable option supports decimals # This configurable option supports decimals
# key_repeat_frequency = 24.9 # key_repeat_frequency = 24.9
# The name of the audio sink used for Audio Loopback # The name of the audio sink used for Audio Loopback
# If you do not specify this variable, pulseaudio will select the default monitor device. # If you do not specify this variable, pulseaudio will select the default monitor device.
# #
# You can find the name of the audio sink using the following command: # You can find the name of the audio sink using the following command:
# !! Linux only !! # !! Linux only !!
# pacmd list-sinks | grep "name:" if running vanilla pulseaudio # pacmd list-sinks | grep "name:" if running vanilla pulseaudio
# pactl info | grep Source` if running pipewire # pactl info | grep Source` if running pipewire
# audio_sink = alsa_output.pci-0000_09_00.3.analog-stereo # audio_sink = alsa_output.pci-0000_09_00.3.analog-stereo
# #
# !! Windows only !! # !! Windows only !!
# tools\audio-info.exe # tools\audio-info.exe
# audio_sink = {0.0.0.00000000}.{FD47D9CC-4218-4135-9CE2-0C195C87405B} # audio_sink = {0.0.0.00000000}.{FD47D9CC-4218-4135-9CE2-0C195C87405B}
# #
# The virtual sink, is the audio device that's virtual (Like Steam Streaming Speakers), it allows Sunshine # The virtual sink, is the audio device that's virtual (Like Steam Streaming Speakers), it allows Sunshine
# to stream audio, while muting the speakers. # to stream audio, while muting the speakers.
# virtual_sink = {0.0.0.00000000}.{8edba70c-1125-467c-b89c-15da389bc1d4} # virtual_sink = {0.0.0.00000000}.{8edba70c-1125-467c-b89c-15da389bc1d4}
# !! Windows only !! # !! Windows only !!
# You can select the video card you want to stream: # You can select the video card you want to stream:
# The appropriate values can be found using the following command: # The appropriate values can be found using the following command:
# tools\dxgi-info.exe # tools\dxgi-info.exe
# adapter_name = Radeon RX 580 Series # adapter_name = Radeon RX 580 Series
# output_name = \\.\DISPLAY1 # output_name = \\.\DISPLAY1
# !! Linux only !! # !! Linux only !!
# Set the display number to stream. # Set the display number to stream.
# You can find them by the following command: # You can find them by the following command:
# xrandr --listmonitors # xrandr --listmonitors
# Example output: "0: +HDMI-1 1920/518x1200/324+0+0 HDMI-1" # Example output: "0: +HDMI-1 1920/518x1200/324+0+0 HDMI-1"
# ^ <-- You need this. # ^ <-- You need this.
# output_name = 0 # output_name = 0
############################################### ###############################################
# FFmpeg software encoding parameters # FFmpeg software encoding parameters
# Honestly, I have no idea what the optimal values would be. # Honestly, I have no idea what the optimal values would be.
# Play around with this :) # Play around with this :)
# Constant Rate Factor. Between 1 and 52. It allows QP to go up during motion and down with still image, resulting in constant perceived quality # Constant Rate Factor. Between 1 and 52. It allows QP to go up during motion and down with still image, resulting in constant perceived quality
# Higher value means more compression, but less quality # Higher value means more compression, but less quality
# If crf == 0, then use QP directly instead # If crf == 0, then use QP directly instead
# crf = 0 # crf = 0
# Quantitization Parameter # Quantitization Parameter
# Higher value means more compression, but less quality # Higher value means more compression, but less quality
# If crf != 0, then this parameter is ignored # If crf != 0, then this parameter is ignored
# qp = 28 # qp = 28
# Minimum number of threads used by ffmpeg to encode the video. # Minimum number of threads used by ffmpeg to encode the video.
# Increasing the value slightly reduces encoding efficiency, but the tradeoff is usually # Increasing the value slightly reduces encoding efficiency, but the tradeoff is usually
# worth it to gain the use of more CPU cores for encoding. The ideal value is the lowest # worth it to gain the use of more CPU cores for encoding. The ideal value is the lowest
# value that can reliably encode at your desired streaming settings on your hardware. # value that can reliably encode at your desired streaming settings on your hardware.
# min_threads = 1 # min_threads = 1
# Allows the client to request HEVC Main or HEVC Main10 video streams. # Allows the client to request HEVC Main or HEVC Main10 video streams.
# HEVC is more CPU-intensive to encode, so enabling this may reduce performance when using software encoding. # HEVC is more CPU-intensive to encode, so enabling this may reduce performance when using software encoding.
# If set to 0 (default), Sunshine will specify support for HEVC based on encoder # If set to 0 (default), Sunshine will specify support for HEVC based on encoder
# If set to 1, Sunshine will not advertise support for HEVC # If set to 1, Sunshine will not advertise support for HEVC
# If set to 2, Sunshine will advertise support for HEVC Main profile # If set to 2, Sunshine will advertise support for HEVC Main profile
# If set to 3, Sunshine will advertise support for HEVC Main and Main10 (HDR) profiles # If set to 3, Sunshine will advertise support for HEVC Main and Main10 (HDR) profiles
# hevc_mode = 2 # hevc_mode = 2
# Force a specific encoder, otherwise Sunshine will use the first encoder that is available # Force a specific encoder, otherwise Sunshine will use the first encoder that is available
# supported encoders: # supported encoders:
# nvenc # nvenc
# amdvce # NOTE: alpha stage. The cursor is not yet displayed # amdvce # NOTE: alpha stage. The cursor is not yet displayed
# software # software
# #
# encoder = nvenc # encoder = nvenc
##################################### Software ##################################### ##################################### Software #####################################
# See x264 --fullhelp for the different presets # See x264 --fullhelp for the different presets
# sw_preset = superfast # sw_preset = superfast
# sw_tune = zerolatency # sw_tune = zerolatency
# #
##################################### NVENC ##################################### ##################################### NVENC #####################################
###### presets ########### ###### presets ###########
# default # default
# hp -- high performance # hp -- high performance
# hq -- high quality # hq -- high quality
# slow -- hq 2 passes # slow -- hq 2 passes
# medium -- hq 1 pass # medium -- hq 1 pass
# fast -- hp 1 pass # fast -- hp 1 pass
# bd # bd
# ll -- low latency # ll -- low latency
# llhq # llhq
# llhp # llhp
# lossless # lossless
# losslesshp # losslesshp
########################## ##########################
# nv_preset = llhq # nv_preset = llhq
# #
####### rate control ##### ####### rate control #####
# auto -- let ffmpeg decide rate control # auto -- let ffmpeg decide rate control
# constqp -- constant QP mode # constqp -- constant QP mode
# vbr -- variable bitrate # vbr -- variable bitrate
# cbr -- constant bitrate # cbr -- constant bitrate
# cbr_hq -- cbr high quality # cbr_hq -- cbr high quality
# cbr_ld_hq -- cbr low delay high quality # cbr_ld_hq -- cbr low delay high quality
# vbr_hq -- vbr high quality # vbr_hq -- vbr high quality
########################## ##########################
# nv_rc = auto # nv_rc = auto
###### h264 entropy ###### ###### h264 entropy ######
# auto -- let ffmpeg nvenc decide the entropy encoding # auto -- let ffmpeg nvenc decide the entropy encoding
# cabac # cabac
# cavlc # cavlc
########################## ##########################
# nv_coder = auto # nv_coder = auto
##################################### AMD ##################################### ##################################### AMD #####################################
###### presets ########### ###### presets ###########
# default # default
# speed # speed
# balanced # balanced
########################## ##########################
# amd_preset = balanced # amd_preset = balanced
# #
####### rate control ##### ####### rate control #####
# auto -- let ffmpeg decide rate control # auto -- let ffmpeg decide rate control
# constqp -- constant QP mode # constqp -- constant QP mode
# vbr_latency -- Latency Constrained Variable Bitrate # vbr_latency -- Latency Constrained Variable Bitrate
# vbr_peak -- Peak Contrained Variable Bitrate # vbr_peak -- Peak Contrained Variable Bitrate
# cbr -- constant bitrate # cbr -- constant bitrate
########################## ##########################
# amd_rc = auto # amd_rc = auto
###### h264 entropy ###### ###### h264 entropy ######
# auto -- let ffmpeg nvenc decide the entropy encoding # auto -- let ffmpeg nvenc decide the entropy encoding
# cabac # cabac
# cavlc # cavlc
########################## ##########################
# amd_coder = auto # amd_coder = auto
#################################### VAAPI ################################### #################################### VAAPI ###################################
####### adapter ########## ####### adapter ##########
# Unlike with `amdvce` and `nvenc`, it doesn't matter if video encoding is done # Unlike with `amdvce` and `nvenc`, it doesn't matter if video encoding is done
# on a different GPU. # on a different GPU.
# Run the following commands: # Run the following commands:
# 1. ls /dev/dri/renderD* # 1. ls /dev/dri/renderD*
# to find all devices capable of VAAPI # to find all devices capable of VAAPI
# 2. vainfo --display drm --device /dev/dri/renderD129 | grep -E "((VAProfileH264High|VAProfileHEVCMain|VAProfileHEVCMain10).*VAEntrypointEncSlice)|Driver version" # 2. vainfo --display drm --device /dev/dri/renderD129 | grep -E "((VAProfileH264High|VAProfileHEVCMain|VAProfileHEVCMain10).*VAEntrypointEncSlice)|Driver version"
# Lists the name and capabilities of the device. # Lists the name and capabilities of the device.
# To be supported by Sunshine, it needs to have at the very minimum: # To be supported by Sunshine, it needs to have at the very minimum:
# VAProfileH264High : VAEntrypointEncSlice # VAProfileH264High : VAEntrypointEncSlice
# adapter_name = /dev/dri/renderD128 # adapter_name = /dev/dri/renderD128
############################################## ##############################################
# Some configurable parameters, are merely toggles for specific features # Some configurable parameters, are merely toggles for specific features
# The first occurrence turns it on, the second occurence turns it off, the third occurence turns it on again, etc, etc # The first occurrence turns it on, the second occurence turns it off, the third occurence turns it on again, etc, etc
# Here, you change the default state of any flag # Here, you change the default state of any flag
# #
# To set the initial state of flags -0 and -1 to on, set the following flags: # To set the initial state of flags -0 and -1 to on, set the following flags:
# flags = 012 # flags = 012
# #
# See: sunshine --help for all options under the header: flags # See: sunshine --help for all options under the header: flags

View File

@@ -4,12 +4,12 @@
#include <codecvt> #include <codecvt>
#include "display.h"
#include "misc.h"
#include "sunshine/config.h" #include "sunshine/config.h"
#include "sunshine/main.h" #include "sunshine/main.h"
#include "sunshine/platform/common.h" #include "sunshine/platform/common.h"
#include "display.h"
namespace platf { namespace platf {
using namespace std::literals; using namespace std::literals;
} }
@@ -91,6 +91,9 @@ int display_base_t::init() {
}); });
*/ */
// Ensure we can duplicate the current display
syncThreadDesktop();
// Get rectangle of full desktop for absolute mouse coordinates // Get rectangle of full desktop for absolute mouse coordinates
env_width = GetSystemMetrics(SM_CXVIRTUALSCREEN); env_width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
env_height = GetSystemMetrics(SM_CYVIRTUALSCREEN); env_height = GetSystemMetrics(SM_CYVIRTUALSCREEN);

View File

@@ -4,20 +4,20 @@
#include <ViGEm/Client.h> #include <ViGEm/Client.h>
#include "misc.h"
#include "sunshine/main.h" #include "sunshine/main.h"
#include "sunshine/platform/common.h" #include "sunshine/platform/common.h"
namespace platf { namespace platf {
using namespace std::literals; using namespace std::literals;
volatile HDESK _lastKnownInputDesktop = NULL; thread_local HDESK _lastKnownInputDesktop = nullptr;
constexpr touch_port_t target_touch_port { constexpr touch_port_t target_touch_port {
0, 0, 0, 0,
65535, 65535 65535, 65535
}; };
HDESK pairInputDesktop();
class vigem_t { class vigem_t {
public: public:
using client_t = util::safe_ptr<_VIGEM_CLIENT_T, vigem_free>; using client_t = util::safe_ptr<_VIGEM_CLIENT_T, vigem_free>;
@@ -102,12 +102,12 @@ void send_input(INPUT &i) {
retry: retry:
auto send = SendInput(1, &i, sizeof(INPUT)); auto send = SendInput(1, &i, sizeof(INPUT));
if(send != 1) { if(send != 1) {
auto hDesk = pairInputDesktop(); auto hDesk = syncThreadDesktop();
if(_lastKnownInputDesktop != hDesk) { if(_lastKnownInputDesktop != hDesk) {
_lastKnownInputDesktop = hDesk; _lastKnownInputDesktop = hDesk;
goto retry; goto retry;
} }
BOOST_LOG(warning) << "Couldn't send input"sv; BOOST_LOG(error) << "Couldn't send input"sv;
} }
} }
void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) { void abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) {
@@ -281,29 +281,6 @@ void gamepad(input_t &input, int nr, const gamepad_state_t &gamepad_state) {
} }
} }
int thread_priority() {
return SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST) ? 0 : 1;
}
HDESK pairInputDesktop() {
auto hDesk = OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, FALSE, GENERIC_ALL);
if(NULL == hDesk) {
auto err = GetLastError();
BOOST_LOG(error) << "Failed to OpenInputDesktop [0x"sv << util::hex(err).to_string_view() << ']';
}
else {
BOOST_LOG(info) << std::endl
<< "Opened desktop [0x"sv << util::hex(hDesk).to_string_view() << ']';
if(!SetThreadDesktop(hDesk)) {
auto err = GetLastError();
BOOST_LOG(error) << "Failed to SetThreadDesktop [0x"sv << util::hex(err).to_string_view() << ']';
}
CloseDesktop(hDesk);
}
return hDesk;
}
void freeInput(void *p) { void freeInput(void *p) {
auto vigem = (vigem_t *)p; auto vigem = (vigem_t *)p;

View File

@@ -87,4 +87,37 @@ std::string get_mac_address(const std::string_view &address) {
BOOST_LOG(warning) << "Unable to find MAC address for "sv << address; BOOST_LOG(warning) << "Unable to find MAC address for "sv << address;
return "00:00:00:00:00:00"s; return "00:00:00:00:00:00"s;
} }
HDESK syncThreadDesktop() {
auto hDesk = OpenInputDesktop(DF_ALLOWOTHERACCOUNTHOOK, FALSE, GENERIC_ALL);
if(!hDesk) {
auto err = GetLastError();
BOOST_LOG(error) << "Failed to Open Input Desktop [0x"sv << util::hex(err).to_string_view() << ']';
return nullptr;
}
if(!SetThreadDesktop(hDesk)) {
auto err = GetLastError();
BOOST_LOG(error) << "Failed to sync desktop to thread [0x"sv << util::hex(err).to_string_view() << ']';
}
CloseDesktop(hDesk);
return hDesk;
}
void print_status(const std::string_view &prefix, HRESULT status) {
char err_string[1024];
DWORD bytes = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
status,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
err_string,
sizeof(err_string),
nullptr);
BOOST_LOG(error) << prefix << ": "sv << std::string_view { err_string, bytes };
}
} // namespace platf } // namespace platf

View File

@@ -7,14 +7,14 @@
#include <boost/asio/ip/host_name.hpp> #include <boost/asio/ip/host_name.hpp>
#include "misc.h"
#include "sunshine/config.h" #include "sunshine/config.h"
#include "sunshine/main.h" #include "sunshine/main.h"
#include "sunshine/network.h"
#include "sunshine/nvhttp.h" #include "sunshine/nvhttp.h"
#include "sunshine/platform/common.h" #include "sunshine/platform/common.h"
#include "sunshine/thread_safe.h" #include "sunshine/thread_safe.h"
#include "sunshine/network.h"
using namespace std::literals; using namespace std::literals;
@@ -96,20 +96,6 @@ PDNS_SERVICE_INSTANCE DnsServiceConstructInstance(
_In_reads_(dwPropertiesCount) PCWSTR *values); _In_reads_(dwPropertiesCount) PCWSTR *values);
} /* extern "C" */ } /* extern "C" */
void print_status(const std::string_view &prefix, HRESULT status) {
char err_string[1024];
DWORD bytes = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
status,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
err_string,
sizeof(err_string),
nullptr);
BOOST_LOG(error) << prefix << ": "sv << std::string_view { err_string, bytes };
}
namespace platf::publish { namespace platf::publish {
VOID WINAPI register_cb(DWORD status, PVOID pQueryContext, PDNS_SERVICE_INSTANCE pInstance) { VOID WINAPI register_cb(DWORD status, PVOID pQueryContext, PDNS_SERVICE_INSTANCE pInstance) {
auto alarm = (safe::alarm_t<DNS_STATUS>::element_type *)pQueryContext; auto alarm = (safe::alarm_t<DNS_STATUS>::element_type *)pQueryContext;