TrinityCore
ServiceWin32.cpp
Go to the documentation of this file.
1/*
2 * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License as published by the
6 * Free Software Foundation; either version 2 of the License, or (at your
7 * option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#ifdef _WIN32
19
20#include "Log.h"
21#include <cstring>
22#include <windows.h>
23#include <winsvc.h>
24
25#if !defined(WINADVAPI)
26#if !defined(_ADVAPI32_)
27#define WINADVAPI DECLSPEC_IMPORT
28#else
29#define WINADVAPI
30#endif
31#endif
32
33extern int main(int argc, char ** argv);
34extern char serviceLongName[];
35extern char serviceName[];
36extern char serviceDescription[];
37
38extern int m_ServiceStatus;
39
40SERVICE_STATUS serviceStatus;
41
42SERVICE_STATUS_HANDLE serviceStatusHandle = nullptr;
43
44typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID);
45
46bool WinServiceInstall()
47{
48 SC_HANDLE serviceControlManager = OpenSCManager(nullptr, nullptr, SC_MANAGER_CREATE_SERVICE);
49
50 if (serviceControlManager)
51 {
52 char path[_MAX_PATH + 10];
53 if (GetModuleFileName( nullptr, path, sizeof(path)/sizeof(path[0]) ) > 0)
54 {
55 SC_HANDLE service;
56 std::strcat(path, " --service run");
57 service = CreateService(serviceControlManager,
58 serviceName, // name of service
59 serviceLongName, // service name to display
60 SERVICE_ALL_ACCESS, // desired access
61 // service type
62 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
63 SERVICE_AUTO_START, // start type
64 SERVICE_ERROR_IGNORE, // error control type
65 path, // service's binary
66 nullptr, // no load ordering group
67 nullptr, // no tag identifier
68 nullptr, // no dependencies
69 nullptr, // LocalSystem account
70 nullptr); // no password
71 if (service)
72 {
73 HMODULE advapi32 = GetModuleHandle("ADVAPI32.DLL");
74 if (!advapi32)
75 {
76 CloseServiceHandle(service);
77 CloseServiceHandle(serviceControlManager);
78 return false;
79 }
80
81 CSD_T ChangeService_Config2 = (CSD_T) GetProcAddress(advapi32, "ChangeServiceConfig2A");
82 if (!ChangeService_Config2)
83 {
84 CloseServiceHandle(service);
85 CloseServiceHandle(serviceControlManager);
86 return false;
87 }
88
89 SERVICE_DESCRIPTION sdBuf;
90 sdBuf.lpDescription = serviceDescription;
91 ChangeService_Config2(
92 service, // handle to service
93 SERVICE_CONFIG_DESCRIPTION, // change: description
94 &sdBuf); // new data
95
96 SC_ACTION _action[1];
97 _action[0].Type = SC_ACTION_RESTART;
98 _action[0].Delay = 10000;
99 SERVICE_FAILURE_ACTIONS sfa;
100 ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS));
101 sfa.lpsaActions = _action;
102 sfa.cActions = 1;
103 sfa.dwResetPeriod =INFINITE;
104 ChangeService_Config2(
105 service, // handle to service
106 SERVICE_CONFIG_FAILURE_ACTIONS, // information level
107 &sfa); // new data
108
109 CloseServiceHandle(service);
110
111 }
112 }
113 CloseServiceHandle(serviceControlManager);
114 }
115
116 printf("Service installed\n");
117 return true;
118}
119
120bool WinServiceUninstall()
121{
122 SC_HANDLE serviceControlManager = OpenSCManager(nullptr, nullptr, SC_MANAGER_CONNECT);
123
124 if (serviceControlManager)
125 {
126 SC_HANDLE service = OpenService(serviceControlManager,
127 serviceName, SERVICE_QUERY_STATUS | DELETE);
128 if (service)
129 {
130 SERVICE_STATUS serviceStatus2;
131 if (QueryServiceStatus(service, &serviceStatus2))
132 {
133 if (serviceStatus2.dwCurrentState == SERVICE_STOPPED)
134 DeleteService(service);
135 }
136 CloseServiceHandle(service);
137 }
138
139 CloseServiceHandle(serviceControlManager);
140 }
141
142 printf("Service uninstalled\n");
143 return true;
144}
145
146void WINAPI ServiceControlHandler(DWORD controlCode)
147{
148 switch (controlCode)
149 {
150 case SERVICE_CONTROL_INTERROGATE:
151 break;
152
153 case SERVICE_CONTROL_SHUTDOWN:
154 case SERVICE_CONTROL_STOP:
155 serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
156 SetServiceStatus(serviceStatusHandle, &serviceStatus);
157
158 m_ServiceStatus = 0;
159 return;
160
161 case SERVICE_CONTROL_PAUSE:
162 m_ServiceStatus = 2;
163 serviceStatus.dwCurrentState = SERVICE_PAUSED;
164 SetServiceStatus(serviceStatusHandle, &serviceStatus);
165 break;
166
167 case SERVICE_CONTROL_CONTINUE:
168 serviceStatus.dwCurrentState = SERVICE_RUNNING;
169 SetServiceStatus(serviceStatusHandle, &serviceStatus);
170 m_ServiceStatus = 1;
171 break;
172
173 default:
174 if ( controlCode >= 128 && controlCode <= 255 )
175 // user defined control code
176 break;
177 else
178 // unrecognized control code
179 break;
180 }
181
182 SetServiceStatus(serviceStatusHandle, &serviceStatus);
183}
184
185void WINAPI ServiceMain(DWORD argc, char *argv[])
186{
187 // initialise service status
188 serviceStatus.dwServiceType = SERVICE_WIN32;
189 serviceStatus.dwCurrentState = SERVICE_START_PENDING;
190 serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
191 serviceStatus.dwWin32ExitCode = NO_ERROR;
192 serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
193 serviceStatus.dwCheckPoint = 0;
194 serviceStatus.dwWaitHint = 0;
195
196 serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, ServiceControlHandler);
197
198 if ( serviceStatusHandle )
199 {
200 char path[_MAX_PATH + 1];
201 unsigned int i, last_slash = 0;
202
203 GetModuleFileName(nullptr, path, sizeof(path)/sizeof(path[0]));
204
205 size_t pathLen = std::strlen(path);
206 for (i = 0; i < pathLen; i++)
207 {
208 if (path[i] == '\\') last_slash = i;
209 }
210
211 path[last_slash] = 0;
212
213 // service is starting
214 serviceStatus.dwCurrentState = SERVICE_START_PENDING;
215 SetServiceStatus(serviceStatusHandle, &serviceStatus);
216
217 // do initialisation here
218 SetCurrentDirectory(path);
219
220 // running
221 serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
222 serviceStatus.dwCurrentState = SERVICE_RUNNING;
223 SetServiceStatus( serviceStatusHandle, &serviceStatus );
224
226 // service main cycle //
228
229 m_ServiceStatus = 1;
230 argc = 1;
231 main(argc, argv);
232
233 // service was stopped
234 serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
235 SetServiceStatus(serviceStatusHandle, &serviceStatus);
236
237 // do cleanup here
238
239 // service is now stopped
240 serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
241 serviceStatus.dwCurrentState = SERVICE_STOPPED;
242 SetServiceStatus(serviceStatusHandle, &serviceStatus);
243 }
244}
245
246bool WinServiceRun()
247{
248 SERVICE_TABLE_ENTRY serviceTable[] =
249 {
250 { serviceName, ServiceMain },
251 { nullptr, nullptr }
252 };
253
254 if (!StartServiceCtrlDispatcher(serviceTable))
255 {
256 TC_LOG_ERROR("server.worldserver", "StartService Failed. Error [{}]", uint32(::GetLastError()));
257 return false;
258 }
259 return true;
260}
261#endif
uint32_t uint32
Definition: Define.h:142
#define TC_LOG_ERROR(filterType__,...)
Definition: Log.h:165
char serviceDescription[]
Definition: Main.cpp:70
char serviceLongName[]
Definition: Main.cpp:69
int main(int argc, char **argv)
Definition: Main.cpp:89
char serviceName[]
Definition: Main.cpp:68
int m_ServiceStatus
Definition: Main.cpp:77