Skip to content

Commit

Permalink
win32: Forte as a Windows service
Browse files Browse the repository at this point in the history
  • Loading branch information
kumajaya committed May 4, 2024
1 parent 1bda348 commit 9918c81
Show file tree
Hide file tree
Showing 10 changed files with 299 additions and 111 deletions.
10 changes: 10 additions & 0 deletions src/arch/utils/mainparam_utils.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*******************************************************************************
* Copyright (c) 2018 fortiss GmbH
* 2024 Samator Indo Gas
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
Expand All @@ -9,6 +10,7 @@
* Contributors:
* Tarik Terzimehic
* - initial API and implementation and/or initial documentation
* Ketut Kumajaya - option to run as a Windows service
*******************************************************************************/

#include <forte_config.h>
Expand Down Expand Up @@ -40,6 +42,10 @@ void listHelp(){
#ifdef FORTE_TRACE_CTF
printf("%-20s Set the output directory for TRACE_CTF\n", " -t <directory>");
#endif //FORTE_TRACE_CTF
#ifdef FORTE_WINDOWS_SERVICE
printf("%-20s To install as a Windows service\n", " -install");
printf("%-20s To remove the service\n", " -remove");
#endif //FORTE_WINDOWS_SERVICE
}

/*!\brief Parses the command line arguments passed to the main function
Expand Down Expand Up @@ -90,6 +96,10 @@ const char *parseCommandLineArguments(int argc, char *arg[]){
barectfSetup(arg[i + 1] ?: "");
break;
#endif //FORTE_TRACE_CTF
#ifdef FORTE_WINDOWS_SERVICE
case 's':
break;
#endif //FORTE_WINDOWS_SERVICE
default: //! Unknown parameter or -h -> Lists the help for FORTE
return "";
}
Expand Down
10 changes: 9 additions & 1 deletion src/arch/win32/main.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
/*******************************************************************************
* Copyright (c) 2010 - 2018 ACIN, Profactor GmbH, fortiss GmbH
* 2024 Samator Indo Gas
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
Expand All @@ -9,6 +10,7 @@
* Contributors:
* Alois Zoitl, Ingo Hegny, Gerhard Ebenhofer - initial API and implementation and/or initial documentation
* Alois Zoitl - cleaned up main, inserted new architecture initilasation api
* Ketut Kumajaya - option to run as a Windows service
*******************************************************************************/
#include "../forte_architecture.h"
#include "../devlog.h"
Expand Down Expand Up @@ -61,7 +63,7 @@ void createDev(const char *paMGRID){
delete poDev;
}

int main(int argc, char *arg[]){
int _main(int argc, char *arg[]){

if(CForteArchitecture::initialize()){

Expand All @@ -83,3 +85,9 @@ int main(int argc, char *arg[]){
}
return 0;
}

#ifndef FORTE_WINDOWS_SERVICE
int main(int argc, char *arg[]){
return _main(argc, arg);
}
#endif
2 changes: 1 addition & 1 deletion src/arch/win32/service/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
# Ketut Kumajaya - initial API and implementation and/or initial documentation
# *******************************************************************************/
if(FORTE_WINDOWS_SERVICE)
forte_add_sourcefile_cpp(CppWindowsService.cpp)
forte_add_sourcefile_cpp(ForteService.cpp)
forte_add_sourcefile_hcpp(SampleService ServiceBase ServiceInstaller)
forte_add_sourcefile_h(ThreadPool.h)
endif()
104 changes: 0 additions & 104 deletions src/arch/win32/service/CppWindowsService.cpp

This file was deleted.

176 changes: 176 additions & 0 deletions src/arch/win32/service/ForteService.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/****************************** Module Header ******************************\
* Module Name: CppWindowsService.cpp
* Project: CppWindowsService
* Copyright (c) Microsoft Corporation.
*
* The file defines the entry point of the application. According to the
* arguments in the command line, the function installs or uninstalls or
* starts the service by calling into different routines.
*
* This source is subject to the Microsoft Public License.
* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
* All other rights reserved.
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
\***************************************************************************/

#pragma region Includes
#include <cstdio>
#include <windows.h>
#include "ServiceInstaller.h"
#include "ServiceBase.h"
#include "SampleService.h"
#pragma endregion


#include <filesystem>
#include "../../devlog.h"
#include "../../forte_stringFunctions.h"

int _main(int argc, char *arg[]);


//
// Settings of the service
//

// Internal name of the service
#define SERVICE_NAME (PWSTR)L"4diac-forte"

// Displayed name of the service
#define SERVICE_DISPLAY_NAME (PWSTR)L"4diac FORTE Runtime for Windows"

// Service start options.
#define SERVICE_START_TYPE SERVICE_DEMAND_START

// List of service dependencies - "dep1\0dep2\0\0"
#define SERVICE_DEPENDENCIES (PWSTR)L""

// The name of the account under which the service should run
#define SERVICE_ACCOUNT (PWSTR)L"NT AUTHORITY\\LocalService"

// The password to the service account name
#define SERVICE_PASSWORD NULL


// User can edit forte command line arguments in
// HKLM\SYSTEM\CurrentControlSet\Services\4diac-forte\ImagePath
static void convertArguments(int argc, wchar_t *argw[], std::vector<std::string> &args)
{
for (int i = 0; i < argc; ++i)
{
std::string str = forte_wstringToString(argw[i]);
args.push_back(str);
if (str.compare("-service") == 0 || str.compare("-s") == 0)
{
if ((argc & 1) == 0) // forte always expect an argument pair
{
// add dummy argument
args.push_back("true");
}
}
}
}


//
// FUNCTION: wmain(int, wchar_t *[])
//
// PURPOSE: entrypoint for the application.
//
// PARAMETERS:
// argc - number of command line arguments
// argv - array of command line arguments
//
// RETURN VALUE:
// none
//
// COMMENTS:
// wmain() either performs the command line task, or run the service.
//
int wmain(int argc, wchar_t *argv[])
{
int ret = -1;

// Convert command line arguments from wide to narrow string
std::vector<std::string> l_argvBuff;
convertArguments(argc, argv, l_argvBuff);

// Reconstruct command line arguments fort FORTE process
int l_argc = static_cast<int>(l_argvBuff.size());
const char **l_argv = new const char *[l_argc];
for (int i = 0; i < l_argc; ++i)
{
// Pointer to string
l_argv[i] = l_argvBuff[i].c_str();
}

if ((argc > 1) && ((*argv[1] == L'-' || (*argv[1] == L'/'))))
{
if (_wcsicmp(L"install", argv[1] + 1) == 0)
{
// Install the service when the command is
// "-install" or "/install".
InstallService(
SERVICE_NAME, // Name of service
SERVICE_DISPLAY_NAME, // Name to display
SERVICE_START_TYPE, // Service start type
SERVICE_DEPENDENCIES, // Dependencies
SERVICE_ACCOUNT, // Service running account
SERVICE_PASSWORD // Password of the account
);
}
else if (_wcsicmp(L"remove", argv[1] + 1) == 0)
{
// Uninstall the service when the command is
// "-remove" or "/remove".
UninstallService(SERVICE_NAME);
}
else if (_wcsicmp(L"service", argv[1] + 1) == 0 || _wcsicmp(L"s", argv[1] + 1) == 0)
{
CSampleService service(SERVICE_NAME, l_argc, (char **)l_argv);

// Start setup stdout/stderr redirection
wchar_t szPath[MAX_PATH];
if (GetModuleFileNameW(NULL, szPath, ARRAYSIZE(szPath)) == 0) {
DEVLOG_ERROR("GetModuleFileNameW failed w/err 0x%08lx\n", GetLastError());
}

std::filesystem::path fullpath(szPath);
// Disable logging with "-service 2" argument
if (std::filesystem::exists(fullpath) && _wcsicmp(L"2", argv[2]) != 0) {
auto path = fullpath.replace_extension("log");
std::string logfile = forte_wstringToString(path);
service.StartLogRedirection(logfile.c_str(), stdout);
path = fullpath.replace_extension("err");
logfile = forte_wstringToString(path);
service.StartLogRedirection(logfile.c_str(), stderr);
}

if (!CServiceBase::Run(service))
{
DEVLOG_ERROR("Service failed to run w/err 0x%08lx\n", GetLastError());
}

// Stop stdout/stderr redirection in reverse order
service.StopLogRedirection(stderr);
service.StopLogRedirection(stdout);
}
else
{
ret = _main(l_argc, (char **)l_argv);
}
}
else
{
ret = _main(l_argc, (char **)l_argv);
}

// Delete the char array first and then clear the string vector
delete[] l_argv;
l_argvBuff.clear();

return ret;
}
Loading

0 comments on commit 9918c81

Please sign in to comment.