Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
ServiceWin32.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#ifdef _WIN32
7
8#include "Common.h"
9#include "Log.h"
10#include <cstring>
11#include <windows.h>
12#include <winsvc.h>
13
14// Avoid third-party main macro collisions.
15#ifdef main
16#undef main
17#endif //main
18
19#if !defined(WINADVAPI)
20#if !defined(_ADVAPI32_)
21#define WINADVAPI DECLSPEC_IMPORT
22#else
23#define WINADVAPI
24#endif
25#endif
26
27extern int main(int argc, char** argv);
28extern char serviceLongName[];
29extern char serviceName[];
30extern char serviceDescription[];
31
32extern int m_ServiceStatus;
33
34SERVICE_STATUS serviceStatus;
35
36SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
37
38typedef WINADVAPI BOOL(WINAPI* CSD_T)(SC_HANDLE, DWORD, LPCVOID);
39
40bool WinServiceInstall()
41{
42 SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
43
44 if (serviceControlManager)
45 {
46 char path[_MAX_PATH + 10];
47 if (GetModuleFileName(0, path, sizeof(path) / sizeof(path[0])) > 0)
48 {
49 SC_HANDLE service;
50 std::strcat(path, " --service");
51 service = CreateService(serviceControlManager,
52 serviceName, // name of service
53 serviceLongName, // service name to display
54 SERVICE_ALL_ACCESS, // desired access
55 // service type
56 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
57 SERVICE_AUTO_START, // start type
58 SERVICE_ERROR_IGNORE, // error control type
59 path, // service's binary
60 0, // no load ordering group
61 0, // no tag identifier
62 0, // no dependencies
63 0, // LocalSystem account
64 0); // no password
65 if (service)
66 {
67 HMODULE advapi32 = GetModuleHandle("ADVAPI32.DLL");
68 if (!advapi32)
69 {
70 CloseServiceHandle(service);
71 CloseServiceHandle(serviceControlManager);
72 return false;
73 }
74
75 CSD_T ChangeService_Config2 = (CSD_T)GetProcAddress(advapi32, "ChangeServiceConfig2A");
76 if (!ChangeService_Config2)
77 {
78 CloseServiceHandle(service);
79 CloseServiceHandle(serviceControlManager);
80 return false;
81 }
82
83 SERVICE_DESCRIPTION sdBuf;
84 sdBuf.lpDescription = serviceDescription;
85 ChangeService_Config2(
86 service, // handle to service
87 SERVICE_CONFIG_DESCRIPTION, // change: description
88 &sdBuf); // new data
89
90 SC_ACTION _action[1];
91 _action[0].Type = SC_ACTION_RESTART;
92 _action[0].Delay = 10000;
93 SERVICE_FAILURE_ACTIONS sfa;
94 ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS));
95 sfa.lpsaActions = _action;
96 sfa.cActions = 1;
97 sfa.dwResetPeriod = INFINITE;
98 ChangeService_Config2(
99 service, // handle to service
100 SERVICE_CONFIG_FAILURE_ACTIONS, // information level
101 &sfa); // new data
102
103 CloseServiceHandle(service);
104 }
105 }
106 CloseServiceHandle(serviceControlManager);
107 }
108 return true;
109}
110
111bool WinServiceUninstall()
112{
113 SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
114
115 if (serviceControlManager)
116 {
117 SC_HANDLE service = OpenService(serviceControlManager,
118 serviceName, SERVICE_QUERY_STATUS | DELETE);
119 if (service)
120 {
121 SERVICE_STATUS serviceStatus2;
122 if (QueryServiceStatus(service, &serviceStatus2))
123 {
124 if (serviceStatus2.dwCurrentState == SERVICE_STOPPED)
125 DeleteService(service);
126 }
127 CloseServiceHandle(service);
128 }
129
130 CloseServiceHandle(serviceControlManager);
131 }
132 return true;
133}
134
135void WINAPI ServiceControlHandler(DWORD controlCode)
136{
137 switch (controlCode)
138 {
139 case SERVICE_CONTROL_INTERROGATE:
140 break;
141
142 case SERVICE_CONTROL_SHUTDOWN:
143 case SERVICE_CONTROL_STOP:
144 serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
145 SetServiceStatus(serviceStatusHandle, &serviceStatus);
146
147 m_ServiceStatus = 0;
148 return;
149
150 case SERVICE_CONTROL_PAUSE:
151 m_ServiceStatus = 2;
152 serviceStatus.dwCurrentState = SERVICE_PAUSED;
153 SetServiceStatus(serviceStatusHandle, &serviceStatus);
154 break;
155
156 case SERVICE_CONTROL_CONTINUE:
157 serviceStatus.dwCurrentState = SERVICE_RUNNING;
158 SetServiceStatus(serviceStatusHandle, &serviceStatus);
159 m_ServiceStatus = 1;
160 break;
161
162 default:
163 if (controlCode >= 128 && controlCode <= 255)
164 // user defined control code
165 break;
166 else
167 // unrecognized control code
168 break;
169 }
170
171 SetServiceStatus(serviceStatusHandle, &serviceStatus);
172}
173
174void WINAPI ServiceMain(DWORD argc, char* argv[])
175{
176 // initialise service status
177 serviceStatus.dwServiceType = SERVICE_WIN32;
178 serviceStatus.dwCurrentState = SERVICE_START_PENDING;
179 serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE;
180 serviceStatus.dwWin32ExitCode = NO_ERROR;
181 serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
182 serviceStatus.dwCheckPoint = 0;
183 serviceStatus.dwWaitHint = 0;
184
185 serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, ServiceControlHandler);
186
187 if (serviceStatusHandle)
188 {
189 char path[_MAX_PATH + 1];
190 unsigned int i, last_slash = 0;
191
192 GetModuleFileName(0, path, sizeof(path) / sizeof(path[0]));
193
194 for (i = 0; i < std::strlen(path); i++)
195 {
196 if (path[i] == '\\') last_slash = i;
197 }
198
199 path[last_slash] = 0;
200
201 // service is starting
202 serviceStatus.dwCurrentState = SERVICE_START_PENDING;
203 SetServiceStatus(serviceStatusHandle, &serviceStatus);
204
205 // do initialisation here
206 SetCurrentDirectory(path);
207
208 // running
209 serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
210 serviceStatus.dwCurrentState = SERVICE_RUNNING;
211 SetServiceStatus(serviceStatusHandle, &serviceStatus);
212
214 // service main cycle //
216
217 m_ServiceStatus = 1;
218 argc = 1;
219 main(argc, argv);
220
221 // service was stopped
222 serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
223 SetServiceStatus(serviceStatusHandle, &serviceStatus);
224
225 // do cleanup here
226
227 // service is now stopped
228 serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
229 serviceStatus.dwCurrentState = SERVICE_STOPPED;
230 SetServiceStatus(serviceStatusHandle, &serviceStatus);
231 }
232}
233
234bool WinServiceRun()
235{
236 SERVICE_TABLE_ENTRY serviceTable[] =
237 {
238 { serviceName, ServiceMain },
239 { 0, 0 }
240 };
241
242 if (!StartServiceCtrlDispatcher(serviceTable))
243 {
244 SF_LOG_ERROR("server.worldserver", "StartService Failed. Error [%u]", ::GetLastError());
245 return false;
246 }
247 return true;
248}
249#endif
250
#define SF_LOG_ERROR(filterType__,...)
Definition Log.h:143
int main(int argc, char **argv)
Launch the auth server.
Definition Main.cpp:207