source: nscp/include/ServiceCmd.cpp

0.4.1
Last change on this file was c74d7b6, checked in by Michael Medin <michael@…>, 15 months ago
  • Added new module CauseCrash? which has a single command CrashClient? to allow the service to be crashed remotly *WARNING* Dont use this command, it is for debugging and testing purpouses only
  • Fixed issue with BreakPad? which was disabled
  • Fixed some unix issues (sorry but hudson's stopped emailing me again:( )
  • Fixed service --install (now sets correct options)
  • Fixed service --install (now sets description correctly)
  • Fixed log level defined in protobuf (now same as rest of the system)
  • Fixed some issues with the check_nscp command
  • Property mode set to 100644
File size: 13.0 KB
Line 
1//////////////////////////////////////////////////////////////////////////
2// Service Helpers.
3//
4// Functions to stop/start/install and uninstall a service.
5//
6// Copyright (c) 2004 MySolutions NORDIC (http://www.medin.nu)
7//
8// Date: 2004-03-13
9// Author: Michael Medin (mickem@medin.nu)
10//
11// This software is provided "AS IS", without a warranty of any kind.
12// You are free to use/modify this code but leave this header intact.
13//
14//////////////////////////////////////////////////////////////////////////
15
16#include <windows.h>
17#include <tchar.h>
18#include "ServiceCmd.h"
19#include <strEx.h>
20#include <tchar.h>
21#include <iostream>
22#include <error.hpp>
23
24namespace serviceControll {
25        /**
26         * Installs the service
27         *
28         * @param szName
29         * @param szDisplayName
30         * @param szDependencies
31         *
32         * @author mickem
33         *
34         * @date 03-13-2004
35         *
36         */
37        void Install(std::wstring szName, std::wstring szDisplayName, std::wstring szDependencies, DWORD dwServiceType, std::wstring args, std::wstring exe) {
38                SC_HANDLE   schService;
39                SC_HANDLE   schSCManager;
40
41                if (exe.empty()) {
42                        TCHAR szPath[512];
43                        if ( GetModuleFileName( NULL, szPath, 512 ) == 0 )
44                                throw SCException(_T("Could not get module"));
45                        exe = szPath;
46                }
47
48                std::wstring bin = _T("\"") + exe + _T("\"");
49                if (!args.empty())
50                        bin += _T(" ") + args;
51                schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
52                if (!schSCManager)
53                        throw SCException(_T("OpenSCManager failed:") + error::lookup::last_error());
54                schService = CreateService(
55                        schSCManager,               // SCManager database
56                        szName.c_str(),                         // name of service
57                        szDisplayName.c_str(),          // name to display
58                        SERVICE_ALL_ACCESS,         // desired access
59                        dwServiceType,                          // service type
60                        SERVICE_AUTO_START,                     // start type
61                        SERVICE_ERROR_NORMAL,       // error control type
62                        bin.c_str(),                // service's binary
63                        NULL,                       // no load ordering group
64                        NULL,                       // no tag identifier
65                        szDependencies.c_str(),     // dependencies
66                        NULL,                       // LocalSystem account
67                        NULL);                      // no password
68
69                if (!schService) {
70                        DWORD err = GetLastError();
71                        CloseServiceHandle(schSCManager);
72                        if (err==ERROR_SERVICE_EXISTS) {
73                                throw SCException(_T("Service already installed!"));
74                        }
75                        throw SCException(_T("Unable to install service.") + error::lookup::last_error(err));
76                }
77                std::wcout << _T("Service ") << szName << _T(" (") << bin << _T(") installed...") << std::endl;;
78                CloseServiceHandle(schService);
79                CloseServiceHandle(schSCManager);
80        }
81
82        void ModifyServiceType(LPCTSTR szName, DWORD dwServiceType) {
83                SC_HANDLE   schService;
84                SC_HANDLE   schSCManager;
85                TCHAR szPath[512];
86
87                if ( GetModuleFileName( NULL, szPath, 512 ) == 0 )
88                        throw SCException(_T("Could not get module"));
89
90                schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
91                if (!schSCManager)
92                        throw SCException(_T("OpenSCManager failed: ") + error::lookup::last_error());
93                schService = OpenService(schSCManager, szName, SERVICE_ALL_ACCESS);
94                if (!schService) {
95                        DWORD err = GetLastError();
96                        CloseServiceHandle(schSCManager);
97                        throw SCException(_T("Unable to open service: ") + error::lookup::last_error(err));
98                }
99                BOOL result = ChangeServiceConfig(schService, dwServiceType, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE , NULL, NULL, NULL,
100                        NULL, NULL, NULL, NULL);
101                CloseServiceHandle(schService);
102                CloseServiceHandle(schSCManager);
103                if (result != TRUE)
104                        throw SCException(_T("Could not change service information"));
105        }
106
107        DWORD GetServiceType(LPCTSTR szName) {
108                LPQUERY_SERVICE_CONFIG lpqscBuf = (LPQUERY_SERVICE_CONFIG) LocalAlloc(LPTR, 4096);
109                if (lpqscBuf == NULL) {
110                        throw SCException(_T("Could not allocate memory"));
111                }
112                SC_HANDLE schService;
113                SC_HANDLE schSCManager;
114                TCHAR szPath[512];
115
116                if ( GetModuleFileName( NULL, szPath, 512 ) == 0 )
117                        throw SCException(_T("Could not get module"));
118
119                schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
120                if (!schSCManager)
121                        throw SCException(_T("OpenSCManager failed."));
122                schService = OpenService(schSCManager, szName, SERVICE_ALL_ACCESS);
123                if (!schService) {
124                        DWORD err = GetLastError();
125                        CloseServiceHandle(schSCManager);
126                        throw SCException(_T("Unable to open service: ") + error::lookup::last_error(err));
127                }
128
129
130                DWORD dwBytesNeeded = 0;
131                BOOL success = QueryServiceConfig(schService, lpqscBuf,  4096, &dwBytesNeeded);
132                CloseServiceHandle(schService);
133                CloseServiceHandle(schSCManager);
134                if (success != TRUE)
135                        throw SCException(_T("Could not query service information"));
136                DWORD ret = lpqscBuf->dwServiceType;
137                LocalFree(lpqscBuf);
138                return ret;
139        }
140
141        /**
142         * Stars the service.
143         *
144         * @param name The name of the service to start
145         *
146         * @author mickem
147         *
148         * @date 03-13-2004
149         *
150         */
151        void Start(std::wstring name) {
152                SC_HANDLE   schService;
153                SC_HANDLE   schSCManager;
154                SERVICE_STATUS ssStatus;
155
156                schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS );
157                if (!schSCManager)
158                        throw SCException(_T("OpenSCManager failed: ") + error::lookup::last_error());
159                schService = OpenService(schSCManager, name.c_str(), SERVICE_ALL_ACCESS);
160                if (schService) {
161                        // try to stop the service
162                        if ( StartService(schService,0,NULL) ) {
163                                std::wcout << _T("Starting ") << name;
164                                Sleep( 1000 );
165                                while( QueryServiceStatus( schService, &ssStatus ) ) {
166                                        if ( ssStatus.dwCurrentState == SERVICE_START_PENDING ) {
167                                                std::wcout << _T(".");
168                                                Sleep( 1000 );
169                                        } else
170                                                break;
171                                }
172                                if ( ssStatus.dwCurrentState != SERVICE_RUNNING ) {
173                                        CloseServiceHandle(schService);
174                                        CloseServiceHandle(schSCManager);
175                                        throw SCException(_T("Service '") +name + _T("' failed to start."));
176                                }
177                        }
178                        CloseServiceHandle(schService);
179                } else {
180                        std::wstring err = _T("OpenService on '") + name + _T("' failed: ") + error::lookup::last_error();
181                        CloseServiceHandle(schSCManager);
182                        throw SCException(err);
183                }
184                CloseServiceHandle(schSCManager);
185        }
186        bool isInstalled(std::wstring name) {
187                SC_HANDLE   schService;
188                SC_HANDLE   schSCManager;
189                schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
190                if (!schSCManager)
191                        throw SCException(_T("OpenSCManager failed: ") + error::lookup::last_error());
192                schService = OpenService(schSCManager, name.c_str(), SERVICE_ALL_ACCESS);
193                if (schService) {
194                        CloseServiceHandle(schService);
195                        CloseServiceHandle(schSCManager);
196                        return true;
197                } else {
198                        CloseServiceHandle(schSCManager);
199                        return false;
200                }
201        }
202        std::wstring get_exe_path(std::wstring svc_name) {
203                std::wstring ret;
204                SC_HANDLE   schService;
205                SC_HANDLE   schSCManager;
206                schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
207                if (!schSCManager)
208                        throw SCException(_T("OpenSCManager failed: ") + error::lookup::last_error());
209                schService = OpenService(schSCManager, svc_name.c_str(),  SERVICE_QUERY_CONFIG);
210                if (!schService) {
211                        CloseServiceHandle(schSCManager);
212                        throw SCException(_T("Failed to open service: ") + svc_name + _T(" because ") + error::lookup::last_error());
213                }
214                DWORD dwBytesNeeded=0;
215                DWORD lErr;
216                if (QueryServiceConfig(schService,NULL,0, &dwBytesNeeded) || ((lErr = GetLastError()) != ERROR_INSUFFICIENT_BUFFER)) {
217                        CloseServiceHandle(schService);
218                        CloseServiceHandle(schSCManager);
219                        throw SCException(_T("Failed to query service information: ") + svc_name + _T(" because ") + error::lookup::last_error(lErr));
220                }
221
222                LPQUERY_SERVICE_CONFIG lpqscBuf = (LPQUERY_SERVICE_CONFIG)LocalAlloc(LPTR, dwBytesNeeded+10);
223                BOOL bRet = (lpqscBuf!=NULL) && (QueryServiceConfig(schService,lpqscBuf,dwBytesNeeded, &dwBytesNeeded)==TRUE);
224                if (!bRet)
225                        lErr = GetLastError();
226                else {
227                        ret = lpqscBuf->lpBinaryPathName;
228                }
229                LocalFree(lpqscBuf);
230                CloseServiceHandle(schService);
231                CloseServiceHandle(schSCManager);
232                if (!bRet)
233                        throw SCException(_T("Failed to query service information: ") + svc_name + _T(" because ") + error::lookup::last_error(lErr));
234                return ret;
235        }
236
237        bool isStarted(std::wstring name) {
238                SC_HANDLE   schService;
239                SC_HANDLE   schSCManager;
240                SERVICE_STATUS ssStatus;
241                bool ret = false;
242
243                schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS );
244                if (!schSCManager)
245                        throw SCException(_T("OpenSCManager failed: ") + error::lookup::last_error());
246                schService = OpenService(schSCManager, name.c_str(), SERVICE_ALL_ACCESS);
247                if (schService) {
248                        if ( QueryServiceStatus( schService, &ssStatus ) ) {
249                                if ( ssStatus.dwCurrentState == SERVICE_RUNNING ) {
250                                        ret = true;
251                                } else if ( ssStatus.dwCurrentState == SERVICE_START_PENDING ) {
252                                        ret = true;
253                                }
254                        }
255                        CloseServiceHandle(schService);
256                } else {
257                        CloseServiceHandle(schSCManager);
258                        ret = false;
259                }
260                CloseServiceHandle(schSCManager);
261                return ret;
262        }
263
264        /**
265         * Stops and removes the service
266         *
267         * @param name The name of the service to uninstall
268         *
269         * @author mickem
270         *
271         * @date 03-13-2004
272         *
273         */
274        void Uninstall(std::wstring name) {
275                SC_HANDLE   schService;
276                SC_HANDLE   schSCManager;
277                Stop(name);
278
279                schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
280                if (!schSCManager)
281                        throw SCException(_T("OpenSCManager failed: ") + error::lookup::last_error());
282                schService = OpenService(schSCManager, name.c_str(), SERVICE_ALL_ACCESS);
283                if (schService) {
284                        if(!DeleteService(schService)) {
285                                std::wstring err = _T("DeleteService failed: ") + error::lookup::last_error();
286                                CloseServiceHandle(schService);
287                                CloseServiceHandle(schSCManager);
288                                throw SCException(err);
289                        }
290                        CloseServiceHandle(schService);
291                } else {
292                        std::wstring err = _T("OpenService failed: ") + error::lookup::last_error();
293                        CloseServiceHandle(schSCManager);
294                        throw SCException(err);
295                }
296                CloseServiceHandle(schSCManager);
297        }
298
299        /**
300         * Stops the service
301         *
302         * @param name The name of the serive to stop
303         *
304         * @author MickeM
305         *
306         * @date 03-13-2004
307         *
308         */
309        void Stop(std::wstring name) {
310                SC_HANDLE   schService;
311                SC_HANDLE   schSCManager;
312                SERVICE_STATUS ssStatus;
313
314                schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
315                if (!schSCManager)
316                        throw SCException(_T("OpenSCManager failed: ") + error::lookup::last_error());
317                schService = OpenService(schSCManager, name.c_str(), SERVICE_ALL_ACCESS);
318                if (schService) {
319                        // try to stop the service
320                        if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) ) {
321                                std::wcout << _T("Stopping service.");
322                                Sleep( 1000 );
323                                while( QueryServiceStatus( schService, &ssStatus ) ) {
324                                        if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING ) {
325                                                std::wcout << _T(".");
326                                                Sleep( 1000 );
327                                        } else
328                                                break;
329                                }
330                                std::wcout << std::endl;
331                                if ( ssStatus.dwCurrentState != SERVICE_STOPPED ) {
332                                        CloseServiceHandle(schService);
333                                        CloseServiceHandle(schSCManager);
334                                        throw SCException(_T("Service failed to stop."));
335                                }
336                        }
337                        CloseServiceHandle(schService);
338                } else {
339                        std::wstring err = _T("OpenService failed: ") + error::lookup::last_error();
340                        CloseServiceHandle(schSCManager);
341                        throw SCException(err);
342                }
343                CloseServiceHandle(schSCManager);
344        }
345
346        void StopNoWait(std::wstring name) {
347                SC_HANDLE   schService;
348                SC_HANDLE   schSCManager;
349                SERVICE_STATUS ssStatus;
350
351                schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
352                if (!schSCManager)
353                        throw SCException(_T("OpenSCManager failed."));
354                schService = OpenService(schSCManager, name.c_str(), SERVICE_ALL_ACCESS);
355                if (schService) {
356                        // try to stop the service
357                        ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus );
358                        CloseServiceHandle(schService);
359                } else {
360                        CloseServiceHandle(schSCManager);
361                        throw SCException(_T("OpenService failed."));
362                }
363                CloseServiceHandle(schSCManager);
364        }
365
366
367        typedef BOOL (WINAPI*PFChangeServiceConfig2)(SC_HANDLE hService,DWORD dwInfoLevel,LPVOID lpInfo);
368
369        void SetDescription(std::wstring name, std::wstring desc) {
370                PFChangeServiceConfig2 FChangeServiceConfig2;
371                HMODULE ADVAPI= ::LoadLibrary(_T("Advapi32"));
372                if (!ADVAPI) {
373                        throw SCException(_T("Couldn't set extended service info (ignore this on NT4)."));
374                }
375#ifdef UNICODE
376                FChangeServiceConfig2 = (PFChangeServiceConfig2)::GetProcAddress(ADVAPI, "ChangeServiceConfig2W");
377#else
378                FChangeServiceConfig2 = (PFChangeServiceConfig2)::GetProcAddress(ADVAPI, _TEXT("ChangeServiceConfig2A"));
379#endif
380                if (!FChangeServiceConfig2) {
381                        FreeLibrary(ADVAPI);
382                        throw SCException(_T("Couldn't set extended service info (ignore this on NT4)."));
383                }
384                SERVICE_DESCRIPTION descr;
385                SC_HANDLE schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
386                if (!schSCManager)
387                        throw SCException(_T("OpenSCManager failed."));
388                SC_HANDLE schService = OpenService(schSCManager, name.c_str(), SERVICE_ALL_ACCESS);
389                if (!schService) {
390                        FreeLibrary(ADVAPI);
391                        CloseServiceHandle(schSCManager);
392                        throw SCException(_T("OpenService failed."));
393                }
394
395                TCHAR* d = new TCHAR[desc.length()+2];
396                wcsncpy(d, desc.c_str(), desc.length()+1);
397                descr.lpDescription = d;
398                BOOL bResult = FChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &descr);
399                delete [] d;
400                FreeLibrary(ADVAPI);
401                CloseServiceHandle(schService);
402                CloseServiceHandle(schSCManager);
403                if (!bResult)
404                        throw SCException(_T("ChangeServiceConfig2 failed."));
405        }
406}
Note: See TracBrowser for help on using the repository browser.