daf24bc8328f2a3f1de1326b87ddb0ed330f185a
[reactos.git] / reactos / subsys / system / servman / servman.c
1 #include <windows.h>
2 #include <stdio.h>
3 #include <tchar.h>
4 #include <commctrl.h>
5 #include "resource.h"
6
7 const TCHAR ClassName[] = _T("ServiceManager");
8
9 HINSTANCE hInstance;
10 HWND hListView;
11 HWND hStatus;
12
13
14 void
15 GetServices ( void )
16 {
17 LV_ITEM item;
18 WORD wCodePage;
19 WORD wLangID;
20 SC_HANDLE ScHandle;
21 SC_HANDLE hService;
22 DWORD BytesNeeded = 0;
23 DWORD ResumeHandle = 0;
24 DWORD NumServices = 0;
25 DWORD dwHandle, dwLen;
26 size_t Index;
27 UINT BufLen;
28 TCHAR szStatus[128];
29 TCHAR* lpData;
30 TCHAR* lpBuffer;
31 TCHAR szStrFileInfo[80];
32 TCHAR FileName[MAX_PATH];
33 TCHAR szNumServices[32];
34 LPVOID pvData;
35
36 LPSERVICE_FAILURE_ACTIONS pServiceFailureActions = NULL;
37 LPQUERY_SERVICE_CONFIG pServiceConfig = NULL;
38 ENUM_SERVICE_STATUS_PROCESS *pServiceStatus = NULL;
39
40 ScHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ENUMERATE_SERVICE);
41 if (ScHandle != INVALID_HANDLE_VALUE)
42 {
43 if (EnumServicesStatusEx(ScHandle,
44 SC_ENUM_PROCESS_INFO,
45 SERVICE_WIN32,
46 SERVICE_STATE_ALL,
47 (LPBYTE)pServiceStatus,
48 0, &BytesNeeded,
49 &NumServices,
50 &ResumeHandle,
51 0) == 0)
52 {
53 /* Call function again if required size was returned */
54 if (GetLastError() == ERROR_MORE_DATA)
55 {
56 /* reserve memory for service info array */
57 pServiceStatus = (ENUM_SERVICE_STATUS_PROCESS *) HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
58 if (pServiceStatus == NULL)
59 return;
60
61 /* fill array with service info */
62 if (EnumServicesStatusEx(ScHandle,
63 SC_ENUM_PROCESS_INFO,
64 SERVICE_WIN32,
65 SERVICE_STATE_ALL,
66 (LPBYTE)pServiceStatus,
67 BytesNeeded,
68 &BytesNeeded,
69 &NumServices,
70 &ResumeHandle,
71 0) == 0)
72 {
73 HeapFree(GetProcessHeap(), 0, pServiceStatus);
74 return;
75 }
76 }
77 else /* exit on failure */
78 {
79 return;
80 }
81 }
82
83 if (NumServices)
84 {
85 HICON hiconItem; // icon for list-view items
86 HIMAGELIST hSmall; // image list for other views
87 TCHAR buf[40];
88
89 /* Create the icon image lists */
90 hSmall = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
91 GetSystemMetrics(SM_CYSMICON), ILC_MASK, 1, 1);
92
93 /* Add an icon to each image list */
94 hiconItem = LoadImage(hInstance, MAKEINTRESOURCE(IDI_SM_ICON), IMAGE_ICON, 16, 16, 0);
95 ImageList_AddIcon(hSmall, hiconItem);
96
97 ListView_SetImageList(hListView, hSmall, LVSIL_SMALL);
98
99 /* set the number of services in the status bar */
100 LoadString(hInstance, IDS_SERVICES_NUM_SERVICES, szNumServices, 32);
101 _stprintf(buf, szNumServices, NumServices);
102 SendMessage(hStatus, SB_SETTEXT, 0, (LPARAM)buf);
103
104 for (Index = 0; Index < NumServices; Index++)
105 {
106 memset(&item, 0, sizeof(LV_ITEM));
107 item.mask = LVIF_TEXT;
108 //item.iImage = 0;
109 item.pszText = pServiceStatus[Index].lpDisplayName;
110 item.iItem = ListView_GetItemCount(hListView);
111 item.lParam = 0;
112 item.iItem = ListView_InsertItem(hListView, &item);
113
114 BytesNeeded = 0;
115 hService = OpenService(ScHandle,
116 pServiceStatus[Index].lpServiceName,
117 SC_MANAGER_CONNECT);
118 if (hService != INVALID_HANDLE_VALUE)
119 {
120 /* check if service is required by the system*/
121 if (!QueryServiceConfig2(hService,
122 SERVICE_CONFIG_FAILURE_ACTIONS,
123 (LPBYTE)pServiceFailureActions,
124 0,
125 &BytesNeeded))
126 {
127 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
128 {
129 pServiceFailureActions = (LPSERVICE_FAILURE_ACTIONS)
130 HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
131 if (pServiceFailureActions == NULL)
132 return;
133
134 if (!QueryServiceConfig2(hService,
135 SERVICE_CONFIG_FAILURE_ACTIONS,
136 (LPBYTE)pServiceFailureActions,
137 BytesNeeded,
138 &BytesNeeded))
139 {
140 HeapFree(GetProcessHeap(), 0, pServiceFailureActions);
141 return;
142 }
143 }
144 else /* exit on failure */
145 {
146 return;
147 }
148 }
149 if (pServiceFailureActions->cActions)
150 {
151 if (pServiceFailureActions->lpsaActions[0].Type == SC_ACTION_REBOOT)
152 {
153 LoadString(hInstance, IDS_SERVICES_YES, szStatus, 128);
154 item.pszText = szStatus;
155 item.iSubItem = 1;
156 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
157 }
158 }
159
160 if (pServiceFailureActions != NULL)
161 {
162 HeapFree(GetProcessHeap(), 0, pServiceFailureActions);
163 pServiceFailureActions = NULL;
164 }
165
166 /* get vendor of service binary */
167 BytesNeeded = 0;
168 if (!QueryServiceConfig(hService, pServiceConfig, 0, &BytesNeeded))
169 {
170 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
171 {
172 pServiceConfig = (LPQUERY_SERVICE_CONFIG)
173 HeapAlloc(GetProcessHeap(), 0, BytesNeeded);
174 if (pServiceConfig == NULL)
175 return;
176
177 if (!QueryServiceConfig(hService,
178 pServiceConfig,
179 BytesNeeded,
180 &BytesNeeded))
181 {
182 HeapFree(GetProcessHeap(), 0, pServiceConfig);
183 return;
184 }
185 }
186 else /* exit on failure */
187 {
188 return;
189 }
190 }
191
192 memset(&FileName, 0, MAX_PATH);
193 if (_tcscspn(pServiceConfig->lpBinaryPathName, _T("\"")))
194 {
195 _tcsncpy(FileName, pServiceConfig->lpBinaryPathName,
196 _tcscspn(pServiceConfig->lpBinaryPathName, _T(" ")) );
197 }
198 else
199 {
200 _tcscpy(FileName, pServiceConfig->lpBinaryPathName);
201 }
202
203 HeapFree(GetProcessHeap(), 0, pServiceConfig);
204 pServiceConfig = NULL;
205
206 dwLen = GetFileVersionInfoSize(FileName, &dwHandle);
207 if (dwLen)
208 {
209 lpData = (TCHAR*) HeapAlloc(GetProcessHeap(), 0, dwLen);
210 if (lpData == NULL)
211 return;
212
213 if (!GetFileVersionInfo (FileName, dwHandle, dwLen, lpData)) {
214 HeapFree(GetProcessHeap(), 0, lpData);
215 return;
216 }
217
218 if (VerQueryValue(lpData, _T("\\VarFileInfo\\Translation"), &pvData, (PUINT) &BufLen))
219 {
220 wCodePage = LOWORD(*(DWORD*) pvData);
221 wLangID = HIWORD(*(DWORD*) pvData);
222 wsprintf(szStrFileInfo, _T("StringFileInfo\\%04X%04X\\CompanyName"), wCodePage, wLangID);
223 }
224
225 if (VerQueryValue (lpData, szStrFileInfo, (LPVOID) &lpBuffer, (PUINT) &BufLen)) {
226 item.pszText = lpBuffer;
227 item.iSubItem = 2;
228 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
229 }
230 HeapFree(GetProcessHeap(), 0, lpData);
231 }
232 else
233 {
234 LoadString(hInstance, IDS_SERVICES_UNKNOWN, szStatus, 128);
235 item.pszText = szStatus;
236 item.iSubItem = 2;
237 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
238 }
239 CloseServiceHandle(hService);
240 }
241
242 if (pServiceStatus[Index].ServiceStatusProcess.dwCurrentState == SERVICE_RUNNING)
243 {
244 LoadString(hInstance, IDS_SERVICES_STATUS_RUNNING, szStatus, 128);
245 item.pszText = szStatus;
246 item.iSubItem = 2;
247 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
248 }
249 else
250 {
251 item.pszText = '\0';
252 item.iSubItem = 2;
253 SendMessage(hListView, LVM_SETITEMTEXT, item.iItem, (LPARAM) &item);
254 }
255
256 }
257 }
258
259 HeapFree(GetProcessHeap(), 0, pServiceStatus);
260 CloseServiceHandle(ScHandle);
261 }
262
263
264 }
265
266
267
268 LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
269 {
270 switch(msg)
271 {
272 case WM_CREATE:
273 {
274 //HFONT hfDefault;
275
276 HWND hTool;
277 TBBUTTON tbb[7];
278 TBADDBITMAP tbab;
279
280 int statwidths[] = {110, -1};
281
282 TCHAR szTemp[256];
283
284 /* Create List View */
285 LVCOLUMN lvc = { 0 };
286 //LVITEM lv = { 0 };
287
288 //GetClientRect(hwnd, &rc);
289 hListView = CreateWindow(WC_LISTVIEW,
290 NULL,
291 WS_CHILD | WS_VISIBLE | LVS_REPORT | WS_BORDER | LVS_EDITLABELS,
292 0, 0, 0, 0, /* sized via WM_SIZE */
293 hwnd,
294 (HMENU) IDC_SERVLIST,
295 hInstance,
296 NULL);
297
298 ListView_SetExtendedListViewStyle(hListView, LVS_EX_FULLROWSELECT |
299 /*LVS_EX_GRIDLINES |*/ LVS_EX_HEADERDRAGDROP);
300
301 lvc.mask = LVCF_TEXT | LVCF_SUBITEM | LVCF_WIDTH | LVCF_FMT;
302 lvc.fmt = LVCFMT_LEFT;
303
304 /* Add columns to the list-view (first column contains check box). */
305 lvc.iSubItem = 0;
306 lvc.cx = 160;
307 LoadString(hInstance, IDS_FIRSTCOLUMN, szTemp, 256);
308 lvc.pszText = szTemp;
309 ListView_InsertColumn(hListView, 0, &lvc);
310
311 lvc.iSubItem = 1;
312 lvc.cx = 150;
313 LoadString(hInstance, IDS_SECONDCOLUMN, szTemp, 256);
314 lvc.pszText = szTemp;
315 ListView_InsertColumn(hListView, 1, &lvc);
316
317 lvc.iSubItem = 2;
318 lvc.cx = 80;
319 LoadString(hInstance, IDS_THIRDCOLUMN, szTemp, 256);
320 lvc.pszText = szTemp;
321 ListView_InsertColumn(hListView, 2, &lvc);
322
323 lvc.iSubItem = 3;
324 lvc.cx = 80;
325 LoadString(hInstance, IDS_FOURTHCOLUMN, szTemp, 256);
326 lvc.pszText = szTemp;
327 ListView_InsertColumn(hListView, 3, &lvc);
328
329 lvc.iSubItem = 4;
330 lvc.cx = 100;
331 LoadString(hInstance, IDS_FITHCOLUMN, szTemp, 256);
332 lvc.pszText = szTemp;
333 ListView_InsertColumn(hListView, 4, &lvc);
334
335 // Create Toolbar
336 hTool = CreateWindowEx(0,
337 TOOLBARCLASSNAME,
338 NULL,
339 WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS,
340 0, 0, 0, 0,
341 hwnd,
342 (HMENU)IDC_TOOLBAR,
343 hInstance,
344 NULL);
345 if(hTool == NULL)
346 MessageBox(hwnd, _T("Could not create tool bar."), _T("Error"), MB_OK | MB_ICONERROR);
347
348 // Send the TB_BUTTONSTRUCTSIZE message, which is required for
349 // backward compatibility.
350 SendMessage(hTool, TB_BUTTONSTRUCTSIZE, (WPARAM)sizeof(TBBUTTON), 0);
351
352 tbab.hInst = HINST_COMMCTRL;
353 tbab.nID = IDB_STD_SMALL_COLOR;
354 SendMessage(hTool, TB_ADDBITMAP, 0, (LPARAM)&tbab);
355
356 ZeroMemory(tbb, sizeof(tbb));
357 tbb[0].iBitmap = STD_PROPERTIES;
358 tbb[0].fsState = TBSTATE_ENABLED;
359 tbb[0].fsStyle = TBSTYLE_BUTTON;
360 tbb[0].idCommand = ID_PROP;
361 tbb[1].iBitmap = STD_FILENEW;
362 tbb[1].fsState = TBSTATE_ENABLED;
363 tbb[1].fsStyle = TBSTYLE_BUTTON;
364 tbb[1].idCommand = ID_REFRESH;
365 tbb[2].iBitmap = STD_FILENEW;
366 tbb[2].fsState = TBSTATE_ENABLED;
367 tbb[2].fsStyle = TBSTYLE_BUTTON;
368 tbb[2].idCommand = ID_EXPORT;
369 /* seperator */
370 tbb[3].iBitmap = STD_FILENEW;
371 tbb[3].fsState = TBSTATE_ENABLED;
372 tbb[3].fsStyle = TBSTYLE_BUTTON;
373 tbb[3].idCommand = ID_START;
374 tbb[4].iBitmap = STD_FILENEW;
375 tbb[4].fsState = TBSTATE_ENABLED;
376 tbb[4].fsStyle = TBSTYLE_BUTTON;
377 tbb[4].idCommand = ID_STOP;
378 tbb[5].iBitmap = STD_FILENEW;
379 tbb[5].fsState = TBSTATE_ENABLED;
380 tbb[5].fsStyle = TBSTYLE_BUTTON;
381 tbb[5].idCommand = ID_PAUSE;
382 tbb[6].iBitmap = STD_FILENEW;
383 tbb[6].fsState = TBSTATE_ENABLED;
384 tbb[6].fsStyle = TBSTYLE_BUTTON;
385 tbb[6].idCommand = ID_RESTART;
386 SendMessage(hTool, TB_ADDBUTTONS, sizeof(tbb)/sizeof(TBBUTTON), (LPARAM)&tbb);
387
388 /* Create Status bar */
389 hStatus = CreateWindowEx(0,
390 STATUSCLASSNAME,
391 NULL,
392 WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
393 0, 0, 0, 0,
394 hwnd,
395 (HMENU)IDC_STATUSBAR,
396 hInstance,
397 NULL);
398 if(hStatus == NULL)
399 MessageBox(hwnd, _T("Could not create status bar."), _T("Error"), MB_OK | MB_ICONERROR);
400
401 SendMessage(hStatus, SB_SETPARTS, sizeof(statwidths)/sizeof(int), (LPARAM)statwidths);
402
403 /* populate the list view with all services */
404 GetServices();
405 }
406 break;
407 case WM_SIZE:
408 {
409 HWND hTool;
410 RECT rcTool;
411 int iToolHeight;
412
413 HWND hStatus;
414 RECT rcStatus;
415 int iStatusHeight;
416
417 HWND hListView;
418 int lvHeight;
419 RECT rcClient;
420
421 /* Size toolbar and get height */
422 hTool = GetDlgItem(hwnd, IDC_TOOLBAR);
423 SendMessage(hTool, TB_AUTOSIZE, 0, 0);
424
425 GetWindowRect(hTool, &rcTool);
426 iToolHeight = rcTool.bottom - rcTool.top;
427
428 /* Size status bar and get height */
429 hStatus = GetDlgItem(hwnd, IDC_STATUSBAR);
430 SendMessage(hStatus, WM_SIZE, 0, 0);
431
432 GetWindowRect(hStatus, &rcStatus);
433 iStatusHeight = rcStatus.bottom - rcStatus.top;
434
435 /* Calculate remaining height and size list view */
436 GetClientRect(hwnd, &rcClient);
437
438 lvHeight = rcClient.bottom - iToolHeight - iStatusHeight;
439
440 hListView = GetDlgItem(hwnd, IDC_SERVLIST);
441 SetWindowPos(hListView, NULL, 0, iToolHeight, rcClient.right, lvHeight, SWP_NOZORDER);
442 }
443 break;
444
445 case WM_NOTIFY:
446 switch (((LPNMHDR) lParam)->code)
447 {
448 case TTN_GETDISPINFO:
449 {
450 LPTOOLTIPTEXT lpttt;
451 UINT idButton;
452
453 lpttt = (LPTOOLTIPTEXT) lParam;
454 lpttt->hinst = hInstance;
455
456 // Specify the resource identifier of the descriptive
457 // text for the given button.
458 idButton = lpttt->hdr.idFrom;
459 switch (idButton)
460 {
461 case ID_PROP:
462 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_PROP);
463 break;
464
465 case ID_REFRESH:
466 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_REFRESH);
467 break;
468
469 case ID_EXPORT:
470 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_EXPORT);
471 break;
472
473 case ID_START:
474 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_START);
475 break;
476
477 case ID_STOP:
478 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_STOP);
479 break;
480
481 case ID_PAUSE:
482 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_PAUSE);
483 break;
484
485 case ID_RESTART:
486 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_RESTART);
487 break;
488
489 }
490 }
491 break;
492
493 // Process other notifications here.
494
495 default:
496 break;
497 }
498 break;
499
500 case WM_CLOSE:
501 DestroyWindow(hwnd);
502 break;
503 case WM_DESTROY:
504 PostQuitMessage(0);
505 break;
506 case WM_COMMAND:
507 switch(LOWORD(wParam))
508 {
509 case ID_FILE_EXIT:
510 PostMessage(hwnd, WM_CLOSE, 0, 0);
511 break;
512
513 case ID_START:
514 break;
515
516 case ID_STOP:
517 break;
518
519 case ID_PAUSE:
520 break;
521
522 case ID_RESUME:
523 break;
524
525 case ID_RESTART:
526 break;
527
528 case ID_REFRESH:
529 break;
530
531 case ID_PROP:
532 break;
533
534 case ID_VIEW_CUSTOMIZE:
535 break;
536
537 case ID_HELP_ABOUT:
538 break;
539
540 case ID_EXPORT:
541 break;
542
543 }
544 break;
545 default:
546 return DefWindowProc(hwnd, msg, wParam, lParam);
547 }
548 return 0;
549 }
550
551
552
553 int WINAPI WinMain(HINSTANCE hThisInstance, HINSTANCE hPrevInstance,
554 LPSTR lpCmdLine, int nCmdShow)
555 {
556 WNDCLASSEX wc;
557 HWND hwnd;
558 MSG Msg;
559 BOOL bRet;
560
561 hInstance = hThisInstance;
562
563 InitCommonControls();
564
565 wc.cbSize = sizeof(WNDCLASSEX);
566 wc.style = 0;
567 wc.lpfnWndProc = WndProc;
568 wc.cbClsExtra = 0;
569 wc.cbWndExtra = 0;
570 wc.hInstance = hInstance;
571 wc.hIcon = LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_SM_ICON));
572 wc.hCursor = LoadCursor(NULL, IDC_ARROW);
573 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
574 wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU);
575 wc.lpszClassName = ClassName;
576 wc.hIconSm = (HICON)LoadImage(hInstance,
577 MAKEINTRESOURCE(IDI_SM_ICON), IMAGE_ICON, 16, 16, 0);
578
579 if(!RegisterClassEx(&wc))
580 {
581 MessageBox(NULL, _T("Window Registration Failed!"), _T("Error!"),
582 MB_ICONEXCLAMATION | MB_OK);
583 return 0;
584 }
585
586 hwnd = CreateWindowEx(
587 0,
588 ClassName,
589 _T("ReactOS Service Manager"),
590 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN,
591 CW_USEDEFAULT, CW_USEDEFAULT, 700, 500,
592 NULL, NULL, hInstance, NULL);
593
594 if(hwnd == NULL)
595 {
596 MessageBox(NULL, _T("Window Creation Failed!"), _T("Error!"),
597 MB_ICONEXCLAMATION | MB_OK);
598 return 0;
599 }
600
601 ShowWindow(hwnd, nCmdShow);
602 UpdateWindow(hwnd);
603
604 while( (bRet = GetMessage( &Msg, NULL, 0, 0 )) != 0)
605 {
606 if (bRet == -1)
607 {
608 /* handle the error and possibly exit */
609 }
610 else
611 {
612 TranslateMessage(&Msg);
613 DispatchMessage(&Msg);
614 }
615 }
616 return Msg.wParam;
617 }
618
619