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