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-2007 Ged Murphy <gedmurphy@reactos.org>
12 static const TCHAR szMainWndClass
[] = TEXT("ServManWndClass");
14 BOOL bSortAscending
= TRUE
;
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 */
24 /* Note: First item for a seperator is its width in pixels */
25 {15, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0}, 0, 0}, /* separator */
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 */
30 {15, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0}, 0, 0}, /* separator */
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 */
40 static const MENU_HINT MainMenuHintTable
[] = {
42 {ID_EXPORT
, IDS_HINT_EXPORT
},
43 {ID_EXIT
, IDS_HINT_EXIT
},
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
},
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
},
66 {ID_HELP
, IDS_HINT_HELP
},
67 {ID_ABOUT
, IDS_HINT_ABOUT
}
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
},
81 MainWndMenuHint(PMAIN_WND_INFO Info
,
83 const MENU_HINT
*HintArray
,
88 const MENU_HINT
*LastHint
;
89 UINT HintId
= DefHintId
;
91 LastHint
= HintArray
+ HintsCount
;
92 while (HintArray
!= LastHint
)
94 if (HintArray
->CmdId
== CmdId
)
96 HintId
= HintArray
->HintId
;
103 StatusBarLoadString(Info
->hStatus
,
113 UpdateMainStatusBar(PMAIN_WND_INFO Info
)
115 if (Info
->hStatus
!= NULL
)
117 SendMessage(Info
->hStatus
,
119 (WPARAM
)Info
->bInMenuLoop
,
125 UpdateServiceCount(PMAIN_WND_INFO Info
)
127 LPTSTR lpNumServices
;
129 if (AllocAndLoadString(&lpNumServices
,
133 TCHAR szNumServices
[32];
135 INT NumListedServ
= ListView_GetItemCount(Info
->hListView
);
137 _sntprintf(szNumServices
,
142 SendMessage(Info
->hStatus
,
145 (LPARAM
)szNumServices
);
147 LocalFree(lpNumServices
);
152 VOID
SetMenuAndButtonStates(PMAIN_WND_INFO Info
)
157 /* get handle to menu */
158 hMainMenu
= GetMenu(Info
->hMainWnd
);
160 /* set all to greyed */
161 for (i
= ID_START
; i
<= ID_RESTART
; i
++)
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));
169 if (Info
->SelectedItem
!= NO_ITEM_SELECTED
)
171 LPQUERY_SERVICE_CONFIG lpServiceConfig
= NULL
;
174 /* allow user to delete service */
175 if (Info
->bIsUserAnAdmin
)
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
);
183 Flags
= Info
->pCurrentService
->ServiceStatusProcess
.dwControlsAccepted
;
184 State
= Info
->pCurrentService
->ServiceStatusProcess
.dwCurrentState
;
186 lpServiceConfig
= GetServiceConfig(Info
->pCurrentService
->lpServiceName
);
188 if (lpServiceConfig
&& lpServiceConfig
->dwStartType
!= SERVICE_DISABLED
)
190 if (State
== SERVICE_STOPPED
)
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));
198 if ( (Flags
& SERVICE_ACCEPT_STOP
) && (State
== SERVICE_RUNNING
) )
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));
206 HeapFree(GetProcessHeap(), 0, lpServiceConfig
);
209 if ( (Flags
& SERVICE_ACCEPT_STOP
) && (State
== SERVICE_RUNNING
) )
211 EnableMenuItem(hMainMenu
, ID_STOP
, MF_ENABLED
);
212 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0), ID_STOP
, MF_ENABLED
);
213 SendMessage(Info
->hTool
, TB_SETSTATE
, ID_STOP
,
214 (LPARAM
)MAKELONG(TBSTATE_ENABLED
, 0));
217 if ( (Flags
& SERVICE_ACCEPT_PAUSE_CONTINUE
) && (State
== SERVICE_RUNNING
) )
219 EnableMenuItem(hMainMenu
, ID_PAUSE
, MF_ENABLED
);
220 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0), ID_PAUSE
, MF_ENABLED
);
221 SendMessage(Info
->hTool
, TB_SETSTATE
, ID_PAUSE
,
222 (LPARAM
)MAKELONG(TBSTATE_ENABLED
, 0));
227 /* disable tools which rely on a selected service */
228 EnableMenuItem(hMainMenu
, ID_PROP
, MF_GRAYED
);
229 EnableMenuItem(hMainMenu
, ID_DELETE
, MF_GRAYED
);
230 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0), ID_PROP
, MF_GRAYED
);
231 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0), ID_DELETE
, MF_GRAYED
);
232 SendMessage(Info
->hTool
, TB_SETSTATE
, ID_PROP
,
233 (LPARAM
)MAKELONG(TBSTATE_INDETERMINATE
, 0));
234 SendMessage(Info
->hTool
, TB_SETSTATE
, ID_DELETE
,
235 (LPARAM
)MAKELONG(TBSTATE_INDETERMINATE
, 0));
242 CompareFunc(LPARAM lParam1
, LPARAM lParam2
, LPARAM lParamSort
)
244 ENUM_SERVICE_STATUS_PROCESS
*Param1
;
245 ENUM_SERVICE_STATUS_PROCESS
*Param2
;
246 // INT iSubItem = (LPARAM)lParamSort;
248 if (bSortAscending
) {
249 Param1
= (ENUM_SERVICE_STATUS_PROCESS
*)lParam1
;
250 Param2
= (ENUM_SERVICE_STATUS_PROCESS
*)lParam2
;
254 Param1
= (ENUM_SERVICE_STATUS_PROCESS
*)lParam2
;
255 Param2
= (ENUM_SERVICE_STATUS_PROCESS
*)lParam1
;
257 return _tcsicmp(Param1
->lpDisplayName
, Param2
->lpDisplayName
);
262 pCreateToolbar(PMAIN_WND_INFO Info
)
264 INT numButtons
= sizeof(Buttons
) / sizeof(Buttons
[0]);
266 Info
->hTool
= CreateWindowEx(0,
269 WS_CHILD
| WS_VISIBLE
| TBSTYLE_FLAT
| TBSTYLE_TOOLTIPS
,
275 if(Info
->hTool
!= NULL
)
277 HIMAGELIST hImageList
;
279 SendMessage(Info
->hTool
,
282 TBSTYLE_EX_HIDECLIPPEDBUTTONS
);
284 SendMessage(Info
->hTool
,
289 hImageList
= InitImageList(IDB_PROP
,
291 GetSystemMetrics(SM_CXSMICON
),
292 GetSystemMetrics(SM_CXSMICON
),
294 if (hImageList
== NULL
)
297 ImageList_Destroy((HIMAGELIST
)SendMessage(Info
->hTool
,
300 (LPARAM
)hImageList
));
302 SendMessage(Info
->hTool
,
314 CreateStatusBar(PMAIN_WND_INFO Info
)
316 INT StatWidths
[] = {110, -1}; /* widths of status bar */
318 Info
->hStatus
= CreateWindowEx(0,
321 WS_CHILD
| WS_VISIBLE
| SBARS_SIZEGRIP
,
324 (HMENU
)IDC_STATUSBAR
,
327 if(Info
->hStatus
== NULL
)
330 SendMessage(Info
->hStatus
,
332 sizeof(StatWidths
) / sizeof(INT
),
340 InitMainWnd(PMAIN_WND_INFO Info
)
342 if (!pCreateToolbar(Info
))
344 DisplayString(_T("error creating toolbar"));
348 if (!CreateListView(Info
))
350 DisplayString(_T("error creating list view"));
354 if (!CreateStatusBar(Info
))
355 DisplayString(_T("error creating status bar"));
357 /* Create Popup Menu */
358 Info
->hShortcutMenu
= LoadMenu(hInstance
,
359 MAKEINTRESOURCE(IDR_POPUP
));
361 Info
->bIsUserAnAdmin
= IsUserAnAdmin();
362 if (Info
->bIsUserAnAdmin
)
364 HMENU hMainMenu
= GetMenu(Info
->hMainWnd
);
366 SendMessage(Info
->hTool
,
369 (LPARAM
)MAKELONG(TBSTATE_ENABLED
, 0));
372 EnableMenuItem(hMainMenu
,
376 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0),
386 MainWndCommand(PMAIN_WND_INFO Info
,
390 UNREFERENCED_PARAMETER(hControl
);
396 if (Info
->SelectedItem
!= NO_ITEM_SELECTED
)
398 Info
->bDlgOpen
= TRUE
;
400 Info
->bDlgOpen
= FALSE
;
401 SetMenuAndButtonStates(Info
);
408 RefreshServiceList(Info
);
409 Info
->SelectedItem
= NO_ITEM_SELECTED
;
411 /* disable menus and buttons */
412 SetMenuAndButtonStates(Info
);
414 /* clear the service in the status bar */
415 SendMessage(Info
->hStatus
,
425 SetFocus(Info
->hListView
);
433 ret
= DialogBoxParam(hInstance
,
434 MAKEINTRESOURCE(IDD_DLG_CREATE
),
439 RefreshServiceList(Info
);
441 SetFocus(Info
->hListView
);
447 if (Info
->pCurrentService
->ServiceStatusProcess
.dwCurrentState
!= SERVICE_RUNNING
)
449 DialogBoxParam(hInstance
,
450 MAKEINTRESOURCE(IDD_DLG_DELETE
),
458 LoadString(hInstance
,
461 sizeof(Buf
) / sizeof(TCHAR
));
465 SetFocus(Info
->hListView
);
472 if (DoStart(Info
, NULL
))
474 UpdateServiceStatus(Info
->pCurrentService
);
475 ChangeListViewText(Info
, Info
->pCurrentService
, LVSTATUS
);
476 SetMenuAndButtonStates(Info
);
477 SetFocus(Info
->hListView
);
485 UpdateServiceStatus(Info
->pCurrentService
);
486 ChangeListViewText(Info
, Info
->pCurrentService
, LVSTATUS
);
487 SetMenuAndButtonStates(Info
);
488 SetFocus(Info
->hListView
);
504 UpdateServiceStatus(Info
->pCurrentService
);
505 ChangeListViewText(Info
, Info
->pCurrentService
, LVSTATUS
);
506 SetMenuAndButtonStates(Info
);
507 SetFocus(Info
->hListView
);
513 _T("Help is not yet implemented\n"),
515 MB_OK
| MB_ICONINFORMATION
);
516 SetFocus(Info
->hListView
);
520 PostMessage(Info
->hMainWnd
,
527 SetListViewStyle(Info
->hListView
,
529 CheckMenuRadioItem(GetMenu(Info
->hMainWnd
),
537 SetListViewStyle(Info
->hListView
,
539 CheckMenuRadioItem(GetMenu(Info
->hMainWnd
),
547 SetListViewStyle(Info
->hListView
,
549 CheckMenuRadioItem(GetMenu(Info
->hMainWnd
),
556 case ID_VIEW_DETAILS
:
557 SetListViewStyle(Info
->hListView
,
559 CheckMenuRadioItem(GetMenu(Info
->hMainWnd
),
571 MAKEINTRESOURCE(IDD_ABOUTBOX
),
574 SetFocus(Info
->hListView
);
582 MainWndResize(PMAIN_WND_INFO Info
,
586 RECT rcClient
, rcTool
, rcStatus
;
587 int lvHeight
, iToolHeight
, iStatusHeight
;
589 /* Size toolbar and get height */
590 SendMessage(Info
->hTool
, TB_AUTOSIZE
, 0, 0);
591 GetWindowRect(Info
->hTool
, &rcTool
);
592 iToolHeight
= rcTool
.bottom
- rcTool
.top
;
594 /* Size status bar and get height */
595 SendMessage(Info
->hStatus
, WM_SIZE
, 0, 0);
596 GetWindowRect(Info
->hStatus
, &rcStatus
);
597 iStatusHeight
= rcStatus
.bottom
- rcStatus
.top
;
599 /* Calculate remaining height and size list view */
600 GetClientRect(Info
->hMainWnd
, &rcClient
);
601 lvHeight
= rcClient
.bottom
- iToolHeight
- iStatusHeight
;
602 SetWindowPos(Info
->hListView
,
612 static LRESULT CALLBACK
613 MainWndProc(HWND hwnd
,
621 /* Get the window context */
622 Info
= (PMAIN_WND_INFO
)GetWindowLongPtr(hwnd
,
624 if (Info
== NULL
&& msg
!= WM_CREATE
)
626 goto HandleDefaultMessage
;
633 Info
= (PMAIN_WND_INFO
)(((LPCREATESTRUCT
)lParam
)->lpCreateParams
);
635 /* Initialize the main window context */
636 Info
->hMainWnd
= hwnd
;
637 Info
->SelectedItem
= NO_ITEM_SELECTED
;
639 SetWindowLongPtr(hwnd
,
643 if (!InitMainWnd(Info
))
646 /* Fill the list-view before showing the main window */
647 RefreshServiceList(Info
);
649 /* Show the window */
653 SetFocus(Info
->hListView
);
667 LPNMHDR pnmhdr
= (LPNMHDR
)lParam
;
669 switch (pnmhdr
->code
)
677 GetWindowRect(Info
->hListView
, &rect
);
679 if (PtInRect(&rect
, pt
))
684 MAKEWPARAM((WORD
)ID_PROP
, (WORD
)0),
688 //OpenPropSheet(Info);
697 MAKEWPARAM((WORD
)ID_PROP
, (WORD
)0),
702 case LVN_COLUMNCLICK
:
704 LPNMLISTVIEW pnmv
= (LPNMLISTVIEW
) lParam
;
706 (void)ListView_SortItems(Info
->hListView
,
709 bSortAscending
= !bSortAscending
;
713 case LVN_ITEMCHANGED
:
715 LPNMLISTVIEW pnmv
= (LPNMLISTVIEW
) lParam
;
717 if (pnmv
->uNewState
!= 0)
719 ListViewSelectionChanged(Info
, pnmv
);
720 SetMenuAndButtonStates(Info
);
725 case TTN_GETDISPINFO
:
730 lpttt
= (LPTOOLTIPTEXT
)lParam
;
732 /* Specify the resource identifier of the descriptive
733 * text for the given button. */
734 idButton
= (UINT
)lpttt
->hdr
.idFrom
;
738 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_PROP
);
742 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_REFRESH
);
746 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_EXPORT
);
750 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_CREATE
);
754 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_DELETE
);
758 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_START
);
762 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_STOP
);
766 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_PAUSE
);
770 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_RESTART
);
784 INT xPos
= GET_X_LPARAM(lParam
);
785 INT yPos
= GET_Y_LPARAM(lParam
);
789 /* display popup when cursor is in the list view */
790 GetWindowRect(Info
->hListView
, &lvRect
);
791 if (PtInRect(&lvRect
, pt
))
793 TrackPopupMenuEx(GetSubMenu(Info
->hShortcutMenu
, 0),
808 goto HandleDefaultMessage
;
813 if (Info
->hStatus
!= NULL
)
815 if (!MainWndMenuHint(Info
,
818 sizeof(MainMenuHintTable
) / sizeof(MainMenuHintTable
[0]),
821 MainWndMenuHint(Info
,
824 sizeof(SystemMenuHintTable
) / sizeof(SystemMenuHintTable
[0]),
831 case WM_ENTERMENULOOP
:
833 Info
->bInMenuLoop
= TRUE
;
834 UpdateMainStatusBar(Info
);
838 case WM_EXITMENULOOP
:
840 Info
->bInMenuLoop
= FALSE
;
841 UpdateMainStatusBar(Info
);
847 HeapFree(ProcessHeap
,
851 DestroyMenu(Info
->hShortcutMenu
);
858 HeapFree(ProcessHeap
,
861 SetWindowLongPtr(hwnd
,
871 HandleDefaultMessage
:
873 Ret
= DefWindowProc(hwnd
,
887 CreateMainWindow(LPCTSTR lpCaption
,
891 HWND hMainWnd
= NULL
;
893 Info
= (MAIN_WND_INFO
*) HeapAlloc(ProcessHeap
,
895 sizeof(MAIN_WND_INFO
));
899 Info
->nCmdShow
= nCmdShow
;
901 hMainWnd
= CreateWindowEx(WS_EX_WINDOWEDGE
,
904 WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
,
913 if (hMainWnd
== NULL
)
916 //ret = GetLastError();
918 HeapFree(ProcessHeap
,
928 InitMainWindowImpl(VOID
)
932 wc
.cbSize
= sizeof(WNDCLASSEX
);
933 wc
.lpfnWndProc
= MainWndProc
;
934 wc
.hInstance
= hInstance
;
935 wc
.hIcon
= LoadIcon(hInstance
,
936 MAKEINTRESOURCE(IDI_SM_ICON
));
937 wc
.hCursor
= LoadCursor(NULL
,
939 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
940 wc
.lpszMenuName
= MAKEINTRESOURCE(IDR_MAINMENU
);
941 wc
.lpszClassName
= szMainWndClass
;
942 wc
.hIconSm
= (HICON
)LoadImage(hInstance
,
943 MAKEINTRESOURCE(IDI_SM_ICON
),
949 return RegisterClassEx(&wc
) != (ATOM
)0;
954 UninitMainWindowImpl(VOID
)
956 UnregisterClass(szMainWndClass
,