// service/BEService.h #pragma once #include "core/WinApi.h" #include "services/GameMonitor.h" #include namespace BEService { inline struct State { bool shouldStop = false; SERVICE_STATUS_HANDLE statusHandle = nullptr; void ReportRunning() const noexcept { SERVICE_STATUS STATUS { SERVICE_WIN32_OWN_PROCESS, SERVICE_RUNNING, SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN, NO_ERROR, 0, 0, 0 }; SetServiceStatus(statusHandle, &STATUS); } void ReportStopped() const noexcept { SERVICE_STATUS STATUS { SERVICE_WIN32_OWN_PROCESS, SERVICE_STOPPED, 0, NO_ERROR, 0, 0, 0 }; SetServiceStatus(statusHandle, &STATUS); } } g_state; VOID WINAPI CtrlHandler(DWORD control) noexcept { if (control == SERVICE_CONTROL_STOP || control == SERVICE_CONTROL_SHUTDOWN) g_state.shouldStop = true; } VOID WINAPI ServiceMain(DWORD, LPWSTR*) noexcept { g_state.statusHandle = RegisterServiceCtrlHandlerW(L"BEService", CtrlHandler); if (!g_state.statusHandle) return; g_state.ReportRunning(); if (!GameMonitor::WaitForGame() || g_state.shouldStop) goto cleanup; while (!g_state.shouldStop && GameMonitor::IsGameRunning()) Sleep(1000); if (!g_state.shouldStop) Sleep(5000); cleanup: g_state.ReportStopped(); } [[nodiscard]] inline bool Run() noexcept { SERVICE_TABLE_ENTRYW table[] = { { const_cast(L"BEService"), ServiceMain }, { nullptr, nullptr } }; return StartServiceCtrlDispatcherW(table) != FALSE; } }