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