source: nscp/include/EnumNtSrv.cpp @ 978bd31

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

2007-11-28 MickeM

  • Fixed some UNICODE issues with process-listings + Added an error message if the "detected" process enumeration method is not available. + Fixed some more unicode issues Password encrypt/decrypt: #107
  • Fixed unicode issues with "external programs" #109
  • Fixed so default string for check_nt:s FILEAGE command is "delta" is 5 minutes ago (and not absolute ie. 1970...), Issue #39 + added support for <date strings> to check_nt:s FILEAGE command, Issue #39

append: .<date string> if you want to use a "custom date" like so: ... -v FILEAGE -l c:
windows,Date: %Y-%m-%d %H:%M:%S" -w 5 -c 6 ...
Only the above listed %<char> works, and default to 0 so might not be to pretty but works...

  • Property mode set to 100644
File size: 7.7 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
138TNtServiceInfo *TNtServiceInfo::EnumServices(DWORD dwType, DWORD dwState, DWORD *pdwCount)
139{
140        ASSERT(pdwCount != NULL);
141        // Maybe check if dwType and dwState have at least one constant specified
142        *pdwCount = 0;
143        TNtServiceInfo *info = NULL;
144        SC_HANDLE scman = ::OpenSCManager(NULL,NULL,SC_MANAGER_ENUMERATE_SERVICE);
145        if (scman) {
146                ENUM_SERVICE_STATUS service, *lpservice;
147                BOOL rc;
148                DWORD bytesNeeded,servicesReturned,resumeHandle = 0;
149                rc = ::EnumServicesStatus(scman,dwType,dwState,&service,sizeof(service),
150                        &bytesNeeded,&servicesReturned,&resumeHandle);
151                if ((rc == FALSE) && (::GetLastError() == ERROR_MORE_DATA)) {
152                        DWORD bytes = bytesNeeded + sizeof(ENUM_SERVICE_STATUS);
153                        lpservice = new ENUM_SERVICE_STATUS [bytes];
154                        ::EnumServicesStatus(scman,dwType,dwState,lpservice,bytes,
155                                &bytesNeeded,&servicesReturned,&resumeHandle);
156                        *pdwCount = servicesReturned;    // Not a chance that 0 services is returned
157                        info = new TNtServiceInfo [servicesReturned];
158                        TCHAR Buffer[1024];                             // Should be enough for service info
159                        QUERY_SERVICE_CONFIG *lpqch = (QUERY_SERVICE_CONFIG*)Buffer;
160                        for (DWORD ndx = 0; ndx < servicesReturned; ndx++) {
161                                info[ndx].m_strServiceName = lpservice[ndx].lpServiceName;
162                                info[ndx].m_strDisplayName = lpservice[ndx].lpDisplayName;
163                                info[ndx].m_dwServiceType = lpservice[ndx].ServiceStatus.dwServiceType;
164                                info[ndx].m_dwCurrentState = lpservice[ndx].ServiceStatus.dwCurrentState;
165                                SC_HANDLE sh = ::OpenService(scman,lpservice[ndx].lpServiceName,SERVICE_QUERY_CONFIG);
166                                if (::QueryServiceConfig(sh,lpqch,sizeof(Buffer),&bytesNeeded)) {
167                                        info[ndx].m_strBinaryPath = lpqch->lpBinaryPathName;
168                                        info[ndx].m_dwStartType = lpqch->dwStartType;
169                                        info[ndx].m_dwErrorControl = lpqch->dwErrorControl;
170                                }
171                                ::CloseServiceHandle(sh);
172                        }
173                        delete [] lpservice;
174                }
175                ::CloseServiceHandle(scman);
176        }
177        return info;
178}
179
180#define SC_BUF_LEN 4096
181TNtServiceInfo TNtServiceInfo::GetService(std::wstring name)
182{
183        TNtServiceInfo info;
184        info.m_strServiceName = name;
185        SC_HANDLE scman = ::OpenSCManager(NULL,NULL,SC_MANAGER_ENUMERATE_SERVICE);
186        if (!scman) {
187                throw NTServiceException(name, _T("Could not open ServiceControl manager"), GetLastError());
188        }
189        SC_HANDLE sh = ::OpenService(scman,name.c_str(),SERVICE_QUERY_STATUS);
190        if (!sh) {
191                DWORD bufLen = SC_BUF_LEN;
192                TCHAR *buf = new TCHAR[bufLen+1];
193                if (GetServiceKeyName(scman, name.c_str(), buf, &bufLen) == 0) {
194                        ::CloseServiceHandle(scman);
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                if (sh == NULL) {
207                        ::CloseServiceHandle(scman);
208                        throw NTServiceException(name, _T("OpenService: Could not open Service"), GetLastError());
209                }
210        }
211        SERVICE_STATUS state;
212        if (::QueryServiceStatus(sh, &state)) {
213                info.m_dwCurrentState = state.dwCurrentState;
214                info.m_dwServiceType = state.dwServiceType;
215        } else {
216                ::CloseServiceHandle(sh);
217                ::CloseServiceHandle(scman);
218                throw NTServiceException(name, _T("QueryServiceStatus: Could not query service status"), GetLastError());
219        }
220        // TODO: Get more info here
221        ::CloseServiceHandle(sh);
222        ::CloseServiceHandle(scman);
223        return info;
224}
225
226
227// Enumerate services on this machine and return an STL list of service objects
228// dwType = bit OR of SERVICE_WIN32, SERVICE_DRIVER
229// dwState = bit OR of SERVICE_ACTIVE, SERVICE_INACTIVE
230void TNtServiceInfo::EnumServices(DWORD dwType, DWORD dwState, TNtServiceInfoList *pList)
231{
232        ASSERT(pList != NULL);
233        TNtServiceInfo *pSrvList = NULL;
234        DWORD dwCount = 0;
235        pSrvList = TNtServiceInfo::EnumServices(dwType, dwState, &dwCount);
236        for (DWORD dwIndex = 0; dwIndex < dwCount; dwIndex ++) {
237                pList->insert(pList->end(), pSrvList[dwIndex]);
238        }
239        delete [] pSrvList;
240}
241
242/*#############################################################################
243# End of file ENUMNTSRV.CPP
244#############################################################################*/
Note: See TracBrowser for help on using the repository browser.