Electroneum
Toggle main menu visibility
Loading...
Searching...
No Matches
windows_service.cpp
Go to the documentation of this file.
1
// Copyrights(c) 2017-2021, The Electroneum Project
2
// Copyrights(c) 2014-2019, The Monero Project
3
//
4
// All rights reserved.
5
//
6
// Redistribution and use in source and binary forms, with or without modification, are
7
// permitted provided that the following conditions are met:
8
//
9
// 1. Redistributions of source code must retain the above copyright notice, this list of
10
// conditions and the following disclaimer.
11
//
12
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
13
// of conditions and the following disclaimer in the documentation and/or other
14
// materials provided with the distribution.
15
//
16
// 3. Neither the name of the copyright holder nor the names of its contributors may be
17
// used to endorse or promote products derived from this software without specific
18
// prior written permission.
19
//
20
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29
30
#include <boost/chrono/chrono.hpp>
31
#include <boost/thread/thread.hpp>
32
33
#undef UNICODE
34
#undef _UNICODE
35
36
#include "
common/scoped_message_writer.h
"
37
#include "
daemonizer/windows_service.h
"
38
#include "
string_tools.h
"
39
#include <chrono>
40
#include <iostream>
41
#include <utility>
42
#include <memory>
43
#include <shellapi.h>
44
#include <thread>
45
#include <windows.h>
46
47
namespace
windows
{
48
49
namespace
{
50
typedef
std::unique_ptr<std::remove_pointer<SC_HANDLE>::type,
decltype
(&::CloseServiceHandle)> service_handle;
51
52
std::string get_last_error()
53
{
54
LPSTR p_error_text =
nullptr
;
55
56
FormatMessage(
57
FORMAT_MESSAGE_FROM_SYSTEM
58
| FORMAT_MESSAGE_ALLOCATE_BUFFER
59
| FORMAT_MESSAGE_IGNORE_INSERTS
60
,
nullptr
61
, GetLastError()
62
, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT)
63
,
reinterpret_cast<
LPSTR
>
(&p_error_text)
64
, 0
65
,
nullptr
66
);
67
68
if
(
nullptr
== p_error_text)
69
{
70
return
""
;
71
}
72
else
73
{
74
std::string ret{p_error_text};
75
LocalFree(p_error_text);
76
return
ret;
77
}
78
}
79
80
bool
relaunch_as_admin(
81
std::string
const
& command
82
, std::string
const
& arguments
83
)
84
{
85
SHELLEXECUTEINFO
info
{};
86
info
.cbSize =
sizeof
(
info
);
87
info
.lpVerb =
"runas"
;
88
info
.lpFile = command.c_str();
89
info
.lpParameters = arguments.c_str();
90
info
.hwnd =
nullptr
;
91
info
.nShow = SW_SHOWNORMAL;
92
if
(!ShellExecuteEx(&
info
))
93
{
94
tools::fail_msg_writer
() <<
"Admin relaunch failed: "
<< get_last_error();
95
return
false
;
96
}
97
else
98
{
99
return
true
;
100
}
101
}
102
103
// When we relaunch as admin, Windows opens a new window. This just pauses
104
// to allow the user to read any output.
105
void
pause_to_display_admin_window_messages()
106
{
107
boost::chrono::milliseconds how_long{1500};
108
boost::this_thread::sleep_for(how_long);
109
}
110
}
111
112
bool
check_admin
(
bool
& result)
113
{
114
BOOL is_admin = FALSE;
115
PSID p_administrators_group =
nullptr
;
116
117
SID_IDENTIFIER_AUTHORITY nt_authority = SECURITY_NT_AUTHORITY;
118
119
if
(!AllocateAndInitializeSid(
120
&nt_authority
121
, 2
122
, SECURITY_BUILTIN_DOMAIN_RID
123
, DOMAIN_ALIAS_RID_ADMINS
124
, 0, 0, 0, 0, 0, 0
125
, &p_administrators_group
126
))
127
{
128
tools::fail_msg_writer
() <<
"Security Identifier creation failed: "
<< get_last_error();
129
return
false
;
130
}
131
132
if
(!CheckTokenMembership(
133
nullptr
134
, p_administrators_group
135
, &is_admin
136
))
137
{
138
tools::fail_msg_writer
() <<
"Permissions check failed: "
<< get_last_error();
139
return
false
;
140
}
141
142
result = is_admin ?
true
:
false
;
143
144
return
true
;
145
}
146
147
bool
ensure_admin
(
148
std::string
const
& arguments
149
)
150
{
151
bool
admin;
152
153
if
(!
check_admin
(admin))
154
{
155
return
false
;
156
}
157
158
if
(admin)
159
{
160
return
true
;
161
}
162
else
163
{
164
std::string command = epee::string_tools::get_current_module_path();
165
relaunch_as_admin(command, arguments);
166
return
false
;
167
}
168
}
169
170
bool
install_service
(
171
std::string
const
& service_name
172
, std::string
const
& arguments
173
)
174
{
175
std::string command = epee::string_tools::get_current_module_path();
176
std::string full_command = command + arguments;
177
178
service_handle p_manager{
179
OpenSCManager(
180
nullptr
181
,
nullptr
182
, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE
183
)
184
, &::CloseServiceHandle
185
};
186
if
(p_manager ==
nullptr
)
187
{
188
tools::fail_msg_writer
() <<
"Couldn't connect to service manager: "
<< get_last_error();
189
return
false
;
190
}
191
192
service_handle p_service{
193
CreateService(
194
p_manager.get()
195
, service_name.c_str()
196
, service_name.c_str()
197
, 0
198
//, GENERIC_EXECUTE | GENERIC_READ
199
, SERVICE_WIN32_OWN_PROCESS
200
, SERVICE_DEMAND_START
201
, SERVICE_ERROR_NORMAL
202
, full_command.c_str()
203
,
nullptr
204
,
nullptr
205
,
""
206
//, "NT AUTHORITY\\LocalService"
207
,
nullptr
// Implies LocalSystem account
208
,
nullptr
209
)
210
, &::CloseServiceHandle
211
};
212
if
(p_service ==
nullptr
)
213
{
214
tools::fail_msg_writer
() <<
"Couldn't create service: "
<< get_last_error();
215
return
false
;
216
}
217
218
tools::success_msg_writer
() <<
"Service installed"
;
219
220
pause_to_display_admin_window_messages();
221
222
return
true
;
223
}
224
225
bool
start_service
(
226
std::string
const
& service_name
227
)
228
{
229
tools::msg_writer
() <<
"Starting service"
;
230
231
SERVICE_STATUS_PROCESS service_status = {};
232
DWORD unused = 0;
233
234
service_handle p_manager{
235
OpenSCManager(
236
nullptr
237
,
nullptr
238
, SC_MANAGER_CONNECT
239
)
240
, &::CloseServiceHandle
241
};
242
if
(p_manager ==
nullptr
)
243
{
244
tools::fail_msg_writer
() <<
"Couldn't connect to service manager: "
<< get_last_error();
245
return
false
;
246
}
247
248
service_handle p_service{
249
OpenService(
250
p_manager.get()
251
, service_name.c_str()
252
//, SERVICE_START | SERVICE_QUERY_STATUS
253
, SERVICE_START
254
)
255
, &::CloseServiceHandle
256
};
257
if
(p_service ==
nullptr
)
258
{
259
tools::fail_msg_writer
() <<
"Couldn't find service: "
<< get_last_error();
260
return
false
;
261
}
262
263
if
(!StartService(
264
p_service.get()
265
, 0
266
,
nullptr
267
))
268
{
269
tools::fail_msg_writer
() <<
"Service start request failed: "
<< get_last_error();
270
return
false
;
271
}
272
273
tools::success_msg_writer
() <<
"Service started"
;
274
275
pause_to_display_admin_window_messages();
276
277
return
true
;
278
}
279
280
bool
stop_service
(
281
std::string
const
& service_name
282
)
283
{
284
tools::msg_writer
() <<
"Stopping service"
;
285
286
service_handle p_manager{
287
OpenSCManager(
288
nullptr
289
,
nullptr
290
, SC_MANAGER_CONNECT
291
)
292
, &::CloseServiceHandle
293
};
294
if
(p_manager ==
nullptr
)
295
{
296
tools::fail_msg_writer
() <<
"Couldn't connect to service manager: "
<< get_last_error();
297
return
false
;
298
}
299
300
service_handle p_service{
301
OpenService(
302
p_manager.get()
303
, service_name.c_str()
304
, SERVICE_STOP | SERVICE_QUERY_STATUS
305
)
306
, &::CloseServiceHandle
307
};
308
if
(p_service ==
nullptr
)
309
{
310
tools::fail_msg_writer
() <<
"Couldn't find service: "
<< get_last_error();
311
return
false
;
312
}
313
314
SERVICE_STATUS status = {};
315
if
(!ControlService(p_service.get(), SERVICE_CONTROL_STOP, &status))
316
{
317
tools::fail_msg_writer
() <<
"Couldn't request service stop: "
<< get_last_error();
318
return
false
;
319
}
320
321
tools::success_msg_writer
() <<
"Service stopped"
;
322
323
pause_to_display_admin_window_messages();
324
325
return
true
;
326
}
327
328
bool
uninstall_service
(
329
std::string
const
& service_name
330
)
331
{
332
service_handle p_manager{
333
OpenSCManager(
334
nullptr
335
,
nullptr
336
, SC_MANAGER_CONNECT
337
)
338
, &::CloseServiceHandle
339
};
340
if
(p_manager ==
nullptr
)
341
{
342
tools::fail_msg_writer
() <<
"Couldn't connect to service manager: "
<< get_last_error();
343
return
false
;
344
}
345
346
service_handle p_service{
347
OpenService(
348
p_manager.get()
349
, service_name.c_str()
350
, SERVICE_QUERY_STATUS | DELETE
351
)
352
, &::CloseServiceHandle
353
};
354
if
(p_service ==
nullptr
)
355
{
356
tools::fail_msg_writer
() <<
"Couldn't find service: "
<< get_last_error();
357
return
false
;
358
}
359
360
SERVICE_STATUS status = {};
361
if
(!DeleteService(p_service.get()))
362
{
363
tools::fail_msg_writer
() <<
"Couldn't uninstall service: "
<< get_last_error();
364
return
false
;
365
}
366
367
tools::success_msg_writer
() <<
"Service uninstalled"
;
368
369
pause_to_display_admin_window_messages();
370
371
return
true
;
372
}
373
374
}
// namespace windows
tools::fail_msg_writer
scoped_message_writer fail_msg_writer()
Definition
scoped_message_writer.h:131
tools::msg_writer
scoped_message_writer msg_writer(epee::console_colors color=epee::console_color_default)
Definition
scoped_message_writer.h:126
tools::success_msg_writer
scoped_message_writer success_msg_writer(bool color=true)
Definition
scoped_message_writer.h:121
windows
Definition
windows_service.cpp:47
windows::install_service
bool install_service(std::string const &service_name, std::string const &arguments)
Definition
windows_service.cpp:170
windows::check_admin
bool check_admin(bool &result)
Definition
windows_service.cpp:112
windows::ensure_admin
bool ensure_admin(std::string const &arguments)
Definition
windows_service.cpp:147
windows::start_service
bool start_service(std::string const &service_name)
Definition
windows_service.cpp:225
windows::stop_service
bool stop_service(std::string const &service_name)
Definition
windows_service.cpp:280
windows::uninstall_service
bool uninstall_service(std::string const &service_name)
Definition
windows_service.cpp:328
scoped_message_writer.h
true
#define true
info
CXA_THROW_INFO_T * info
Definition
stack_trace.cpp:91
string_tools.h
windows_service.h
src
daemonizer
windows_service.cpp
Generated on
for Electroneum by
1.17.0