Merge my current work done on the kd++ branch:
[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 return NumServices;
139 }
140 }
141 }
142
143 ReportLastError();
144 if (pServiceStatus)
145 HeapFree(GetProcessHeap(), 0, *pServiceStatus);
146
147 return NumServices;
148 }
149
150
151 BOOL
152 Query(LPCTSTR *ServiceArgs,
153 DWORD ArgCount,
154 BOOL bExtended)
155 {
156 LPENUM_SERVICE_STATUS_PROCESS pServiceStatus = NULL;
157 DWORD NumServices = 0;
158 //DWORD ServiceType;
159 //DWORD ServiceState;
160 BOOL bServiceName = TRUE;
161 DWORD OptSize, i;
162
163 LPCTSTR *TmpArgs;
164 INT TmpCnt;
165
166 #ifdef SCDBG
167 TmpArgs = ServiceArgs;
168 TmpCnt = ArgCount;
169 _tprintf(_T("Arguments:\n"));
170 while (TmpCnt)
171 {
172 _tprintf(_T(" %s\n"), *TmpArgs);
173 TmpArgs++;
174 TmpCnt--;
175 }
176 _tprintf(_T("\n"));
177 #endif /* SCDBG */
178
179 /* display all running services and drivers */
180 if (ArgCount == 0)
181 {
182 NumServices = EnumServices(&pServiceStatus,
183 SERVICE_WIN32,
184 SERVICE_ACTIVE);
185
186 if (NumServices != 0)
187 {
188 for (i=0; i < NumServices; i++)
189 {
190 PrintService(pServiceStatus[i].lpServiceName,
191 &pServiceStatus[i].ServiceStatusProcess,
192 bExtended);
193 }
194
195 _tprintf(_T("number : %lu\n"), NumServices);
196
197 if (pServiceStatus)
198 HeapFree(GetProcessHeap(), 0, pServiceStatus);
199
200 return TRUE;
201 }
202
203 return FALSE;
204 }
205
206 TmpArgs = ServiceArgs;
207 TmpCnt = ArgCount;
208 OptSize = sizeof(QueryOpts) / sizeof(QueryOpts[0]);
209 while (TmpCnt--)
210 {
211 for (i=0; i < OptSize; i++)
212 {
213 if (!lstrcmpi(*TmpArgs, QueryOpts[i]))
214 {
215 bServiceName = FALSE;
216 }
217 }
218 TmpArgs++;
219 }
220
221
222 /* FIXME: parse options */
223
224
225 /* print only the service requested */
226 if (bServiceName)
227 {
228 LPSERVICE_STATUS_PROCESS pStatus;
229 LPCTSTR ServiceName = *ServiceArgs;
230
231 pStatus = QueryService(ServiceName);
232 if (pStatus)
233 {
234 PrintService(ServiceName,
235 pStatus,
236 bExtended);
237 }
238 }
239
240 if (pServiceStatus)
241 HeapFree(GetProcessHeap(), 0, pServiceStatus);
242
243 return TRUE;
244 }