1 /*
2  * PROJECT:     ReactOS Services
3  * LICENSE:     GPL - See COPYING in the top level directory
4  * FILE:        base/applications/mscutils/servman/query.c
5  * PURPOSE:     Query service information
6  * COPYRIGHT:   Copyright 2006-2007 Ged Murphy <gedmurphy@reactos.org>
7  *
8  */
9 
10 #include "precomp.h"
11 
12 ENUM_SERVICE_STATUS_PROCESS*
13 GetSelectedService(PMAIN_WND_INFO Info)
14 {
15     LVITEM lvItem;
16 
17     lvItem.mask = LVIF_PARAM;
18     lvItem.iItem = Info->SelectedItem;
19     SendMessage(Info->hListView,
20                 LVM_GETITEM,
21                 0,
22                 (LPARAM)&lvItem);
23 
24     /* return pointer to selected service */
25     return (ENUM_SERVICE_STATUS_PROCESS *)lvItem.lParam;
26 }
27 
28 LPQUERY_SERVICE_CONFIG
29 GetServiceConfig(LPWSTR lpServiceName)
30 {
31     LPQUERY_SERVICE_CONFIGW lpServiceConfig = NULL;
32     SC_HANDLE hSCManager;
33     SC_HANDLE hService;
34     DWORD dwBytesNeeded;
35 
36     hSCManager = OpenSCManagerW(NULL,
37                                 NULL,
38                                 SC_MANAGER_CONNECT);
39     if (hSCManager)
40     {
41         hService = OpenServiceW(hSCManager,
42                                 lpServiceName,
43                                 SERVICE_QUERY_CONFIG);
44         if (hService)
45         {
46             if (!QueryServiceConfigW(hService,
47                                      NULL,
48                                      0,
49                                      &dwBytesNeeded))
50             {
51                 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
52                 {
53                     lpServiceConfig = (LPQUERY_SERVICE_CONFIG)HeapAlloc(GetProcessHeap(),
54                                                                         0,
55                                                                         dwBytesNeeded);
56                     if (lpServiceConfig)
57                     {
58                         if (!QueryServiceConfigW(hService,
59                                                 lpServiceConfig,
60                                                 dwBytesNeeded,
61                                                 &dwBytesNeeded))
62                         {
63                             HeapFree(GetProcessHeap(),
64                                      0,
65                                      lpServiceConfig);
66                             lpServiceConfig = NULL;
67                         }
68                     }
69                 }
70             }
71 
72             CloseServiceHandle(hService);
73         }
74 
75         CloseServiceHandle(hSCManager);
76     }
77 
78     return lpServiceConfig;
79 }
80 
81 BOOL
82 SetServiceConfig(LPQUERY_SERVICE_CONFIG pServiceConfig,
83                  LPWSTR lpServiceName,
84                  LPWSTR lpPassword)
85 {
86     SC_HANDLE hSCManager;
87     SC_HANDLE hSc;
88     SC_LOCK scLock;
89     BOOL bRet = FALSE;
90 
91     hSCManager = OpenSCManagerW(NULL,
92                                 NULL,
93                                 SC_MANAGER_LOCK);
94     if (hSCManager)
95     {
96         scLock = LockServiceDatabase(hSCManager);
97         if (scLock)
98         {
99             hSc = OpenServiceW(hSCManager,
100                                lpServiceName,
101                                SERVICE_CHANGE_CONFIG);
102             if (hSc)
103             {
104                 if (ChangeServiceConfigW(hSc,
105                                          pServiceConfig->dwServiceType,
106                                          pServiceConfig->dwStartType,
107                                          pServiceConfig->dwErrorControl,
108                                          pServiceConfig->lpBinaryPathName,
109                                          pServiceConfig->lpLoadOrderGroup,
110                                          pServiceConfig->dwTagId ? &pServiceConfig->dwTagId : NULL,
111                                          pServiceConfig->lpDependencies,
112                                          pServiceConfig->lpServiceStartName,
113                                          lpPassword,
114                                          pServiceConfig->lpDisplayName))
115                 {
116                     bRet = TRUE;
117                 }
118 
119                 CloseServiceHandle(hSc);
120             }
121 
122             UnlockServiceDatabase(scLock);
123         }
124 
125         CloseServiceHandle(hSCManager);
126     }
127 
128     if (!bRet)
129         GetError();
130 
131     return bRet;
132 }
133 
134 LPWSTR
135 GetServiceDescription(LPWSTR lpServiceName)
136 {
137     SC_HANDLE hSCManager = NULL;
138     SC_HANDLE hSc = NULL;
139     SERVICE_DESCRIPTIONW *pServiceDescription = NULL;
140     LPWSTR lpDescription = NULL;
141     DWORD BytesNeeded = 0;
142     DWORD dwSize;
143 
144     hSCManager = OpenSCManagerW(NULL,
145                                 NULL,
146                                 SC_MANAGER_ENUMERATE_SERVICE);
147     if (hSCManager == NULL)
148     {
149         GetError();
150         return NULL;
151     }
152 
153     hSc = OpenServiceW(hSCManager,
154                        lpServiceName,
155                        SERVICE_QUERY_CONFIG);
156     if (hSc)
157     {
158         if (!QueryServiceConfig2W(hSc,
159                                   SERVICE_CONFIG_DESCRIPTION,
160                                   NULL,
161                                   0,
162                                   &BytesNeeded))
163         {
164             if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
165             {
166                 pServiceDescription = (SERVICE_DESCRIPTION *) HeapAlloc(ProcessHeap,
167                                                                         0,
168                                                                         BytesNeeded);
169                 if (pServiceDescription == NULL)
170                     goto cleanup;
171 
172                 if (QueryServiceConfig2W(hSc,
173                                          SERVICE_CONFIG_DESCRIPTION,
174                                          (LPBYTE)pServiceDescription,
175                                          BytesNeeded,
176                                          &BytesNeeded))
177                 {
178                     if (pServiceDescription->lpDescription)
179                     {
180                         dwSize = wcslen(pServiceDescription->lpDescription) + 1;
181                         lpDescription = HeapAlloc(ProcessHeap,
182                                                   0,
183                                                   dwSize * sizeof(WCHAR));
184                         if (lpDescription)
185                         {
186                             StringCchCopyW(lpDescription,
187                                            dwSize,
188                                            pServiceDescription->lpDescription);
189                         }
190                     }
191                 }
192             }
193         }
194     }
195 
196 cleanup:
197     if (pServiceDescription)
198         HeapFree(ProcessHeap,
199                  0,
200                  pServiceDescription);
201     if (hSCManager != NULL)
202         CloseServiceHandle(hSCManager);
203     if (hSc != NULL)
204         CloseServiceHandle(hSc);
205 
206     return lpDescription;
207 }
208 
209 BOOL
210 SetServiceDescription(LPWSTR lpServiceName,
211                       LPWSTR lpDescription)
212 {
213     SC_HANDLE hSCManager;
214     SC_HANDLE hSc;
215     SC_LOCK scLock;
216     SERVICE_DESCRIPTION ServiceDescription;
217     BOOL bRet = FALSE;
218 
219     hSCManager = OpenSCManagerW(NULL,
220                                 NULL,
221                                 SC_MANAGER_LOCK);
222     if (hSCManager)
223     {
224         scLock = LockServiceDatabase(hSCManager);
225         if (scLock)
226         {
227             hSc = OpenServiceW(hSCManager,
228                                lpServiceName,
229                                SERVICE_CHANGE_CONFIG);
230             if (hSc)
231             {
232                 ServiceDescription.lpDescription = lpDescription;
233 
234                 if (ChangeServiceConfig2W(hSc,
235                                           SERVICE_CONFIG_DESCRIPTION,
236                                           &ServiceDescription))
237                 {
238                     bRet = TRUE;
239                 }
240 
241                 CloseServiceHandle(hSc);
242             }
243 
244             UnlockServiceDatabase(scLock);
245         }
246 
247         CloseServiceHandle(hSCManager);
248     }
249 
250     if (!bRet)
251         GetError();
252 
253     return bRet;
254 }
255 
256 VOID
257 FreeServiceList(PMAIN_WND_INFO Info)
258 {
259     DWORD i;
260 
261     if (Info->pAllServices != NULL)
262     {
263         for (i = 0; i < Info->NumServices; i++)
264         {
265             if (Info->pAllServices[i].lpServiceName)
266                 HeapFree(ProcessHeap, 0, Info->pAllServices[i].lpServiceName);
267 
268             if (Info->pAllServices[i].lpDisplayName)
269                 HeapFree(ProcessHeap, 0, Info->pAllServices[i].lpDisplayName);
270         }
271 
272         HeapFree(ProcessHeap, 0, Info->pAllServices);
273         Info->pAllServices = NULL;
274         Info->NumServices = 0;
275     }
276 }
277 
278 BOOL
279 GetServiceList(PMAIN_WND_INFO Info)
280 {
281     ENUM_SERVICE_STATUS_PROCESS *pServices = NULL;
282     SC_HANDLE ScHandle;
283     BOOL bRet = FALSE;
284 
285     DWORD BytesNeeded = 0;
286     DWORD ResumeHandle = 0;
287     DWORD NumServices = 0;
288     DWORD i;
289 
290     FreeServiceList(Info);
291 
292     ScHandle = OpenSCManagerW(NULL,
293                               NULL,
294                               SC_MANAGER_ENUMERATE_SERVICE);
295     if (ScHandle != NULL)
296     {
297         if (!EnumServicesStatusEx(ScHandle,
298                                   SC_ENUM_PROCESS_INFO,
299                                   SERVICE_WIN32,
300                                   SERVICE_STATE_ALL,
301                                   NULL,
302                                   0,
303                                   &BytesNeeded,
304                                   &NumServices,
305                                   &ResumeHandle,
306                                   0))
307         {
308             /* Call function again if required size was returned */
309             if (GetLastError() == ERROR_MORE_DATA)
310             {
311                 /* reserve memory for service info array */
312                 pServices = (ENUM_SERVICE_STATUS_PROCESS *)HeapAlloc(ProcessHeap,
313                                                                      0,
314                                                                      BytesNeeded);
315                 if (pServices)
316                 {
317                     /* fill array with service info */
318                     if (EnumServicesStatusEx(ScHandle,
319                                              SC_ENUM_PROCESS_INFO,
320                                              SERVICE_WIN32,
321                                              SERVICE_STATE_ALL,
322                                              (LPBYTE)pServices,
323                                              BytesNeeded,
324                                              &BytesNeeded,
325                                              &NumServices,
326                                              &ResumeHandle,
327                                              0))
328                     {
329                         bRet = TRUE;
330                     }
331                 }
332             }
333         }
334     }
335 
336     if (ScHandle)
337         CloseServiceHandle(ScHandle);
338 
339     Info->pAllServices = (ENUM_SERVICE_STATUS_PROCESS *)HeapAlloc(ProcessHeap,
340                                                                   HEAP_ZERO_MEMORY,
341                                                                   NumServices * sizeof(ENUM_SERVICE_STATUS_PROCESS));
342     if (Info->pAllServices != NULL)
343     {
344         Info->NumServices = NumServices;
345 
346         for (i = 0; i < NumServices; i++)
347         {
348             Info->pAllServices[i].lpServiceName = HeapAlloc(ProcessHeap,
349                                                             HEAP_ZERO_MEMORY,
350                                                             (wcslen(pServices[i].lpServiceName) + 1) * sizeof(WCHAR));
351             if (Info->pAllServices[i].lpServiceName)
352                 wcscpy(Info->pAllServices[i].lpServiceName, pServices[i].lpServiceName);
353 
354             Info->pAllServices[i].lpDisplayName = HeapAlloc(ProcessHeap,
355                                                             HEAP_ZERO_MEMORY,
356                                                             (wcslen(pServices[i].lpDisplayName) + 1) * sizeof(WCHAR));
357             if (Info->pAllServices[i].lpDisplayName)
358                 wcscpy(Info->pAllServices[i].lpDisplayName, pServices[i].lpDisplayName);
359 
360             CopyMemory(&Info->pAllServices[i].ServiceStatusProcess,
361                        &pServices[i].ServiceStatusProcess,
362                        sizeof(SERVICE_STATUS_PROCESS));
363         }
364     }
365 
366     if (pServices)
367         HeapFree(ProcessHeap, 0, pServices);
368 
369     return bRet;
370 }
371 
372 BOOL
373 UpdateServiceStatus(ENUM_SERVICE_STATUS_PROCESS* pService)
374 {
375     SC_HANDLE hScm;
376     BOOL bRet = FALSE;
377 
378     hScm = OpenSCManagerW(NULL,
379                           NULL,
380                           SC_MANAGER_ENUMERATE_SERVICE);
381     if (hScm != NULL)
382     {
383         SC_HANDLE hService;
384 
385         hService = OpenServiceW(hScm,
386                                 pService->lpServiceName,
387                                 SERVICE_QUERY_STATUS);
388         if (hService)
389         {
390             DWORD size;
391 
392             QueryServiceStatusEx(hService,
393                                  SC_STATUS_PROCESS_INFO,
394                                  (LPBYTE)&pService->ServiceStatusProcess,
395                                  sizeof(SERVICE_STATUS_PROCESS),
396                                  &size);
397 
398             CloseServiceHandle(hService);
399             bRet = TRUE;
400         }
401 
402         CloseServiceHandle(hScm);
403     }
404 
405     return bRet;
406 }
407