4 * The secure anycast tunneling protocol (satp) defines a protocol used
5 * for communication between any combination of unicast and anycast
6 * tunnel endpoints. It has less protocol overhead than IPSec in Tunnel
7 * mode and allows tunneling of every ETHER TYPE protocol (e.g.
8 * ethernet, ip, arp ...). satp directly includes cryptography and
9 * message authentication based on the methodes used by SRTP. It is
10 * intended to deliver a generic, scaleable and secure solution for
11 * tunneling and relaying of packets of any protocol.
14 * Copyright (C) 2007-2008 Othmar Gsenger, Erwin Nindl,
15 * Christian Pointner <satp@wirdorange.org>
17 * This file is part of Anytun.
19 * Anytun is free software: you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License version 3 as
21 * published by the Free Software Foundation.
23 * Anytun is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
28 * You should have received a copy of the GNU General Public License
29 * along with anytun. If not, see <http://www.gnu.org/licenses/>.
38 #include "winService.h"
40 #include "../anytunError.h"
41 #include "../threadUtils.hpp"
43 WinService* WinService::inst = NULL;
44 Mutex WinService::instMutex;
45 WinService& gWinService = WinService::instance();
47 WinService& WinService::instance()
50 static instanceCleaner c;
52 inst = new WinService();
57 WinService::~WinService()
60 CloseHandle(stop_event_);
63 void WinService::install()
65 SC_HANDLE schSCManager;
67 char szPath[MAX_PATH];
69 if(!GetModuleFileNameA(NULL, szPath, MAX_PATH))
70 AnytunError::throwErr() << "Error on GetModuleFileName: " << AnytunErrno(GetLastError());
72 schSCManager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
73 if(NULL == schSCManager)
74 AnytunError::throwErr() << "Error on OpenSCManager: " << AnytunErrno(GetLastError());
76 schService = CreateServiceA(schSCManager, SVC_NAME, SVC_NAME, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
77 SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, szPath, NULL, NULL, NULL, NULL, NULL);
78 if(schService == NULL) {
79 CloseServiceHandle(schSCManager);
80 AnytunError::throwErr() << "Error on CreateService: " << AnytunErrno(GetLastError());
83 std::cout << "Service installed successfully" << std::endl;
85 CloseServiceHandle(schService);
86 CloseServiceHandle(schSCManager);
89 void WinService::uninstall()
91 SC_HANDLE schSCManager;
94 schSCManager = OpenSCManagerA(NULL, NULL, SC_MANAGER_ALL_ACCESS);
95 if(NULL == schSCManager)
96 AnytunError::throwErr() << "Error on OpenSCManager: " << AnytunErrno(GetLastError());
98 schService = OpenServiceA(schSCManager, SVC_NAME, SERVICE_ALL_ACCESS);
99 if(schService == NULL) {
100 CloseServiceHandle(schSCManager);
101 AnytunError::throwErr() << "Error on CreateService: " << AnytunErrno(GetLastError());
104 if(!DeleteService(schService)) {
105 CloseServiceHandle(schService);
106 CloseServiceHandle(schSCManager);
107 AnytunError::throwErr() << "Error on DeleteService: " << AnytunErrno(GetLastError());
110 std::cout << "Service uninstalled successfully" << std::endl;
112 CloseServiceHandle(schService);
113 CloseServiceHandle(schSCManager);
116 void WinService::start()
118 SERVICE_TABLE_ENTRY DispatchTable[] = {
119 {SVC_NAME, (LPSERVICE_MAIN_FUNCTION)WinService::main },
123 if(!StartServiceCtrlDispatcherA(DispatchTable))
124 AnytunError::throwErr() << "Error on StartServiceCtrlDispatcher: " << AnytunErrno(GetLastError());
127 void WinService::waitForStop()
130 AnytunError::throwErr() << "Service not started correctly";
132 reportStatus(SERVICE_RUNNING, NO_ERROR);
133 WaitForSingleObject(stop_event_, INFINITE);
134 reportStatus(SERVICE_STOP_PENDING, NO_ERROR);
135 cLog.msg(Log::PRIO_NOTICE) << "WinService received stop signal, exitting";
138 void WinService::stop()
141 AnytunError::throwErr() << "Service not started correctly";
143 reportStatus(SERVICE_STOPPED, NO_ERROR);
146 int real_main(int argc, char* argv[]);
148 VOID WINAPI WinService::main(DWORD dwArgc, LPTSTR *lpszArgv)
150 if(gWinService.started_) {
151 cLog.msg(Log::PRIO_ERROR) << "Service is already running";
155 gWinService.status_handle_ = RegisterServiceCtrlHandlerA(SVC_NAME, WinService::ctrlHandler);
156 if(!gWinService.status_handle_) {
157 cLog.msg(Log::PRIO_ERROR) << "Error on RegisterServiceCtrlHandler: " << AnytunErrno(GetLastError());
160 gWinService.status_.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
161 gWinService.status_.dwServiceSpecificExitCode = 0;
162 gWinService.reportStatus(SERVICE_START_PENDING, NO_ERROR);
163 gWinService.started_ = true;
165 gWinService.stop_event_ = CreateEvent(NULL, true, false, NULL);
166 if(!gWinService.stop_event_) {
167 cLog.msg(Log::PRIO_ERROR) << "WinService Error on CreateEvent: " << AnytunErrno(GetLastError());
168 gWinService.reportStatus(SERVICE_STOPPED, -1);
172 real_main(dwArgc, lpszArgv);
175 VOID WINAPI WinService::ctrlHandler(DWORD dwCtrl)
178 case SERVICE_CONTROL_STOP: {
179 gWinService.reportStatus(SERVICE_STOP_PENDING, NO_ERROR);
180 SetEvent(gWinService.stop_event_);
183 case SERVICE_CONTROL_INTERROGATE: break;
186 gWinService.reportStatus(gWinService.status_.dwCurrentState, NO_ERROR);
189 void WinService::reportStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint)
191 static DWORD dwCheckPoint = 1;
193 status_.dwCurrentState = dwCurrentState;
194 status_.dwWin32ExitCode = dwWin32ExitCode;
195 status_.dwWaitHint = dwWaitHint;
197 if((dwCurrentState == SERVICE_START_PENDING) ||
198 (dwCurrentState == SERVICE_STOP_PENDING))
199 status_.dwControlsAccepted = 0;
201 status_.dwControlsAccepted = SERVICE_ACCEPT_STOP;
203 if((dwCurrentState == SERVICE_RUNNING) ||
204 (dwCurrentState == SERVICE_STOPPED))
205 status_.dwCheckPoint = 0;
207 status_.dwCheckPoint = dwCheckPoint++;
209 SetServiceStatus(status_handle_, &status_);