Electroneum
Toggle main menu visibility
Loading...
Searching...
No Matches
service_impl_base.h
Go to the documentation of this file.
1
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
2
// All rights reserved.
3
//
4
// Redistribution and use in source and binary forms, with or without
5
// modification, are permitted provided that the following conditions are met:
6
// * Redistributions of source code must retain the above copyright
7
// notice, this list of conditions and the following disclaimer.
8
// * Redistributions in binary form must reproduce the above copyright
9
// notice, this list of conditions and the following disclaimer in the
10
// documentation and/or other materials provided with the distribution.
11
// * Neither the name of the Andrey N. Sabelnikov nor the
12
// names of its contributors may be used to endorse or promote products
13
// derived from this software without specific prior written permission.
14
//
15
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
19
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
//
26
27
28
#ifndef _SERVICE_IMPL_BASE_H_
29
#define _SERVICE_IMPL_BASE_H_
30
31
#pragma comment(lib, "advapi32.lib")
32
33
34
namespace
epee
35
{
36
class
service_impl_base
{
37
public
:
38
service_impl_base
();
39
virtual
~service_impl_base
();
40
41
virtual
const
char
*
get_name
() = 0;
42
virtual
const
char
*
get_caption
() = 0;
43
virtual
const
char
*
get_description
() = 0;
44
45
bool
run_service
();
46
virtual
bool
install
();
47
virtual
bool
remove
();
48
virtual
bool
init
();
49
void
set_control_accepted
(
unsigned
controls);
50
void
set_status
(
unsigned
state
,
unsigned
pending
= 0);
51
unsigned
get_control_accepted
();
52
53
private
:
54
virtual
void
service_main() = 0;
55
virtual
unsigned
service_handler(
unsigned
control,
unsigned
event_code,
56
void
*pdata) = 0;
57
//-------------------------------------------------------------------------
58
static
service_impl_base
*& instance();
59
//-------------------------------------------------------------------------
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();
64
65
private
:
66
SC_HANDLE m_manager;
67
SC_HANDLE m_service;
68
SERVICE_STATUS_HANDLE m_status_handle;
69
DWORD m_accepted_control;
70
};
71
72
inline
service_impl_base::service_impl_base
() {
73
m_manager = 0;
74
m_service = 0;
75
m_status_handle = 0;
76
m_accepted_control = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN
77
| SERVICE_ACCEPT_PAUSE_CONTINUE;
78
79
instance() =
this
;
80
}
81
//-----------------------------------------------------------------------------
82
inline
service_impl_base::~service_impl_base
() {
83
if
(m_service) {
84
::CloseServiceHandle(m_service);
85
}
86
m_service = 0;
87
if
(m_manager) {
88
::CloseServiceHandle(m_manager);
89
}
90
m_manager = 0;
91
instance() = 0;
92
}
93
//-----------------------------------------------------------------------------
94
inline
service_impl_base
*& service_impl_base::instance() {
95
static
service_impl_base
*pservice = NULL;
96
return
pservice;
97
}
98
//-----------------------------------------------------------------------------
99
inline
100
bool
service_impl_base::install
() {
101
CHECK_AND_ASSERT
(!m_service,
false
);
102
const
char
*psz_descr =
get_description
();
103
SERVICE_FAILURE_ACTIONSA* fail_acts = get_failure_actions();
104
105
char
sz_path[MAX_PATH];
106
::GetModuleFileNameA(0, sz_path,
sizeof
(sz_path));
107
::GetShortPathNameA(sz_path, sz_path,
sizeof
(sz_path));
108
109
while
(TRUE) {
110
if
(!m_manager) {
111
m_manager = ::OpenSCManager(NULL, NULL, GENERIC_ALL);
112
if
(!m_manager) {
113
int
err = GetLastError();
114
LOG_ERROR
(
115
"Failed to OpenSCManager(), last err="
116
<< log_space::get_win32_err_descr(err));
117
break
;
118
}
119
}
120
m_service = ::CreateServiceA(m_manager,
get_name
(),
get_caption
(),
121
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START,
122
SERVICE_ERROR_IGNORE, sz_path, 0, 0, 0, 0, 0);
123
if
(!m_service) {
124
int
err = GetLastError();
125
LOG_ERROR
(
126
"Failed to CreateService(), last err="
127
<< log_space::get_win32_err_descr(err));
128
break
;
129
}
130
131
if
(psz_descr) {
132
SERVICE_DESCRIPTIONA sd = { (
char
*) psz_descr };
133
if
(!::ChangeServiceConfig2A(m_service, SERVICE_CONFIG_DESCRIPTION,
134
&sd)) {
135
int
err = GetLastError();
136
LOG_ERROR
(
137
"Failed to ChangeServiceConfig2(SERVICE_CONFIG_DESCRIPTION), last err="
138
<< log_space::get_win32_err_descr(err));
139
break
;
140
}
141
}
142
143
if
(fail_acts) {
144
if
(!::ChangeServiceConfig2A(m_service, SERVICE_CONFIG_FAILURE_ACTIONS,
145
fail_acts)) {
146
int
err = GetLastError();
147
LOG_ERROR
(
148
"Failed to ChangeServiceConfig2(SERVICE_CONFIG_FAILURE_ACTIONS), last err="
149
<< log_space::get_win32_err_descr(err));
150
break
;
151
}
152
}
153
LOG_PRINT(
"Installed succesfully."
, LOG_LEVEL_0);
154
return
true
;
155
}
156
LOG_PRINT(
"Failed to install."
, LOG_LEVEL_0);
157
return
false
;
158
}
159
//-----------------------------------------------------------------------------
160
inline
161
bool
service_impl_base::remove
() {
162
CHECK_AND_ASSERT
(!m_service,
false
);
163
164
while
(TRUE) {
165
if
(!m_manager) {
166
m_manager = ::OpenSCManager(0, 0, GENERIC_ALL);
167
if
(!m_manager) {
168
int
err = GetLastError();
169
LOG_ERROR
(
170
"Failed to OpenSCManager(), last err="
171
<< log_space::get_win32_err_descr(err));
172
break
;
173
}
174
}
175
176
if
(!m_service) {
177
m_service = ::OpenServiceA(m_manager,
get_name
(), SERVICE_STOP | DELETE);
178
if
(!m_service) {
179
int
err = GetLastError();
180
LOG_ERROR
(
181
"Failed to OpenService(), last err="
182
<< log_space::get_win32_err_descr(err));
183
break
;
184
}
185
}
186
187
SERVICE_STATUS status = { };
188
if
(!::ControlService(m_service, SERVICE_CONTROL_STOP, &status)) {
189
int
err = ::GetLastError();
190
if
(err == ERROR_SHUTDOWN_IN_PROGRESS)
191
continue
;
192
else
if
(err != ERROR_SERVICE_NOT_ACTIVE) {
193
LOG_ERROR
(
194
"Failed to ControlService(SERVICE_CONTROL_STOP), last err="
195
<< log_space::get_win32_err_descr(err));
196
break
;
197
}
198
}
199
200
if
(!::DeleteService(m_service)) {
201
int
err = ::GetLastError();
202
LOG_ERROR
(
203
"Failed to ControlService(SERVICE_CONTROL_STOP), last err="
204
<< log_space::get_win32_err_descr(err));
205
break
;
206
}
207
208
LOG_PRINT(
"Removed successfully."
, LOG_LEVEL_0);
209
break
;
210
}
211
212
return
true
;
213
}
214
//-----------------------------------------------------------------------------
215
inline
216
bool
service_impl_base::init
() {
217
return
true
;
218
}
219
//-----------------------------------------------------------------------------
220
inline
221
bool
service_impl_base::run_service
() {
222
CHECK_AND_ASSERT
(!m_service,
false
);
223
224
long
error_code = 0;
225
226
SERVICE_TABLE_ENTRYA service_table[2];
227
ZeroMemory(&service_table,
sizeof
(service_table));
228
229
service_table->lpServiceName = (
char
*)
get_name
();
230
service_table->lpServiceProc = service_entry;
231
232
LOG_PRINT(
"[+] Start service control dispatcher for \""
<<
get_name
() <<
"\""
,
233
LOG_LEVEL_1);
234
235
error_code = 1;
236
BOOL
res
= ::StartServiceCtrlDispatcherA(service_table);
237
if
(!
res
) {
238
int
err = GetLastError();
239
LOG_PRINT(
240
"[+] Error starting service control dispatcher, err="
241
<< log_space::get_win32_err_descr(err), LOG_LEVEL_1);
242
return
false
;
243
}
else
{
244
LOG_PRINT(
"[+] End service control dispatcher for \""
<<
get_name
() <<
"\""
,
245
LOG_LEVEL_1);
246
}
247
return
true
;
248
}
249
//-----------------------------------------------------------------------------
250
inline
DWORD __stdcall service_impl_base::_service_handler(DWORD control,
251
DWORD
event
,
void
*pdata,
void
*pcontext) {
252
CHECK_AND_ASSERT
(pcontext, ERROR_CALL_NOT_IMPLEMENTED);
253
254
service_impl_base
*pservice = (
service_impl_base
*) pcontext;
255
return
pservice->service_handler(control,
event
, pdata);
256
}
257
//-----------------------------------------------------------------------------
258
inline
259
void
__stdcall service_impl_base::service_entry(DWORD argc,
char
**pargs) {
260
service_impl_base
*pme = instance();
261
LOG_PRINT(
"instance: "
<< pme, LOG_LEVEL_4);
262
if
(!pme) {
263
LOG_ERROR
(
"Error: at service_entry() pme = NULL"
);
264
return
;
265
}
266
pme->m_status_handle = ::RegisterServiceCtrlHandlerExA(pme->get_name(),
267
_service_handler, pme);
268
269
pme->set_status(SERVICE_RUNNING);
270
pme->service_main();
271
pme->set_status(SERVICE_STOPPED);
272
}
273
//-----------------------------------------------------------------------------
274
inline
275
void
service_impl_base::set_status
(
unsigned
state
,
unsigned
pending
) {
276
if
(!m_status_handle)
277
return
;
278
279
SERVICE_STATUS status = { 0 };
280
status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
281
status.dwCurrentState =
state
;
282
status.dwControlsAccepted = m_accepted_control;
283
/*status.dwWin32ExitCode = NO_ERROR;
284
status.dwServiceSpecificExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
285
status.dwCheckPoint = 0;
286
status.dwWaitHint = 0;
287
288
status.dwCurrentState = state;*/
289
290
if
(
state
== SERVICE_START_PENDING ||
state
== SERVICE_STOP_PENDING
291
||
state
== SERVICE_CONTINUE_PENDING ||
state
== SERVICE_PAUSE_PENDING) {
292
status.dwWaitHint = 2000;
293
status.dwCheckPoint =
pending
;
294
}
295
::SetServiceStatus(m_status_handle, &status);
296
}
297
//-----------------------------------------------------------------------------------------
298
inline
299
void
service_impl_base::set_control_accepted
(
unsigned
controls) {
300
m_accepted_control = controls;
301
}
302
//-----------------------------------------------------------------------------------------
303
inline
304
unsigned
service_impl_base::get_control_accepted
() {
305
return
m_accepted_control;
306
}
307
//-----------------------------------------------------------------------------------------
308
inline
SERVICE_FAILURE_ACTIONSA* service_impl_base::get_failure_actions() {
309
// first 3 failures in 30 minutes. Service will be restarted.
310
// do nothing for next failures
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 } };
314
315
static
SERVICE_FAILURE_ACTIONSA sfa = { 1800,
// interval for failures counter - 30 min
316
""
, NULL, 4, (SC_ACTION*) &sa };
317
318
// TODO: refactor this code, really unsafe!
319
return
&sfa;
320
}
321
}
322
323
#endif
//_SERVICE_IMPL_BASE_H_
epee::event
Definition
winobj.h:168
epee::service_impl_base
Definition
service_impl_base.h:36
epee::service_impl_base::install
virtual bool install()
Definition
service_impl_base.h:100
epee::service_impl_base::init
virtual bool init()
Definition
service_impl_base.h:216
epee::service_impl_base::get_control_accepted
unsigned get_control_accepted()
Definition
service_impl_base.h:304
epee::service_impl_base::set_status
void set_status(unsigned state, unsigned pending=0)
Definition
service_impl_base.h:275
epee::service_impl_base::get_name
virtual const char * get_name()=0
epee::service_impl_base::service_impl_base
service_impl_base()
Definition
service_impl_base.h:72
epee::service_impl_base::remove
virtual bool remove()
Definition
service_impl_base.h:161
epee::service_impl_base::get_description
virtual const char * get_description()=0
epee::service_impl_base::get_caption
virtual const char * get_caption()=0
epee::service_impl_base::~service_impl_base
virtual ~service_impl_base()
Definition
service_impl_base.h:82
epee::service_impl_base::run_service
bool run_service()
Definition
service_impl_base.h:221
epee::service_impl_base::set_control_accepted
void set_control_accepted(unsigned controls)
Definition
service_impl_base.h:299
res
const char * res
Definition
hmac_keccak.cpp:41
LOG_ERROR
#define LOG_ERROR(x)
Definition
misc_log_ex.h:98
CHECK_AND_ASSERT
#define CHECK_AND_ASSERT(expr, fail_ret_val)
Definition
misc_log_ex.h:177
epee
Definition
ado_db_helper.h:67
pending
Definition
outside_network.h:211
state
Definition
blake256.h:37
contrib
epee
include
service_impl_base.h
Generated on
for Electroneum by
1.17.0