- Resource added for creating a service
[reactos.git] / reactos / subsys / system / servman / query.c
1 /*
2 * PROJECT: ReactOS Services
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: subsys/system/servman/query.c
5 * PURPOSE: Query service information
6 * COPYRIGHT: Copyright 2005 - 2006 Ged Murphy <gedmurphy@gmail.com>
7 *
8 */
9
10 #include "servman.h"
11
12 extern HINSTANCE hInstance;
13 extern HWND hListView;
14 extern HWND hStatus;
15
16 /* Stores the complete services array */
17 ENUM_SERVICE_STATUS_PROCESS *pServiceStatus = NULL;
18
19
20 /* Free service array */
21 VOID FreeMemory(VOID)
22 {
23 HeapFree(GetProcessHeap(), 0, pServiceStatus);
24 }
25
26
27 /* Retrives the service description from the registry */
28 BOOL GetDescription(HKEY hKey, LPTSTR *retDescription)
29 {
30
31 LPTSTR Description = NULL;
32 DWORD dwValueSize = 0;
33 LONG ret = RegQueryValueEx(hKey,
34 _T("Description"),
35 NULL,
36 NULL,
37 NULL,
38 &dwValueSize);
39 if (ret != ERROR_SUCCESS && ret != ERROR_FILE_NOT_FOUND && ret != ERROR_INVALID_HANDLE)
40 {
41 RegCloseKey(hKey);
42 return FALSE;
43 }
44
45 if (ret != ERROR_FILE_NOT_FOUND)
46 {
47 Description = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwValueSize);
48 if (Description == NULL)
49 {
50 RegCloseKey(hKey);
51 return FALSE;
52 }
53
54 if(RegQueryValueEx(hKey,
55 _T("Description"),
56 NULL,
57 NULL,
58 (LPBYTE)Description,
59 &dwValueSize))
60 {
61 HeapFree(GetProcessHeap(), 0, Description);
62 RegCloseKey(hKey);
63 return FALSE;
64 }
65 }
66
67 /* copy pointer over */
68 *retDescription = Description;
69
70 return TRUE;
71 }
72
73
74 /* get vendor of service binary */
75 BOOL GetExecutablePath(LPTSTR *ExePath)
76 {
77 SC_HANDLE hSCManager = NULL;
78 SC_HANDLE hSc = NULL;
79 LPQUERY_SERVICE_CONFIG pServiceConfig = NULL;
80 ENUM_SERVICE_STATUS_PROCESS *Service = NULL;
81 LVITEM item;
82 DWORD BytesNeeded = 0;
83 TCHAR FileName[MAX_PATH];
84
85
86 item.mask = LVIF_PARAM;
87 item.iItem = GetSelectedItem();
88 SendMessage(hListView, LVM_GETITEM, 0, (LPARAM)&item);
89
90 /* copy pointer to selected service */
91 Service = (ENUM_SERVICE_STATUS_PROCESS *)item.lParam;
92
93 /* open handle to the SCM */
94 hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
95 if (hSCManager == NULL)
96 {
97 GetError(0);
98 return FALSE;
99 }
100
101 /* get a handle to the service requested for starting */
102 hSc = OpenService(hSCManager, Service->lpServiceName, SERVICE_QUERY_CONFIG);
103 if (hSc == NULL)
104 {
105 GetError(0);
106 goto cleanup;
107 }
108
109
110 if (!QueryServiceConfig(hSc, pServiceConfig, 0, &BytesNeeded))
111 {
112 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
113 {
114 pServiceConfig = (LPQUERY_SERVICE_CONFIG)
115 HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
116 if (pServiceConfig == NULL)
117 goto cleanup;
118
119 if (!QueryServiceConfig(hSc,
120 pServiceConfig,
121 BytesNeeded,
122 &BytesNeeded))
123 {
124 HeapFree(GetProcessHeap(), 0, pServiceConfig);
125 goto cleanup;
126 }
127 }
128 else /* exit on failure */
129 {
130 goto cleanup;
131 }
132 }
133
134 ZeroMemory(&FileName, MAX_PATH);
135 if (_tcscspn(pServiceConfig->lpBinaryPathName, _T("\"")))
136 {
137 _tcsncpy(FileName, pServiceConfig->lpBinaryPathName,
138 _tcscspn(pServiceConfig->lpBinaryPathName, _T(" ")) );
139 }
140 else
141 {
142 _tcscpy(FileName, pServiceConfig->lpBinaryPathName);
143 }
144
145 *ExePath = FileName;
146
147 CloseServiceHandle(hSCManager);
148 CloseServiceHandle(hSc);
149
150 return TRUE;
151
152 cleanup:
153 if (hSCManager != NULL)
154 CloseServiceHandle(hSCManager);
155 if (hSc != NULL)
156 CloseServiceHandle(hSc);
157 return FALSE;
158 }
159
160
161
162
163 BOOL
164 RefreshServiceList(VOID)
165 {
166 LVITEM item;
167 TCHAR szNumServices[32];
168 TCHAR szStatus[64];
169 DWORD NumServices = 0;
170 DWORD Index;
171 LPCTSTR Path = _T("System\\CurrentControlSet\\Services\\%s");
172
173 ListView_DeleteAllItems(hListView);
174
175 NumServices = GetServiceList();
176
177 if (NumServices)
178 {
179 HICON hiconItem; /* icon for list-view items */
180 HIMAGELIST hSmall; /* image list for other views */
181 TCHAR buf[300]; /* buffer to hold key path */
182 INT NumListedServ = 0; /* how many services were listed */
183
184 /* Create the icon image lists */
185 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
186 GetSystemMetrics(SM_CYSMICON), ILC_MASK | ILC_COLOR16, 1, 1);
187
188 /* Add an icon to each image list */
189 hiconItem = LoadImage(hInstance, MAKEINTRESOURCE(IDI_SM_ICON),
190 IMAGE_ICON, 16, 16, 0);
191 ImageList_AddIcon(hSmall, hiconItem);
192
193 /* assign the image to the list view */
194 ListView_SetImageList(hListView, hSmall, LVSIL_SMALL);
195
196 for (Index = 0; Index < NumServices; Index++)
197 {
198 HKEY hKey = NULL;
199 LPTSTR Description = NULL;
200 LPTSTR LogOnAs = NULL;
201 DWORD StartUp = 0;
202 DWORD dwValueSize;
203
204 /* open the registry key for the service */
205 _sntprintf(buf, 300, Path,
206 pServiceStatus[Index].lpServiceName);
207
208 RegOpenKeyEx(HKEY_LOCAL_MACHINE,
209 buf,
210 0,
211 KEY_READ,
212 &hKey);
213
214
215 /* set the display name */
216
217 ZeroMemory(&item, sizeof(LVITEM));
218 item.mask = LVIF_TEXT | LVIF_PARAM;
219 item.pszText = pServiceStatus[Index].lpDisplayName;
220
221 /* Set a pointer for each service so we can query it later.
222 * Not all services are added to the list, so we can't query
223 * the item number as they become out of sync with the array */
224 item.lParam = (LPARAM)&pServiceStatus[Index];
225
226 item.iItem = ListView_GetItemCount(hListView);
227 item.iItem = ListView_InsertItem(hListView, &item);
228
229
230
231
232 /* set the description */
233
234 if (GetDescription(hKey, &Description))
235 {
236 item.pszText = Description;
237 item.iSubItem = 1;
238 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
239
240 HeapFree(GetProcessHeap(), 0, Description);
241 }
242
243
244 /* set the status */
245
246 if (pServiceStatus[Index].ServiceStatusProcess.dwCurrentState
247 == SERVICE_RUNNING)
248 {
249 LoadString(hInstance, IDS_SERVICES_STARTED, szStatus,
250 sizeof(szStatus) / sizeof(TCHAR));
251 item.pszText = szStatus;
252 item.iSubItem = 2;
253 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
254 }
255
256
257
258 /* set the startup type */
259
260 dwValueSize = sizeof(DWORD);
261 if (RegQueryValueEx(hKey,
262 _T("Start"),
263 NULL,
264 NULL,
265 (LPBYTE)&StartUp,
266 &dwValueSize))
267 {
268 RegCloseKey(hKey);
269 continue;
270 }
271
272 if (StartUp == 0x02)
273 {
274 LoadString(hInstance, IDS_SERVICES_AUTO, szStatus,
275 sizeof(szStatus) / sizeof(TCHAR));
276 item.pszText = szStatus;
277 item.iSubItem = 3;
278 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
279 }
280 else if (StartUp == 0x03)
281 {
282 LoadString(hInstance, IDS_SERVICES_MAN, szStatus,
283 sizeof(szStatus) / sizeof(TCHAR));
284 item.pszText = szStatus;
285 item.iSubItem = 3;
286 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
287 }
288 else if (StartUp == 0x04)
289 {
290 LoadString(hInstance, IDS_SERVICES_DIS, szStatus,
291 sizeof(szStatus) / sizeof(TCHAR));
292 item.pszText = szStatus;
293 item.iSubItem = 3;
294 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
295 }
296
297
298
299 /* set Log On As */
300
301 dwValueSize = 0;
302 if (RegQueryValueEx(hKey,
303 _T("ObjectName"),
304 NULL,
305 NULL,
306 NULL,
307 &dwValueSize))
308 {
309 RegCloseKey(hKey);
310 continue;
311 }
312
313 LogOnAs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwValueSize);
314 if (LogOnAs == NULL)
315 {
316 RegCloseKey(hKey);
317 return FALSE;
318 }
319 if(RegQueryValueEx(hKey,
320 _T("ObjectName"),
321 NULL,
322 NULL,
323 (LPBYTE)LogOnAs,
324 &dwValueSize))
325 {
326 HeapFree(GetProcessHeap(), 0, LogOnAs);
327 RegCloseKey(hKey);
328 continue;
329 }
330
331 item.pszText = LogOnAs;
332 item.iSubItem = 4;
333 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
334
335 HeapFree(GetProcessHeap(), 0, LogOnAs);
336
337 RegCloseKey(hKey);
338
339 }
340
341 NumListedServ = ListView_GetItemCount(hListView);
342
343 /* set the number of listed services in the status bar */
344 LoadString(hInstance, IDS_NUM_SERVICES, szNumServices,
345 sizeof(szNumServices) / sizeof(TCHAR));
346 _sntprintf(buf, 300, szNumServices, NumListedServ);
347 SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)buf);
348 }
349
350 /* turn redraw flag on. It's turned off initially via the LBS_NOREDRAW flag */
351 SendMessage (hListView, WM_SETREDRAW, TRUE, 0) ;
352
353 return TRUE;
354 }
355
356
357
358
359 DWORD
360 GetServiceList(VOID)
361 {
362 SC_HANDLE ScHandle;
363
364 DWORD BytesNeeded = 0;
365 DWORD ResumeHandle = 0;
366 DWORD NumServices = 0;
367
368 ScHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
369 if (ScHandle != INVALID_HANDLE_VALUE)
370 {
371 if (EnumServicesStatusEx(ScHandle,
372 SC_ENUM_PROCESS_INFO,
373 SERVICE_WIN32,
374 SERVICE_STATE_ALL,
375 (LPBYTE)pServiceStatus,
376 0, &BytesNeeded,
377 &NumServices,
378 &ResumeHandle,
379 0) == 0)
380 {
381 /* Call function again if required size was returned */
382 if (GetLastError() == ERROR_MORE_DATA)
383 {
384 /* reserve memory for service info array */
385 pServiceStatus = (ENUM_SERVICE_STATUS_PROCESS *)
386 HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
387 if (pServiceStatus == NULL)
388 return FALSE;
389
390 /* fill array with service info */
391 if (EnumServicesStatusEx(ScHandle,
392 SC_ENUM_PROCESS_INFO,
393 SERVICE_WIN32,
394 SERVICE_STATE_ALL,
395 (LPBYTE)pServiceStatus,
396 BytesNeeded,
397 &BytesNeeded,
398 &NumServices,
399 &ResumeHandle,
400 0) == 0)
401 {
402 HeapFree(GetProcessHeap(), 0, pServiceStatus);
403 return FALSE;
404 }
405 }
406 else /* exit on failure */
407 {
408 return FALSE;
409 }
410 }
411 }
412
413 CloseServiceHandle(ScHandle);
414
415 return NumServices;
416 }
417
418
419
420
421
422
423
424
425
426
427
428 /*
429 //WORD wCodePage;
430 //WORD wLangID;
431 //SC_HANDLE hService;
432 //DWORD dwHandle, dwLen;
433 //UINT BufLen;
434 //TCHAR* lpData;
435 //TCHAR* lpBuffer;
436 //TCHAR szStrFileInfo[80];
437 //TCHAR FileName[MAX_PATH];
438 //LPVOID pvData;
439
440 //LPSERVICE_FAILURE_ACTIONS pServiceFailureActions = NULL;
441 //LPQUERY_SERVICE_CONFIG pServiceConfig = NULL;
442
443 BytesNeeded = 0;
444 hService = OpenService(ScHandle,
445 pServiceStatus[Index].lpServiceName,
446 SC_MANAGER_CONNECT);
447 if (hService != INVALID_HANDLE_VALUE)
448 {
449 / * check if service is required by the system* /
450 if (!QueryServiceConfig2(hService,
451 SERVICE_CONFIG_FAILURE_ACTIONS,
452 (LPBYTE)pServiceFailureActions,
453 0,
454 &BytesNeeded))
455 {
456 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
457 {
458 pServiceFailureActions = (LPSERVICE_FAILURE_ACTIONS)
459 HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
460 if (pServiceFailureActions == NULL)
461 return FALSE;
462
463 if (!QueryServiceConfig2(hService,
464 SERVICE_CONFIG_FAILURE_ACTIONS,
465 (LPBYTE)pServiceFailureActions,
466 BytesNeeded,
467 &BytesNeeded))
468 {
469 HeapFree(GetProcessHeap(), 0, pServiceFailureActions);
470 return FALSE;
471 }
472 }
473 else / * exit on failure * /
474 {
475 return FALSE;
476 }
477 }
478 if (pServiceFailureActions->cActions)
479 {
480 if (pServiceFailureActions->lpsaActions[0].Type == SC_ACTION_REBOOT)
481 {
482 LoadString(hInstance, IDS_SERVICES_YES, szStatus, 128);
483 item.pszText = szStatus;
484 item.iSubItem = 1;
485 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
486 }
487 }
488
489 if (pServiceFailureActions != NULL)
490 {
491 HeapFree(GetProcessHeap(), 0, pServiceFailureActions);
492 pServiceFailureActions = NULL;
493 }
494
495 / * get vendor of service binary * /
496 BytesNeeded = 0;
497 if (!QueryServiceConfig(hService, pServiceConfig, 0, &BytesNeeded))
498 {
499 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
500 {
501 pServiceConfig = (LPQUERY_SERVICE_CONFIG)
502 HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
503 if (pServiceConfig == NULL)
504 return FALSE;
505
506 if (!QueryServiceConfig(hService,
507 pServiceConfig,
508 BytesNeeded,
509 &BytesNeeded))
510 {
511 HeapFree(GetProcessHeap(), 0, pServiceConfig);
512 return FALSE;
513 }
514 }
515 else / * exit on failure * /
516 {
517 return FALSE;
518 }
519 }
520
521 memset(&FileName, 0, MAX_PATH);
522 if (_tcscspn(pServiceConfig->lpBinaryPathName, _T("\"")))
523 {
524 _tcsncpy(FileName, pServiceConfig->lpBinaryPathName,
525 _tcscspn(pServiceConfig->lpBinaryPathName, _T(" ")) );
526 }
527 else
528 {
529 _tcscpy(FileName, pServiceConfig->lpBinaryPathName);
530 }
531
532 HeapFree(GetProcessHeap(), 0, pServiceConfig);
533 pServiceConfig = NULL;
534
535 dwLen = GetFileVersionInfoSize(FileName, &dwHandle);
536 if (dwLen)
537 {
538 lpData = (TCHAR*) HeapAlloc(GetProcessHeap(), 0, dwLen);
539 if (lpData == NULL)
540 return FALSE;
541
542 if (!GetFileVersionInfo (FileName, dwHandle, dwLen, lpData)) {
543 HeapFree(GetProcessHeap(), 0, lpData);
544 return FALSE;
545 }
546
547 if (VerQueryValue(lpData, _T("\\VarFileInfo\\Translation"), &pvData, (PUINT) &BufLen))
548 {
549 wCodePage = LOWORD(*(DWORD*) pvData);
550 wLangID = HIWORD(*(DWORD*) pvData);
551 wsprintf(szStrFileInfo, _T("StringFileInfo\\%04X%04X\\CompanyName"), wCodePage, wLangID);
552 }
553
554 if (VerQueryValue (lpData, szStrFileInfo, (LPVOID) &lpBuffer, (PUINT) &BufLen)) {
555 item.pszText = lpBuffer;
556 item.iSubItem = 2;
557 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
558 }
559 HeapFree(GetProcessHeap(), 0, lpData);
560 }
561 else
562 {
563 LoadString(hInstance, IDS_SERVICES_UNKNOWN, szStatus, 128);
564 item.pszText = szStatus;
565 item.iSubItem = 2;
566 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
567 }
568 CloseServiceHandle(hService);
569 }
570
571
572
573
574
575
576
577 HeapFree(GetProcessHeap(), 0, pServiceConfig);
578 pServiceConfig = NULL;
579
580 dwLen = GetFileVersionInfoSize(FileName, &dwHandle);
581 if (dwLen)
582 {
583 lpData = (TCHAR*) HeapAlloc(GetProcessHeap(), 0, dwLen);
584 if (lpData == NULL)
585 return FALSE;
586
587 if (!GetFileVersionInfo (FileName, dwHandle, dwLen, lpData)) {
588 HeapFree(GetProcessHeap(), 0, lpData);
589 return FALSE;
590 }
591
592 if (VerQueryValue(lpData, _T("\\VarFileInfo\\Translation"),
593 &pvData, (PUINT) &BufLen))
594 {
595 wCodePage = LOWORD(*(DWORD*) pvData);
596 wLangID = HIWORD(*(DWORD*) pvData);
597 wsprintf(szStrFileInfo, _T("StringFileInfo\\%04X%04X\\CompanyName"),
598 wCodePage, wLangID);
599 }
600
601 if (VerQueryValue (lpData, szStrFileInfo, (LPVOID) &lpBuffer, (PUINT) &BufLen))
602 {
603 item.pszText = lpBuffer;
604 item.iSubItem = 2;
605 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
606 }
607 HeapFree(GetProcessHeap(), 0, lpData);
608 }
609 else
610 {
611 LoadString(hInstance, IDS_SERVICES_UNKNOWN, szStatus, 128);
612 item.pszText = szStatus;
613 item.iSubItem = 2;
614 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
615 }
616
617
618 */
619