From 8bc56304f5601bcc1ed2a3d169d87958efa3410b Mon Sep 17 00:00:00 2001 From: es3n1n Date: Fri, 30 May 2025 18:35:57 +0200 Subject: [PATCH] feat(loader): start wscsvc manually if needed --- defendnot-loader/core/ensure_environment.cpp | 31 ++++++++++++++++---- defendnot-loader/main.cpp | 13 +++++++- defendnot-loader/util/scm.hpp | 17 +++++++---- 3 files changed, 50 insertions(+), 11 deletions(-) diff --git a/defendnot-loader/core/ensure_environment.cpp b/defendnot-loader/core/ensure_environment.cpp index 926f3d4..3e1dd3c 100644 --- a/defendnot-loader/core/ensure_environment.cpp +++ b/defendnot-loader/core/ensure_environment.cpp @@ -3,6 +3,7 @@ #include "util/scm.hpp" #include +#include #include namespace loader { @@ -14,13 +15,33 @@ namespace loader { auto service = manager.get_service(L"wscsvc"); if (!service.valid() || !service.query_status()) { - throw std::runtime_error(strings::wsc_unavailable_error().data()); + throw std::runtime_error(std::format("{}\nOpen error: {}", strings::wsc_unavailable_error().data(), GetLastError())); } - const auto state = service.state(); - if (state != scm::ServiceState::RUNNING) { - throw std::runtime_error(std::format("{}\nService state: {}, but should be RUNNING", strings::wsc_unavailable_error(), - scm::kServiceStateNames[static_cast>(state)])); + if (service.state() == scm::ServiceState::RUNNING) { + /// Wsc service has been already started, no need to start it ourselves + return; + } + + /// Let's start the service ourselves + std::println("** wscsvc is not running, starting it.."); + if (!service.start()) { + throw std::runtime_error(std::format("{}\nTried to start the service, but go an error: {}", strings::wsc_unavailable_error(), GetLastError())); + } + + std::println("** successfully started the service, waiting for it to get up.."); + while (true) { + if (!service.query_status(/*force=*/true)) { + throw std::runtime_error( + std::format("{}\nStarted the service, got an error while querying: {}", strings::wsc_unavailable_error(), GetLastError())); + } + + if (const auto state = service.state(); state == scm::ServiceState::RUNNING) { + std::println("** we are good to go"); + return; + } + + std::this_thread::sleep_for(std::chrono::milliseconds(500)); } } } // namespace loader diff --git a/defendnot-loader/main.cpp b/defendnot-loader/main.cpp index 6364d5c..4cf7975 100644 --- a/defendnot-loader/main.cpp +++ b/defendnot-loader/main.cpp @@ -127,6 +127,12 @@ int main(int argc, char* argv[]) try { .enable_autorun = !program.get("--disable-autorun"), }; + /// When running from autorun, we'll be missing all the cli arguments, so lets load some relevant ones + if (config.from_autorun) { + shared::ctx.deserialize(); + config.verbose = shared::ctx.verbose; + } + if (!config.alloc_console && config.verbose) { fatal_print("--silent flag can not be used in combination with --verbose"); } @@ -147,7 +153,12 @@ int main(int argc, char* argv[]) try { }; wait_for_finish(ipc); - process_autorun(config); + + /// Only create autorun task when not running from autorun, no need to recreate it because we're missing some config vars + if (!config.from_autorun) { + process_autorun(config); + } + banner(config); return EXIT_SUCCESS; diff --git a/defendnot-loader/util/scm.hpp b/defendnot-loader/util/scm.hpp index ea2dce3..ddf8985 100644 --- a/defendnot-loader/util/scm.hpp +++ b/defendnot-loader/util/scm.hpp @@ -33,8 +33,8 @@ namespace scm { ~Service() = default; public: - bool query_status() noexcept { - if (status_process_.has_value()) { + bool query_status(bool force = false) noexcept { + if (!force && status_process_.has_value()) { return true; } @@ -73,6 +73,12 @@ namespace scm { } } + bool start() noexcept { + return StartServiceW(handle_.get(), 0, nullptr) || // + GetLastError() == ERROR_SERVICE_ALREADY_RUNNING; + } + + public: [[nodiscard]] bool valid() const noexcept { return handle_.get() != nullptr; } @@ -87,15 +93,16 @@ namespace scm { }; class Manager { - constexpr static auto kDesiredPermissions = GENERIC_READ; + constexpr static auto kDesiredAccess = GENERIC_READ; + constexpr static auto kServiceDesiredAccess = SERVICE_QUERY_STATUS | SERVICE_START; public: - Manager(): handle_(make_sc_handle(OpenSCManagerW(nullptr, nullptr, kDesiredPermissions))) { }; + Manager(): handle_(make_sc_handle(OpenSCManagerW(nullptr, nullptr, kDesiredAccess))) { }; ~Manager() = default; public: [[nodiscard]] Service get_service(const std::wstring_view service_name) noexcept { - return Service(OpenServiceW(handle_.get(), service_name.data(), kDesiredPermissions)); + return Service(OpenServiceW(handle_.get(), service_name.data(), kServiceDesiredAccess)); } public: