diff --git a/src/main.cpp b/src/main.cpp index 08b56f5..cfae957 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,6 +31,7 @@ #include "http/httpserver.hpp" #include "http/webapp.hpp" #include "tracker.hpp" +#include "service.hpp" UDPT::Logger *logger = NULL; @@ -83,6 +84,9 @@ int main(int argc, char *argv[]) ("config,c", boost::program_options::value()->default_value("/etc/udpt.conf"), "configuration file to use") #ifdef linux ("interactive,i", "doesn't start as daemon") +#endif +#ifdef WIN32 + ("service,s", boost::program_options::value(), "start/stop/install/uninstall service") #endif ; @@ -109,6 +113,9 @@ int main(int argc, char *argv[]) #ifdef linux ("daemon.chdir", boost::program_options::value()->default_value("/"), "home directory for daemon") +#endif +#ifdef WIN32 + ("service.name", boost::program_options::value()->default_value("udpt"), "service name to use") #endif ; @@ -177,6 +184,55 @@ int main(int argc, char *argv[]) } ::signal(SIGTERM, _signal_handler); #endif +#ifdef WIN32 + UDPT::Service svc(var_map); + if (var_map.count("service")) + { + const std::string& action = var_map["service"].as(); + try + { + if ("install" == action) + { + std::cout << "Installing service..." << std::endl; + svc.install(); + std::cout << "Installed." << std::endl; + } + else if ("uninstall" == action) + { + std::cout << "Removing service..." << std::endl; + svc.uninstall(); + std::cout << "Removed." << std::endl; + } + else if ("start" == action) + { + svc.start(); + } + else if ("stop" == action) + { + svc.stop(); + } + } + catch (const UDPT::OSError& ex) + { + std::cout << "An operating system error occurred: " << ex.getErrorCode() << std::endl; + return -1; + } + + return 0; + } + + try + { + svc.setup(); + } + catch (const OSError& err) + { + if (ERROR_FAILED_SERVICE_CONTROLLER_CONNECT != err.getErrorCode()) + { + logger->log(UDPT::Logger::LL_ERROR, "failed to start as service"); + } + } +#endif tracker.start(var_map); tracker.wait(); diff --git a/src/service.cpp b/src/service.cpp new file mode 100644 index 0000000..1d2169b --- /dev/null +++ b/src/service.cpp @@ -0,0 +1,135 @@ +/* +* Copyright © 2012-2016 Naim A. +* +* This file is part of UDPT. +* +* UDPT is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* UDPT is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with UDPT. If not, see . +*/ +#include "service.hpp" + +#ifdef WIN32 + +namespace UDPT +{ + Service::Service(const boost::program_options::variables_map& conf) : m_conf(conf) + { + + } + + Service::~Service() + { + + } + + void Service::install() + { + std::string& binaryPath = getFilename(); + binaryPath = "\"" + binaryPath + "\""; + std::shared_ptr svcMgr = getServiceManager(SC_MANAGER_CREATE_SERVICE); + { + SC_HANDLE installedService = ::CreateService(reinterpret_cast(svcMgr.get()), + m_conf["service.name"].as().c_str(), + "UDPT Tracker", + SC_MANAGER_CREATE_SERVICE, + SERVICE_WIN32_OWN_PROCESS, + SERVICE_AUTO_START, + SERVICE_ERROR_NORMAL, + binaryPath.c_str(), + NULL, + NULL, + NULL, + NULL, + NULL + ); + if (nullptr == installedService) + { + throw OSError(); + } + + ::CloseServiceHandle(installedService); + } + } + + void Service::uninstall() + { + std::shared_ptr service = getService(DELETE); + BOOL bRes = ::DeleteService(reinterpret_cast(service.get())); + if (FALSE == bRes) + { + throw OSError(); + } + } + + void Service::start() + { + + } + + void Service::stop() + { + + } + + void Service::setup() + { + SERVICE_TABLE_ENTRY service = { 0 }; + service.lpServiceName = const_cast(m_conf["service.name"].as().c_str()); + service.lpServiceProc = reinterpret_cast(&Service::serviceMain); + if (FALSE == ::StartServiceCtrlDispatcher(&service)) + { + throw OSError(); + } + } + + VOID Service::serviceMain(DWORD argc, LPCSTR argv[]) + { + + } + + std::shared_ptr Service::getService(DWORD access) + { + std::shared_ptr serviceManager = getServiceManager(access); + { + SC_HANDLE service = ::OpenService(reinterpret_cast(serviceManager.get()), m_conf["service.name"].as().c_str(), access); + if (nullptr == service) + { + throw OSError(); + } + return std::shared_ptr(service, ::CloseServiceHandle); + } + } + + std::shared_ptr Service::getServiceManager(DWORD access) + { + SC_HANDLE svcMgr = ::OpenSCManager(NULL, NULL, access); + if (nullptr == svcMgr) + { + throw OSError(); + } + return std::shared_ptr(svcMgr, ::CloseServiceHandle); + } + + std::string Service::getFilename() + { + char filename[MAX_PATH]; + DWORD dwRet = ::GetModuleFileName(NULL, filename, sizeof(filename) / sizeof(char)); + if (0 == dwRet) + { + throw OSError(); + } + return std::string(filename); + } +} + +#endif diff --git a/src/service.hpp b/src/service.hpp new file mode 100644 index 0000000..4255756 --- /dev/null +++ b/src/service.hpp @@ -0,0 +1,60 @@ +/* +* Copyright © 2012-2016 Naim A. +* +* This file is part of UDPT. +* +* UDPT is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* UDPT is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with UDPT. If not, see . +*/ +#pragma once + +#include +#include "multiplatform.h" +#include "exceptions.h" + +#ifdef WIN32 +namespace UDPT +{ + class Service + { + public: + Service(const boost::program_options::variables_map& conf); + + virtual ~Service(); + + + void install(); + + void uninstall(); + + void start(); + + void stop(); + + void setup(); + private: + const boost::program_options::variables_map& m_conf; + + std::shared_ptr getService(DWORD access); + + static VOID WINAPI handler(DWORD controlCode); + + static VOID WINAPI serviceMain(DWORD argc, LPCSTR argv[]); + + static std::shared_ptr getServiceManager(DWORD access); + + static std::string getFilename(); + }; +} + +#endif \ No newline at end of file diff --git a/vs/UDPT/UDPT.vcxproj b/vs/UDPT/UDPT.vcxproj index d7bcb9a..a32e40f 100644 --- a/vs/UDPT/UDPT.vcxproj +++ b/vs/UDPT/UDPT.vcxproj @@ -59,7 +59,7 @@ true - ws2_32.lib;sqlite3.lib; + ws2_32.lib;sqlite3.lib;advapi32.lib @@ -73,10 +73,11 @@ Async - true - true - true - ws2_32.lib;sqlite3.lib;%(AdditionalDependencies) + + + + + ws2_32.lib;sqlite3.lib;advapi32.lib @@ -86,6 +87,7 @@ + @@ -98,6 +100,7 @@ + diff --git a/vs/UDPT/UDPT.vcxproj.filters b/vs/UDPT/UDPT.vcxproj.filters index db3e909..431084e 100644 --- a/vs/UDPT/UDPT.vcxproj.filters +++ b/vs/UDPT/UDPT.vcxproj.filters @@ -54,6 +54,9 @@ Source Files + + Source Files + @@ -86,5 +89,8 @@ Header Files + + Header Files + \ No newline at end of file