From 545cca792bdb5cf7f39044bbbac3ed8c3169eb0f Mon Sep 17 00:00:00 2001 From: loki Date: Wed, 30 Jun 2021 22:03:21 +0200 Subject: [PATCH] Fix inabillity to display secure desktop even when runnig as system account --- CMakeLists.txt | 1 + assets/sunshine.conf | 542 ++++++++++----------- sunshine/platform/windows/display_base.cpp | 7 +- sunshine/platform/windows/input.cpp | 33 +- sunshine/platform/windows/misc.cpp | 33 ++ sunshine/platform/windows/publish.cpp | 18 +- 6 files changed, 317 insertions(+), 317 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1a80ab08..edf103f1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,7 @@ if(WIN32) set(PLATFORM_TARGET_FILES sunshine/platform/windows/publish.cpp + sunshine/platform/windows/misc.h sunshine/platform/windows/misc.cpp sunshine/platform/windows/input.cpp sunshine/platform/windows/display.h diff --git a/assets/sunshine.conf b/assets/sunshine.conf index f7c0fcd6..ca556179 100644 --- a/assets/sunshine.conf +++ b/assets/sunshine.conf @@ -1,271 +1,271 @@ -# If no external IP address is given, Sunshine will attempt to automatically detect external ip-address -# external_ip = 123.456.789.12 - -# Set the familly of ports used by Sunshine -# port = 47989 - -# The private key must be 2048 bits -# pkey = /dir/pkey.pem - -# The certificate must be signed with a 2048 bit key -# cert = /dir/cert.pem - -# The name displayed by Moonlight -# If not specified, the PC's hostname is used -# sunshine_name = Sunshine - -# The minimum log level printed to standard out -# -# none -> no logs are printed to standard out -# -# verbose = [0] -# debug = [1] -# info = [2] -# warning = [3] -# error = [4] -# fatal = [5] -# none = [6] -# -# min_log_level = info - -# The origin of the remote endpoint address that is not denied for HTTP method /pin -# Could be any of the following values: -# pc|lan|wan -# pc: Only localhost may access /pin -# lan: Only those in LAN may access /pin -# wan: Anyone may access /pin -# -# origin_pin_allowed = pc - -# The origin of the remote endpoint address that is not denied for HTTPS Web UI -# Could be any of the following values: -# pc|lan|wan -# pc: Only localhost may access the Web Manager -# lan: Only those in LAN may access the Web Manager -# wan: Anyone may access the Web Manager -# -# origin_web_ui_allowed = lan - -# If UPnP is enabled, Sunshine will attempt to open ports for streaming over the internet -# To enable it, uncomment the following line: -# upnp = on - -# The file where current state of Sunshine is stored -# file_state = sunshine_state.json - -# The file where user credentials for the UI are stored -# By default, credentials are stored in `file_state` -# credentials_file = sunshine_state.json - -# The display modes advertised by Sunshine -# -# Some versions of Moonlight, such as Moonlight-nx (Switch), -# rely on this list to ensure that the requested resolutions and fps -# are supported. -# -# fps = [10, 30, 60, 90, 120] -# resolutions = [ -# 352x240, -# 480x360, -# 858x480, -# 1280x720, -# 1920x1080, -# 2560x1080, -# 3440x1440, -# 1920x1200, -# 3860x2160, -# 3840x1600, -# ] - -# How long to wait in milliseconds for data from moonlight before shutting down the stream -# ping_timeout = 2000 - -# The file where configuration for the different applications that Sunshine can run during a stream -# file_apps = apps.json - -# How much error correcting packets must be send for every video -# 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 value must be greater than 0 and lower than or equal to 100 -# fec_percentage = 10 - -# When multicasting, it could be usefull to have different configurations for each connected Client. -# For example: -# Clients connected through WAN and LAN have different bitrate contstraints. -# Decoders may require different settings for color -# -# Unlike simply broadcasting to multiple Client, this will generate distinct video streams. -# Note, CPU usage increases for each distinct video stream generated -# channels = 1 - -# The back/select button on the controller -# 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 back_button_timeout < 0, then the Home/Guide button will not be emulated -# back_button_timeout = 2000 - -# !! Windows only !! -# Control how fast keys will repeat themselves -# The initial delay in milliseconds before repeating keys -# key_repeat_delay = 500 -# -# How often keys repeat every second -# This configurable option supports decimals -# key_repeat_frequency = 24.9 - -# The name of the audio sink used for Audio Loopback -# 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: -# !! Linux only !! -# pacmd list-sinks | grep "name:" if running vanilla pulseaudio -# pactl info | grep Source` if running pipewire -# audio_sink = alsa_output.pci-0000_09_00.3.analog-stereo -# -# !! Windows only !! -# tools\audio-info.exe -# 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 -# to stream audio, while muting the speakers. -# virtual_sink = {0.0.0.00000000}.{8edba70c-1125-467c-b89c-15da389bc1d4} - -# !! Windows only !! -# You can select the video card you want to stream: -# The appropriate values can be found using the following command: -# tools\dxgi-info.exe -# adapter_name = Radeon RX 580 Series -# output_name = \\.\DISPLAY1 - -# !! Linux only !! -# Set the display number to stream. -# You can find them by the following command: -# xrandr --listmonitors -# Example output: "0: +HDMI-1 1920/518x1200/324+0+0 HDMI-1" -# ^ <-- You need this. -# output_name = 0 - -############################################### -# FFmpeg software encoding parameters -# Honestly, I have no idea what the optimal values would be. -# 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 -# Higher value means more compression, but less quality -# If crf == 0, then use QP directly instead -# crf = 0 - -# Quantitization Parameter -# Higher value means more compression, but less quality -# If crf != 0, then this parameter is ignored -# qp = 28 - -# Minimum number of threads used by ffmpeg to encode the video. -# 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 -# value that can reliably encode at your desired streaming settings on your hardware. -# min_threads = 1 - -# 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. -# 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 2, Sunshine will advertise support for HEVC Main profile -# If set to 3, Sunshine will advertise support for HEVC Main and Main10 (HDR) profiles -# hevc_mode = 2 - -# Force a specific encoder, otherwise Sunshine will use the first encoder that is available -# supported encoders: -# nvenc -# amdvce # NOTE: alpha stage. The cursor is not yet displayed -# software -# -# encoder = nvenc -##################################### Software ##################################### -# See x264 --fullhelp for the different presets -# sw_preset = superfast -# sw_tune = zerolatency -# - -##################################### NVENC ##################################### -###### presets ########### -# default -# hp -- high performance -# hq -- high quality -# slow -- hq 2 passes -# medium -- hq 1 pass -# fast -- hp 1 pass -# bd -# ll -- low latency -# llhq -# llhp -# lossless -# losslesshp -########################## -# nv_preset = llhq -# -####### rate control ##### -# auto -- let ffmpeg decide rate control -# constqp -- constant QP mode -# vbr -- variable bitrate -# cbr -- constant bitrate -# cbr_hq -- cbr high quality -# cbr_ld_hq -- cbr low delay high quality -# vbr_hq -- vbr high quality -########################## -# nv_rc = auto - -###### h264 entropy ###### -# auto -- let ffmpeg nvenc decide the entropy encoding -# cabac -# cavlc -########################## -# nv_coder = auto - -##################################### AMD ##################################### -###### presets ########### -# default -# speed -# balanced -########################## -# amd_preset = balanced -# -####### rate control ##### -# auto -- let ffmpeg decide rate control -# constqp -- constant QP mode -# vbr_latency -- Latency Constrained Variable Bitrate -# vbr_peak -- Peak Contrained Variable Bitrate -# cbr -- constant bitrate -########################## -# amd_rc = auto - -###### h264 entropy ###### -# auto -- let ffmpeg nvenc decide the entropy encoding -# cabac -# cavlc -########################## -# amd_coder = auto - -#################################### VAAPI ################################### -####### adapter ########## -# Unlike with `amdvce` and `nvenc`, it doesn't matter if video encoding is done -# on a different GPU. -# Run the following commands: -# 1. ls /dev/dri/renderD* -# to find all devices capable of VAAPI -# 2. vainfo --display drm --device /dev/dri/renderD129 | grep -E "((VAProfileH264High|VAProfileHEVCMain|VAProfileHEVCMain10).*VAEntrypointEncSlice)|Driver version" -# Lists the name and capabilities of the device. -# To be supported by Sunshine, it needs to have at the very minimum: -# VAProfileH264High : VAEntrypointEncSlice -# adapter_name = /dev/dri/renderD128 - -############################################## -# 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 -# 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: -# flags = 012 -# -# See: sunshine --help for all options under the header: flags +# If no external IP address is given, Sunshine will attempt to automatically detect external ip-address +# external_ip = 123.456.789.12 + +# Set the familly of ports used by Sunshine +# port = 47989 + +# The private key must be 2048 bits +# pkey = /dir/pkey.pem + +# The certificate must be signed with a 2048 bit key +# cert = /dir/cert.pem + +# The name displayed by Moonlight +# If not specified, the PC's hostname is used +# sunshine_name = Sunshine + +# The minimum log level printed to standard out +# +# none -> no logs are printed to standard out +# +# verbose = [0] +# debug = [1] +# info = [2] +# warning = [3] +# error = [4] +# fatal = [5] +# none = [6] +# +# min_log_level = info + +# The origin of the remote endpoint address that is not denied for HTTP method /pin +# Could be any of the following values: +# pc|lan|wan +# pc: Only localhost may access /pin +# lan: Only those in LAN may access /pin +# wan: Anyone may access /pin +# +# origin_pin_allowed = pc + +# The origin of the remote endpoint address that is not denied for HTTPS Web UI +# Could be any of the following values: +# pc|lan|wan +# pc: Only localhost may access the Web Manager +# lan: Only those in LAN may access the Web Manager +# wan: Anyone may access the Web Manager +# +# origin_web_ui_allowed = lan + +# If UPnP is enabled, Sunshine will attempt to open ports for streaming over the internet +# To enable it, uncomment the following line: +# upnp = on + +# The file where current state of Sunshine is stored +# file_state = sunshine_state.json + +# The file where user credentials for the UI are stored +# By default, credentials are stored in `file_state` +# credentials_file = sunshine_state.json + +# The display modes advertised by Sunshine +# +# Some versions of Moonlight, such as Moonlight-nx (Switch), +# rely on this list to ensure that the requested resolutions and fps +# are supported. +# +# fps = [10, 30, 60, 90, 120] +# resolutions = [ +# 352x240, +# 480x360, +# 858x480, +# 1280x720, +# 1920x1080, +# 2560x1080, +# 3440x1440, +# 1920x1200, +# 3860x2160, +# 3840x1600, +# ] + +# How long to wait in milliseconds for data from moonlight before shutting down the stream +# ping_timeout = 2000 + +# The file where configuration for the different applications that Sunshine can run during a stream +# file_apps = apps.json + +# How much error correcting packets must be send for every video +# 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 value must be greater than 0 and lower than or equal to 100 +# fec_percentage = 10 + +# When multicasting, it could be usefull to have different configurations for each connected Client. +# For example: +# Clients connected through WAN and LAN have different bitrate contstraints. +# Decoders may require different settings for color +# +# Unlike simply broadcasting to multiple Client, this will generate distinct video streams. +# Note, CPU usage increases for each distinct video stream generated +# channels = 1 + +# The back/select button on the controller +# 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 back_button_timeout < 0, then the Home/Guide button will not be emulated +# back_button_timeout = 2000 + +# !! Windows only !! +# Control how fast keys will repeat themselves +# The initial delay in milliseconds before repeating keys +# key_repeat_delay = 500 +# +# How often keys repeat every second +# This configurable option supports decimals +# key_repeat_frequency = 24.9 + +# The name of the audio sink used for Audio Loopback +# 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: +# !! Linux only !! +# pacmd list-sinks | grep "name:" if running vanilla pulseaudio +# pactl info | grep Source` if running pipewire +# audio_sink = alsa_output.pci-0000_09_00.3.analog-stereo +# +# !! Windows only !! +# tools\audio-info.exe +# 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 +# to stream audio, while muting the speakers. +# virtual_sink = {0.0.0.00000000}.{8edba70c-1125-467c-b89c-15da389bc1d4} + +# !! Windows only !! +# You can select the video card you want to stream: +# The appropriate values can be found using the following command: +# tools\dxgi-info.exe +# adapter_name = Radeon RX 580 Series +# output_name = \\.\DISPLAY1 + +# !! Linux only !! +# Set the display number to stream. +# You can find them by the following command: +# xrandr --listmonitors +# Example output: "0: +HDMI-1 1920/518x1200/324+0+0 HDMI-1" +# ^ <-- You need this. +# output_name = 0 + +############################################### +# FFmpeg software encoding parameters +# Honestly, I have no idea what the optimal values would be. +# 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 +# Higher value means more compression, but less quality +# If crf == 0, then use QP directly instead +# crf = 0 + +# Quantitization Parameter +# Higher value means more compression, but less quality +# If crf != 0, then this parameter is ignored +# qp = 28 + +# Minimum number of threads used by ffmpeg to encode the video. +# 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 +# value that can reliably encode at your desired streaming settings on your hardware. +# min_threads = 1 + +# 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. +# 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 2, Sunshine will advertise support for HEVC Main profile +# If set to 3, Sunshine will advertise support for HEVC Main and Main10 (HDR) profiles +# hevc_mode = 2 + +# Force a specific encoder, otherwise Sunshine will use the first encoder that is available +# supported encoders: +# nvenc +# amdvce # NOTE: alpha stage. The cursor is not yet displayed +# software +# +# encoder = nvenc +##################################### Software ##################################### +# See x264 --fullhelp for the different presets +# sw_preset = superfast +# sw_tune = zerolatency +# + +##################################### NVENC ##################################### +###### presets ########### +# default +# hp -- high performance +# hq -- high quality +# slow -- hq 2 passes +# medium -- hq 1 pass +# fast -- hp 1 pass +# bd +# ll -- low latency +# llhq +# llhp +# lossless +# losslesshp +########################## +# nv_preset = llhq +# +####### rate control ##### +# auto -- let ffmpeg decide rate control +# constqp -- constant QP mode +# vbr -- variable bitrate +# cbr -- constant bitrate +# cbr_hq -- cbr high quality +# cbr_ld_hq -- cbr low delay high quality +# vbr_hq -- vbr high quality +########################## +# nv_rc = auto + +###### h264 entropy ###### +# auto -- let ffmpeg nvenc decide the entropy encoding +# cabac +# cavlc +########################## +# nv_coder = auto + +##################################### AMD ##################################### +###### presets ########### +# default +# speed +# balanced +########################## +# amd_preset = balanced +# +####### rate control ##### +# auto -- let ffmpeg decide rate control +# constqp -- constant QP mode +# vbr_latency -- Latency Constrained Variable Bitrate +# vbr_peak -- Peak Contrained Variable Bitrate +# cbr -- constant bitrate +########################## +# amd_rc = auto + +###### h264 entropy ###### +# auto -- let ffmpeg nvenc decide the entropy encoding +# cabac +# cavlc +########################## +# amd_coder = auto + +#################################### VAAPI ################################### +####### adapter ########## +# Unlike with `amdvce` and `nvenc`, it doesn't matter if video encoding is done +# on a different GPU. +# Run the following commands: +# 1. ls /dev/dri/renderD* +# to find all devices capable of VAAPI +# 2. vainfo --display drm --device /dev/dri/renderD129 | grep -E "((VAProfileH264High|VAProfileHEVCMain|VAProfileHEVCMain10).*VAEntrypointEncSlice)|Driver version" +# Lists the name and capabilities of the device. +# To be supported by Sunshine, it needs to have at the very minimum: +# VAProfileH264High : VAEntrypointEncSlice +# adapter_name = /dev/dri/renderD128 + +############################################## +# 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 +# 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: +# flags = 012 +# +# See: sunshine --help for all options under the header: flags diff --git a/sunshine/platform/windows/display_base.cpp b/sunshine/platform/windows/display_base.cpp index 240c17f9..3fde7a68 100644 --- a/sunshine/platform/windows/display_base.cpp +++ b/sunshine/platform/windows/display_base.cpp @@ -4,12 +4,12 @@ #include +#include "display.h" +#include "misc.h" #include "sunshine/config.h" #include "sunshine/main.h" #include "sunshine/platform/common.h" -#include "display.h" - namespace platf { 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 env_width = GetSystemMetrics(SM_CXVIRTUALSCREEN); env_height = GetSystemMetrics(SM_CYVIRTUALSCREEN); diff --git a/sunshine/platform/windows/input.cpp b/sunshine/platform/windows/input.cpp index 9eb6667b..6889de00 100755 --- a/sunshine/platform/windows/input.cpp +++ b/sunshine/platform/windows/input.cpp @@ -4,20 +4,20 @@ #include +#include "misc.h" #include "sunshine/main.h" #include "sunshine/platform/common.h" namespace platf { using namespace std::literals; -volatile HDESK _lastKnownInputDesktop = NULL; +thread_local HDESK _lastKnownInputDesktop = nullptr; + constexpr touch_port_t target_touch_port { 0, 0, 65535, 65535 }; -HDESK pairInputDesktop(); - class vigem_t { public: using client_t = util::safe_ptr<_VIGEM_CLIENT_T, vigem_free>; @@ -102,12 +102,12 @@ void send_input(INPUT &i) { retry: auto send = SendInput(1, &i, sizeof(INPUT)); if(send != 1) { - auto hDesk = pairInputDesktop(); + auto hDesk = syncThreadDesktop(); if(_lastKnownInputDesktop != hDesk) { _lastKnownInputDesktop = hDesk; 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) { @@ -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) { auto vigem = (vigem_t *)p; diff --git a/sunshine/platform/windows/misc.cpp b/sunshine/platform/windows/misc.cpp index 90a59689..828e0374 100644 --- a/sunshine/platform/windows/misc.cpp +++ b/sunshine/platform/windows/misc.cpp @@ -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; 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 \ No newline at end of file diff --git a/sunshine/platform/windows/publish.cpp b/sunshine/platform/windows/publish.cpp index 2d4888d2..652785d0 100644 --- a/sunshine/platform/windows/publish.cpp +++ b/sunshine/platform/windows/publish.cpp @@ -7,14 +7,14 @@ #include +#include "misc.h" #include "sunshine/config.h" #include "sunshine/main.h" +#include "sunshine/network.h" #include "sunshine/nvhttp.h" #include "sunshine/platform/common.h" #include "sunshine/thread_safe.h" -#include "sunshine/network.h" - using namespace std::literals; @@ -96,20 +96,6 @@ PDNS_SERVICE_INSTANCE DnsServiceConstructInstance( _In_reads_(dwPropertiesCount) PCWSTR *values); } /* 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 { VOID WINAPI register_cb(DWORD status, PVOID pQueryContext, PDNS_SERVICE_INSTANCE pInstance) { auto alarm = (safe::alarm_t::element_type *)pQueryContext;