-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathservice_installer.cpp
120 lines (98 loc) · 3.74 KB
/
service_installer.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
#include "service_installer.h"
#include <Windows.h>
#include <atlstr.h>
namespace {
class ServiceHandle {
public:
ServiceHandle(SC_HANDLE handle)
: m_handle(handle) {}
~ServiceHandle() {
if (m_handle) {
::CloseServiceHandle(m_handle);
}
}
operator SC_HANDLE() {
return m_handle;
}
private:
SC_HANDLE m_handle = nullptr;
};
}
//static
bool ServiceInstaller::Install(const ServiceBase& service) {
CString escapedPath;
TCHAR* modulePath = escapedPath.GetBufferSetLength(MAX_PATH);
if (::GetModuleFileName(nullptr, modulePath, MAX_PATH) == 0) {
_tprintf(_T("Couldn't get module file name: %d\n"), ::GetLastError());
return false;
}
escapedPath.ReleaseBuffer();
escapedPath.Remove(_T('\"'));
escapedPath = _T('\"') + escapedPath + _T('\"');
ServiceHandle svcControlManager = ::OpenSCManager(nullptr, nullptr,
SC_MANAGER_CONNECT |
SC_MANAGER_CREATE_SERVICE);
if (!svcControlManager) {
_tprintf(_T("Couldn't open service control manager: %d\n"), GetLastError());
return false;
}
const CString& depends = service.GetDependencies();
const CString& acc = service.GetAccount();
const CString& pass = service.GetPassword();
ServiceHandle servHandle = ::CreateService(svcControlManager,
service.GetName(),
service.GetDisplayName(),
SERVICE_QUERY_STATUS,
SERVICE_WIN32_OWN_PROCESS,
service.GetStartType(),
service.GetErrorControlType(),
escapedPath,
nullptr,
nullptr,
(depends.IsEmpty() ? nullptr : depends.GetString()),
(acc.IsEmpty() ? nullptr : acc.GetString()),
(pass.IsEmpty() ? nullptr : pass.GetString()));
if (!servHandle) {
_tprintf(_T("Couldn't create service: %d\n"), ::GetLastError());
return false;
}
return true;
}
//static
bool ServiceInstaller::Uninstall(const ServiceBase& service) {
ServiceHandle svcControlManager = ::OpenSCManager(nullptr, nullptr,
SC_MANAGER_CONNECT);
if (!svcControlManager) {
_tprintf(_T("Couldn't open service control manager: %d\n"), GetLastError());
return false;
}
ServiceHandle servHandle = ::OpenService(svcControlManager, service.GetName(),
SERVICE_QUERY_STATUS |
SERVICE_STOP |
DELETE);
if (!servHandle) {
_tprintf(_T("Couldn't open service control manager: %d\n"), ::GetLastError());
return false;
}
SERVICE_STATUS servStatus = {};
if (::ControlService(servHandle, SERVICE_CONTROL_STOP, &servStatus)) {
_tprintf(_T("Stoping service %s\n"), service.GetName());
while (::QueryServiceStatus(servHandle, &servStatus)) {
if (servStatus.dwCurrentState != SERVICE_STOP_PENDING) {
break;
}
}
if (servStatus.dwCurrentState != SERVICE_STOPPED) {
_tprintf(_T("Failed to stop the service\n"));
} else {
_tprintf(_T("Service stopped\n"));
}
} else {
_tprintf(_T("Didn't control service: %d\n"), ::GetLastError());
}
if (!::DeleteService(servHandle)) {
_tprintf(_T("Failed to delete the service: %d\n"), GetLastError());
return false;
}
return true;
}