From 76a437ed322ae5a5fe317d4a2dbe392a21ac9932 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Fri, 20 Feb 2009 14:45:26 +0000 Subject: windows service works now --- src/anytun.cpp | 52 ++++++++++++++- src/anytun.sln | 6 ++ src/anytun.suo | Bin 61952 -> 62976 bytes src/anytun.vcproj | 166 +++++++++++++++++++++++++++++++++++++++++++++++ src/win32/winService.cpp | 82 +++++++++++++++++++---- src/win32/winService.h | 19 ++++-- 6 files changed, 301 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/anytun.cpp b/src/anytun.cpp index 054013b..fc7404c 100644 --- a/src/anytun.cpp +++ b/src/anytun.cpp @@ -51,6 +51,9 @@ #ifndef NO_SIGNALCONTROLLER #include "signalController.h" #endif +#ifdef WIN_SERVICE +#include "win32/winService.h" +#endif #include "packetSource.h" #include "tunDevice.h" #include "options.h" @@ -312,10 +315,43 @@ void receiver(void* p) } } - +#ifdef WIN_SERVICE +int main(int argc, char* argv[]) +{ + try { + if(argc > 1) { + if(std::string(argv[1]) == "install") { + WinService::install(); + return 0; + } + else if(std::string(argv[1]) == "uninstall") { + WinService::uninstall(); + return 0; + } + } + WinService::start(); + return 0; + } + catch(std::runtime_error& e) + { + std::cout << "caught runtime error, exiting: " << e.what() << std::endl; + } + catch(std::exception& e) + { + std::cout << "caught exception, exiting: " << e.what() << std::endl; + } +} + +int real_main(int argc, char* argv[]) +#else int main(int argc, char* argv[]) +#endif { +#ifdef WIN_SERVICE + bool daemonized=true; +#else bool daemonized=false; +#endif try { cLog.msg(Log::PRIO_NOTICE) << "anytun started..."; @@ -434,7 +470,7 @@ int main(int argc, char* argv[]) ThreadParam p(dev, *src, *connTo); boost::thread senderThread(boost::bind(sender,&p)); -#ifndef NO_SIGNALCONTROLLER +#if defined(WIN_SERVICE) || !defined(NO_SIGNALCONTROLLER) boost::thread receiverThread(boost::bind(receiver,&p)); #endif #ifndef ANYTUN_NOSYNC @@ -449,7 +485,10 @@ int main(int argc, char* argv[]) } #endif -#ifndef NO_SIGNALCONTROLLER +#if defined(WIN_SERVICE) + int ret = 0; + gWinService.waitForStop(); +#elif !defined(NO_SIGNALCONTROLLER) int ret = sig.run(); #else receiver(&p); @@ -480,6 +519,9 @@ int main(int argc, char* argv[]) if(connTo) delete connTo; */ +#if defined(WIN_SERVICE) + gWinService.stop(); +#endif return ret; } catch(std::runtime_error& e) @@ -498,6 +540,10 @@ int main(int argc, char* argv[]) std::cout << "uncaught exception, exiting: " << e.what() << std::endl; #endif } +#if defined(WIN_SERVICE) + gWinService.stop(); +#endif + return -1; } diff --git a/src/anytun.sln b/src/anytun.sln index 256ef8c..b562246 100644 --- a/src/anytun.sln +++ b/src/anytun.sln @@ -7,12 +7,18 @@ Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 Release|Win32 = Release|Win32 + Service Debug|Win32 = Service Debug|Win32 + Service Release|Win32 = Service Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {12460D00-D78A-4C68-BDE2-9E3B2F9CD0F3}.Debug|Win32.ActiveCfg = Debug|Win32 {12460D00-D78A-4C68-BDE2-9E3B2F9CD0F3}.Debug|Win32.Build.0 = Debug|Win32 {12460D00-D78A-4C68-BDE2-9E3B2F9CD0F3}.Release|Win32.ActiveCfg = Release|Win32 {12460D00-D78A-4C68-BDE2-9E3B2F9CD0F3}.Release|Win32.Build.0 = Release|Win32 + {12460D00-D78A-4C68-BDE2-9E3B2F9CD0F3}.Service Debug|Win32.ActiveCfg = Service Debug|Win32 + {12460D00-D78A-4C68-BDE2-9E3B2F9CD0F3}.Service Debug|Win32.Build.0 = Service Debug|Win32 + {12460D00-D78A-4C68-BDE2-9E3B2F9CD0F3}.Service Release|Win32.ActiveCfg = Service Release|Win32 + {12460D00-D78A-4C68-BDE2-9E3B2F9CD0F3}.Service Release|Win32.Build.0 = Service Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/anytun.suo b/src/anytun.suo index 084470a..dc86967 100644 Binary files a/src/anytun.suo and b/src/anytun.suo differ diff --git a/src/anytun.vcproj b/src/anytun.vcproj index a74e715..3b0727f 100644 --- a/src/anytun.vcproj +++ b/src/anytun.vcproj @@ -165,6 +165,156 @@ Name="VCPostBuildEventTool" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -417,6 +567,22 @@ PreprocessorDefinitions="ANYTUN_OPTIONS" /> + + + + + + . */ +#ifdef WIN_SERVICE + #include #include @@ -54,7 +56,7 @@ WinService& WinService::instance() WinService::~WinService() { if(started_) - CloseHandle(exit_event_); + CloseHandle(stop_event_); } void WinService::install() @@ -76,8 +78,8 @@ void WinService::install() throw std::runtime_error(msg.str()); } - schService = CreateServiceA(schSCManager, name_.c_str(), name_.c_str(), SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, - SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, szPath, NULL, NULL, NULL, NULL, NULL); // no password + schService = CreateServiceA(schSCManager, SVC_NAME, SVC_NAME, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, + SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, szPath, NULL, NULL, NULL, NULL, NULL); if(schService == NULL) { CloseServiceHandle(schSCManager); std::stringstream msg; @@ -91,13 +93,44 @@ void WinService::install() CloseServiceHandle(schSCManager); } -void WinService::start() +void WinService::uninstall() { - if(started_) - throw std::runtime_error("Service already started"); + SC_HANDLE schSCManager; + SC_HANDLE schService; + + schSCManager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS); + if(NULL == schSCManager) { + std::stringstream msg; + msg << "Error on OpenSCManager: " << LogErrno(GetLastError()); + throw std::runtime_error(msg.str()); + } + + schService = OpenServiceA(schSCManager, SVC_NAME, SERVICE_ALL_ACCESS); + if(schService == NULL) { + CloseServiceHandle(schSCManager); + std::stringstream msg; + msg << "Error on CreateService: " << LogErrno(GetLastError()); + throw std::runtime_error(msg.str()); + } + if(!DeleteService(schService)) { + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); + std::stringstream msg; + msg << "Error on DeleteService: " << LogErrno(GetLastError()); + throw std::runtime_error(msg.str()); + } + + std::cout << "Service uninstalled successfully" << std::endl; + + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); +} + +void WinService::start() +{ SERVICE_TABLE_ENTRY DispatchTable[] = { - {(LPSTR)name_.c_str(), (LPSERVICE_MAIN_FUNCTION)WinService::main }, + {SVC_NAME, (LPSERVICE_MAIN_FUNCTION)WinService::main }, {NULL, NULL} }; @@ -108,26 +141,33 @@ void WinService::start() } } -void WinService::waitForExit() +void WinService::waitForStop() { - if(started_) + if(!started_) throw std::runtime_error("Service not started correctly"); - WaitForSingleObject(exit_event_, INFINITE); + WaitForSingleObject(stop_event_, INFINITE); reportStatus(SERVICE_STOP_PENDING, NO_ERROR); } void WinService::stop() { - if(started_) + if(!started_) throw std::runtime_error("Service not started correctly"); reportStatus(SERVICE_STOPPED, NO_ERROR); } +int real_main(int argc, char* argv[]); + VOID WINAPI WinService::main(DWORD dwArgc, LPTSTR *lpszArgv) { - gWinService.status_handle_ = RegisterServiceCtrlHandlerA(gWinService.name_.c_str(), WinService::ctrlHandler); + if(gWinService.started_) { + cLog.msg(Log::PRIO_ERR) << "Service is already running"; + return; + } + + gWinService.status_handle_ = RegisterServiceCtrlHandlerA(SVC_NAME, WinService::ctrlHandler); if(!gWinService.status_handle_) { cLog.msg(Log::PRIO_ERR) << "Error on RegisterServiceCtrlHandler: " << LogErrno(GetLastError()); return; @@ -136,18 +176,30 @@ VOID WINAPI WinService::main(DWORD dwArgc, LPTSTR *lpszArgv) gWinService.status_.dwServiceSpecificExitCode = 0; gWinService.reportStatus(SERVICE_START_PENDING, NO_ERROR); - gWinService.exit_event_ = CreateEvent(NULL, true, false, NULL); - if(!gWinService.exit_event_) { + gWinService.stop_event_ = CreateEvent(NULL, true, false, NULL); + if(!gWinService.stop_event_) { cLog.msg(Log::PRIO_ERR) << "Error on CreateEvent: " << LogErrno(GetLastError()); gWinService.reportStatus(SERVICE_STOPPED, -1); return; } gWinService.started_ = true; gWinService.reportStatus(SERVICE_RUNNING, NO_ERROR); + + real_main(dwArgc, lpszArgv); } VOID WINAPI WinService::ctrlHandler(DWORD dwCtrl) { + switch(dwCtrl) { + case SERVICE_CONTROL_STOP: { + gWinService.reportStatus(SERVICE_STOP_PENDING, NO_ERROR); + SetEvent(gWinService.stop_event_); + return; + } + case SERVICE_CONTROL_INTERROGATE: break; + default: break; + } + gWinService.reportStatus(gWinService.status_.dwCurrentState, NO_ERROR); } void WinService::reportStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint) @@ -172,3 +224,5 @@ void WinService::reportStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD SetServiceStatus(status_handle_, &status_); } + +#endif \ No newline at end of file diff --git a/src/win32/winService.h b/src/win32/winService.h index dc648d8..53c2750 100644 --- a/src/win32/winService.h +++ b/src/win32/winService.h @@ -32,22 +32,26 @@ #ifndef _WIN_SERVICE_H_ #define _WIN_SERVICE_H_ +#ifdef WIN_SERVICE + #include "../threadUtils.hpp" class WinService { public: static WinService& instance(); + #define SVC_NAME "anytun" + static void install(); + static void uninstall(); + static void start(); - void install(); - void start(); - void waitForExit(); + void waitForStop(); void stop(); static VOID WINAPI main(DWORD dwArgc, LPTSTR *lpszArgv); static VOID WINAPI ctrlHandler(DWORD dwCtrl); private: - WinService() : name_("anytun"), started_(false) {}; + WinService() : started_(false) {}; ~WinService(); WinService(const WinService &w); void operator=(const WinService &w); @@ -63,14 +67,15 @@ private: } }; friend class instanceCleaner; - - std::string name_; + bool started_; SERVICE_STATUS status_; SERVICE_STATUS_HANDLE status_handle_; - HANDLE exit_event_; + HANDLE stop_event_; }; extern WinService& gWinService; +#endif + #endif \ No newline at end of file -- cgit v1.2.3