aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--zenhttp/httpnull.cpp4
-rw-r--r--zenhttp/httpnull.h2
-rw-r--r--zenhttp/httpsys.cpp23
-rw-r--r--zenhttp/httpuws.cpp4
-rw-r--r--zenhttp/httpuws.h2
-rw-r--r--zenhttp/include/zenhttp/httpserver.h2
-rw-r--r--zenserver/windows/service.cpp246
-rw-r--r--zenserver/windows/service.h21
-rw-r--r--zenserver/zenserver.cpp79
9 files changed, 201 insertions, 182 deletions
diff --git a/zenhttp/httpnull.cpp b/zenhttp/httpnull.cpp
index 57cba13d3..e49051ac5 100644
--- a/zenhttp/httpnull.cpp
+++ b/zenhttp/httpnull.cpp
@@ -28,8 +28,10 @@ HttpNullServer::Initialize(int BasePort)
}
void
-HttpNullServer::Run(bool TestMode)
+HttpNullServer::Run(bool IsInteractiveSession)
{
+ const bool TestMode = !IsInteractiveSession;
+
if (TestMode == false)
{
zen::logging::ConsoleLog().info("Zen Server running (null HTTP). Press ESC or Q to quit");
diff --git a/zenhttp/httpnull.h b/zenhttp/httpnull.h
index b15b1b123..867bbe4d2 100644
--- a/zenhttp/httpnull.h
+++ b/zenhttp/httpnull.h
@@ -19,7 +19,7 @@ public:
virtual void RegisterService(HttpService& Service) override;
virtual void Initialize(int BasePort) override;
- virtual void Run(bool TestMode) override;
+ virtual void Run(bool IsInteractiveSession) override;
virtual void RequestExit() override;
private:
diff --git a/zenhttp/httpsys.cpp b/zenhttp/httpsys.cpp
index c2d4ef14c..b5313021c 100644
--- a/zenhttp/httpsys.cpp
+++ b/zenhttp/httpsys.cpp
@@ -707,29 +707,30 @@ HttpSysServer::StartServer()
}
void
-HttpSysServer::Run(bool TestMode)
+HttpSysServer::Run(bool IsInteractive)
{
- if (TestMode == false)
+ if (IsInteractive)
{
zen::logging::ConsoleLog().info("Zen Server running. Press ESC or Q to quit");
}
do
{
- int WaitTimeout = -1;
+ //int WaitTimeout = -1;
+ int WaitTimeout = 100;
- if (!TestMode)
+ if (IsInteractive)
{
WaitTimeout = 1000;
- }
-
- if (!TestMode && _kbhit() != 0)
- {
- char c = (char)_getch();
- if (c == 27 || c == 'Q' || c == 'q')
+ if (_kbhit() != 0)
{
- RequestApplicationExit(0);
+ char c = (char)_getch();
+
+ if (c == 27 || c == 'Q' || c == 'q')
+ {
+ RequestApplicationExit(0);
+ }
}
}
diff --git a/zenhttp/httpuws.cpp b/zenhttp/httpuws.cpp
index 992809b17..e062e7747 100644
--- a/zenhttp/httpuws.cpp
+++ b/zenhttp/httpuws.cpp
@@ -37,8 +37,10 @@ HttpUwsServer::Initialize(int BasePort)
}
void
-HttpUwsServer::Run(bool TestMode)
+HttpUwsServer::Run(bool IsInteractive)
{
+ const bool TestMode = !IsInteractive;
+
if (TestMode == false)
{
zen::logging::ConsoleLog().info("Zen Server running (null HTTP). Press ESC or Q to quit");
diff --git a/zenhttp/httpuws.h b/zenhttp/httpuws.h
index ec55ae2fd..5e300202f 100644
--- a/zenhttp/httpuws.h
+++ b/zenhttp/httpuws.h
@@ -16,7 +16,7 @@ public:
virtual void RegisterService(HttpService& Service) override;
virtual void Initialize(int BasePort) override;
- virtual void Run(bool TestMode) override;
+ virtual void Run(bool IsInteractiveSession) override;
virtual void RequestExit() override;
private:
diff --git a/zenhttp/include/zenhttp/httpserver.h b/zenhttp/include/zenhttp/httpserver.h
index ed6075c92..6a7dc8a70 100644
--- a/zenhttp/include/zenhttp/httpserver.h
+++ b/zenhttp/include/zenhttp/httpserver.h
@@ -167,7 +167,7 @@ class HttpServer : public RefCounted
public:
virtual void RegisterService(HttpService& Service) = 0;
virtual void Initialize(int BasePort) = 0;
- virtual void Run(bool TestMode) = 0;
+ virtual void Run(bool IsInteractiveSession) = 0;
virtual void RequestExit() = 0;
};
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();
+}