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

Revision 2, 8.5 kB (checked in by yumileroy, 17 years ago)

[svn] * Proper SVN structure

Original author: Neo2003
Date: 2008-10-02 16:23:55-05:00

Line 
1/*
2 * Copyright (C) 2005-2008 MaNGOS <http://www.mangosproject.org/>
3 *
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.
8 *
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.
13 *
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.
17 */
18
19#ifdef WIN32
20
21#include "Common.h"
22#include "Log.h"
23#include <cstring>
24#include <windows.h>
25#include <winsvc.h>
26
27#if !defined(WINADVAPI)
28#if !defined(_ADVAPI32_)
29#define WINADVAPI DECLSPEC_IMPORT
30#else
31#define WINADVAPI
32#endif
33#endif
34
35extern int main(int argc, char ** argv);
36extern char serviceLongName[];
37extern char serviceName[];
38extern char serviceDescription[];
39
40extern int m_ServiceStatus;
41
42SERVICE_STATUS serviceStatus;
43
44SERVICE_STATUS_HANDLE serviceStatusHandle = 0;
45
46typedef WINADVAPI BOOL (WINAPI *CSD_T)(SC_HANDLE, DWORD, LPCVOID);
47
48bool WinServiceInstall()
49{
50    CSD_T ChangeService_Config2;
51    HMODULE advapi32;
52    SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
53
54    if (serviceControlManager)
55    {
56        char path[_MAX_PATH + 10];
57        if (GetModuleFileName( 0, path, sizeof(path)/sizeof(path[0]) ) > 0)
58        {
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)
76            {
77                advapi32 = GetModuleHandle("ADVAPI32.DLL");
78                if(!advapi32)
79                {
80                    CloseServiceHandle(service);
81                    CloseServiceHandle(serviceControlManager);
82                    return false;
83                }
84
85                ChangeService_Config2 = (CSD_T) GetProcAddress(advapi32, "ChangeServiceConfig2A");
86                if (!ChangeService_Config2)
87                {
88                    CloseServiceHandle(service);
89                    CloseServiceHandle(serviceControlManager);
90                    return false;
91                }
92
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
99
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
112
113                CloseServiceHandle(service);
114
115            }
116        }
117        CloseServiceHandle(serviceControlManager);
118    }
119    return true;
120}
121
122bool WinServiceUninstall()
123{
124    SC_HANDLE serviceControlManager = OpenSCManager(0, 0, SC_MANAGER_CONNECT);
125
126    if (serviceControlManager)
127    {
128        SC_HANDLE service = OpenService(serviceControlManager,
129            serviceName, SERVICE_QUERY_STATUS | DELETE);
130        if (service)
131        {
132            SERVICE_STATUS serviceStatus;
133            if (QueryServiceStatus(service, &serviceStatus))
134            {
135                if (serviceStatus.dwCurrentState == SERVICE_STOPPED)
136                    DeleteService(service);
137            }
138            CloseServiceHandle(service);
139        }
140
141        CloseServiceHandle(serviceControlManager);
142    }
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(0, path, sizeof(path)/sizeof(path[0]));
204
205        for (i = 0; i < std::strlen(path); i++)
206        {
207            if (path[i] == '\\') last_slash = i;
208        }
209
210        path[last_slash] = 0;
211
212        // service is starting
213        serviceStatus.dwCurrentState = SERVICE_START_PENDING;
214        SetServiceStatus(serviceStatusHandle, &serviceStatus);
215
216        // do initialisation here
217        SetCurrentDirectory(path);
218
219        // running
220        serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
221        serviceStatus.dwCurrentState = SERVICE_RUNNING;
222        SetServiceStatus( serviceStatusHandle, &serviceStatus );
223
224        ////////////////////////
225        // service main cycle //
226        ////////////////////////
227
228        m_ServiceStatus = 1;
229        argc = 1;
230        main(argc , argv);
231
232        // service was stopped
233        serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
234        SetServiceStatus(serviceStatusHandle, &serviceStatus);
235
236        // do cleanup here
237
238        // service is now stopped
239        serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN);
240        serviceStatus.dwCurrentState = SERVICE_STOPPED;
241        SetServiceStatus(serviceStatusHandle, &serviceStatus);
242    }
243}
244
245bool WinServiceRun()
246{
247    SERVICE_TABLE_ENTRY serviceTable[] =
248    {
249        { serviceName, ServiceMain },
250        { 0, 0 }
251    };
252
253    if (!StartServiceCtrlDispatcher(serviceTable))
254    {
255        sLog.outError("StartService Failed. Error [%u]", ::GetLastError());
256        return false;
257    }
258    return true;
259}
260#endif
Note: See TracBrowser for help on using the browser.