[SERVMAN] Introduce the ability to sort the services list-view by any column in ascen...
[reactos.git] / reactos / base / applications / mscutils / servman / mainwnd.c
1 /*
2 * PROJECT: ReactOS Services
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/applications/mscutils/servman/mainwnd.c
5 * PURPOSE: Main window message handler
6 * COPYRIGHT: Copyright 2006-20015 Ged Murphy <gedmurphy@reactos.org>
7 *
8 */
9
10 #include "precomp.h"
11
12 #include <windowsx.h>
13
14 static const WCHAR szMainWndClass[] = L"ServManWndClass";
15
16 BOOL bSortAscending = TRUE;
17
18 /* Temporary copy for access from list-view sort CompareFunc */
19 HWND hListView;
20
21 /* Toolbar buttons */
22 static const TBBUTTON Buttons [] =
23 { /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */
24 {TBICON_PROP, ID_PROP, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0}, /* properties */
25 {TBICON_REFRESH, ID_REFRESH, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, /* refresh */
26 {TBICON_EXPORT, ID_EXPORT, TBSTATE_ENABLED, BTNS_BUTTON, {0}, 0, 0}, /* export */
27
28 /* Note: First item for a separator is its width in pixels */
29 {15, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */
30
31 {TBICON_CREATE, ID_CREATE, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* create */
32 {TBICON_DELETE, ID_DELETE, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* delete */
33
34 {15, 0, TBSTATE_ENABLED, BTNS_SEP, {0}, 0, 0}, /* separator */
35
36 {TBICON_START, ID_START, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* start */
37 {TBICON_STOP, ID_STOP, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* stop */
38 {TBICON_PAUSE, ID_PAUSE, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* pause */
39 {TBICON_RESTART, ID_RESTART, TBSTATE_INDETERMINATE, BTNS_BUTTON, {0}, 0, 0 }, /* restart */
40 };
41
42
43 /* menu hints */
44 static const MENU_HINT MainMenuHintTable[] = {
45 /* File Menu */
46 {ID_EXPORT, IDS_HINT_EXPORT},
47 {ID_EXIT, IDS_HINT_EXIT},
48
49 /* Action Menu */
50 {ID_CONNECT, IDS_HINT_CONNECT},
51 {ID_START, IDS_HINT_START},
52 {ID_STOP, IDS_HINT_STOP},
53 {ID_PAUSE, IDS_HINT_PAUSE},
54 {ID_RESUME, IDS_HINT_RESUME},
55 {ID_RESTART, IDS_HINT_RESTART},
56 {ID_REFRESH, IDS_HINT_REFRESH},
57 {ID_EDIT, IDS_HINT_EDIT},
58 {ID_CREATE, IDS_HINT_CREATE},
59 {ID_DELETE, IDS_HINT_DELETE},
60 {ID_PROP, IDS_HINT_PROP},
61
62 /* View menu */
63 {ID_VIEW_LARGE, IDS_HINT_LARGE},
64 {ID_VIEW_SMALL, IDS_HINT_SMALL},
65 {ID_VIEW_LIST, IDS_HINT_LIST},
66 {ID_VIEW_DETAILS, IDS_HINT_DETAILS},
67 {ID_VIEW_CUST, IDS_HINT_CUST},
68
69 /* Help Menu */
70 {ID_HELP, IDS_HINT_HELP},
71 {ID_ABOUT, IDS_HINT_ABOUT}
72 };
73 /* system menu hints */
74 static const MENU_HINT SystemMenuHintTable[] = {
75 {SC_RESTORE, IDS_HINT_SYS_RESTORE},
76 {SC_MOVE, IDS_HINT_SYS_MOVE},
77 {SC_SIZE, IDS_HINT_SYS_SIZE},
78 {SC_MINIMIZE, IDS_HINT_SYS_MINIMIZE},
79 {SC_MAXIMIZE, IDS_HINT_SYS_MAXIMIZE},
80 {SC_CLOSE, IDS_HINT_SYS_CLOSE},
81 };
82
83
84 static BOOL
85 MainWndMenuHint(PMAIN_WND_INFO Info,
86 WORD CmdId,
87 const MENU_HINT *HintArray,
88 DWORD HintsCount,
89 UINT DefHintId)
90 {
91 BOOL Found = FALSE;
92 const MENU_HINT *LastHint;
93 UINT HintId = DefHintId;
94
95 LastHint = HintArray + HintsCount;
96 while (HintArray != LastHint)
97 {
98 if (HintArray->CmdId == CmdId)
99 {
100 HintId = HintArray->HintId;
101 Found = TRUE;
102 break;
103 }
104 HintArray++;
105 }
106
107 StatusBarLoadString(Info->hStatus,
108 SB_SIMPLEID,
109 hInstance,
110 HintId);
111
112 return Found;
113 }
114
115
116 static VOID
117 UpdateMainStatusBar(PMAIN_WND_INFO Info)
118 {
119 if (Info->hStatus != NULL)
120 {
121 SendMessage(Info->hStatus,
122 SB_SIMPLE,
123 (WPARAM)Info->bInMenuLoop,
124 0);
125 }
126 }
127
128 VOID
129 UpdateServiceCount(PMAIN_WND_INFO Info)
130 {
131 LPWSTR lpNumServices;
132
133 if (AllocAndLoadString(&lpNumServices,
134 hInstance,
135 IDS_NUM_SERVICES))
136 {
137 WCHAR szNumServices[32];
138
139 INT NumListedServ = ListView_GetItemCount(Info->hListView);
140
141 _snwprintf(szNumServices,
142 31,
143 lpNumServices,
144 NumListedServ);
145
146 SendMessage(Info->hStatus,
147 SB_SETTEXT,
148 0,
149 (LPARAM)szNumServices);
150
151 LocalFree(lpNumServices);
152 }
153 }
154
155
156 VOID SetMenuAndButtonStates(PMAIN_WND_INFO Info)
157 {
158 HMENU hMainMenu;
159 UINT i;
160
161 /* get handle to menu */
162 hMainMenu = GetMenu(Info->hMainWnd);
163
164 /* set all to greyed */
165 for (i = ID_START; i <= ID_RESTART; i++)
166 {
167 EnableMenuItem(hMainMenu, i, MF_GRAYED);
168 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), i, MF_GRAYED);
169 SendMessage(Info->hTool, TB_SETSTATE, i,
170 (LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0));
171 }
172
173 if (Info->SelectedItem != NO_ITEM_SELECTED)
174 {
175 LPQUERY_SERVICE_CONFIG lpServiceConfig = NULL;
176 DWORD Flags, State;
177
178 /* allow user to delete service */
179 if (Info->bIsUserAnAdmin)
180 {
181 SendMessage(Info->hTool, TB_SETSTATE, ID_DELETE,
182 (LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
183 EnableMenuItem(hMainMenu, ID_DELETE, MF_ENABLED);
184 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_DELETE, MF_ENABLED);
185 }
186
187 Flags = Info->pCurrentService->ServiceStatusProcess.dwControlsAccepted;
188 State = Info->pCurrentService->ServiceStatusProcess.dwCurrentState;
189
190 lpServiceConfig = GetServiceConfig(Info->pCurrentService->lpServiceName);
191
192 if (lpServiceConfig && lpServiceConfig->dwStartType != SERVICE_DISABLED)
193 {
194 if (State == SERVICE_STOPPED)
195 {
196 EnableMenuItem(hMainMenu, ID_START, MF_ENABLED);
197 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_START, MF_ENABLED);
198 SendMessage(Info->hTool, TB_SETSTATE, ID_START,
199 (LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
200 }
201
202 if ( (Flags & SERVICE_ACCEPT_STOP) && (State == SERVICE_RUNNING) )
203 {
204 EnableMenuItem(hMainMenu, ID_RESTART, MF_ENABLED);
205 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_RESTART, MF_ENABLED);
206 SendMessage(Info->hTool, TB_SETSTATE, ID_RESTART,
207 (LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
208 }
209 }
210
211 if(lpServiceConfig)
212 HeapFree(GetProcessHeap(), 0, lpServiceConfig);
213
214 if ( (Flags & SERVICE_ACCEPT_STOP) && (State == SERVICE_RUNNING) )
215 {
216 EnableMenuItem(hMainMenu, ID_STOP, MF_ENABLED);
217 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_STOP, MF_ENABLED);
218 SendMessage(Info->hTool, TB_SETSTATE, ID_STOP,
219 (LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
220 }
221
222 if ( (Flags & SERVICE_ACCEPT_PAUSE_CONTINUE) && (State == SERVICE_RUNNING) )
223 {
224 EnableMenuItem(hMainMenu, ID_PAUSE, MF_ENABLED);
225 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_PAUSE, MF_ENABLED);
226 SendMessage(Info->hTool, TB_SETSTATE, ID_PAUSE,
227 (LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
228 }
229 }
230 else
231 {
232 /* disable tools which rely on a selected service */
233 EnableMenuItem(hMainMenu, ID_PROP, MF_GRAYED);
234 EnableMenuItem(hMainMenu, ID_DELETE, MF_GRAYED);
235 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_PROP, MF_GRAYED);
236 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0), ID_DELETE, MF_GRAYED);
237 SendMessage(Info->hTool, TB_SETSTATE, ID_PROP,
238 (LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0));
239 SendMessage(Info->hTool, TB_SETSTATE, ID_DELETE,
240 (LPARAM)MAKELONG(TBSTATE_INDETERMINATE, 0));
241 }
242
243 }
244
245
246 static INT CALLBACK
247 CompareFunc(LPARAM lParam1, LPARAM lParam2, LPARAM lParamSort)
248 {
249 WCHAR Item1[256], Item2[256];
250 LVFINDINFO IndexInfo;
251 INT Index;
252
253 IndexInfo.flags = LVFI_PARAM;
254
255 IndexInfo.lParam = lParam1;
256 Index = ListView_FindItem(hListView, -1, &IndexInfo);
257 ListView_GetItemText(hListView, Index, (INT)lParamSort, Item1, sizeof(Item1) / sizeof(WCHAR));
258
259 IndexInfo.lParam = lParam2;
260 Index = ListView_FindItem(hListView, -1, &IndexInfo);
261 ListView_GetItemText(hListView, Index, (INT)lParamSort, Item2, sizeof(Item2) / sizeof(WCHAR));
262
263 return bSortAscending ? wcscmp(Item1, Item2) : wcscmp(Item2, Item1);
264 }
265
266
267 static BOOL
268 pCreateToolbar(PMAIN_WND_INFO Info)
269 {
270 INT numButtons = sizeof(Buttons) / sizeof(Buttons[0]);
271
272 Info->hTool = CreateWindowEx(0,
273 TOOLBARCLASSNAME,
274 NULL,
275 WS_CHILD | WS_VISIBLE | TBSTYLE_FLAT | TBSTYLE_TOOLTIPS,
276 0, 0, 0, 0,
277 Info->hMainWnd,
278 0,
279 hInstance,
280 NULL);
281 if(Info->hTool != NULL)
282 {
283 HIMAGELIST hImageList;
284
285 SendMessage(Info->hTool,
286 TB_SETEXTENDEDSTYLE,
287 0,
288 TBSTYLE_EX_HIDECLIPPEDBUTTONS);
289
290 SendMessage(Info->hTool,
291 TB_BUTTONSTRUCTSIZE,
292 sizeof(Buttons[0]),
293 0);
294
295 hImageList = InitImageList(IDB_PROP,
296 IDB_RESTART,
297 GetSystemMetrics(SM_CXSMICON),
298 GetSystemMetrics(SM_CXSMICON),
299 IMAGE_BITMAP);
300 if (hImageList == NULL)
301 return FALSE;
302
303 ImageList_Destroy((HIMAGELIST)SendMessage(Info->hTool,
304 TB_SETIMAGELIST,
305 0,
306 (LPARAM)hImageList));
307
308 SendMessage(Info->hTool,
309 TB_ADDBUTTONS,
310 numButtons,
311 (LPARAM)Buttons);
312
313 return TRUE;
314 }
315
316 return FALSE;
317 }
318
319 static BOOL
320 CreateStatusBar(PMAIN_WND_INFO Info)
321 {
322 INT StatWidths[] = {110, -1}; /* widths of status bar */
323
324 Info->hStatus = CreateWindowEx(0,
325 STATUSCLASSNAME,
326 NULL,
327 WS_CHILD | WS_VISIBLE | SBARS_SIZEGRIP,
328 0, 0, 0, 0,
329 Info->hMainWnd,
330 (HMENU)IDC_STATUSBAR,
331 hInstance,
332 NULL);
333 if(Info->hStatus == NULL)
334 return FALSE;
335
336 SendMessage(Info->hStatus,
337 SB_SETPARTS,
338 sizeof(StatWidths) / sizeof(INT),
339 (LPARAM)StatWidths);
340
341 return TRUE;
342 }
343
344
345 static BOOL
346 InitMainWnd(PMAIN_WND_INFO Info)
347 {
348 if (!pCreateToolbar(Info))
349 {
350 DisplayString(L"error creating toolbar");
351 return FALSE;
352 }
353
354 if (!CreateListView(Info))
355 {
356 DisplayString(L"error creating list view");
357 return FALSE;
358 }
359
360 if (!CreateStatusBar(Info))
361 DisplayString(L"error creating status bar");
362
363 /* Create Popup Menu */
364 Info->hShortcutMenu = LoadMenu(hInstance,
365 MAKEINTRESOURCE(IDR_POPUP));
366
367 Info->bIsUserAnAdmin = TRUE;// IsUserAnAdmin();
368 if (Info->bIsUserAnAdmin)
369 {
370 HMENU hMainMenu = GetMenu(Info->hMainWnd);
371
372 SendMessage(Info->hTool,
373 TB_SETSTATE,
374 ID_CREATE,
375 (LPARAM)MAKELONG(TBSTATE_ENABLED, 0));
376 if (hMainMenu)
377 {
378 EnableMenuItem(hMainMenu,
379 ID_CREATE,
380 MF_ENABLED);
381 }
382 EnableMenuItem(GetSubMenu(Info->hShortcutMenu, 0),
383 ID_CREATE,
384 MF_ENABLED);
385 }
386
387 return TRUE;
388 }
389
390
391 static VOID
392 MainWndCommand(PMAIN_WND_INFO Info,
393 WORD CmdId,
394 HWND hControl)
395 {
396 UNREFERENCED_PARAMETER(hControl);
397
398 switch (CmdId)
399 {
400 case ID_PROP:
401 {
402 if (Info->SelectedItem != NO_ITEM_SELECTED)
403 {
404 Info->bDlgOpen = TRUE;
405 OpenPropSheet(Info);
406 Info->bDlgOpen = FALSE;
407 SetMenuAndButtonStates(Info);
408 }
409 }
410 break;
411
412 case ID_REFRESH:
413 {
414 RefreshServiceList(Info);
415 Info->SelectedItem = NO_ITEM_SELECTED;
416
417 /* disable menus and buttons */
418 SetMenuAndButtonStates(Info);
419
420 /* clear the service in the status bar */
421 SendMessage(Info->hStatus,
422 SB_SETTEXT,
423 1,
424 L'\0');
425 }
426 break;
427
428 case ID_EXPORT:
429 {
430 ExportFile(Info);
431 SetFocus(Info->hListView);
432 }
433 break;
434
435 case ID_CREATE:
436 {
437 INT ret;
438
439 ret = DialogBoxParam(hInstance,
440 MAKEINTRESOURCE(IDD_DLG_CREATE),
441 Info->hMainWnd,
442 CreateDialogProc,
443 (LPARAM)Info);
444 if (ret == IDOK)
445 RefreshServiceList(Info);
446
447 SetFocus(Info->hListView);
448 }
449 break;
450
451 case ID_DELETE:
452 {
453 if (Info->pCurrentService->ServiceStatusProcess.dwCurrentState != SERVICE_RUNNING)
454 {
455 DialogBoxParam(hInstance,
456 MAKEINTRESOURCE(IDD_DLG_DELETE),
457 Info->hMainWnd,
458 DeleteDialogProc,
459 (LPARAM)Info);
460 }
461 else
462 {
463 WCHAR Buf[60];
464 LoadString(hInstance,
465 IDS_DELETE_STOP,
466 Buf,
467 sizeof(Buf) / sizeof(WCHAR));
468 DisplayString(Buf);
469 }
470
471 SetFocus(Info->hListView);
472
473 }
474 break;
475
476 case ID_START:
477 {
478 RunActionWithProgress(Info->hMainWnd,
479 Info->pCurrentService->lpServiceName,
480 Info->pCurrentService->lpDisplayName,
481 ACTION_START,
482 NULL); //FIXME: Add start params
483
484 UpdateServiceStatus(Info->pCurrentService);
485 ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
486 SetMenuAndButtonStates(Info);
487 SetFocus(Info->hListView);
488
489 }
490 break;
491
492 case ID_STOP:
493 RunActionWithProgress(Info->hMainWnd,
494 Info->pCurrentService->lpServiceName,
495 Info->pCurrentService->lpDisplayName,
496 ACTION_STOP,
497 NULL);
498
499 UpdateServiceStatus(Info->pCurrentService);
500 ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
501 SetMenuAndButtonStates(Info);
502 SetFocus(Info->hListView);
503
504 break;
505
506 case ID_PAUSE:
507 RunActionWithProgress(Info->hMainWnd,
508 Info->pCurrentService->lpServiceName,
509 Info->pCurrentService->lpDisplayName,
510 ACTION_PAUSE,
511 NULL);
512
513 UpdateServiceStatus(Info->pCurrentService);
514 ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
515 SetMenuAndButtonStates(Info);
516 SetFocus(Info->hListView);
517 break;
518
519 case ID_RESUME:
520 RunActionWithProgress(Info->hMainWnd,
521 Info->pCurrentService->lpServiceName,
522 Info->pCurrentService->lpDisplayName,
523 ACTION_RESUME,
524 NULL);
525
526 UpdateServiceStatus(Info->pCurrentService);
527 ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
528 SetMenuAndButtonStates(Info);
529 SetFocus(Info->hListView);
530 break;
531
532 case ID_RESTART:
533 RunActionWithProgress(Info->hMainWnd,
534 Info->pCurrentService->lpServiceName,
535 Info->pCurrentService->lpDisplayName,
536 ACTION_RESTART,
537 NULL);
538
539 UpdateServiceStatus(Info->pCurrentService);
540 ChangeListViewText(Info, Info->pCurrentService, LVSTATUS);
541 SetMenuAndButtonStates(Info);
542 SetFocus(Info->hListView);
543 break;
544
545 case ID_HELP:
546 MessageBoxW(NULL,
547 L"Help is not yet implemented\n",
548 L"Note!",
549 MB_OK | MB_ICONINFORMATION);
550 SetFocus(Info->hListView);
551 break;
552
553 case ID_EXIT:
554 PostMessage(Info->hMainWnd,
555 WM_CLOSE,
556 0,
557 0);
558 break;
559
560 case ID_VIEW_LARGE:
561 SetListViewStyle(Info->hListView,
562 LVS_ICON);
563 CheckMenuRadioItem(GetMenu(Info->hMainWnd),
564 ID_VIEW_LARGE,
565 ID_VIEW_DETAILS,
566 ID_VIEW_LARGE,
567 MF_BYCOMMAND);
568 break;
569
570 case ID_VIEW_SMALL:
571 SetListViewStyle(Info->hListView,
572 LVS_SMALLICON);
573 CheckMenuRadioItem(GetMenu(Info->hMainWnd),
574 ID_VIEW_LARGE,
575 ID_VIEW_DETAILS,
576 ID_VIEW_SMALL,
577 MF_BYCOMMAND);
578 break;
579
580 case ID_VIEW_LIST:
581 SetListViewStyle(Info->hListView,
582 LVS_LIST);
583 CheckMenuRadioItem(GetMenu(Info->hMainWnd),
584 ID_VIEW_LARGE,
585 ID_VIEW_DETAILS,
586 ID_VIEW_LIST,
587 MF_BYCOMMAND);
588 break;
589
590 case ID_VIEW_DETAILS:
591 SetListViewStyle(Info->hListView,
592 LVS_REPORT);
593 CheckMenuRadioItem(GetMenu(Info->hMainWnd),
594 ID_VIEW_LARGE,
595 ID_VIEW_DETAILS,
596 ID_VIEW_DETAILS,
597 MF_BYCOMMAND);
598 break;
599
600 case ID_VIEW_CUST:
601 break;
602
603 case ID_ABOUT:
604 DialogBox(hInstance,
605 MAKEINTRESOURCE(IDD_ABOUTBOX),
606 Info->hMainWnd,
607 AboutDialogProc);
608 SetFocus(Info->hListView);
609 break;
610
611 }
612 }
613
614
615 static VOID CALLBACK
616 MainWndResize(PMAIN_WND_INFO Info,
617 WORD cx,
618 WORD cy)
619 {
620 RECT rcClient, rcTool, rcStatus;
621 int lvHeight, iToolHeight, iStatusHeight;
622
623 /* Size toolbar and get height */
624 SendMessage(Info->hTool, TB_AUTOSIZE, 0, 0);
625 GetWindowRect(Info->hTool, &rcTool);
626 iToolHeight = rcTool.bottom - rcTool.top;
627
628 /* Size status bar and get height */
629 SendMessage(Info->hStatus, WM_SIZE, 0, 0);
630 GetWindowRect(Info->hStatus, &rcStatus);
631 iStatusHeight = rcStatus.bottom - rcStatus.top;
632
633 /* Calculate remaining height and size list view */
634 GetClientRect(Info->hMainWnd, &rcClient);
635 lvHeight = rcClient.bottom - iToolHeight - iStatusHeight;
636 SetWindowPos(Info->hListView,
637 NULL,
638 0,
639 iToolHeight,
640 rcClient.right,
641 lvHeight,
642 SWP_NOZORDER);
643 }
644
645
646 static LRESULT CALLBACK
647 MainWndProc(HWND hwnd,
648 UINT msg,
649 WPARAM wParam,
650 LPARAM lParam)
651 {
652 PMAIN_WND_INFO Info;
653 LRESULT Ret = 0;
654
655 /* Get the window context */
656 Info = (PMAIN_WND_INFO)GetWindowLongPtr(hwnd,
657 GWLP_USERDATA);
658 if (Info == NULL && msg != WM_CREATE)
659 {
660 goto HandleDefaultMessage;
661 }
662
663 switch(msg)
664 {
665 case WM_CREATE:
666 {
667 Info = (PMAIN_WND_INFO)(((LPCREATESTRUCT)lParam)->lpCreateParams);
668
669 /* Initialize the main window context */
670 Info->hMainWnd = hwnd;
671 Info->SelectedItem = NO_ITEM_SELECTED;
672
673 SetWindowLongPtr(hwnd,
674 GWLP_USERDATA,
675 (LONG_PTR)Info);
676
677 if (!InitMainWnd(Info))
678 return -1;
679
680 /* Fill the list-view before showing the main window */
681 RefreshServiceList(Info);
682
683 /* Show the window */
684 ShowWindow(hwnd,
685 Info->nCmdShow);
686
687 SetFocus(Info->hListView);
688 }
689 break;
690
691 case WM_SIZE:
692 {
693 MainWndResize(Info,
694 LOWORD(lParam),
695 HIWORD(lParam));
696 }
697 break;
698
699 case WM_NOTIFY:
700 {
701 LPNMHDR pnmhdr = (LPNMHDR)lParam;
702
703 switch (pnmhdr->code)
704 {
705 case NM_DBLCLK:
706 {
707 POINT pt;
708 RECT rect;
709
710 GetCursorPos(&pt);
711 GetWindowRect(Info->hListView, &rect);
712
713 if (PtInRect(&rect, pt))
714 {
715 SendMessage(hwnd,
716 WM_COMMAND,
717 //ID_PROP,
718 MAKEWPARAM((WORD)ID_PROP, (WORD)0),
719 0);
720 }
721
722 //OpenPropSheet(Info);
723 }
724 break;
725
726 case NM_RETURN:
727 {
728 SendMessage(hwnd,
729 WM_COMMAND,
730 //ID_PROP,
731 MAKEWPARAM((WORD)ID_PROP, (WORD)0),
732 0);
733 }
734 break;
735
736 case LVN_COLUMNCLICK:
737 {
738 static int iLastSortColumn = 0;
739 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
740
741 /* get new sort parameters */
742 if (pnmv->iSubItem == iLastSortColumn)
743 bSortAscending = !bSortAscending;
744 else
745 {
746 iLastSortColumn = pnmv->iSubItem;
747 bSortAscending = TRUE;
748 }
749
750 /* store a copy to have access from callback */
751 hListView = Info->hListView;
752 (void)ListView_SortItems(Info->hListView,
753 CompareFunc,
754 pnmv->iSubItem);
755 }
756 break;
757 case LVN_ITEMCHANGED:
758 {
759 LPNMLISTVIEW pnmv = (LPNMLISTVIEW) lParam;
760
761 if (pnmv->uNewState != 0)
762 {
763 ListViewSelectionChanged(Info, pnmv);
764 SetMenuAndButtonStates(Info);
765 }
766 }
767 break;
768
769 case TTN_GETDISPINFO:
770 {
771 LPTOOLTIPTEXT lpttt;
772 UINT idButton;
773
774 lpttt = (LPTOOLTIPTEXT)lParam;
775
776 /* Specify the resource identifier of the descriptive
777 * text for the given button. */
778 idButton = (UINT)lpttt->hdr.idFrom;
779 switch (idButton)
780 {
781 case ID_PROP:
782 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_PROP);
783 break;
784
785 case ID_REFRESH:
786 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_REFRESH);
787 break;
788
789 case ID_EXPORT:
790 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_EXPORT);
791 break;
792
793 case ID_CREATE:
794 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_CREATE);
795 break;
796
797 case ID_DELETE:
798 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_DELETE);
799 break;
800
801 case ID_START:
802 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_START);
803 break;
804
805 case ID_STOP:
806 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_STOP);
807 break;
808
809 case ID_PAUSE:
810 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_PAUSE);
811 break;
812
813 case ID_RESTART:
814 lpttt->lpszText = MAKEINTRESOURCE(IDS_TOOLTIP_RESTART);
815 break;
816 }
817 }
818 break;
819 }
820 }
821 break;
822
823 case WM_CONTEXTMENU:
824 {
825 POINT pt;
826 RECT lvRect;
827
828 INT xPos = GET_X_LPARAM(lParam);
829 INT yPos = GET_Y_LPARAM(lParam);
830
831 GetCursorPos(&pt);
832
833 /* display popup when cursor is in the list view */
834 GetWindowRect(Info->hListView, &lvRect);
835 if (PtInRect(&lvRect, pt))
836 {
837 TrackPopupMenuEx(GetSubMenu(Info->hShortcutMenu, 0),
838 TPM_RIGHTBUTTON,
839 xPos,
840 yPos,
841 Info->hMainWnd,
842 NULL);
843 }
844 }
845 break;
846
847 case WM_COMMAND:
848 {
849 MainWndCommand(Info,
850 LOWORD(wParam),
851 (HWND)lParam);
852 goto HandleDefaultMessage;
853 }
854
855 case WM_MENUSELECT:
856 {
857 if (Info->hStatus != NULL)
858 {
859 if (!MainWndMenuHint(Info,
860 LOWORD(wParam),
861 MainMenuHintTable,
862 sizeof(MainMenuHintTable) / sizeof(MainMenuHintTable[0]),
863 IDS_HINT_BLANK))
864 {
865 MainWndMenuHint(Info,
866 LOWORD(wParam),
867 SystemMenuHintTable,
868 sizeof(SystemMenuHintTable) / sizeof(SystemMenuHintTable[0]),
869 IDS_HINT_BLANK);
870 }
871 }
872 }
873 break;
874
875 case WM_ENTERMENULOOP:
876 {
877 Info->bInMenuLoop = TRUE;
878 UpdateMainStatusBar(Info);
879 break;
880 }
881
882 case WM_EXITMENULOOP:
883 {
884 Info->bInMenuLoop = FALSE;
885 UpdateMainStatusBar(Info);
886 break;
887 }
888
889 case WM_CLOSE:
890 {
891 HeapFree(ProcessHeap,
892 0,
893 Info->pAllServices);
894
895 DestroyMenu(Info->hShortcutMenu);
896 DestroyWindow(hwnd);
897 }
898 break;
899
900 case WM_DESTROY:
901 {
902 HeapFree(ProcessHeap,
903 0,
904 Info);
905 SetWindowLongPtr(hwnd,
906 GWLP_USERDATA,
907 0);
908
909 PostQuitMessage(0);
910 }
911 break;
912
913 default:
914 {
915 HandleDefaultMessage:
916
917 Ret = DefWindowProc(hwnd,
918 msg,
919 wParam,
920 lParam);
921 }
922 break;
923 }
924
925 return Ret;
926 }
927
928
929
930 HWND
931 CreateMainWindow(LPCTSTR lpCaption,
932 int nCmdShow)
933 {
934 PMAIN_WND_INFO Info;
935 HWND hMainWnd = NULL;
936
937 Info = (MAIN_WND_INFO*) HeapAlloc(ProcessHeap,
938 HEAP_ZERO_MEMORY,
939 sizeof(MAIN_WND_INFO));
940
941 if (Info != NULL)
942 {
943 Info->nCmdShow = nCmdShow;
944
945 hMainWnd = CreateWindowEx(WS_EX_WINDOWEDGE,
946 szMainWndClass,
947 lpCaption,
948 WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
949 CW_USEDEFAULT,
950 CW_USEDEFAULT,
951 680,
952 450,
953 NULL,
954 NULL,
955 hInstance,
956 Info);
957 if (hMainWnd == NULL)
958 {
959 //int ret;
960 //ret = GetLastError();
961 GetError();
962 HeapFree(ProcessHeap,
963 0,
964 Info);
965 }
966 }
967
968 return hMainWnd;
969 }
970
971 BOOL
972 InitMainWindowImpl(VOID)
973 {
974 WNDCLASSEX wc = {0};
975
976 wc.cbSize = sizeof(WNDCLASSEX);
977 wc.lpfnWndProc = MainWndProc;
978 wc.hInstance = hInstance;
979 wc.hIcon = LoadIcon(hInstance,
980 MAKEINTRESOURCE(IDI_SM_ICON));
981 wc.hCursor = LoadCursor(NULL,
982 IDC_ARROW);
983 wc.hbrBackground = (HBRUSH)(COLOR_BTNFACE + 1);
984 wc.lpszMenuName = MAKEINTRESOURCE(IDR_MAINMENU);
985 wc.lpszClassName = szMainWndClass;
986 wc.hIconSm = (HICON)LoadImage(hInstance,
987 MAKEINTRESOURCE(IDI_SM_ICON),
988 IMAGE_ICON,
989 16,
990 16,
991 LR_SHARED);
992
993 return RegisterClassEx(&wc) != (ATOM)0;
994 }
995
996
997 VOID
998 UninitMainWindowImpl(VOID)
999 {
1000 UnregisterClass(szMainWndClass,
1001 hInstance);
1002 }