28 #ifndef _SERVICE_IMPL_BASE_H_ 29 #define _SERVICE_IMPL_BASE_H_ 31 #pragma comment(lib, "advapi32.lib") 47 virtual bool remove();
54 virtual void service_main() = 0;
55 virtual unsigned service_handler(
unsigned control,
unsigned event_code,
60 static DWORD __stdcall _service_handler(DWORD control, DWORD
event,
61 void *pdata,
void *pcontext);
62 static void __stdcall service_entry(DWORD argc,
char **pargs);
63 virtual SERVICE_FAILURE_ACTIONSA* get_failure_actions();
68 SERVICE_STATUS_HANDLE m_status_handle;
69 DWORD m_accepted_control;
76 m_accepted_control = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN
77 | SERVICE_ACCEPT_PAUSE_CONTINUE;
84 ::CloseServiceHandle(m_service);
88 ::CloseServiceHandle(m_manager);
103 SERVICE_FAILURE_ACTIONSA* fail_acts = get_failure_actions();
105 char sz_path[MAX_PATH];
106 ::GetModuleFileNameA(0, sz_path,
sizeof(sz_path));
107 ::GetShortPathNameA(sz_path, sz_path,
sizeof(sz_path));
111 m_manager = ::OpenSCManager(NULL, NULL, GENERIC_ALL);
113 int err = GetLastError();
115 "Failed to OpenSCManager(), last err=" 116 << log_space::get_win32_err_descr(err));
121 SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START,
122 SERVICE_ERROR_IGNORE, sz_path, 0, 0, 0, 0, 0);
124 int err = GetLastError();
126 "Failed to CreateService(), last err=" 127 << log_space::get_win32_err_descr(err));
132 SERVICE_DESCRIPTIONA sd = { (
char*) psz_descr };
133 if (!::ChangeServiceConfig2A(m_service, SERVICE_CONFIG_DESCRIPTION,
135 int err = GetLastError();
137 "Failed to ChangeServiceConfig2(SERVICE_CONFIG_DESCRIPTION), last err=" 138 << log_space::get_win32_err_descr(err));
144 if (!::ChangeServiceConfig2A(m_service, SERVICE_CONFIG_FAILURE_ACTIONS,
146 int err = GetLastError();
148 "Failed to ChangeServiceConfig2(SERVICE_CONFIG_FAILURE_ACTIONS), last err=" 149 << log_space::get_win32_err_descr(err));
153 LOG_PRINT(
"Installed succesfully.", LOG_LEVEL_0);
156 LOG_PRINT(
"Failed to install.", LOG_LEVEL_0);
166 m_manager = ::OpenSCManager(0, 0, GENERIC_ALL);
168 int err = GetLastError();
170 "Failed to OpenSCManager(), last err=" 171 << log_space::get_win32_err_descr(err));
177 m_service = ::OpenServiceA(m_manager,
get_name(), SERVICE_STOP | DELETE);
179 int err = GetLastError();
181 "Failed to OpenService(), last err=" 182 << log_space::get_win32_err_descr(err));
187 SERVICE_STATUS status = { };
188 if (!::ControlService(m_service, SERVICE_CONTROL_STOP, &status)) {
189 int err = ::GetLastError();
190 if (err == ERROR_SHUTDOWN_IN_PROGRESS)
192 else if (err != ERROR_SERVICE_NOT_ACTIVE) {
194 "Failed to ControlService(SERVICE_CONTROL_STOP), last err=" 195 << log_space::get_win32_err_descr(err));
200 if (!::DeleteService(m_service)) {
201 int err = ::GetLastError();
203 "Failed to ControlService(SERVICE_CONTROL_STOP), last err=" 204 << log_space::get_win32_err_descr(err));
208 LOG_PRINT(
"Removed successfully.", LOG_LEVEL_0);
226 SERVICE_TABLE_ENTRYA service_table[2];
227 ZeroMemory(&service_table,
sizeof(service_table));
229 service_table->lpServiceName = (
char*)
get_name();
230 service_table->lpServiceProc = service_entry;
232 LOG_PRINT(
"[+] Start service control dispatcher for \"" <<
get_name() <<
"\"",
236 BOOL
res = ::StartServiceCtrlDispatcherA(service_table);
238 int err = GetLastError();
240 "[+] Error starting service control dispatcher, err=" 241 << log_space::get_win32_err_descr(err), LOG_LEVEL_1);
244 LOG_PRINT(
"[+] End service control dispatcher for \"" <<
get_name() <<
"\"",
250 inline DWORD __stdcall service_impl_base::_service_handler(DWORD control,
251 DWORD
event,
void *pdata,
void *pcontext) {
255 return pservice->service_handler(control,
event, pdata);
259 void __stdcall service_impl_base::service_entry(DWORD argc,
char **pargs) {
261 LOG_PRINT(
"instance: " << pme, LOG_LEVEL_4);
263 LOG_ERROR(
"Error: at service_entry() pme = NULL");
266 pme->m_status_handle = ::RegisterServiceCtrlHandlerExA(pme->get_name(),
267 _service_handler, pme);
269 pme->set_status(SERVICE_RUNNING);
271 pme->set_status(SERVICE_STOPPED);
276 if (!m_status_handle)
279 SERVICE_STATUS status = { 0 };
280 status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
281 status.dwCurrentState =
state;
282 status.dwControlsAccepted = m_accepted_control;
290 if (
state == SERVICE_START_PENDING ||
state == SERVICE_STOP_PENDING
291 ||
state == SERVICE_CONTINUE_PENDING ||
state == SERVICE_PAUSE_PENDING) {
292 status.dwWaitHint = 2000;
295 ::SetServiceStatus(m_status_handle, &status);
300 m_accepted_control = controls;
305 return m_accepted_control;
308 inline SERVICE_FAILURE_ACTIONSA* service_impl_base::get_failure_actions() {
311 static SC_ACTION sa[] = { { SC_ACTION_RESTART, 3 * 1000 }, {
312 SC_ACTION_RESTART, 3 * 1000 }, { SC_ACTION_RESTART, 3 * 1000 }, {
313 SC_ACTION_NONE, 0 } };
315 static SERVICE_FAILURE_ACTIONSA sfa = { 1800,
316 "", NULL, 4, (SC_ACTION*) &sa };
323 #endif //_SERVICE_IMPL_BASE_H_
unsigned get_control_accepted()
void set_control_accepted(unsigned controls)
virtual const char * get_description()=0
#define CHECK_AND_ASSERT(expr, fail_ret_val)
virtual const char * get_caption()=0
virtual const char * get_name()=0
virtual ~service_impl_base()
void set_status(unsigned state, unsigned pending=0)