Import of Mangos
[auctionmangos.git] / src / shared / ServiceWin32.cpp
blob09c5cd9070a051b730a640432e6babf774497f6b
1 /*
2 * Copyright (C) 2005-2008 MaNGOS <http://getmangos.com/>
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 #ifdef WIN32
21 #include "Common.h"
22 #include "Log.h"
23 #include <cstring>
24 #include <windows.h>
25 #include <winsvc.h>
27 #if !defined(WINADVAPI)
28 #if !defined(_ADVAPI32_)
29 #define WINADVAPI DECLSPEC_IMPORT
30 #else
31 #define WINADVAPI
32 #endif
33 #endif
35 extern int main(int argc, char ** argv);
36 extern char serviceLongName[];
37 extern char serviceName[];
38 extern char serviceDescription[];
40 extern int m_ServiceStatus;
42 SERVICE_STATUS serviceStatus;
44 SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
46 typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID);
48 bool WinServiceInstall()
50 CSD_T ChangeService_Config2;
51 HMODULE advapi32;
52 SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
54 if (serviceControlManager)
56 char path[_MAX_PATH + 10];
57 if (GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0)
59 SC_HANDLE service;
60 std::strcat(path, " --service");
61 service = CreateService(serviceControlManager,
62 serviceName, // name of service
63 serviceLongName, // service name to display
64 SERVICE_ALL_ACCESS, // desired access
65 // service type
66 SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
67 SERVICE_AUTO_START, // start type
68 SERVICE_ERROR_IGNORE, // error control type
69 path, // service's binary
70 0, // no load ordering group
71 0, // no tag identifier
72 0, // no dependencies
73 0, // LocalSystem account
74 0); // no password
75 if (service)
77 advapi32 = GetModuleHandle("ADVAPI32.DLL");
78 if(!advapi32)
80 CloseServiceHandle(service);
81 CloseServiceHandle(serviceControlManager);
82 return false;
85 ChangeService_Config2 = (CSD_T) GetProcAddress(advapi32, "ChangeServiceConfig2A");
86 if (!ChangeService_Config2)
88 CloseServiceHandle(service);
89 CloseServiceHandle(serviceControlManager);
90 return false;
93 SERVICE_DESCRIPTION sdBuf;
94 sdBuf.lpDescription = serviceDescription;
95 ChangeService_Config2(
96 service, // handle to service
97 SERVICE_CONFIG_DESCRIPTION, // change: description
98 &sdBuf); // new data
100 SC_ACTION _action[1];
101 _action[0].Type = SC_ACTION_RESTART;
102 _action[0].Delay = 10000;
103 SERVICE_FAILURE_ACTIONS sfa;
104 ZeroMemory(&sfa, sizeof(SERVICE_FAILURE_ACTIONS));
105 sfa.lpsaActions = _action;
106 sfa.cActions = 1;
107 sfa.dwResetPeriod =INFINITE;
108 ChangeService_Config2(
109 service, // handle to service
110 SERVICE_CONFIG_FAILURE_ACTIONS, // information level
111 &sfa); // new data
113 CloseServiceHandle(service);
117 CloseServiceHandle(serviceControlManager);
119 return true;
122 bool WinServiceUninstall()
124 SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
126 if (serviceControlManager)
128 SC_HANDLE service = OpenService(serviceControlManager,
129 serviceName, SERVICE_QUERY_STATUS | DELETE);
130 if (service)
132 SERVICE_STATUS serviceStatus;
133 if (QueryServiceStatus(service, &serviceStatus))
135 if (serviceStatus.dwCurrentState == SERVICE_STOPPED)
136 DeleteService(service);
138 CloseServiceHandle(service);
141 CloseServiceHandle(serviceControlManager);
143 return true;
146 void WINAPI ServiceControlHandler(DWORD controlCode)
148 switch (controlCode)
150 case SERVICE_CONTROL_INTERROGATE:
151 break;
153 case SERVICE_CONTROL_SHUTDOWN:
154 case SERVICE_CONTROL_STOP:
155 serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
156 SetServiceStatus(serviceStatusHandle, &serviceStatus);
158 m_ServiceStatus = 0;
159 return;
161 case SERVICE_CONTROL_PAUSE:
162 m_ServiceStatus = 2;
163 serviceStatus.dwCurrentState = SERVICE_PAUSED;
164 SetServiceStatus(serviceStatusHandle, &serviceStatus);
165 break;
167 case SERVICE_CONTROL_CONTINUE:
168 serviceStatus.dwCurrentState = SERVICE_RUNNING;
169 SetServiceStatus(serviceStatusHandle, &serviceStatus);
170 m_ServiceStatus = 1;
171 break;
173 default:
174 if ( controlCode >= 128 && controlCode <= 255 )
175 // user defined control code
176 break;
177 else
178 // unrecognized control code
179 break;
182 SetServiceStatus(serviceStatusHandle, &serviceStatus);
185 void WINAPI ServiceMain(DWORD argc, char *argv[])
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;
196 serviceStatusHandle = RegisterServiceCtrlHandler(serviceName, ServiceControlHandler);
198 if ( serviceStatusHandle )
200 char path[_MAX_PATH + 1];
201 unsigned int i, last_slash = 0;
203 GetModuleFileName(0, path, sizeof(path)/sizeof(path[0]));
205 for (i = 0; i < std::strlen(path); i++)
207 if (path[i] == '\\') last_slash = i;
210 path[last_slash] = 0;
212 // service is starting
213 serviceStatus.dwCurrentState = SERVICE_START_PENDING;
214 SetServiceStatus(serviceStatusHandle, &serviceStatus);
216 // do initialisation here
217 SetCurrentDirectory(path);
219 // running
220 serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
221 serviceStatus.dwCurrentState = SERVICE_RUNNING;
222 SetServiceStatus( serviceStatusHandle, &serviceStatus );
224 ////////////////////////
225 // service main cycle //
226 ////////////////////////
228 m_ServiceStatus = 1;
229 argc = 1;
230 main(argc , argv);
232 // service was stopped
233 serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
234 SetServiceStatus(serviceStatusHandle, &serviceStatus);
236 // do cleanup here
238 // service is now stopped
239 serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
240 serviceStatus.dwCurrentState = SERVICE_STOPPED;
241 SetServiceStatus(serviceStatusHandle, &serviceStatus);
245 bool WinServiceRun()
247 SERVICE_TABLE_ENTRY serviceTable[] =
249 { serviceName, ServiceMain },
250 { 0, 0 }
253 if (!StartServiceCtrlDispatcher(serviceTable))
255 sLog.outError("StartService Failed. Error [%u]", ::GetLastError());
256 return false;
258 return true;
260 #endif