mirror of
https://github.com/LizardByte/Sunshine.git
synced 2025-08-10 00:52:16 +00:00
Compare commits
4 Commits
v2025.805.
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fc7b9e30c8 | ||
|
|
dbe80d0f92 | ||
|
|
a28c20df18 | ||
|
|
4503fea7fb |
2
.github/workflows/ci-copr.yml
vendored
2
.github/workflows/ci-copr.yml
vendored
@@ -49,7 +49,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
path: artifacts
|
||||
pattern: build-*
|
||||
|
||||
2
.github/workflows/ci-homebrew.yml
vendored
2
.github/workflows/ci-homebrew.yml
vendored
@@ -36,8 +36,6 @@ jobs:
|
||||
include:
|
||||
# https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories
|
||||
# while GitHub has larger macOS runners, they are not available for our repos :(
|
||||
- os_version: "13"
|
||||
os_name: "macos"
|
||||
- os_version: "14"
|
||||
os_name: "macos"
|
||||
- os_version: "15"
|
||||
|
||||
9
.github/workflows/ci.yml
vendored
9
.github/workflows/ci.yml
vendored
@@ -56,6 +56,7 @@ jobs:
|
||||
uses: LizardByte/.github/.github/workflows/__call-docker.yml@master
|
||||
with:
|
||||
maximize_build_space: true
|
||||
maximize_build_space_root_reserve_size: 32768
|
||||
publish_release: ${{ needs.release-setup.outputs.publish_release }}
|
||||
release_commit: ${{ needs.release-setup.outputs.release_commit }}
|
||||
release_tag: ${{ needs.release-setup.outputs.release_tag }}
|
||||
@@ -136,8 +137,6 @@ jobs:
|
||||
include:
|
||||
- name: Linux-AppImage
|
||||
coverage: true
|
||||
- name: Homebrew-macos-13
|
||||
coverage: false
|
||||
- name: Homebrew-macos-14
|
||||
coverage: false
|
||||
- name: Homebrew-macos-15
|
||||
@@ -151,7 +150,7 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Download coverage artifact
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: coverage-${{ matrix.name }}
|
||||
path: _coverage
|
||||
@@ -192,7 +191,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
path: artifacts
|
||||
pattern: build-*
|
||||
@@ -225,7 +224,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download homebrew artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
uses: actions/download-artifact@v5
|
||||
with:
|
||||
name: beta-Homebrew
|
||||
path: homebrew
|
||||
|
||||
@@ -72,13 +72,13 @@ LizardByte has the full documentation hosted on [Read the Docs](https://docs.liz
|
||||
<td>Windows: 10+ (Windows Server does not support virtual gamepads)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>macOS: 13+</td>
|
||||
<td>macOS: 14+</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Linux/Debian: 12+ (bookworm)</td>
|
||||
<td>Linux/Debian: 13+ (trixie)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Linux/Fedora: 40+</td>
|
||||
<td>Linux/Fedora: 41+</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Linux/Ubuntu: 22.04+ (jammy)</td>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
# platforms: linux/amd64
|
||||
# platforms_pr: linux/amd64
|
||||
# no-cache-filters: toolchain-base,toolchain
|
||||
ARG BASE=ubuntu
|
||||
ARG TAG=22.04
|
||||
ARG BASE=debian
|
||||
ARG TAG=trixie-slim
|
||||
FROM ${BASE}:${TAG} AS toolchain-base
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
@@ -25,11 +25,11 @@ set -e
|
||||
apt-get update -y
|
||||
apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
cmake=3.22.* \
|
||||
cmake=3.31.* \
|
||||
ca-certificates \
|
||||
doxygen \
|
||||
gcc=4:11.2.* \
|
||||
g++=4:11.2.* \
|
||||
gcc=4:14.2.* \
|
||||
g++=4:14.2.* \
|
||||
gdb \
|
||||
git \
|
||||
graphviz \
|
||||
@@ -59,20 +59,13 @@ apt-get install -y --no-install-recommends \
|
||||
xvfb
|
||||
apt-get clean
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# Install Node
|
||||
wget --max-redirect=0 -qO- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash
|
||||
source "$HOME/.nvm/nvm.sh"
|
||||
nvm install node
|
||||
nvm use node
|
||||
nvm alias default node
|
||||
_DEPS
|
||||
|
||||
# install cuda
|
||||
WORKDIR /build/cuda
|
||||
# versions: https://developer.nvidia.com/cuda-toolkit-archive
|
||||
ENV CUDA_VERSION="11.8.0"
|
||||
ENV CUDA_BUILD="520.61.05"
|
||||
ENV CUDA_VERSION="12.9.1"
|
||||
ENV CUDA_BUILD="575.57.08"
|
||||
RUN <<_INSTALL_CUDA
|
||||
#!/bin/bash
|
||||
set -e
|
||||
@@ -83,18 +76,31 @@ if [[ "${TARGETPLATFORM}" == 'linux/arm64' ]]; then
|
||||
fi
|
||||
url="${cuda_prefix}${CUDA_VERSION}/local_installers/cuda_${CUDA_VERSION}_${CUDA_BUILD}_linux${cuda_suffix}.run"
|
||||
echo "cuda url: ${url}"
|
||||
wget "$url" --progress=bar:force:noscroll -q --show-progress -O ./cuda.run
|
||||
chmod a+x ./cuda.run
|
||||
./cuda.run --silent --toolkit --toolkitpath=/usr/local --no-opengl-libs --no-man-page --no-drm
|
||||
rm ./cuda.run
|
||||
tmpfile="/tmp/cuda.run"
|
||||
wget "$url" --progress=bar:force:noscroll --show-progress -O "$tmpfile"
|
||||
chmod a+x "${tmpfile}"
|
||||
"${tmpfile}" --silent --toolkit --toolkitpath=/usr/local --no-opengl-libs --no-man-page --no-drm
|
||||
rm -f "${tmpfile}"
|
||||
_INSTALL_CUDA
|
||||
|
||||
WORKDIR /
|
||||
# Write a shell script that starts Xvfb and then runs a shell
|
||||
# install node
|
||||
RUN <<_INSTALL_NODE
|
||||
#!/bin/bash
|
||||
set -e
|
||||
wget --max-redirect=0 -qO- https://raw.githubusercontent.com/nvm-sh/nvm/master/install.sh | bash
|
||||
source "$HOME/.nvm/nvm.sh"
|
||||
nvm install node
|
||||
nvm use node
|
||||
nvm alias default node
|
||||
_INSTALL_NODE
|
||||
|
||||
WORKDIR /toolchain
|
||||
# Create a shell script that starts Xvfb and then runs a shell
|
||||
RUN <<_ENTRYPOINT
|
||||
#!/bin/bash
|
||||
set -e
|
||||
cat <<EOF > /entrypoint.sh
|
||||
cat <<EOF > entrypoint.sh
|
||||
#!/bin/bash
|
||||
Xvfb ${DISPLAY} -screen 0 1024x768x24 &
|
||||
if [ "\$#" -eq 0 ]; then
|
||||
@@ -105,11 +111,11 @@ fi
|
||||
EOF
|
||||
|
||||
# Make the script executable
|
||||
chmod +x /entrypoint.sh
|
||||
chmod +x entrypoint.sh
|
||||
|
||||
# Note about CLion
|
||||
echo "ATTENTION: CLion will override the entrypoint, you can disable this in the toolchain settings"
|
||||
_ENTRYPOINT
|
||||
|
||||
# Use the shell script as the entrypoint
|
||||
ENTRYPOINT ["/entrypoint.sh"]
|
||||
ENTRYPOINT ["/toolchain/entrypoint.sh"]
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
# platforms_pr: linux/amd64
|
||||
# no-cache-filters: sunshine-base,artifacts,sunshine
|
||||
ARG BASE=debian
|
||||
ARG TAG=bookworm
|
||||
ARG TAG=trixie
|
||||
FROM ${BASE}:${TAG} AS sunshine-base
|
||||
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
@@ -32,6 +32,7 @@ RUN <<_BUILD
|
||||
set -e
|
||||
chmod +x ./scripts/linux_build.sh
|
||||
./scripts/linux_build.sh \
|
||||
--cuda-patches \
|
||||
--publisher-name='LizardByte' \
|
||||
--publisher-website='https://app.lizardbyte.dev' \
|
||||
--publisher-issue-url='https://app.lizardbyte.dev/support' \
|
||||
@@ -35,7 +35,8 @@ chmod +x ./scripts/linux_build.sh
|
||||
--publisher-name='LizardByte' \
|
||||
--publisher-website='https://app.lizardbyte.dev' \
|
||||
--publisher-issue-url='https://app.lizardbyte.dev/support' \
|
||||
--sudo-off
|
||||
--sudo-off \
|
||||
--ubuntu-test-repo
|
||||
apt-get clean
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
_BUILD
|
||||
|
||||
@@ -3,6 +3,15 @@ Sunshine binaries are built using [CMake](https://cmake.org) and requires `cmake
|
||||
|
||||
## Building Locally
|
||||
|
||||
### Compiler
|
||||
It is recommended to use one of the following compilers:
|
||||
|
||||
| Compiler | Version |
|
||||
|:------------|:--------|
|
||||
| GCC | 13+ |
|
||||
| Clang | 17+ |
|
||||
| Apple Clang | 15+ |
|
||||
|
||||
### Dependencies
|
||||
|
||||
#### Linux
|
||||
@@ -16,7 +25,7 @@ Sunshine requires CUDA Toolkit for NVFBC capture. There are two caveats to CUDA:
|
||||
|
||||
1. The version installed depends on the version of GCC.
|
||||
2. The version of CUDA you use will determine compatibility with various GPU generations.
|
||||
At the time of writing, the recommended version to use is CUDA ~11.8.
|
||||
At the time of writing, the recommended version to use is CUDA ~12.9.
|
||||
See [CUDA compatibility](https://docs.nvidia.com/deploy/cuda-compatibility/index.html) for more info.
|
||||
|
||||
@tip{To install older versions, select the appropriate run file based on your desired CUDA version and architecture
|
||||
|
||||
@@ -31,7 +31,7 @@ See [Docker](../DOCKER_README.md) for more information.
|
||||
CUDA is used for NVFBC capture.
|
||||
|
||||
@tip{See [CUDA GPUS](https://developer.nvidia.com/cuda-gpus) to cross-reference Compute Capability to your GPU.
|
||||
The table below applies to packages provided by LizardByte. If you use an official LizardByte package then you do not
|
||||
The table below applies to packages provided by LizardByte. If you use an official LizardByte package, then you do not
|
||||
need to install CUDA.}
|
||||
|
||||
<table>
|
||||
@@ -43,9 +43,9 @@ need to install CUDA.}
|
||||
<th>Package</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="3">11.8.0</td>
|
||||
<td rowspan="3">450.80.02</td>
|
||||
<td rowspan="3">35;50;52;60;61;62;70;72;75;80;86;87;89;90</td>
|
||||
<td rowspan="8">12.9.1</td>
|
||||
<td rowspan="8">575.57.08</td>
|
||||
<td rowspan="8">50;52;60;61;62;70;72;75;80;86;87;89;90</td>
|
||||
<td>sunshine.AppImage</td>
|
||||
</tr>
|
||||
<tr>
|
||||
@@ -55,27 +55,18 @@ need to install CUDA.}
|
||||
<td>sunshine-ubuntu-24.04-{arch}.deb</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="1">12.0.0</td>
|
||||
<td rowspan="1">525.60.13</td>
|
||||
<td rowspan="5">50;52;60;61;62;70;72;75;80;86;87;89;90</td>
|
||||
<td>sunshine-debian-bookworm-{arch}.deb</td>
|
||||
<td>sunshine-debian-trixie-{arch}.deb</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="2">12.6.2</td>
|
||||
<td rowspan="2">560.35.03</td>
|
||||
<td>sunshine_{arch}.flatpak</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Sunshine (copr - Fedora 41)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="1">12.8.1</td>
|
||||
<td rowspan="1">570.124.06</td>
|
||||
<td>Sunshine (copr - Fedora 42)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td rowspan="1">12.9.1</td>
|
||||
<td rowspan="1">575.57.08</td>
|
||||
<td>sunshine.pkg.tar.zst</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -89,13 +80,15 @@ According to AppImageLint the supported distro matrix of the AppImage is below.
|
||||
- ✔ Debian bookworm
|
||||
- ✔ Debian trixie
|
||||
- ✔ Debian sid
|
||||
- ✔ Ubuntu plucky
|
||||
- ✔ Ubuntu noble
|
||||
- ✔ Ubuntu jammy
|
||||
- ✖ Ubuntu focal
|
||||
- ✖ Ubuntu bionic
|
||||
- ✖ Ubuntu xenial
|
||||
- ✖ Ubuntu trusty
|
||||
- ✖ CentOS 7
|
||||
- ✖ Rocky Linux 8
|
||||
- ✖ Rocky Linux 9
|
||||
|
||||
##### Install
|
||||
1. Download [sunshine.AppImage](https://github.com/LizardByte/Sunshine/releases/latest/download/sunshine.AppImage)
|
||||
|
||||
@@ -56,18 +56,18 @@ BuildRequires: which
|
||||
BuildRequires: xorg-x11-server-Xvfb
|
||||
|
||||
# Conditional BuildRequires for cuda-gcc based on Fedora version
|
||||
%if 0%{?fedora} >= 40 && 0%{?fedora} <= 41
|
||||
%if 0%{?fedora} <= 41
|
||||
BuildRequires: gcc13
|
||||
BuildRequires: gcc13-c++
|
||||
%global gcc_version 13
|
||||
%global cuda_version 12.6.3
|
||||
%global cuda_build 560.35.05
|
||||
%global cuda_version 12.9.1
|
||||
%global cuda_build 575.57.08
|
||||
%elif %{?fedora} >= 42
|
||||
BuildRequires: gcc14
|
||||
BuildRequires: gcc14-c++
|
||||
%global gcc_version 14
|
||||
%global cuda_version 12.8.1
|
||||
%global cuda_build 570.124.06
|
||||
%global cuda_version 12.9.1
|
||||
%global cuda_build 575.57.08
|
||||
%endif
|
||||
|
||||
%global cuda_dir %{_builddir}/cuda
|
||||
@@ -171,7 +171,7 @@ function install_cuda() {
|
||||
--backup \
|
||||
--directory="%{cuda_dir}" \
|
||||
--verbose \
|
||||
< "%{_builddir}/Sunshine/packaging/linux/fedora/patches/f42/${architecture}/01-math_functions.patch"
|
||||
< "%{_builddir}/Sunshine/packaging/linux/patches/${architecture}/01-math_functions.patch"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
"only-arches": [
|
||||
"x86_64"
|
||||
],
|
||||
"url": "https://developer.download.nvidia.com/compute/cuda/12.6.2/local_installers/cuda_12.6.2_560.35.03_linux.run",
|
||||
"sha256": "3729a89cb58f7ca6a46719cff110d6292aec7577585a8d71340f0dbac54fb237",
|
||||
"url": "https://developer.download.nvidia.com/compute/cuda/12.9.1/local_installers/cuda_12.9.1_575.57.08_linux.run",
|
||||
"sha256": "0f6d806ddd87230d2adbe8a6006a9d20144fdbda9de2d6acc677daa5d036417a",
|
||||
"dest-filename": "cuda.run"
|
||||
},
|
||||
{
|
||||
@@ -28,8 +28,8 @@
|
||||
"only-arches": [
|
||||
"aarch64"
|
||||
],
|
||||
"url": "https://developer.download.nvidia.com/compute/cuda/12.6.2/local_installers/cuda_12.6.2_560.35.03_linux_sbsa.run",
|
||||
"sha256": "2249408848b705c18b9eadfb5161b52e4e36fcc5753647329cce93db141e5466",
|
||||
"url": "https://developer.download.nvidia.com/compute/cuda/12.9.1/local_installers/cuda_12.9.1_575.57.08_linux_sbsa.run",
|
||||
"sha256": "64f47ab791a76b6889702425e0755385f5fa216c5a9f061875c7deed5f08cdb6",
|
||||
"dest-filename": "cuda.run"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -37,6 +37,10 @@ class @PROJECT_NAME@ < Formula
|
||||
depends_on "opus"
|
||||
depends_on "icu4c" => :recommended
|
||||
|
||||
on_macos do
|
||||
depends_on xcode: ["15.3", :build]
|
||||
end
|
||||
|
||||
on_linux do
|
||||
depends_on "avahi"
|
||||
depends_on "libayatana-appindicator"
|
||||
@@ -59,6 +63,16 @@ class @PROJECT_NAME@ < Formula
|
||||
depends_on "wayland"
|
||||
end
|
||||
|
||||
fails_with :clang do
|
||||
build 1400
|
||||
cause "Requires C++23 support"
|
||||
end
|
||||
|
||||
fails_with :gcc do
|
||||
version "12" # fails with GCC 12.x and earlier
|
||||
cause "Requires C++23 support"
|
||||
end
|
||||
|
||||
def install
|
||||
ENV["BRANCH"] = "@GITHUB_BRANCH@"
|
||||
ENV["BUILD_VERSION"] = "@BUILD_VERSION@"
|
||||
|
||||
@@ -3,6 +3,7 @@ set -e
|
||||
|
||||
# Default value for arguments
|
||||
appimage_build=0
|
||||
cuda_patches=0
|
||||
num_processors=$(nproc)
|
||||
publisher_name="Third Party Publisher"
|
||||
publisher_website=""
|
||||
@@ -28,6 +29,7 @@ Options:
|
||||
-h, --help Display this help message.
|
||||
-s, --sudo-off Disable sudo command.
|
||||
--appimage-build Compile for AppImage, this will not create the AppImage, just the executable.
|
||||
--cuda-patches Apply cuda patches.
|
||||
--num-processors The number of processors to use for compilation. Default is the value of 'nproc'.
|
||||
--publisher-name The name of the publisher (not developer) of the application.
|
||||
--publisher-website The URL of the publisher's website.
|
||||
@@ -55,6 +57,9 @@ while getopts ":hs-:" opt; do
|
||||
appimage_build=1
|
||||
skip_libva=1
|
||||
;;
|
||||
cuda-patches)
|
||||
cuda_patches=1
|
||||
;;
|
||||
num-processors=*)
|
||||
num_processors="${OPTARG#*=}"
|
||||
;;
|
||||
@@ -185,7 +190,15 @@ function add_debian_based_deps() {
|
||||
fi
|
||||
}
|
||||
|
||||
function add_test_ppa() {
|
||||
if [ "$ubuntu_test_repo" == 1 ]; then
|
||||
$package_install_command "software-properties-common"
|
||||
${sudo_cmd} add-apt-repository ppa:ubuntu-toolchain-r/test -y
|
||||
fi
|
||||
}
|
||||
|
||||
function add_debian_deps() {
|
||||
add_test_ppa
|
||||
add_debian_based_deps
|
||||
dependencies+=(
|
||||
"libayatana-appindicator3-dev"
|
||||
@@ -193,11 +206,7 @@ function add_debian_deps() {
|
||||
}
|
||||
|
||||
function add_ubuntu_deps() {
|
||||
if [ "$ubuntu_test_repo" == 1 ]; then
|
||||
# allow newer gcc
|
||||
${sudo_cmd} add-apt-repository ppa:ubuntu-toolchain-r/test -y
|
||||
fi
|
||||
|
||||
add_test_ppa
|
||||
add_debian_based_deps
|
||||
dependencies+=(
|
||||
"libappindicator3-dev"
|
||||
@@ -298,6 +307,24 @@ function install_cuda() {
|
||||
"${build_dir}/cuda.run" --silent --toolkit --toolkitpath="${build_dir}/cuda" --no-opengl-libs --no-man-page --no-drm
|
||||
rm "${build_dir}/cuda.run"
|
||||
nvcc_path="${build_dir}/cuda/bin/nvcc"
|
||||
|
||||
# run cuda patches
|
||||
if [ "$cuda_patches" == 1 ]; then
|
||||
echo "Applying CUDA patches"
|
||||
local patch_dir="${script_dir}/../packaging/linux/patches/${architecture}"
|
||||
if [ -d "$patch_dir" ]; then
|
||||
for patch in "$patch_dir"/*.patch; do
|
||||
echo "Applying patch: $patch"
|
||||
patch -p2 \
|
||||
--backup \
|
||||
--directory="${build_dir}/cuda" \
|
||||
--verbose \
|
||||
< "$patch"
|
||||
done
|
||||
else
|
||||
echo "No patches found for architecture: $architecture"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
||||
function check_version() {
|
||||
@@ -536,27 +563,26 @@ elif grep -q "Debian GNU/Linux 12 (bookworm)" /etc/os-release; then
|
||||
version="12"
|
||||
package_update_command="${sudo_cmd} apt-get update"
|
||||
package_install_command="${sudo_cmd} apt-get install -y"
|
||||
cuda_version="12.0.0"
|
||||
cuda_build="525.60.13"
|
||||
gcc_version="12"
|
||||
nvm_node=0
|
||||
elif grep -q "PLATFORM_ID=\"platform:f40\"" /etc/os-release; then
|
||||
distro="fedora"
|
||||
version="40"
|
||||
package_update_command="${sudo_cmd} dnf update -y"
|
||||
package_install_command="${sudo_cmd} dnf install -y"
|
||||
cuda_version=12.6.3
|
||||
cuda_build=560.35.05
|
||||
cuda_version="12.9.1"
|
||||
cuda_build="575.57.08"
|
||||
gcc_version="13"
|
||||
nvm_node=0
|
||||
dev_tools_group="Development Tools"
|
||||
elif grep -q "Debian GNU/Linux 13 (trixie)" /etc/os-release; then
|
||||
distro="debian"
|
||||
version="13"
|
||||
package_update_command="${sudo_cmd} apt-get update"
|
||||
package_install_command="${sudo_cmd} apt-get install -y"
|
||||
cuda_version="12.9.1"
|
||||
cuda_build="575.57.08"
|
||||
gcc_version="14"
|
||||
nvm_node=0
|
||||
elif grep -q "PLATFORM_ID=\"platform:f41\"" /etc/os-release; then
|
||||
distro="fedora"
|
||||
version="41"
|
||||
package_update_command="${sudo_cmd} dnf update -y"
|
||||
package_install_command="${sudo_cmd} dnf install -y"
|
||||
cuda_version=12.6.3
|
||||
cuda_build=560.35.05
|
||||
cuda_version="12.9.1"
|
||||
cuda_build="575.57.08"
|
||||
gcc_version="13"
|
||||
nvm_node=0
|
||||
dev_tools_group="development-tools"
|
||||
@@ -565,8 +591,8 @@ elif grep -q "PLATFORM_ID=\"platform:f42\"" /etc/os-release; then
|
||||
version="42"
|
||||
package_update_command="${sudo_cmd} dnf update -y"
|
||||
package_install_command="${sudo_cmd} dnf install -y"
|
||||
cuda_version=12.8.1
|
||||
cuda_build=570.124.06
|
||||
cuda_version="12.9.1"
|
||||
cuda_build="575.57.08"
|
||||
gcc_version="14"
|
||||
nvm_node=0
|
||||
dev_tools_group="development-tools"
|
||||
@@ -575,27 +601,27 @@ elif grep -q "Ubuntu 22.04" /etc/os-release; then
|
||||
version="22.04"
|
||||
package_update_command="${sudo_cmd} apt-get update"
|
||||
package_install_command="${sudo_cmd} apt-get install -y"
|
||||
cuda_version="11.8.0"
|
||||
cuda_build="520.61.05"
|
||||
gcc_version="11"
|
||||
cuda_version="12.9.1"
|
||||
cuda_build="575.57.08"
|
||||
gcc_version="13"
|
||||
nvm_node=1
|
||||
elif grep -q "Ubuntu 24.04" /etc/os-release; then
|
||||
distro="ubuntu"
|
||||
version="24.04"
|
||||
package_update_command="${sudo_cmd} apt-get update"
|
||||
package_install_command="${sudo_cmd} apt-get install -y"
|
||||
cuda_version="11.8.0"
|
||||
cuda_build="520.61.05"
|
||||
gcc_version="11"
|
||||
cuda_version="12.9.1"
|
||||
cuda_build="575.57.08"
|
||||
gcc_version="14"
|
||||
nvm_node=0
|
||||
elif grep -q "Ubuntu 25.04" /etc/os-release; then
|
||||
distro="ubuntu"
|
||||
version="25.04"
|
||||
package_update_command="${sudo_cmd} apt-get update"
|
||||
package_install_command="${sudo_cmd} apt-get install -y"
|
||||
cuda_version="11.8.0"
|
||||
cuda_build="520.61.05"
|
||||
gcc_version="11"
|
||||
cuda_version="12.9.1"
|
||||
cuda_build="575.57.08"
|
||||
gcc_version="14"
|
||||
nvm_node=0
|
||||
else
|
||||
echo "Unsupported Distro or Version"
|
||||
|
||||
@@ -1421,7 +1421,7 @@ namespace config {
|
||||
if (!service_ctrl::is_service_running()) {
|
||||
// If the service isn't running, relaunch ourselves as admin to start it
|
||||
WCHAR executable[MAX_PATH];
|
||||
GetModuleFileNameW(NULL, executable, ARRAYSIZE(executable));
|
||||
GetModuleFileNameW(nullptr, executable, ARRAYSIZE(executable));
|
||||
|
||||
SHELLEXECUTEINFOW shell_exec_info {};
|
||||
shell_exec_info.cbSize = sizeof(shell_exec_info);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
// standard includes
|
||||
#include <filesystem>
|
||||
#include <format>
|
||||
#include <fstream>
|
||||
#include <set>
|
||||
|
||||
@@ -713,7 +714,7 @@ namespace confighttp {
|
||||
if (const int max_index = static_cast<int>(apps_node.size()) - 1; max_index < 0) {
|
||||
error = "No applications to delete";
|
||||
} else {
|
||||
error = "'index' out of range, max index is "s + std::to_string(max_index);
|
||||
error = std::format("'index' {} out of range, max index is {}", index, max_index);
|
||||
}
|
||||
bad_request(response, request, error);
|
||||
return;
|
||||
@@ -730,7 +731,7 @@ namespace confighttp {
|
||||
proc::refresh(config::stream.file_apps);
|
||||
|
||||
output_tree["status"] = true;
|
||||
output_tree["result"] = "application " + std::to_string(index) + " deleted";
|
||||
output_tree["result"] = std::format("application {} deleted", index);
|
||||
send_response(response, output_tree);
|
||||
} catch (std::exception &e) {
|
||||
BOOST_LOG(warning) << "DeleteApp: "sv << e.what();
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
// standard includes
|
||||
#include <csignal>
|
||||
#include <format>
|
||||
#include <iostream>
|
||||
#include <thread>
|
||||
|
||||
@@ -25,13 +26,11 @@ extern "C" {
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
void launch_ui() {
|
||||
std::string url = "https://localhost:" + std::to_string(net::map_port(confighttp::PORT_HTTPS));
|
||||
platf::open_url(url);
|
||||
}
|
||||
|
||||
void launch_ui_with_path(std::string path) {
|
||||
std::string url = "https://localhost:" + std::to_string(net::map_port(confighttp::PORT_HTTPS)) + path;
|
||||
void launch_ui(const std::optional<std::string> &path) {
|
||||
std::string url = std::format("https://localhost:{}", static_cast<int>(net::map_port(confighttp::PORT_HTTPS)));
|
||||
if (path) {
|
||||
url += *path;
|
||||
}
|
||||
platf::open_url(url);
|
||||
}
|
||||
|
||||
@@ -192,8 +191,8 @@ namespace service_ctrl {
|
||||
}
|
||||
|
||||
private:
|
||||
SC_HANDLE scm_handle = NULL;
|
||||
SC_HANDLE service_handle = NULL;
|
||||
SC_HANDLE scm_handle = nullptr;
|
||||
SC_HANDLE service_handle = nullptr;
|
||||
};
|
||||
|
||||
bool is_service_running() {
|
||||
|
||||
@@ -14,19 +14,13 @@
|
||||
|
||||
/**
|
||||
* @brief Launch the Web UI.
|
||||
* @param path Optional path to append to the base URL.
|
||||
* @examples
|
||||
* launch_ui();
|
||||
* launch_ui("/pin");
|
||||
* @examples_end
|
||||
*/
|
||||
void launch_ui();
|
||||
|
||||
/**
|
||||
* @brief Launch the Web UI at a specific endpoint.
|
||||
* @examples
|
||||
* launch_ui_with_path("/pin");
|
||||
* @examples_end
|
||||
*/
|
||||
void launch_ui_with_path(std::string path);
|
||||
void launch_ui(const std::optional<std::string> &path = std::nullopt);
|
||||
|
||||
/**
|
||||
* @brief Functions for handling command line arguments.
|
||||
|
||||
@@ -186,7 +186,7 @@ int main(int argc, char *argv[]) {
|
||||
wnd_class.lpszClassName = "SunshineSessionMonitorClass";
|
||||
wnd_class.lpfnWndProc = SessionMonitorWindowProc;
|
||||
if (!RegisterClassA(&wnd_class)) {
|
||||
session_monitor_hwnd_promise.set_value(NULL);
|
||||
session_monitor_hwnd_promise.set_value(nullptr);
|
||||
BOOST_LOG(error) << "Failed to register session monitor window class"sv << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
// this include
|
||||
#include "nvenc_base.h"
|
||||
|
||||
// standard includes
|
||||
#include <format>
|
||||
|
||||
// local includes
|
||||
#include "src/config.h"
|
||||
#include "src/logging.h"
|
||||
@@ -427,7 +430,7 @@ namespace nvenc {
|
||||
extra += " two-pass";
|
||||
}
|
||||
if (config.vbv_percentage_increase > 0 && get_encoder_cap(NV_ENC_CAPS_SUPPORT_CUSTOM_VBV_BUF_SIZE)) {
|
||||
extra += " vbv+" + std::to_string(config.vbv_percentage_increase);
|
||||
extra += std::format(" vbv+{}", config.vbv_percentage_increase);
|
||||
}
|
||||
if (encoder_params.rfi) {
|
||||
extra += " rfi";
|
||||
@@ -439,7 +442,7 @@ namespace nvenc {
|
||||
extra += " spatial-aq";
|
||||
}
|
||||
if (enc_config.rcParams.enableMinQP) {
|
||||
extra += " qpmin=" + std::to_string(enc_config.rcParams.minQP.qpInterP);
|
||||
extra += std::format(" qpmin={}", enc_config.rcParams.minQP.qpInterP);
|
||||
}
|
||||
if (config.insert_filler_data) {
|
||||
extra += " filler-data";
|
||||
|
||||
@@ -12,13 +12,13 @@ namespace nvenc {
|
||||
|
||||
nvenc_d3d11::nvenc_d3d11(NV_ENC_DEVICE_TYPE device_type):
|
||||
nvenc_base(device_type) {
|
||||
async_event_handle = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
async_event_handle = CreateEvent(nullptr, FALSE, FALSE, nullptr);
|
||||
}
|
||||
|
||||
nvenc_d3d11::~nvenc_d3d11() {
|
||||
if (dll) {
|
||||
FreeLibrary(dll);
|
||||
dll = NULL;
|
||||
dll = nullptr;
|
||||
}
|
||||
if (async_event_handle) {
|
||||
CloseHandle(async_event_handle);
|
||||
@@ -36,7 +36,7 @@ namespace nvenc {
|
||||
constexpr auto dll_name = "nvEncodeAPI.dll";
|
||||
#endif
|
||||
|
||||
if ((dll = LoadLibraryEx(dll_name, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32))) {
|
||||
if ((dll = LoadLibraryEx(dll_name, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32))) {
|
||||
if (auto create_instance = (decltype(NvEncodeAPICreateInstance) *) GetProcAddress(dll, "NvEncodeAPICreateInstance")) {
|
||||
auto new_nvenc = std::make_unique<NV_ENCODE_API_FUNCTION_LIST>();
|
||||
new_nvenc->version = min_struct_version(NV_ENCODE_API_FUNCTION_LIST_VER);
|
||||
@@ -55,7 +55,7 @@ namespace nvenc {
|
||||
|
||||
if (dll) {
|
||||
FreeLibrary(dll);
|
||||
dll = NULL;
|
||||
dll = nullptr;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace nvenc {
|
||||
bool wait_for_async_event(uint32_t timeout_ms) override;
|
||||
|
||||
private:
|
||||
HMODULE dll = NULL;
|
||||
HMODULE dll = nullptr;
|
||||
};
|
||||
|
||||
} // namespace nvenc
|
||||
|
||||
@@ -63,7 +63,7 @@ namespace nvenc {
|
||||
|
||||
constexpr auto dll_name = "nvcuda.dll";
|
||||
|
||||
if ((cuda_functions.dll = LoadLibraryEx(dll_name, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32))) {
|
||||
if ((cuda_functions.dll = LoadLibraryEx(dll_name, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32))) {
|
||||
auto load_function = [&]<typename T>(T &location, auto symbol) -> bool {
|
||||
location = (T) GetProcAddress(cuda_functions.dll, symbol);
|
||||
return location != nullptr;
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace nvenc {
|
||||
|
||||
autopop_context push_context();
|
||||
|
||||
HMODULE dll = NULL;
|
||||
HMODULE dll = nullptr;
|
||||
const ID3D11DevicePtr d3d_device;
|
||||
ID3D11Texture2DPtr d3d_input_texture;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
// standard includes
|
||||
#include <filesystem>
|
||||
#include <format>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
@@ -154,7 +155,7 @@ namespace nvhttp {
|
||||
std::string get_arg(const args_t &args, const char *name, const char *default_value = nullptr) {
|
||||
auto it = args.find(name);
|
||||
if (it == std::end(args)) {
|
||||
if (default_value != NULL) {
|
||||
if (default_value != nullptr) {
|
||||
return std::string(default_value);
|
||||
}
|
||||
|
||||
@@ -636,7 +637,7 @@ namespace nvhttp {
|
||||
tree.put("root.<xmlattr>.status_code", 400);
|
||||
tree.put(
|
||||
"root.<xmlattr>.status_message",
|
||||
"Pin must be 4 digits, " + std::to_string(pin.size()) + " provided"
|
||||
std::format("Pin must be 4 digits, {} provided", pin.size())
|
||||
);
|
||||
return false;
|
||||
}
|
||||
@@ -896,7 +897,15 @@ namespace nvhttp {
|
||||
}
|
||||
|
||||
tree.put("root.<xmlattr>.status_code", 200);
|
||||
tree.put("root.sessionUrl0", launch_session->rtsp_url_scheme + net::addr_to_url_escaped_string(request->local_endpoint().address()) + ':' + std::to_string(net::map_port(rtsp_stream::RTSP_SETUP_PORT)));
|
||||
tree.put(
|
||||
"root.sessionUrl0",
|
||||
std::format(
|
||||
"{}{}:{}",
|
||||
launch_session->rtsp_url_scheme,
|
||||
net::addr_to_url_escaped_string(request->local_endpoint().address()),
|
||||
static_cast<int>(net::map_port(rtsp_stream::RTSP_SETUP_PORT))
|
||||
)
|
||||
);
|
||||
tree.put("root.gamesession", 1);
|
||||
|
||||
rtsp_stream::launch_session_raise(launch_session);
|
||||
@@ -978,7 +987,15 @@ namespace nvhttp {
|
||||
}
|
||||
|
||||
tree.put("root.<xmlattr>.status_code", 200);
|
||||
tree.put("root.sessionUrl0", launch_session->rtsp_url_scheme + net::addr_to_url_escaped_string(request->local_endpoint().address()) + ':' + std::to_string(net::map_port(rtsp_stream::RTSP_SETUP_PORT)));
|
||||
tree.put(
|
||||
"root.sessionUrl0",
|
||||
std::format(
|
||||
"{}{}:{}",
|
||||
launch_session->rtsp_url_scheme,
|
||||
net::addr_to_url_escaped_string(request->local_endpoint().address()),
|
||||
static_cast<int>(net::map_port(rtsp_stream::RTSP_SETUP_PORT))
|
||||
)
|
||||
);
|
||||
tree.put("root.resume", 1);
|
||||
|
||||
rtsp_stream::launch_session_raise(launch_session);
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
// standard includes
|
||||
#include <fcntl.h>
|
||||
#include <format>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
||||
@@ -574,7 +575,7 @@ namespace va {
|
||||
if (!display) {
|
||||
char string[1024];
|
||||
|
||||
auto bytes = readlink(("/proc/self/fd/" + std::to_string(fd)).c_str(), string, sizeof(string));
|
||||
auto bytes = readlink(std::format("/proc/self/fd/{}", fd).c_str(), string, sizeof(string));
|
||||
|
||||
std::string_view render_device {string, (std::size_t) bytes};
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
*/
|
||||
#define INITGUID
|
||||
|
||||
// standard includes
|
||||
#include <format>
|
||||
|
||||
// platform includes
|
||||
#include <Audioclient.h>
|
||||
#include <avrt.h>
|
||||
@@ -168,8 +171,7 @@ namespace {
|
||||
waveformat.SubFormat == KSDATAFORMAT_SUBTYPE_PCM ? "S" :
|
||||
"UNKNOWN";
|
||||
|
||||
result += std::to_string(waveformat.Samples.wValidBitsPerSample) + " " +
|
||||
std::to_string(waveformat.Format.nSamplesPerSec) + " ";
|
||||
result += std::format("{} {} ", static_cast<int>(waveformat.Samples.wValidBitsPerSample), static_cast<int>(waveformat.Format.nSamplesPerSec));
|
||||
|
||||
switch (waveformat.dwChannelMask) {
|
||||
case waveformat_mask_stereo:
|
||||
@@ -189,7 +191,7 @@ namespace {
|
||||
break;
|
||||
|
||||
default:
|
||||
result += std::to_string(waveformat.Format.nChannels) + " channels (unrecognized)";
|
||||
result += std::format("{} channels (unrecognized)", static_cast<int>(waveformat.Format.nChannels));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -375,7 +377,7 @@ namespace platf::audio {
|
||||
*ppvInterface = (IMMNotificationClient *) this;
|
||||
return S_OK;
|
||||
} else {
|
||||
*ppvInterface = NULL;
|
||||
*ppvInterface = nullptr;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
}
|
||||
@@ -677,7 +679,7 @@ namespace platf::audio {
|
||||
float *sample_buf_pos;
|
||||
int channels;
|
||||
|
||||
HANDLE mmcss_task_handle = NULL;
|
||||
HANDLE mmcss_task_handle = nullptr;
|
||||
};
|
||||
|
||||
class audio_control_t: public ::platf::audio_control_t {
|
||||
|
||||
@@ -601,12 +601,12 @@ namespace platf::dxgi {
|
||||
LUID val;
|
||||
|
||||
if (OpenProcessToken(GetCurrentProcess(), flags, &token) &&
|
||||
!!LookupPrivilegeValue(NULL, SE_INC_BASE_PRIORITY_NAME, &val)) {
|
||||
!!LookupPrivilegeValue(nullptr, SE_INC_BASE_PRIORITY_NAME, &val)) {
|
||||
tp.PrivilegeCount = 1;
|
||||
tp.Privileges[0].Luid = val;
|
||||
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
||||
|
||||
if (!AdjustTokenPrivileges(token, false, &tp, sizeof(tp), NULL, NULL)) {
|
||||
if (!AdjustTokenPrivileges(token, false, &tp, sizeof(tp), nullptr, nullptr)) {
|
||||
BOOST_LOG(warning) << "Could not set privilege to increase GPU priority";
|
||||
}
|
||||
}
|
||||
@@ -918,20 +918,20 @@ namespace platf::dxgi {
|
||||
"DXGI_FORMAT_A8P8",
|
||||
"DXGI_FORMAT_B4G4R4A4_UNORM",
|
||||
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
nullptr,
|
||||
|
||||
"DXGI_FORMAT_P208",
|
||||
"DXGI_FORMAT_V208",
|
||||
|
||||
@@ -1739,7 +1739,7 @@ namespace platf::dxgi {
|
||||
img->data = nullptr;
|
||||
if (img->encoder_texture_handle) {
|
||||
CloseHandle(img->encoder_texture_handle);
|
||||
img->encoder_texture_handle = NULL;
|
||||
img->encoder_texture_handle = nullptr;
|
||||
}
|
||||
|
||||
// Initialize format-dependent fields
|
||||
|
||||
@@ -293,7 +293,7 @@ namespace platf {
|
||||
|
||||
if (gamepad.repeat_task) {
|
||||
task_pool.cancel(gamepad.repeat_task);
|
||||
gamepad.repeat_task = 0;
|
||||
gamepad.repeat_task = nullptr;
|
||||
}
|
||||
|
||||
if (gamepad.gp && vigem_target_is_attached(gamepad.gp.get())) {
|
||||
@@ -1452,7 +1452,7 @@ namespace platf {
|
||||
// Cancel any pending updates. We will requeue one here when we're finished.
|
||||
if (gamepad.repeat_task) {
|
||||
task_pool.cancel(gamepad.repeat_task);
|
||||
gamepad.repeat_task = 0;
|
||||
gamepad.repeat_task = nullptr;
|
||||
}
|
||||
|
||||
if (gamepad.gp && vigem_target_is_attached(gamepad.gp.get())) {
|
||||
|
||||
@@ -117,7 +117,7 @@ namespace platf {
|
||||
|
||||
std::filesystem::path appdata() {
|
||||
WCHAR sunshine_path[MAX_PATH];
|
||||
GetModuleFileNameW(NULL, sunshine_path, _countof(sunshine_path));
|
||||
GetModuleFileNameW(nullptr, sunshine_path, _countof(sunshine_path));
|
||||
return std::filesystem::path {sunshine_path}.remove_filename() / L"config"sv;
|
||||
}
|
||||
|
||||
@@ -410,16 +410,16 @@ namespace platf {
|
||||
|
||||
LPPROC_THREAD_ATTRIBUTE_LIST allocate_proc_thread_attr_list(DWORD attribute_count) {
|
||||
SIZE_T size;
|
||||
InitializeProcThreadAttributeList(NULL, attribute_count, 0, &size);
|
||||
InitializeProcThreadAttributeList(nullptr, attribute_count, 0, &size);
|
||||
|
||||
auto list = (LPPROC_THREAD_ATTRIBUTE_LIST) HeapAlloc(GetProcessHeap(), 0, size);
|
||||
if (list == NULL) {
|
||||
return NULL;
|
||||
if (list == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!InitializeProcThreadAttributeList(list, attribute_count, 0, &size)) {
|
||||
HeapFree(GetProcessHeap(), 0, list);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return list;
|
||||
@@ -518,7 +518,7 @@ namespace platf {
|
||||
|
||||
// Allocate a process attribute list with space for 2 elements
|
||||
startup_info.lpAttributeList = allocate_proc_thread_attr_list(2);
|
||||
if (startup_info.lpAttributeList == NULL) {
|
||||
if (startup_info.lpAttributeList == nullptr) {
|
||||
// If the allocation failed, set ec to an appropriate error code and return the structure
|
||||
ec = std::make_error_code(std::errc::not_enough_memory);
|
||||
return startup_info;
|
||||
@@ -530,7 +530,7 @@ namespace platf {
|
||||
|
||||
// Populate std handles if the caller gave us a log file to use
|
||||
startup_info.StartupInfo.dwFlags |= STARTF_USESTDHANDLES;
|
||||
startup_info.StartupInfo.hStdInput = NULL;
|
||||
startup_info.StartupInfo.hStdInput = nullptr;
|
||||
startup_info.StartupInfo.hStdOutput = log_file_handle;
|
||||
startup_info.StartupInfo.hStdError = log_file_handle;
|
||||
|
||||
@@ -539,7 +539,7 @@ namespace platf {
|
||||
//
|
||||
// Note: The value we point to here must be valid for the lifetime of the attribute list,
|
||||
// so we need to point into the STARTUPINFO instead of our log_file_variable on the stack.
|
||||
UpdateProcThreadAttribute(startup_info.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &startup_info.StartupInfo.hStdOutput, sizeof(startup_info.StartupInfo.hStdOutput), NULL, NULL);
|
||||
UpdateProcThreadAttribute(startup_info.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &startup_info.StartupInfo.hStdOutput, sizeof(startup_info.StartupInfo.hStdOutput), nullptr, nullptr);
|
||||
}
|
||||
|
||||
if (job) {
|
||||
@@ -547,7 +547,7 @@ namespace platf {
|
||||
//
|
||||
// Note: The value we point to here must be valid for the lifetime of the attribute list,
|
||||
// so we take a HANDLE* instead of just a HANDLE to use the caller's stack storage.
|
||||
UpdateProcThreadAttribute(startup_info.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, job, sizeof(*job), NULL, NULL);
|
||||
UpdateProcThreadAttribute(startup_info.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, job, sizeof(*job), nullptr, nullptr);
|
||||
}
|
||||
|
||||
return startup_info;
|
||||
@@ -555,11 +555,11 @@ namespace platf {
|
||||
|
||||
/**
|
||||
* @brief This function overrides HKEY_CURRENT_USER and HKEY_CLASSES_ROOT using the provided token.
|
||||
* @param token The primary token identifying the user to use, or `NULL` to restore original keys.
|
||||
* @param token The primary token identifying the user to use, or `nullptr` to restore original keys.
|
||||
* @return `true` if the override or restore operation was successful.
|
||||
*/
|
||||
bool override_per_user_predefined_keys(HANDLE token) {
|
||||
HKEY user_classes_root = NULL;
|
||||
HKEY user_classes_root = nullptr;
|
||||
if (token) {
|
||||
auto err = RegOpenUserClassesRoot(token, 0, GENERIC_ALL, &user_classes_root);
|
||||
if (err != ERROR_SUCCESS) {
|
||||
@@ -573,14 +573,14 @@ namespace platf {
|
||||
}
|
||||
});
|
||||
|
||||
HKEY user_key = NULL;
|
||||
HKEY user_key = nullptr;
|
||||
if (token) {
|
||||
impersonate_current_user(token, [&]() {
|
||||
// RegOpenCurrentUser() doesn't take a token. It assumes we're impersonating the desired user.
|
||||
auto err = RegOpenCurrentUser(GENERIC_ALL, &user_key);
|
||||
if (err != ERROR_SUCCESS) {
|
||||
BOOST_LOG(error) << "Failed to open user key for target user: "sv << err;
|
||||
user_key = NULL;
|
||||
user_key = nullptr;
|
||||
}
|
||||
});
|
||||
if (!user_key) {
|
||||
@@ -602,7 +602,7 @@ namespace platf {
|
||||
err = RegOverridePredefKey(HKEY_CURRENT_USER, user_key);
|
||||
if (err != ERROR_SUCCESS) {
|
||||
BOOST_LOG(error) << "Failed to override HKEY_CURRENT_USER: "sv << err;
|
||||
RegOverridePredefKey(HKEY_CLASSES_ROOT, NULL);
|
||||
RegOverridePredefKey(HKEY_CLASSES_ROOT, nullptr);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -671,7 +671,7 @@ namespace platf {
|
||||
* @details This converts URLs and non-executable file paths into a runnable command like ShellExecute().
|
||||
* @param raw_cmd The raw command provided by the user.
|
||||
* @param working_dir The working directory for the new process.
|
||||
* @param token The user token currently being impersonated or `NULL` if running as ourselves.
|
||||
* @param token The user token currently being impersonated or `nullptr` if running as ourselves.
|
||||
* @param creation_flags The creation flags for CreateProcess(), which may be modified by this function.
|
||||
* @return A command string suitable for use by CreateProcess().
|
||||
*/
|
||||
@@ -757,7 +757,7 @@ namespace platf {
|
||||
}
|
||||
|
||||
// Reset per-user keys back to the original value
|
||||
override_per_user_predefined_keys(NULL);
|
||||
override_per_user_predefined_keys(nullptr);
|
||||
}
|
||||
|
||||
if (res != S_OK) {
|
||||
@@ -972,7 +972,7 @@ namespace platf {
|
||||
ec = impersonate_current_user(user_token, [&]() {
|
||||
std::wstring env_block = create_environment_block(cloned_env);
|
||||
std::wstring wcmd = resolve_command_string(cmd, start_dir, user_token, creation_flags);
|
||||
ret = CreateProcessAsUserW(user_token, NULL, (LPWSTR) wcmd.c_str(), NULL, NULL, !!(startup_info.StartupInfo.dwFlags & STARTF_USESTDHANDLES), creation_flags, env_block.data(), start_dir.empty() ? NULL : start_dir.c_str(), (LPSTARTUPINFOW) &startup_info, &process_info);
|
||||
ret = CreateProcessAsUserW(user_token, nullptr, (LPWSTR) wcmd.c_str(), nullptr, nullptr, !!(startup_info.StartupInfo.dwFlags & STARTF_USESTDHANDLES), creation_flags, env_block.data(), start_dir.empty() ? nullptr : start_dir.c_str(), (LPSTARTUPINFOW) &startup_info, &process_info);
|
||||
});
|
||||
}
|
||||
// Otherwise, launch the process using CreateProcessW()
|
||||
@@ -995,8 +995,8 @@ namespace platf {
|
||||
}
|
||||
|
||||
std::wstring env_block = create_environment_block(cloned_env);
|
||||
std::wstring wcmd = resolve_command_string(cmd, start_dir, NULL, creation_flags);
|
||||
ret = CreateProcessW(NULL, (LPWSTR) wcmd.c_str(), NULL, NULL, !!(startup_info.StartupInfo.dwFlags & STARTF_USESTDHANDLES), creation_flags, env_block.data(), start_dir.empty() ? NULL : start_dir.c_str(), (LPSTARTUPINFOW) &startup_info, &process_info);
|
||||
std::wstring wcmd = resolve_command_string(cmd, start_dir, nullptr, creation_flags);
|
||||
ret = CreateProcessW(nullptr, (LPWSTR) wcmd.c_str(), nullptr, nullptr, !!(startup_info.StartupInfo.dwFlags & STARTF_USESTDHANDLES), creation_flags, env_block.data(), start_dir.empty() ? nullptr : start_dir.c_str(), (LPSTARTUPINFOW) &startup_info, &process_info);
|
||||
}
|
||||
|
||||
// Use the results of the launch to create a bp::child object
|
||||
@@ -1052,7 +1052,7 @@ namespace platf {
|
||||
static std::once_flag load_wlanapi_once_flag;
|
||||
std::call_once(load_wlanapi_once_flag, []() {
|
||||
// wlanapi.dll is not installed by default on Windows Server, so we load it dynamically
|
||||
HMODULE wlanapi = LoadLibraryExA("wlanapi.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
HMODULE wlanapi = LoadLibraryExA("wlanapi.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
if (!wlanapi) {
|
||||
BOOST_LOG(debug) << "wlanapi.dll is not available on this OS"sv;
|
||||
return;
|
||||
@@ -1129,7 +1129,7 @@ namespace platf {
|
||||
fn_WlanFreeMemory(wlan_interface_list);
|
||||
} else {
|
||||
fn_WlanCloseHandle(wlan_handle, nullptr);
|
||||
wlan_handle = NULL;
|
||||
wlan_handle = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1200,7 +1200,7 @@ namespace platf {
|
||||
startup_info.StartupInfo.cb = sizeof(startup_info);
|
||||
|
||||
WCHAR executable[MAX_PATH];
|
||||
if (GetModuleFileNameW(NULL, executable, ARRAYSIZE(executable)) == 0) {
|
||||
if (GetModuleFileNameW(nullptr, executable, ARRAYSIZE(executable)) == 0) {
|
||||
auto winerr = GetLastError();
|
||||
BOOST_LOG(fatal) << "Failed to get Sunshine path: "sv << winerr;
|
||||
return;
|
||||
@@ -1220,7 +1220,7 @@ namespace platf {
|
||||
void restart() {
|
||||
// If we're running standalone, we have to respawn ourselves via CreateProcess().
|
||||
// If we're running from the service, we should just exit and let it respawn us.
|
||||
if (GetConsoleWindow() != NULL) {
|
||||
if (GetConsoleWindow() != nullptr) {
|
||||
// Avoid racing with the new process by waiting until we're exiting to start it.
|
||||
atexit(restart_on_exit);
|
||||
}
|
||||
@@ -1538,7 +1538,7 @@ namespace platf {
|
||||
}
|
||||
|
||||
virtual ~qos_t() {
|
||||
if (!fn_QOSRemoveSocketFromFlow(qos_handle, (SOCKET) NULL, flow_id, 0)) {
|
||||
if (!fn_QOSRemoveSocketFromFlow(qos_handle, (SOCKET) nullptr, flow_id, 0)) {
|
||||
auto winerr = GetLastError();
|
||||
BOOST_LOG(warning) << "QOSRemoveSocketFromFlow() failed: "sv << winerr;
|
||||
}
|
||||
@@ -1570,7 +1570,7 @@ namespace platf {
|
||||
static std::once_flag load_qwave_once_flag;
|
||||
std::call_once(load_qwave_once_flag, []() {
|
||||
// qWAVE is not installed by default on Windows Server, so we load it dynamically
|
||||
HMODULE qwave = LoadLibraryExA("qwave.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
HMODULE qwave = LoadLibraryExA("qwave.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32);
|
||||
if (!qwave) {
|
||||
BOOST_LOG(debug) << "qwave.dll is not available on this OS"sv;
|
||||
return;
|
||||
@@ -1788,11 +1788,11 @@ namespace platf {
|
||||
}
|
||||
|
||||
operator bool() override {
|
||||
return timer != NULL;
|
||||
return timer != nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
HANDLE timer = NULL;
|
||||
HANDLE timer = nullptr;
|
||||
};
|
||||
|
||||
std::unique_ptr<high_precision_timer> create_high_precision_timer() {
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace nvprefs {
|
||||
void driver_settings_t::destroy() {
|
||||
if (session_handle) {
|
||||
NvAPI_DRS_DestroySession(session_handle);
|
||||
session_handle = 0;
|
||||
session_handle = nullptr;
|
||||
}
|
||||
NvAPI_Unload();
|
||||
}
|
||||
@@ -105,7 +105,7 @@ namespace nvprefs {
|
||||
if (swapchain_data) {
|
||||
NvAPI_Status status;
|
||||
|
||||
NvDRSProfileHandle profile_handle = 0;
|
||||
NvDRSProfileHandle profile_handle = nullptr;
|
||||
status = NvAPI_DRS_GetBaseProfile(session_handle, &profile_handle);
|
||||
if (status != NVAPI_OK) {
|
||||
nvapi_error_message(status);
|
||||
@@ -168,7 +168,7 @@ namespace nvprefs {
|
||||
return true;
|
||||
}
|
||||
|
||||
NvDRSProfileHandle profile_handle = 0;
|
||||
NvDRSProfileHandle profile_handle = nullptr;
|
||||
status = NvAPI_DRS_GetBaseProfile(session_handle, &profile_handle);
|
||||
if (status != NVAPI_OK) {
|
||||
nvapi_error_message(status);
|
||||
@@ -224,7 +224,7 @@ namespace nvprefs {
|
||||
NvAPI_UnicodeString profile_name = {};
|
||||
fill_nvapi_string(profile_name, sunshine_application_profile_name);
|
||||
|
||||
NvDRSProfileHandle profile_handle = 0;
|
||||
NvDRSProfileHandle profile_handle = nullptr;
|
||||
status = NvAPI_DRS_FindProfileByName(session_handle, profile_name, &profile_handle);
|
||||
|
||||
if (status != NVAPI_OK) {
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace nvprefs {
|
||||
bool check_and_modify_application_profile(bool &modified);
|
||||
|
||||
private:
|
||||
NvDRSSessionHandle session_handle = 0;
|
||||
NvDRSSessionHandle session_handle = nullptr;
|
||||
};
|
||||
|
||||
} // namespace nvprefs
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
namespace {
|
||||
|
||||
std::map<const char *, void *> interfaces;
|
||||
HMODULE dll = NULL;
|
||||
HMODULE dll = nullptr;
|
||||
|
||||
template<typename Func, typename... Args>
|
||||
NvAPI_Status call_interface(const char *name, Args... args) {
|
||||
@@ -47,7 +47,7 @@ NvAPI_Initialize() {
|
||||
auto dll_name = "nvapi.dll";
|
||||
#endif
|
||||
|
||||
if ((dll = LoadLibraryEx(dll_name, NULL, LOAD_LIBRARY_SEARCH_SYSTEM32))) {
|
||||
if ((dll = LoadLibraryEx(dll_name, nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32))) {
|
||||
if (auto query_interface = (decltype(nvapi_QueryInterface) *) GetProcAddress(dll, "nvapi_QueryInterface")) {
|
||||
for (const auto &item : nvapi_interface_table) {
|
||||
interfaces[item.func] = query_interface(item.id);
|
||||
@@ -64,7 +64,7 @@ NVAPI_INTERFACE NvAPI_Unload() {
|
||||
if (dll) {
|
||||
interfaces.clear();
|
||||
FreeLibrary(dll);
|
||||
dll = NULL;
|
||||
dll = nullptr;
|
||||
}
|
||||
return NVAPI_OK;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace nvprefs {
|
||||
|
||||
explicit operator bool() const {
|
||||
auto handle = get();
|
||||
return handle != NULL && handle != INVALID_HANDLE_VALUE;
|
||||
return handle != nullptr && handle != INVALID_HANDLE_VALUE;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace nvprefs {
|
||||
|
||||
std::optional<undo_file_t> undo_file_t::open_existing_file(std::filesystem::path file_path, bool &access_denied) {
|
||||
undo_file_t file;
|
||||
file.file_handle.reset(CreateFileW(file_path.c_str(), GENERIC_READ | DELETE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL));
|
||||
file.file_handle.reset(CreateFileW(file_path.c_str(), GENERIC_READ | DELETE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
|
||||
if (file.file_handle) {
|
||||
access_denied = false;
|
||||
return file;
|
||||
@@ -64,7 +64,7 @@ namespace nvprefs {
|
||||
|
||||
std::optional<undo_file_t> undo_file_t::create_new_file(std::filesystem::path file_path) {
|
||||
undo_file_t file;
|
||||
file.file_handle.reset(CreateFileW(file_path.c_str(), GENERIC_WRITE | STANDARD_RIGHTS_ALL, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL));
|
||||
file.file_handle.reset(CreateFileW(file_path.c_str(), GENERIC_WRITE | STANDARD_RIGHTS_ALL, 0, nullptr, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, nullptr));
|
||||
|
||||
if (file.file_handle) {
|
||||
// give GENERIC_READ, GENERIC_WRITE and DELETE permissions to Users group
|
||||
|
||||
@@ -12,6 +12,7 @@ extern "C" {
|
||||
// standard includes
|
||||
#include <array>
|
||||
#include <cctype>
|
||||
#include <format>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
@@ -864,7 +865,7 @@ namespace rtsp_stream {
|
||||
session_option.next = &port_option;
|
||||
|
||||
// Moonlight merely requires 'server_port=<port>'
|
||||
auto port_value = "server_port=" + std::to_string(port);
|
||||
auto port_value = std::format("server_port={}", static_cast<int>(port));
|
||||
|
||||
port_option.option = const_cast<char *>("Transport");
|
||||
port_option.content = port_value.data();
|
||||
|
||||
@@ -84,7 +84,7 @@ namespace system_tray {
|
||||
#ifdef _WIN32
|
||||
// If we're running in a service, return a special status to
|
||||
// tell it to terminate too, otherwise it will just respawn us.
|
||||
if (GetConsoleWindow() == NULL) {
|
||||
if (GetConsoleWindow() == nullptr) {
|
||||
lifetime::exit_sunshine(ERROR_SHUTDOWN_IN_PROGRESS, true);
|
||||
return;
|
||||
}
|
||||
@@ -230,10 +230,10 @@ namespace system_tray {
|
||||
return;
|
||||
}
|
||||
|
||||
tray.notification_title = NULL;
|
||||
tray.notification_text = NULL;
|
||||
tray.notification_cb = NULL;
|
||||
tray.notification_icon = NULL;
|
||||
tray.notification_title = nullptr;
|
||||
tray.notification_text = nullptr;
|
||||
tray.notification_cb = nullptr;
|
||||
tray.notification_icon = nullptr;
|
||||
tray.icon = TRAY_ICON_PLAYING;
|
||||
tray_update(&tray);
|
||||
tray.icon = TRAY_ICON_PLAYING;
|
||||
@@ -251,10 +251,10 @@ namespace system_tray {
|
||||
return;
|
||||
}
|
||||
|
||||
tray.notification_title = NULL;
|
||||
tray.notification_text = NULL;
|
||||
tray.notification_cb = NULL;
|
||||
tray.notification_icon = NULL;
|
||||
tray.notification_title = nullptr;
|
||||
tray.notification_text = nullptr;
|
||||
tray.notification_cb = nullptr;
|
||||
tray.notification_icon = nullptr;
|
||||
tray.icon = TRAY_ICON_PAUSING;
|
||||
tray_update(&tray);
|
||||
char msg[256];
|
||||
@@ -272,10 +272,10 @@ namespace system_tray {
|
||||
return;
|
||||
}
|
||||
|
||||
tray.notification_title = NULL;
|
||||
tray.notification_text = NULL;
|
||||
tray.notification_cb = NULL;
|
||||
tray.notification_icon = NULL;
|
||||
tray.notification_title = nullptr;
|
||||
tray.notification_text = nullptr;
|
||||
tray.notification_cb = nullptr;
|
||||
tray.notification_icon = nullptr;
|
||||
tray.icon = TRAY_ICON;
|
||||
tray_update(&tray);
|
||||
char msg[256];
|
||||
@@ -293,10 +293,10 @@ namespace system_tray {
|
||||
return;
|
||||
}
|
||||
|
||||
tray.notification_title = NULL;
|
||||
tray.notification_text = NULL;
|
||||
tray.notification_cb = NULL;
|
||||
tray.notification_icon = NULL;
|
||||
tray.notification_title = nullptr;
|
||||
tray.notification_text = nullptr;
|
||||
tray.notification_cb = nullptr;
|
||||
tray.notification_icon = nullptr;
|
||||
tray.icon = TRAY_ICON;
|
||||
tray_update(&tray);
|
||||
tray.icon = TRAY_ICON;
|
||||
@@ -305,7 +305,7 @@ namespace system_tray {
|
||||
tray.notification_icon = TRAY_ICON_LOCKED;
|
||||
tray.tooltip = PROJECT_NAME;
|
||||
tray.notification_cb = []() {
|
||||
launch_ui_with_path("/pin");
|
||||
launch_ui("/pin");
|
||||
};
|
||||
tray_update(&tray);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
#include "../tests_common.h"
|
||||
|
||||
#include <format>
|
||||
#include <src/config.h>
|
||||
#include <src/display_device.h>
|
||||
#include <src/rtsp.h>
|
||||
@@ -473,7 +474,7 @@ namespace {
|
||||
} else {
|
||||
const auto [manual_res] = std::get<manual_value_t<res_t>>(input_res);
|
||||
video_config.dd.resolution_option = manual;
|
||||
video_config.dd.manual_resolution = std::to_string(manual_res.m_width) + "x"s + std::to_string(manual_res.m_height);
|
||||
video_config.dd.manual_resolution = std::format("{}x{}", static_cast<int>(manual_res.m_width), static_cast<int>(manual_res.m_height));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
*/
|
||||
#include "../tests_common.h"
|
||||
|
||||
#include <format>
|
||||
#include <src/file_handler.h>
|
||||
|
||||
struct FileHandlerParentDirectoryTest: testing::TestWithParam<std::tuple<std::string, std::string>> {};
|
||||
@@ -79,13 +80,13 @@ Hey, hey, hey!
|
||||
|
||||
TEST_P(FileHandlerTests, WriteFileTest) {
|
||||
auto [fileNum, content] = GetParam();
|
||||
std::string fileName = "write_file_test_" + std::to_string(fileNum) + ".txt";
|
||||
const std::string fileName = std::format("write_file_test_{}.txt", fileNum);
|
||||
EXPECT_EQ(file_handler::write_file(fileName.c_str(), content), 0);
|
||||
}
|
||||
|
||||
TEST_P(FileHandlerTests, ReadFileTest) {
|
||||
auto [fileNum, content] = GetParam();
|
||||
std::string fileName = "write_file_test_" + std::to_string(fileNum) + ".txt";
|
||||
const std::string fileName = std::format("write_file_test_{}.txt", fileNum);
|
||||
EXPECT_EQ(file_handler::read_file(fileName.c_str()), content);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "../tests_common.h"
|
||||
#include "../tests_log_checker.h"
|
||||
|
||||
#include <format>
|
||||
#include <random>
|
||||
#include <src/logging.h>
|
||||
|
||||
@@ -39,7 +40,7 @@ TEST_P(LogLevelsTest, PutMessage) {
|
||||
|
||||
std::random_device rand_dev;
|
||||
std::mt19937_64 rand_gen(rand_dev());
|
||||
auto test_message = std::to_string(rand_gen()) + std::to_string(rand_gen());
|
||||
auto test_message = std::format("{}{}", rand_gen(), rand_gen());
|
||||
BOOST_LOG(logger) << test_message;
|
||||
|
||||
ASSERT_TRUE(log_checker::line_contains(log_file, test_message));
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* @brief Handles launching Sunshine.exe into user sessions as SYSTEM
|
||||
*/
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <format>
|
||||
#include <string>
|
||||
#include <Windows.h>
|
||||
#include <WtsApi32.h>
|
||||
@@ -51,9 +52,9 @@ DWORD WINAPI HandlerEx(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, L
|
||||
}
|
||||
|
||||
HANDLE CreateJobObjectForChildProcess() {
|
||||
HANDLE job_handle = CreateJobObjectW(NULL, NULL);
|
||||
HANDLE job_handle = CreateJobObjectW(nullptr, nullptr);
|
||||
if (!job_handle) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_limit_info = {};
|
||||
@@ -68,7 +69,7 @@ HANDLE CreateJobObjectForChildProcess() {
|
||||
|
||||
if (!SetInformationJobObject(job_handle, JobObjectExtendedLimitInformation, &job_limit_info, sizeof(job_limit_info))) {
|
||||
CloseHandle(job_handle);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return job_handle;
|
||||
@@ -76,16 +77,16 @@ HANDLE CreateJobObjectForChildProcess() {
|
||||
|
||||
LPPROC_THREAD_ATTRIBUTE_LIST AllocateProcThreadAttributeList(DWORD attribute_count) {
|
||||
SIZE_T size;
|
||||
InitializeProcThreadAttributeList(NULL, attribute_count, 0, &size);
|
||||
InitializeProcThreadAttributeList(nullptr, attribute_count, 0, &size);
|
||||
|
||||
auto list = (LPPROC_THREAD_ATTRIBUTE_LIST) HeapAlloc(GetProcessHeap(), 0, size);
|
||||
if (list == NULL) {
|
||||
return NULL;
|
||||
if (list == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!InitializeProcThreadAttributeList(list, attribute_count, 0, &size)) {
|
||||
HeapFree(GetProcessHeap(), 0, list);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return list;
|
||||
@@ -94,14 +95,14 @@ LPPROC_THREAD_ATTRIBUTE_LIST AllocateProcThreadAttributeList(DWORD attribute_cou
|
||||
HANDLE DuplicateTokenForSession(DWORD console_session_id) {
|
||||
HANDLE current_token;
|
||||
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE, ¤t_token)) {
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Duplicate our own LocalSystem token
|
||||
HANDLE new_token;
|
||||
if (!DuplicateTokenEx(current_token, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &new_token)) {
|
||||
if (!DuplicateTokenEx(current_token, TOKEN_ALL_ACCESS, nullptr, SecurityImpersonation, TokenPrimary, &new_token)) {
|
||||
CloseHandle(current_token);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
CloseHandle(current_token);
|
||||
@@ -109,7 +110,7 @@ HANDLE DuplicateTokenForSession(DWORD console_session_id) {
|
||||
// Change the duplicated token to the console session ID
|
||||
if (!SetTokenInformation(new_token, TokenSessionId, &console_session_id, sizeof(console_session_id))) {
|
||||
CloseHandle(new_token);
|
||||
return NULL;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new_token;
|
||||
@@ -123,21 +124,21 @@ HANDLE OpenLogFileHandle() {
|
||||
wcscat_s(log_file_name, L"sunshine.log");
|
||||
|
||||
// The file handle must be inheritable for our child process to use it
|
||||
SECURITY_ATTRIBUTES security_attributes = {sizeof(security_attributes), NULL, TRUE};
|
||||
SECURITY_ATTRIBUTES security_attributes = {sizeof(security_attributes), nullptr, TRUE};
|
||||
|
||||
// Overwrite the old sunshine.log
|
||||
return CreateFileW(log_file_name, GENERIC_WRITE, FILE_SHARE_READ, &security_attributes, CREATE_ALWAYS, 0, NULL);
|
||||
return CreateFileW(log_file_name, GENERIC_WRITE, FILE_SHARE_READ, &security_attributes, CREATE_ALWAYS, 0, nullptr);
|
||||
}
|
||||
|
||||
bool RunTerminationHelper(HANDLE console_token, DWORD pid) {
|
||||
WCHAR module_path[MAX_PATH];
|
||||
GetModuleFileNameW(NULL, module_path, _countof(module_path));
|
||||
GetModuleFileNameW(nullptr, module_path, _countof(module_path));
|
||||
std::wstring command;
|
||||
|
||||
command += L'"';
|
||||
command += module_path;
|
||||
command += L'"';
|
||||
command += L" --terminate " + std::to_wstring(pid);
|
||||
command += std::format(L" --terminate {}", pid);
|
||||
|
||||
STARTUPINFOW startup_info = {};
|
||||
startup_info.cb = sizeof(startup_info);
|
||||
@@ -146,7 +147,7 @@ bool RunTerminationHelper(HANDLE console_token, DWORD pid) {
|
||||
// Execute ourselves as a detached process in the user session with the --terminate argument.
|
||||
// This will allow us to attach to Sunshine's console and send it a Ctrl-C event.
|
||||
PROCESS_INFORMATION process_info;
|
||||
if (!CreateProcessAsUserW(console_token, module_path, (LPWSTR) command.c_str(), NULL, NULL, FALSE, CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS, NULL, NULL, &startup_info, &process_info)) {
|
||||
if (!CreateProcessAsUserW(console_token, module_path, (LPWSTR) command.c_str(), nullptr, nullptr, FALSE, CREATE_UNICODE_ENVIRONMENT | DETACHED_PROCESS, nullptr, nullptr, &startup_info, &process_info)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -166,8 +167,8 @@ bool RunTerminationHelper(HANDLE console_token, DWORD pid) {
|
||||
}
|
||||
|
||||
VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) {
|
||||
service_status_handle = RegisterServiceCtrlHandlerEx(SERVICE_NAME, HandlerEx, NULL);
|
||||
if (service_status_handle == NULL) {
|
||||
service_status_handle = RegisterServiceCtrlHandlerEx(SERVICE_NAME, HandlerEx, nullptr);
|
||||
if (service_status_handle == nullptr) {
|
||||
// Nothing we can really do here but terminate ourselves
|
||||
ExitProcess(GetLastError());
|
||||
return;
|
||||
@@ -184,8 +185,8 @@ VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) {
|
||||
SetServiceStatus(service_status_handle, &service_status);
|
||||
|
||||
// Create a manual-reset stop event
|
||||
stop_event = CreateEventA(NULL, TRUE, FALSE, NULL);
|
||||
if (stop_event == NULL) {
|
||||
stop_event = CreateEventA(nullptr, TRUE, FALSE, nullptr);
|
||||
if (stop_event == nullptr) {
|
||||
// Tell SCM we failed to start
|
||||
service_status.dwWin32ExitCode = GetLastError();
|
||||
service_status.dwCurrentState = SERVICE_STOPPED;
|
||||
@@ -194,8 +195,8 @@ VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) {
|
||||
}
|
||||
|
||||
// Create an auto-reset session change event
|
||||
session_change_event = CreateEventA(NULL, FALSE, FALSE, NULL);
|
||||
if (session_change_event == NULL) {
|
||||
session_change_event = CreateEventA(nullptr, FALSE, FALSE, nullptr);
|
||||
if (session_change_event == nullptr) {
|
||||
// Tell SCM we failed to start
|
||||
service_status.dwWin32ExitCode = GetLastError();
|
||||
service_status.dwCurrentState = SERVICE_STOPPED;
|
||||
@@ -217,13 +218,13 @@ VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) {
|
||||
startup_info.StartupInfo.cb = sizeof(startup_info);
|
||||
startup_info.StartupInfo.lpDesktop = (LPWSTR) L"winsta0\\default";
|
||||
startup_info.StartupInfo.dwFlags = STARTF_USESTDHANDLES;
|
||||
startup_info.StartupInfo.hStdInput = NULL;
|
||||
startup_info.StartupInfo.hStdInput = nullptr;
|
||||
startup_info.StartupInfo.hStdOutput = log_file_handle;
|
||||
startup_info.StartupInfo.hStdError = log_file_handle;
|
||||
|
||||
// Allocate an attribute list with space for 2 entries
|
||||
startup_info.lpAttributeList = AllocateProcThreadAttributeList(2);
|
||||
if (startup_info.lpAttributeList == NULL) {
|
||||
if (startup_info.lpAttributeList == nullptr) {
|
||||
// Tell SCM we failed to start
|
||||
service_status.dwWin32ExitCode = GetLastError();
|
||||
service_status.dwCurrentState = SERVICE_STOPPED;
|
||||
@@ -232,7 +233,7 @@ VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) {
|
||||
}
|
||||
|
||||
// Only allow Sunshine.exe to inherit the log file handle, not all inheritable handles
|
||||
UpdateProcThreadAttribute(startup_info.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &log_file_handle, sizeof(log_file_handle), NULL, NULL);
|
||||
UpdateProcThreadAttribute(startup_info.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &log_file_handle, sizeof(log_file_handle), nullptr, nullptr);
|
||||
|
||||
// Tell SCM we're running (and stoppable now)
|
||||
service_status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PRESHUTDOWN | SERVICE_ACCEPT_SESSIONCHANGE;
|
||||
@@ -248,22 +249,22 @@ VOID WINAPI ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) {
|
||||
}
|
||||
|
||||
auto console_token = DuplicateTokenForSession(console_session_id);
|
||||
if (console_token == NULL) {
|
||||
if (console_token == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Job objects cannot span sessions, so we must create one for each process
|
||||
auto job_handle = CreateJobObjectForChildProcess();
|
||||
if (job_handle == NULL) {
|
||||
if (job_handle == nullptr) {
|
||||
CloseHandle(console_token);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Start Sunshine.exe inside our job object
|
||||
UpdateProcThreadAttribute(startup_info.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, &job_handle, sizeof(job_handle), NULL, NULL);
|
||||
UpdateProcThreadAttribute(startup_info.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_JOB_LIST, &job_handle, sizeof(job_handle), nullptr, nullptr);
|
||||
|
||||
PROCESS_INFORMATION process_info;
|
||||
if (!CreateProcessAsUserW(console_token, L"Sunshine.exe", NULL, NULL, NULL, TRUE, CREATE_UNICODE_ENVIRONMENT | CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT, NULL, NULL, (LPSTARTUPINFOW) &startup_info, &process_info)) {
|
||||
if (!CreateProcessAsUserW(console_token, L"Sunshine.exe", nullptr, nullptr, nullptr, TRUE, CREATE_UNICODE_ENVIRONMENT | CREATE_NO_WINDOW | EXTENDED_STARTUPINFO_PRESENT, nullptr, nullptr, (LPSTARTUPINFOW) &startup_info, &process_info)) {
|
||||
CloseHandle(console_token);
|
||||
CloseHandle(job_handle);
|
||||
continue;
|
||||
@@ -326,7 +327,7 @@ int DoGracefulTermination(DWORD pid) {
|
||||
}
|
||||
|
||||
// Disable our own Ctrl-C handling
|
||||
SetConsoleCtrlHandler(NULL, TRUE);
|
||||
SetConsoleCtrlHandler(nullptr, TRUE);
|
||||
|
||||
// Send a Ctrl-C event to Sunshine
|
||||
if (!GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0)) {
|
||||
@@ -339,7 +340,7 @@ int DoGracefulTermination(DWORD pid) {
|
||||
int main(int argc, char *argv[]) {
|
||||
static const SERVICE_TABLE_ENTRY service_table[] = {
|
||||
{(LPSTR) SERVICE_NAME, ServiceMain},
|
||||
{NULL, NULL}
|
||||
{nullptr, nullptr}
|
||||
};
|
||||
|
||||
// Check if this is a reinvocation of ourselves to send Ctrl-C to Sunshine.exe
|
||||
@@ -351,7 +352,7 @@ int main(int argc, char *argv[]) {
|
||||
// We want to use the directory where Sunshine.exe is located instead of system32.
|
||||
// This requires stripping off 2 path components: the file name and the last folder
|
||||
WCHAR module_path[MAX_PATH];
|
||||
GetModuleFileNameW(NULL, module_path, _countof(module_path));
|
||||
GetModuleFileNameW(nullptr, module_path, _countof(module_path));
|
||||
for (auto i = 0; i < 2; i++) {
|
||||
auto last_sep = wcsrchr(module_path, '\\');
|
||||
if (last_sep) {
|
||||
|
||||
Reference in New Issue
Block a user