forgot to remove this
[reactos.git] / reactos / subsys / system / sc / query.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS SC utility
4 * FILE: subsys/system/sc/query.c
5 * PURPOSE: control ReactOS services
6 * PROGRAMMERS: Ged Murphy (gedmurphy@gmail.com)
7 * REVISIONS:
8 * Ged Murphy 20/10/05 Created
9 *
10 */
11 /*
12 * TODO:
13 * Allow calling of 2 options e.g.:
14 * type= driver state= inactive
15 */
16
17 #include "sc.h"
18
19 /* local function decs */
20 VOID PrintService(BOOL bExtended);
21 BOOL EnumServices(DWORD ServiceType, DWORD ServiceState);
22 BOOL QueryService(LPCTSTR ServiceName, BOOL bExtended);
23
24 /* global variables */
25 static ENUM_SERVICE_STATUS_PROCESS *pServiceStatus = NULL;
26 DWORD NumServices = 0;
27
28
29 BOOL
30 Query(LPCTSTR ServiceName, LPCTSTR *ServiceArgs, BOOL bExtended)
31 {
32 if (! ServiceName) /* display all running services and drivers */
33 {
34 /* get default values */
35 EnumServices(SERVICE_WIN32, SERVICE_ACTIVE);
36
37 /* print default values */
38 PrintService(bExtended);
39 }
40 else if (_tcsicmp(ServiceName, _T("type=")) == 0)
41 {
42 LPCTSTR Type = *ServiceArgs;
43
44 if (_tcsicmp(Type, _T("driver")) == 0)
45 EnumServices(SERVICE_DRIVER, SERVICE_ACTIVE);
46 else if (_tcsicmp(Type, _T("service")) == 0)
47 EnumServices(SERVICE_WIN32, SERVICE_ACTIVE);
48 else if (_tcsicmp(Type, _T("all")) == 0)
49 EnumServices(SERVICE_DRIVER|SERVICE_WIN32, SERVICE_ACTIVE);
50 else
51 {
52 _tprintf(_T("\nERROR following \"type=\"!\n"));
53 _tprintf(_T("Must be \"driver\" or \"service\" or \"all\"\n"));
54 }
55
56 PrintService(bExtended);
57 }
58 else if(_tcsicmp(ServiceName, _T("state=")) == 0)
59 {
60 LPCTSTR State = *ServiceArgs;
61
62 if (_tcsicmp(State, _T("inactive")) == 0)
63 EnumServices(SERVICE_WIN32, SERVICE_INACTIVE);
64 else if (_tcsicmp(State, _T("all")) == 0)
65 EnumServices(SERVICE_WIN32, SERVICE_STATE_ALL);
66 else
67 {
68 _tprintf(_T("\nERROR following \"state=\"!\n"));
69 _tprintf(_T("Must be \"active\" or \"inactive\" or \"all\"\n"));
70 }
71
72 PrintService(bExtended);
73 }
74 /*
75 else if(_tcsicmp(ServiceName, _T("bufsize=")))
76
77 else if(_tcsicmp(ServiceName, _T("ri=")))
78
79 else if(_tcsicmp(ServiceName, _T("group=")))
80 */
81 else /* print only the service requested */
82 {
83 QueryService(ServiceName, bExtended);
84 }
85
86 return TRUE;
87 }
88
89
90 BOOL
91 QueryService(LPCTSTR ServiceName, BOOL bExtended)
92 {
93 SERVICE_STATUS_PROCESS *pServiceInfo = NULL;
94 SC_HANDLE hSc;
95 DWORD BufSiz = 0;
96 DWORD BytesNeeded = 0;
97 DWORD Ret;
98
99 hSc = OpenService(hSCManager, ServiceName, SERVICE_QUERY_STATUS);
100
101 if (hSc == NULL)
102 {
103 _tprintf(_T("QueryService: openService failed\n"));
104 ReportLastError();
105 return FALSE;
106 }
107
108 Ret = QueryServiceStatusEx(hSc,
109 SC_STATUS_PROCESS_INFO,
110 NULL,
111 BufSiz,
112 &BytesNeeded);
113
114 if ((Ret != 0) || (GetLastError() != ERROR_INSUFFICIENT_BUFFER))
115 {
116 _tprintf(_T("QueryService: First call to QueryServiceStatusEx failed : "));
117 ReportLastError();
118 return FALSE;
119 }
120 else /* Call function again if required size was returned */
121 {
122 /* reserve memory for service info array */
123 pServiceInfo = (SERVICE_STATUS_PROCESS *)
124 HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
125 if (pServiceInfo == NULL)
126 {
127 _tprintf(_T("QueryService: Failed to allocate memory : "));
128 ReportLastError();
129 return FALSE;
130 }
131
132 /* fill array with service info */
133 if (! QueryServiceStatusEx(hSc,
134 SC_STATUS_PROCESS_INFO,
135 (LPBYTE)pServiceInfo,
136 BytesNeeded,
137 &BytesNeeded))
138 {
139 _tprintf(_T("QueryService: Second call to QueryServiceStatusEx failed : "));
140 ReportLastError();
141 HeapFree(GetProcessHeap(), 0, pServiceInfo);
142 return FALSE;
143 }
144 }
145
146
147 _tprintf(_T("SERVICE_NAME: %s\n"), ServiceName);
148
149 _tprintf(_T("\tTYPE : %x "),
150 (unsigned int)pServiceInfo->dwServiceType);
151 switch (pServiceInfo->dwServiceType)
152 {
153 case 1 : _tprintf(_T("KERNEL_DRIVER\n")); break;
154 case 2 : _tprintf(_T("FILE_SYSTEM_DRIVER\n")); break;
155 case 16 : _tprintf(_T("WIN32_OWN_PROCESS\n")); break;
156 case 32 : _tprintf(_T("WIN32_SHARE_PROCESS\n")); break;
157 default : _tprintf(_T("\n")); break;
158 }
159
160 _tprintf(_T("\tSTATE : %x "),
161 (unsigned int)pServiceInfo->dwCurrentState);
162
163 switch (pServiceInfo->dwCurrentState)
164 {
165 case 1 : _tprintf(_T("STOPPED\n")); break;
166 case 2 : _tprintf(_T("START_PENDING\n")); break;
167 case 3 : _tprintf(_T("STOP_PENDING\n")); break;
168 case 4 : _tprintf(_T("RUNNING\n")); break;
169 case 5 : _tprintf(_T("CONTINUE_PENDING\n")); break;
170 case 6 : _tprintf(_T("PAUSE_PENDING\n")); break;
171 case 7 : _tprintf(_T("PAUSED\n")); break;
172 default : _tprintf(_T("\n")); break;
173 }
174
175 // _tprintf(_T("\n\taccepted : 0x%x\n\n"),
176 // pServiceStatus[i].ServiceStatusProcess.dwControlsAccepted);
177 // (STOPPABLE,NOT_PAUSABLE,ACCEPTS_SHUTDOWN)
178
179 _tprintf(_T("\tWIN32_EXIT_CODE : %d (0x%x)\n"),
180 (unsigned int)pServiceInfo->dwWin32ExitCode,
181 (unsigned int)pServiceInfo->dwWin32ExitCode);
182 _tprintf(_T("\tSERVICE_EXIT_CODE : %d (0x%x)\n"),
183 (unsigned int)pServiceInfo->dwServiceSpecificExitCode,
184 (unsigned int)pServiceInfo->dwServiceSpecificExitCode);
185 _tprintf(_T("\tCHECKPOINT : 0x%x\n"),
186 (unsigned int)pServiceInfo->dwCheckPoint);
187 _tprintf(_T("\tWAIT_HINT : 0x%x\n"),
188 (unsigned int)pServiceInfo->dwWaitHint);
189 if (bExtended)
190 {
191 _tprintf(_T("\tPID : %lu\n"),
192 pServiceInfo->dwProcessId);
193 _tprintf(_T("\tFLAGS : %lu\n"),
194 pServiceInfo->dwServiceFlags);
195 }
196
197 HeapFree(GetProcessHeap(), 0, pServiceInfo);
198
199 return TRUE;
200 }
201
202
203 BOOL
204 EnumServices(DWORD ServiceType, DWORD ServiceState)
205 {
206 DWORD BufSize = 0;
207 DWORD BytesNeeded = 0;
208 DWORD ResumeHandle = 0;
209 DWORD Ret;
210
211 /* determine required buffer size */
212 Ret = EnumServicesStatusEx(hSCManager,
213 SC_ENUM_PROCESS_INFO,
214 ServiceType,
215 ServiceState,
216 (LPBYTE)pServiceStatus,
217 BufSize,
218 &BytesNeeded,
219 &NumServices,
220 &ResumeHandle,
221 0);
222
223 if ((Ret != 0) && (GetLastError() != ERROR_MORE_DATA))
224 {
225 _tprintf(_T("EnumServices: First call to EnumServicesStatusEx failed : "));
226 ReportLastError();
227 return FALSE;
228 }
229 else /* Call function again if required size was returned */
230 {
231 /* reserve memory for service info array */
232 pServiceStatus = (ENUM_SERVICE_STATUS_PROCESS *)
233 HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
234 if (pServiceStatus == NULL)
235 {
236 _tprintf(_T("EnumServices: Failed to allocate memory : "));
237 ReportLastError();
238 return FALSE;
239 }
240
241 /* fill array with service info */
242 if (! EnumServicesStatusEx(hSCManager,
243 SC_ENUM_PROCESS_INFO,
244 ServiceType,
245 ServiceState,
246 (LPBYTE)pServiceStatus,
247 BytesNeeded,
248 &BytesNeeded,
249 &NumServices,
250 &ResumeHandle,
251 0))
252 {
253 _tprintf(_T("EnumServices: Second call to EnumServicesStatusEx failed : "));
254 ReportLastError();
255 HeapFree(GetProcessHeap(), 0, pServiceStatus);
256 return FALSE;
257 }
258 }
259
260 return TRUE;
261 }
262
263
264 VOID
265 PrintService(BOOL bExtended)
266 {
267 DWORD i;
268
269 for (i=0; i < NumServices; i++)
270 {
271
272 _tprintf(_T("SERVICE_NAME: %s\n"), pServiceStatus[i].lpServiceName);
273 _tprintf(_T("DISPLAY_NAME: %s\n"), pServiceStatus[i].lpDisplayName);
274
275 _tprintf(_T("\tTYPE : %x "),
276 (unsigned int)pServiceStatus[i].ServiceStatusProcess.dwServiceType);
277 switch (pServiceStatus[i].ServiceStatusProcess.dwServiceType)
278 {
279 case 1 : _tprintf(_T("KERNEL_DRIVER\n")); break;
280 case 2 : _tprintf(_T("FILE_SYSTEM_DRIVER\n")); break;
281 case 16 : _tprintf(_T("WIN32_OWN_PROCESS\n")); break;
282 case 32 : _tprintf(_T("WIN32_SHARE_PROCESS\n")); break;
283 default : _tprintf(_T("\n")); break;
284 }
285
286 _tprintf(_T("\tSTATE : %x "),
287 (unsigned int)pServiceStatus[i].ServiceStatusProcess.dwCurrentState);
288
289 switch (pServiceStatus[i].ServiceStatusProcess.dwCurrentState)
290 {
291 case 1 : _tprintf(_T("STOPPED\n")); break;
292 case 2 : _tprintf(_T("START_PENDING\n")); break;
293 case 3 : _tprintf(_T("STOP_PENDING\n")); break;
294 case 4 : _tprintf(_T("RUNNING\n")); break;
295 case 5 : _tprintf(_T("CONTINUE_PENDING\n")); break;
296 case 6 : _tprintf(_T("PAUSE_PENDING\n")); break;
297 case 7 : _tprintf(_T("PAUSED\n")); break;
298 default : _tprintf(_T("\n")); break;
299 }
300
301 // _tprintf(_T("\n\taccepted : 0x%x\n\n"),
302 // pServiceStatus[i].ServiceStatusProcess.dwControlsAccepted);
303 // (STOPPABLE,NOT_PAUSABLE,ACCEPTS_SHUTDOWN)
304
305 _tprintf(_T("\tWIN32_EXIT_CODE : %d (0x%x)\n"),
306 (unsigned int)pServiceStatus[i].ServiceStatusProcess.dwWin32ExitCode,
307 (unsigned int)pServiceStatus[i].ServiceStatusProcess.dwWin32ExitCode);
308 _tprintf(_T("\tSERVICE_EXIT_CODE : %d (0x%x)\n"),
309 (unsigned int)pServiceStatus[i].ServiceStatusProcess.dwServiceSpecificExitCode,
310 (unsigned int)pServiceStatus[i].ServiceStatusProcess.dwServiceSpecificExitCode);
311 _tprintf(_T("\tCHECKPOINT : 0x%x\n"),
312 (unsigned int)pServiceStatus[i].ServiceStatusProcess.dwCheckPoint);
313 _tprintf(_T("\tWAIT_HINT : 0x%x\n"),
314 (unsigned int)pServiceStatus[i].ServiceStatusProcess.dwWaitHint);
315 if (bExtended)
316 {
317 _tprintf(_T("\tPID : %lu\n"),
318 pServiceStatus[i].ServiceStatusProcess.dwProcessId);
319 _tprintf(_T("\tFLAGS : %lu\n"),
320 pServiceStatus[i].ServiceStatusProcess.dwServiceFlags);
321 }
322
323 _tprintf(_T("\n"));
324 }
325
326 _tprintf(_T("number : %lu\n"), NumServices);
327 }