[BRANCHES]
[reactos.git] / reactos / base / applications / sc / query.c
1 /*
2 * PROJECT: ReactOS Services
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/sc/query.c
5 * PURPOSE: queries service info
6 * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy <gedmurphy@gmail.com>
7 *
8 */
9 /*
10 * TODO:
11 * Allow calling of 2 options e.g.:
12 * type= driver state= inactive
13 */
14
15 #include "sc.h"
16
17 LPTSTR QueryOpts[] = {
18 _T("type="),
19 _T("state="),
20 _T("bufsize="),
21 _T("ri="),
22 _T("group="),
23 };
24
25
26 LPSERVICE_STATUS_PROCESS
27 QueryService(LPCTSTR ServiceName)
28 {
29 SC_HANDLE hSCManager = NULL;
30 LPSERVICE_STATUS_PROCESS pServiceInfo = NULL;
31 SC_HANDLE hSc = NULL;
32 DWORD BufSiz = 0;
33 DWORD BytesNeeded = 0;
34 DWORD Ret;
35
36 hSCManager = OpenSCManager(NULL,
37 NULL,
38 SC_MANAGER_CONNECT);
39 if (hSCManager == NULL)
40 {
41 ReportLastError();
42 return NULL;
43 }
44
45 hSc = OpenService(hSCManager,
46 ServiceName,
47 SERVICE_QUERY_STATUS);
48 if (hSc == NULL)
49 goto fail;
50
51 Ret = QueryServiceStatusEx(hSc,
52 SC_STATUS_PROCESS_INFO,
53 NULL,
54 BufSiz,
55 &BytesNeeded);
56 if ((Ret != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
57 goto fail;
58
59 pServiceInfo = (LPSERVICE_STATUS_PROCESS)HeapAlloc(GetProcessHeap(),
60 0,
61 BytesNeeded);
62 if (pServiceInfo == NULL)
63 goto fail;
64
65 if (!QueryServiceStatusEx(hSc,
66 SC_STATUS_PROCESS_INFO,
67 (LPBYTE)pServiceInfo,
68 BytesNeeded,
69 &BytesNeeded))
70 {
71 goto fail;
72 }
73
74 CloseServiceHandle(hSc);
75 CloseServiceHandle(hSCManager);
76 return pServiceInfo;
77
78 fail:
79 ReportLastError();
80 if (pServiceInfo) HeapFree(GetProcessHeap(), 0, pServiceInfo);
81 if (hSc) CloseServiceHandle(hSc);
82 if (hSCManager) CloseServiceHandle(hSCManager);
83 return NULL;
84 }
85
86
87 static BOOL
88 EnumServices(ENUM_SERVICE_STATUS_PROCESS **pServiceStatus,
89 DWORD ServiceType,
90 DWORD ServiceState)
91 {
92 SC_HANDLE hSCManager;
93 DWORD BufSize = 0;
94 DWORD BytesNeeded = 0;
95 DWORD ResumeHandle = 0;
96 DWORD NumServices = 0;
97 DWORD Ret;
98
99 hSCManager = OpenSCManager(NULL,
100 NULL,
101 SC_MANAGER_ENUMERATE_SERVICE);
102 if (hSCManager == NULL)
103 {
104 ReportLastError();
105 return FALSE;
106 }
107
108 Ret = EnumServicesStatusEx(hSCManager,
109 SC_ENUM_PROCESS_INFO,
110 ServiceType,
111 ServiceState,
112 (LPBYTE)*pServiceStatus,
113 BufSize,
114 &BytesNeeded,
115 &NumServices,
116 &ResumeHandle,
117 0);
118
119 if ((Ret == 0) && (GetLastError() == ERROR_MORE_DATA))
120 {
121 *pServiceStatus = (ENUM_SERVICE_STATUS_PROCESS *)
122 HeapAlloc(GetProcessHeap(),
123 0,
124 BytesNeeded);
125 if (*pServiceStatus != NULL)
126 {
127 if (EnumServicesStatusEx(hSCManager,
128 SC_ENUM_PROCESS_INFO,
129 ServiceType,
130 ServiceState,
131 (LPBYTE)*pServiceStatus,
132 BytesNeeded,
133 &BytesNeeded,
134 &NumServices,
135 &ResumeHandle,
136 0))
137 {
138 CloseServiceHandle(hSCManager);
139 return NumServices;
140 }
141 }
142 }
143
144 ReportLastError();
145 if (*pServiceStatus)
146 HeapFree(GetProcessHeap(), 0, *pServiceStatus);
147
148 CloseServiceHandle(hSCManager);
149
150 return NumServices;
151 }
152
153
154 BOOL
155 Query(LPCTSTR *ServiceArgs,
156 DWORD ArgCount,
157 BOOL bExtended)
158 {
159 LPENUM_SERVICE_STATUS_PROCESS pServiceStatus = NULL;
160 DWORD NumServices = 0;
161 //DWORD ServiceType;
162 //DWORD ServiceState;
163 BOOL bServiceName = TRUE;
164 DWORD OptSize, i;
165
166 LPCTSTR *TmpArgs;
167 INT TmpCnt;
168
169 #ifdef SCDBG
170 TmpArgs = ServiceArgs;
171 TmpCnt = ArgCount;
172 _tprintf(_T("Arguments:\n"));
173 while (TmpCnt)
174 {
175 _tprintf(_T(" %s\n"), *TmpArgs);
176 TmpArgs++;
177 TmpCnt--;
178 }
179 _tprintf(_T("\n"));
180 #endif /* SCDBG */
181
182 /* display all running services and drivers */
183 if (ArgCount == 0)
184 {
185 NumServices = EnumServices(&pServiceStatus,
186 SERVICE_WIN32,
187 SERVICE_ACTIVE);
188
189 if (NumServices != 0)
190 {
191 for (i=0; i < NumServices; i++)
192 {
193 PrintService(pServiceStatus[i].lpServiceName,
194 &pServiceStatus[i].ServiceStatusProcess,
195 bExtended);
196 }
197
198 _tprintf(_T("number : %lu\n"), NumServices);
199
200 if (pServiceStatus)
201 HeapFree(GetProcessHeap(), 0, pServiceStatus);
202
203 return TRUE;
204 }
205
206 return FALSE;
207 }
208
209 TmpArgs = ServiceArgs;
210 TmpCnt = ArgCount;
211 OptSize = sizeof(QueryOpts) / sizeof(QueryOpts[0]);
212 while (TmpCnt--)
213 {
214 for (i=0; i < OptSize; i++)
215 {
216 if (!lstrcmpi(*TmpArgs, QueryOpts[i]))
217 {
218 bServiceName = FALSE;
219 }
220 }
221 TmpArgs++;
222 }
223
224
225 /* FIXME: parse options */
226
227
228 /* print only the service requested */
229 if (bServiceName)
230 {
231 LPSERVICE_STATUS_PROCESS pStatus;
232 LPCTSTR ServiceName = *ServiceArgs;
233
234 pStatus = QueryService(ServiceName);
235 if (pStatus)
236 {
237 PrintService(ServiceName,
238 pStatus,
239 bExtended);
240 }
241 }
242
243 return TRUE;
244 }