diff options
Diffstat (limited to 'zenserver')
| -rw-r--r-- | zenserver/windows/service.cpp | 246 | ||||
| -rw-r--r-- | zenserver/windows/service.h | 21 | ||||
| -rw-r--r-- | zenserver/zenserver.cpp | 79 |
3 files changed, 180 insertions, 166 deletions
diff --git a/zenserver/windows/service.cpp b/zenserver/windows/service.cpp index 7a7864b39..bd80e0c2c 100644 --- a/zenserver/windows/service.cpp +++ b/zenserver/windows/service.cpp @@ -1,3 +1,5 @@ +// Copyright Epic Games, Inc. All Rights Reserved. + #include "service.h" #include <zencore/zencore.h> @@ -12,14 +14,19 @@ SERVICE_STATUS gSvcStatus; SERVICE_STATUS_HANDLE gSvcStatusHandle; HANDLE ghSvcStopEvent = NULL; -void SvcInstall(void); -void WINAPI SvcCtrlHandler(DWORD); -void WINAPI SvcMain(DWORD, LPTSTR*); +void SvcInstall(void); void ReportSvcStatus(DWORD, DWORD, DWORD); -void SvcInit(DWORD, LPTSTR*); void SvcReportEvent(LPTSTR); +WindowsService::WindowsService() +{ +} + +WindowsService::~WindowsService() +{ +} + // // Purpose: // Installs a service in the SCM database @@ -31,7 +38,7 @@ void SvcReportEvent(LPTSTR); // None // VOID -SvcInstall() +WindowsService::Install() { SC_HANDLE schSCManager; SC_HANDLE schService; @@ -84,17 +91,8 @@ SvcInstall() CloseServiceHandle(schSCManager); } -// -// Purpose: -// Deletes a service from the SCM database -// -// Parameters: -// None -// -// Return value: -// None -// -void SvcDelete() +void +WindowsService::Delete() { SC_HANDLE schSCManager; SC_HANDLE schService; @@ -137,6 +135,89 @@ void SvcDelete() CloseServiceHandle(schSCManager); } +WindowsService* gSvc; + +void WINAPI +CallMain(DWORD, LPSTR*) +{ + gSvc->SvcMain(); +} + +int +WindowsService::ServiceMain() +{ + if (zen::IsInteractiveSession()) + { + // Not actually running as a service + return Run(); + } + else + { + gSvc = this; + + SERVICE_TABLE_ENTRY DispatchTable[] = {{(LPWSTR)SVCNAME, (LPSERVICE_MAIN_FUNCTION)&CallMain}, {NULL, NULL}}; + + // This call returns when the service has stopped. + // The process should simply terminate when the call returns. + + if (!StartServiceCtrlDispatcher(DispatchTable)) + { + SvcReportEvent((LPTSTR)L"StartServiceCtrlDispatcher"); + } + } + + return 0; +} + +int +WindowsService::SvcMain() +{ + // Register the handler function for the service + + gSvcStatusHandle = RegisterServiceCtrlHandler(SVCNAME, SvcCtrlHandler); + + if (!gSvcStatusHandle) + { + SvcReportEvent((LPTSTR)TEXT("RegisterServiceCtrlHandler")); + + return 1; + } + + // These SERVICE_STATUS members remain as set here + + gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + gSvcStatus.dwServiceSpecificExitCode = 0; + + // Report initial status to the SCM + + ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000); + + // Create an event. The control handler function, SvcCtrlHandler, + // signals this event when it receives the stop control code. + + ghSvcStopEvent = CreateEvent(NULL, // default security attributes + TRUE, // manual reset event + FALSE, // not signaled + NULL); // no name + + if (ghSvcStopEvent == NULL) + { + ReportSvcStatus(SERVICE_STOPPED, GetLastError(), 0); + + return 1; + } + + // Report running status when initialization is complete. + + ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0); + + int ReturnCode = Run(); + + ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); + + return ReturnCode; +} + // // Purpose: // Retrieves and displays the current service configuration. @@ -147,7 +228,8 @@ void SvcDelete() // Return value: // None // -void __stdcall DoQuerySvc() +void +DoQuerySvc() { SC_HANDLE schSCManager{}; SC_HANDLE schService{}; @@ -249,6 +331,7 @@ cleanup: CloseServiceHandle(schService); CloseServiceHandle(schSCManager); } + // // Purpose: // Disables the service. @@ -259,7 +342,8 @@ cleanup: // Return value: // None // -VOID __stdcall DoDisableSvc() +void +DoDisableSvc() { SC_HANDLE schSCManager; SC_HANDLE schService; @@ -384,7 +468,8 @@ VOID __stdcall DoEnableSvc() // Return value: // None // -VOID __stdcall DoUpdateSvcDesc() +void +DoUpdateSvcDesc() { SC_HANDLE schSCManager; SC_HANDLE schService; @@ -435,100 +520,6 @@ VOID __stdcall DoUpdateSvcDesc() // // Purpose: -// Entry point for the service -// -// Parameters: -// dwArgc - Number of arguments in the lpszArgv array -// lpszArgv - Array of strings. The first string is the name of -// the service and subsequent strings are passed by the process -// that called the StartService function to start the service. -// -// Return value: -// None. -// -VOID WINAPI -SvcMain(DWORD dwArgc, LPTSTR* lpszArgv) -{ - // Register the handler function for the service - - gSvcStatusHandle = RegisterServiceCtrlHandler(SVCNAME, SvcCtrlHandler); - - if (!gSvcStatusHandle) - { - SvcReportEvent((LPTSTR)TEXT("RegisterServiceCtrlHandler")); - return; - } - - // These SERVICE_STATUS members remain as set here - - gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; - gSvcStatus.dwServiceSpecificExitCode = 0; - - // Report initial status to the SCM - - ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000); - - // Perform service-specific initialization and work. - - SvcInit(dwArgc, lpszArgv); -} - -// -// Purpose: -// The service code -// -// Parameters: -// dwArgc - Number of arguments in the lpszArgv array -// lpszArgv - Array of strings. The first string is the name of -// the service and subsequent strings are passed by the process -// that called the StartService function to start the service. -// -// Return value: -// None -// -VOID -SvcInit(DWORD dwArgc, LPTSTR* lpszArgv) -{ - // TO_DO: Declare and set any required variables. - // Be sure to periodically call ReportSvcStatus() with - // SERVICE_START_PENDING. If initialization fails, call - // ReportSvcStatus with SERVICE_STOPPED. - - ZEN_UNUSED(lpszArgv, dwArgc); - - // Create an event. The control handler function, SvcCtrlHandler, - // signals this event when it receives the stop control code. - - ghSvcStopEvent = CreateEvent(NULL, // default security attributes - TRUE, // manual reset event - FALSE, // not signaled - NULL); // no name - - if (ghSvcStopEvent == NULL) - { - ReportSvcStatus(SERVICE_STOPPED, GetLastError(), 0); - return; - } - - // Report running status when initialization is complete. - - ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0); - - // TO_DO: Perform work until service stops. - - while (1) - { - // Check whether to stop the service. - - WaitForSingleObject(ghSvcStopEvent, INFINITE); - - ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); - return; - } -} - -// -// Purpose: // Sets the current service status and reports it to the SCM. // // Parameters: @@ -565,21 +556,13 @@ ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint) SetServiceStatus(gSvcStatusHandle, &gSvcStatus); } -// -// Purpose: -// Called by SCM whenever a control code is sent to the service -// using the ControlService function. -// -// Parameters: -// dwCtrl - control code -// -// Return value: -// None -// -VOID WINAPI -SvcCtrlHandler(DWORD dwCtrl) +void +WindowsService::SvcCtrlHandler(DWORD dwCtrl) { // Handle the requested control code. + // + // Called by SCM whenever a control code is sent to the service + // using the ControlService function. switch (dwCtrl) { @@ -589,8 +572,9 @@ SvcCtrlHandler(DWORD dwCtrl) // Signal the service to stop. SetEvent(ghSvcStopEvent); - ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0); + zen::RequestApplicationExit(0); + ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0); return; case SERVICE_CONTROL_INTERROGATE: @@ -645,11 +629,3 @@ SvcReportEvent(LPTSTR szFunction) // DeregisterEventSource(hEventSource); //} } - -WindowsServiceBase::WindowsServiceBase() -{ -} - -WindowsServiceBase::~WindowsServiceBase() -{ -} diff --git a/zenserver/windows/service.h b/zenserver/windows/service.h index 0f76d7447..7c9610983 100644 --- a/zenserver/windows/service.h +++ b/zenserver/windows/service.h @@ -2,14 +2,19 @@ #pragma once -void SvcInstall(void); -void SvcDelete(); - -class WindowsServiceBase +class WindowsService { public: - WindowsServiceBase(); - ~WindowsServiceBase(); + WindowsService(); + ~WindowsService(); + + virtual int Run() = 0; + + int ServiceMain(); + + static void Install(); + static void Delete(); -private: -};
\ No newline at end of file + int SvcMain(); + static void __stdcall SvcCtrlHandler(unsigned long); +}; diff --git a/zenserver/zenserver.cpp b/zenserver/zenserver.cpp index 83580b288..ea4a2915e 100644 --- a/zenserver/zenserver.cpp +++ b/zenserver/zenserver.cpp @@ -316,7 +316,9 @@ public: __debugbreak(); } - m_Http->Run(m_TestMode); + const bool IsInteractiveMode = zen::IsInteractiveSession() && !m_TestMode; + + m_Http->Run(IsInteractiveMode); ZEN_INFO(ZEN_APP_NAME " exiting"); @@ -436,33 +438,29 @@ private: } // namespace zen -int -main(int argc, char* argv[]) +class ZenWindowsService : public WindowsService { - using namespace zen; - - mi_version(); - - ZenServerOptions GlobalOptions; - ZenServiceConfig ServiceConfig; - ParseGlobalCliOptions(argc, argv, GlobalOptions, ServiceConfig); - InitializeLogging(GlobalOptions); - -#if ZEN_PLATFORM_WINDOWS - if (GlobalOptions.InstallService) +public: + ZenWindowsService(ZenServerOptions& GlobalOptions, ZenServiceConfig& ServiceConfig) + : m_GlobalOptions(GlobalOptions) + , m_ServiceConfig(ServiceConfig) { - SvcInstall(); - - std::exit(0); } - if (GlobalOptions.UninstallService) - { - SvcDelete(); + ZenWindowsService(const ZenWindowsService&) = delete; + ZenWindowsService& operator=(const ZenWindowsService&) = delete; - std::exit(0); - } -#endif + virtual int Run() override; + +private: + ZenServerOptions& m_GlobalOptions; + ZenServiceConfig& m_ServiceConfig; +}; + +int +ZenWindowsService::Run() +{ + using namespace zen; #if USE_SENTRY // Initialize sentry.io client @@ -474,6 +472,9 @@ main(int argc, char* argv[]) auto _ = zen::MakeGuard([] { sentry_close(); }); #endif + auto& GlobalOptions = m_GlobalOptions; + auto& ServiceConfig = m_ServiceConfig; + try { // Prototype config system, we'll see how this pans out @@ -559,3 +560,35 @@ main(int argc, char* argv[]) return 0; } + +int +main(int argc, char* argv[]) +{ + using namespace zen; + + mi_version(); + + ZenServerOptions GlobalOptions; + ZenServiceConfig ServiceConfig; + ParseGlobalCliOptions(argc, argv, GlobalOptions, ServiceConfig); + InitializeLogging(GlobalOptions); + +#if ZEN_PLATFORM_WINDOWS + if (GlobalOptions.InstallService) + { + WindowsService::Install(); + + std::exit(0); + } + + if (GlobalOptions.UninstallService) + { + WindowsService::Delete(); + + std::exit(0); + } +#endif + + ZenWindowsService App(GlobalOptions, ServiceConfig); + return App.ServiceMain(); +} |