root/trunk/src/shared/ServiceWin32.cpp @ 102

Revision 102, 8.6 kB (checked in by yumileroy, 17 years ago)

[svn] Fixed copyright notices to comply with GPL.

Original author: w12x
Date: 2008-10-23 03:29:52-05:00

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