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.
27 #if !defined(WINADVAPI)
28 #if !defined(_ADVAPI32_)
29 #define WINADVAPI DECLSPEC_IMPORT
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
;
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)
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
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
73 0, // LocalSystem account
77 advapi32
= GetModuleHandle("ADVAPI32.DLL");
80 CloseServiceHandle(service
);
81 CloseServiceHandle(serviceControlManager
);
85 ChangeService_Config2
= (CSD_T
) GetProcAddress(advapi32
, "ChangeServiceConfig2A");
86 if (!ChangeService_Config2
)
88 CloseServiceHandle(service
);
89 CloseServiceHandle(serviceControlManager
);
93 SERVICE_DESCRIPTION sdBuf
;
94 sdBuf
.lpDescription
= serviceDescription
;
95 ChangeService_Config2(
96 service
, // handle to service
97 SERVICE_CONFIG_DESCRIPTION
, // change: description
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
;
107 sfa
.dwResetPeriod
=INFINITE
;
108 ChangeService_Config2(
109 service
, // handle to service
110 SERVICE_CONFIG_FAILURE_ACTIONS
, // information level
113 CloseServiceHandle(service
);
117 CloseServiceHandle(serviceControlManager
);
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
);
132 SERVICE_STATUS serviceStatus
;
133 if (QueryServiceStatus(service
, &serviceStatus
))
135 if (serviceStatus
.dwCurrentState
== SERVICE_STOPPED
)
136 DeleteService(service
);
138 CloseServiceHandle(service
);
141 CloseServiceHandle(serviceControlManager
);
146 void WINAPI
ServiceControlHandler(DWORD controlCode
)
150 case SERVICE_CONTROL_INTERROGATE
:
153 case SERVICE_CONTROL_SHUTDOWN
:
154 case SERVICE_CONTROL_STOP
:
155 serviceStatus
.dwCurrentState
= SERVICE_STOP_PENDING
;
156 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
161 case SERVICE_CONTROL_PAUSE
:
163 serviceStatus
.dwCurrentState
= SERVICE_PAUSED
;
164 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
167 case SERVICE_CONTROL_CONTINUE
:
168 serviceStatus
.dwCurrentState
= SERVICE_RUNNING
;
169 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
174 if ( controlCode
>= 128 && controlCode
<= 255 )
175 // user defined control code
178 // unrecognized control code
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
);
220 serviceStatus
.dwControlsAccepted
|= (SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN
);
221 serviceStatus
.dwCurrentState
= SERVICE_RUNNING
;
222 SetServiceStatus( serviceStatusHandle
, &serviceStatus
);
224 ////////////////////////
225 // service main cycle //
226 ////////////////////////
232 // service was stopped
233 serviceStatus
.dwCurrentState
= SERVICE_STOP_PENDING
;
234 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
238 // service is now stopped
239 serviceStatus
.dwControlsAccepted
&= ~(SERVICE_ACCEPT_STOP
| SERVICE_ACCEPT_SHUTDOWN
);
240 serviceStatus
.dwCurrentState
= SERVICE_STOPPED
;
241 SetServiceStatus(serviceStatusHandle
, &serviceStatus
);
247 SERVICE_TABLE_ENTRY serviceTable
[] =
249 { serviceName
, ServiceMain
},
253 if (!StartServiceCtrlDispatcher(serviceTable
))
255 sLog
.outError("StartService Failed. Error [%u]", ::GetLastError());