source: nscp/include/EnumNtSrv.cpp @ 8f167e8

0.4.00.4.10.4.2stable
Last change on this file since 8f167e8 was 8f167e8, checked in by Michael Medin <michael@…>, 5 years ago

proper versions (memleak fix)

  • Property mode set to 100644
File size: 7.5 KB
Line 
1/*#############################################################################
2# ENUMNTSRV.CPP
3#
4# SCA Software International S.A.
5# http://www.scasoftware.com
6# scaadmin@scasoftware.com
7#
8# Copyright (c) 1999 SCA Software International S.A.
9#
10# Date: 05.12.1999.
11# Author: Zoran M.Todorovic
12#
13# This software is provided "AS IS", without a warranty of any kind.
14# You are free to use/modify this code but leave this header intact.
15#
16#############################################################################*/
17
18#define WIN32_LEAN_AND_MEAN             // Exclude rarely-used stuff from Windows headers
19#include <windows.h>
20#include <WinSvc.h>
21#include "EnumNtSrv.h"
22
23#ifdef _DEBUG
24//#define new DEBUG_NEW
25#undef THIS_FILE
26static char THIS_FILE[] = __FILE__;
27#endif
28
29#define ASSERT(x)
30
31//=============================================================================
32// class TNtServiceInfo
33//
34//=============================================================================
35
36TNtServiceInfo::TNtServiceInfo()
37{
38        m_strServiceName.clear();
39        m_strDisplayName.clear();
40        m_strBinaryPath.clear();
41        m_dwServiceType = 0;
42        m_dwStartType = 0;
43        m_dwErrorControl = 0;
44        m_dwCurrentState = 0;
45}
46
47TNtServiceInfo::TNtServiceInfo(const TNtServiceInfo& source)
48{
49        *this = source;
50}
51
52TNtServiceInfo::~TNtServiceInfo()
53{
54}
55
56TNtServiceInfo& TNtServiceInfo::operator=(const TNtServiceInfo& source)
57{
58        m_strServiceName = source.m_strServiceName;
59        m_strDisplayName = source.m_strDisplayName;
60        m_strBinaryPath = source.m_strBinaryPath;
61        m_dwServiceType = source.m_dwServiceType;
62        m_dwStartType = source.m_dwStartType;
63        m_dwErrorControl = source.m_dwErrorControl;
64        m_dwCurrentState = source.m_dwCurrentState;
65        return *this;
66}
67
68// Return a service type as a string
69std::wstring TNtServiceInfo::GetServiceType(void)
70{
71        std::wstring str = _T("UNKNOWN");
72        if (m_dwServiceType & SERVICE_WIN32) {
73                if (m_dwServiceType & SERVICE_WIN32_OWN_PROCESS)
74                        str = _T("WIN32_OWN_PROCESS");
75                else if (m_dwServiceType & SERVICE_WIN32_SHARE_PROCESS)
76                        str = _T("WIN32_SHARE_PROCESS");
77                if (m_dwServiceType & SERVICE_INTERACTIVE_PROCESS)
78                        str += _T(" (INTERACTIVE_PROCESS)");
79        }
80        switch (m_dwServiceType) {
81        case SERVICE_KERNEL_DRIVER:
82                str = _T("KERNEL_DRIVER");
83                break;
84        case SERVICE_FILE_SYSTEM_DRIVER:
85                str = _T("FILE_SYSTEM_DRIVER");
86                break;
87        };
88        return str;
89}
90
91// Return a service start type as a string
92std::wstring TNtServiceInfo::GetStartType(void)
93{
94        TCHAR *types[] = {
95                _T("BOOT_START"),               // 0
96                        _T("SYSTEM_START"), // 1
97                        _T("AUTO_START"),       // 2
98                        _T("DEMAND_START"), // 3
99                        _T("DISABLED")          // 4
100        };
101        return std::wstring(types[m_dwStartType]);
102}
103
104// Return this service error control as a string
105std::wstring TNtServiceInfo::GetErrorControl(void)
106{
107        ASSERT(m_dwErrorControl < 4);
108        TCHAR *types[] = {
109                _T("ERROR_IGNORE"),             // 0
110                        _T("ERROR_NORMAL"), // 1
111                        _T("ERROR_SEVERE"), // 2
112                        _T("ERROR_CRITICAL")// 3
113        };
114        return std::wstring(types[m_dwErrorControl]);
115}
116
117// Return this service current state as a string
118std::wstring TNtServiceInfo::GetCurrentState(void)
119{
120        ASSERT(m_dwCurrentState < 8);
121        TCHAR *types[] = {
122                _T("UNKNOWN"),
123                        _T("STOPPED"),                  // 1
124                        _T("START_PENDING"),    // 2
125                        _T("STOP_PENDING"),             // 3
126                        _T("RUNNING"),                  // 4
127                        _T("CONTINUE_PENDING"), // 5
128                        _T("PAUSE_PENDING"),    // 6
129                        _T("PAUSED")                    // 7
130        };
131        return std::wstring(types[m_dwCurrentState]);
132}
133
134// Enumerate services on this machine and return a pointer to an array of objects.
135// Caller is responsible to delete this pointer using delete [] ...
136// dwType = bit OR of SERVICE_WIN32, SERVICE_DRIVER
137// dwState = bit OR of SERVICE_ACTIVE, SERVICE_INACTIVE
138TNtServiceInfoList TNtServiceInfo::EnumServices(DWORD dwType, DWORD dwState)
139{
140        TNtServiceInfoList ret;
141        // Maybe check if dwType and dwState have at least one constant specified
142        SC_HANDLE scman = ::OpenSCManager(NULL,NULL,SC_MANAGER_ENUMERATE_SERVICE);
143        if (scman) {
144                ENUM_SERVICE_STATUS service, *lpservice;
145                BOOL rc;
146                DWORD bytesNeeded,servicesReturned,resumeHandle = 0;
147                rc = ::EnumServicesStatus(scman,dwType,dwState,&service,sizeof(service),
148                        &bytesNeeded,&servicesReturned,&resumeHandle);
149                if ((rc == FALSE) && (::GetLastError() == ERROR_MORE_DATA)) {
150                        DWORD bytes = bytesNeeded + sizeof(ENUM_SERVICE_STATUS);
151                        lpservice = new ENUM_SERVICE_STATUS [bytes];
152                        ::EnumServicesStatus(scman,dwType,dwState,lpservice,bytes,
153                                &bytesNeeded,&servicesReturned,&resumeHandle);
154                        TCHAR Buffer[1024];                             // Should be enough for service info
155                        QUERY_SERVICE_CONFIG *lpqch = (QUERY_SERVICE_CONFIG*)Buffer;
156                        for (DWORD ndx = 0; ndx < servicesReturned; ndx++) {
157                                TNtServiceInfo info;
158                                info.m_strServiceName = lpservice[ndx].lpServiceName;
159                                info.m_strDisplayName = lpservice[ndx].lpDisplayName;
160                                info.m_dwServiceType = lpservice[ndx].ServiceStatus.dwServiceType;
161                                info.m_dwCurrentState = lpservice[ndx].ServiceStatus.dwCurrentState;
162                                SC_HANDLE sh = ::OpenService(scman,lpservice[ndx].lpServiceName,SERVICE_QUERY_CONFIG);
163                                if (::QueryServiceConfig(sh,lpqch,sizeof(Buffer),&bytesNeeded)) {
164                                        info.m_strBinaryPath = lpqch->lpBinaryPathName;
165                                        info.m_dwStartType = lpqch->dwStartType;
166                                        info.m_dwErrorControl = lpqch->dwErrorControl;
167                                }
168                                ::CloseServiceHandle(sh);
169                                ret.push_back(info);
170                        }
171                        delete [] lpservice;
172                }
173                ::CloseServiceHandle(scman);
174        }
175        return ret;
176}
177
178
179#define SC_BUF_LEN 4096
180TNtServiceInfo TNtServiceInfo::GetService(std::wstring name)
181{
182        TNtServiceInfo info;
183        info.m_strServiceName = name;
184        SC_HANDLE scman = ::OpenSCManager(NULL,NULL,SC_MANAGER_ENUMERATE_SERVICE);
185        if (!scman) {
186                throw NTServiceException(name, _T("Could not open ServiceControl manager"), GetLastError());
187        }
188        SC_HANDLE sh = ::OpenService(scman,name.c_str(),SERVICE_QUERY_STATUS);
189        if (!sh) {
190                DWORD bufLen = SC_BUF_LEN;
191                TCHAR *buf = new TCHAR[bufLen+1];
192                if (GetServiceKeyName(scman, name.c_str(), buf, &bufLen) == 0) {
193                        ::CloseServiceHandle(scman);
194                        delete [] buf;
195                        throw NTServiceException(name, _T("GetServiceKeyName: Could not translate service name"), GetLastError());
196                }
197                /*
198                Why does this not work? (a bug in the API? says it should return the correct size?)
199                if (bufLen >= SC_BUF_LEN) {
200                        ::CloseServiceHandle(scman);
201                        throw NTServiceException(name, "Service name to long to handle", GetLastError());
202                }
203                buf[bufLen] = 0;
204                */
205                sh = ::OpenService(scman,buf,SERVICE_QUERY_STATUS);
206                delete [] buf;
207                if (sh == NULL) {
208                        ::CloseServiceHandle(scman);
209                        throw NTServiceException(name, _T("OpenService: Could not open Service"), GetLastError());
210                }
211        }
212        SERVICE_STATUS state;
213        if (::QueryServiceStatus(sh, &state)) {
214                info.m_dwCurrentState = state.dwCurrentState;
215                info.m_dwServiceType = state.dwServiceType;
216        } else {
217                ::CloseServiceHandle(sh);
218                ::CloseServiceHandle(scman);
219                throw NTServiceException(name, _T("QueryServiceStatus: Could not query service status"), GetLastError());
220        }
221        // TODO: Get more info here
222        ::CloseServiceHandle(sh);
223        ::CloseServiceHandle(scman);
224        return info;
225}
226
227/*
228// Enumerate services on this machine and return an STL list of service objects
229// dwType = bit OR of SERVICE_WIN32, SERVICE_DRIVER
230// dwState = bit OR of SERVICE_ACTIVE, SERVICE_INACTIVE
231void TNtServiceInfo::EnumServices(DWORD dwType, DWORD dwState, TNtServiceInfoList *pList)
232{
233        ASSERT(pList != NULL);
234        TNtServiceInfo *pSrvList = NULL;
235        DWORD dwCount = 0;
236        pSrvList = TNtServiceInfo::EnumServices(dwType, dwState, &dwCount);
237        for (DWORD dwIndex = 0; dwIndex < dwCount; dwIndex ++) {
238                pList->insert(pList->end(), pSrvList[dwIndex]);
239        }
240        delete [] pSrvList;
241}
242*/
243/*#############################################################################
244# End of file ENUMNTSRV.CPP
245#############################################################################*/
Note: See TracBrowser for help on using the repository browser.