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>
14 static const TCHAR szMainWndClass
[] = TEXT("ServManWndClass");
16 BOOL bSortAscending
= TRUE
;
20 static const TBBUTTON Buttons
[] =
21 { /* iBitmap, idCommand, fsState, fsStyle, bReserved[2], dwData, iString */
22 {TBICON_PROP
, ID_PROP
, TBSTATE_INDETERMINATE
, BTNS_BUTTON
, {0}, 0, 0}, /* properties */
23 {TBICON_REFRESH
, ID_REFRESH
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0}, /* refresh */
24 {TBICON_EXPORT
, ID_EXPORT
, TBSTATE_ENABLED
, BTNS_BUTTON
, {0}, 0, 0}, /* export */
26 /* Note: First item for a seperator is its width in pixels */
27 {15, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0}, 0, 0}, /* separator */
29 {TBICON_CREATE
, ID_CREATE
, TBSTATE_INDETERMINATE
, BTNS_BUTTON
, {0}, 0, 0 }, /* create */
30 {TBICON_DELETE
, ID_DELETE
, TBSTATE_INDETERMINATE
, BTNS_BUTTON
, {0}, 0, 0 }, /* delete */
32 {15, 0, TBSTATE_ENABLED
, BTNS_SEP
, {0}, 0, 0}, /* separator */
34 {TBICON_START
, ID_START
, TBSTATE_INDETERMINATE
, BTNS_BUTTON
, {0}, 0, 0 }, /* start */
35 {TBICON_STOP
, ID_STOP
, TBSTATE_INDETERMINATE
, BTNS_BUTTON
, {0}, 0, 0 }, /* stop */
36 {TBICON_PAUSE
, ID_PAUSE
, TBSTATE_INDETERMINATE
, BTNS_BUTTON
, {0}, 0, 0 }, /* pause */
37 {TBICON_RESTART
, ID_RESTART
, TBSTATE_INDETERMINATE
, BTNS_BUTTON
, {0}, 0, 0 }, /* restart */
42 static const MENU_HINT MainMenuHintTable
[] = {
44 {ID_EXPORT
, IDS_HINT_EXPORT
},
45 {ID_EXIT
, IDS_HINT_EXIT
},
48 {ID_CONNECT
, IDS_HINT_CONNECT
},
49 {ID_START
, IDS_HINT_START
},
50 {ID_STOP
, IDS_HINT_STOP
},
51 {ID_PAUSE
, IDS_HINT_PAUSE
},
52 {ID_RESUME
, IDS_HINT_RESUME
},
53 {ID_RESTART
, IDS_HINT_RESTART
},
54 {ID_REFRESH
, IDS_HINT_REFRESH
},
55 {ID_EDIT
, IDS_HINT_EDIT
},
56 {ID_CREATE
, IDS_HINT_CREATE
},
57 {ID_DELETE
, IDS_HINT_DELETE
},
58 {ID_PROP
, IDS_HINT_PROP
},
61 {ID_VIEW_LARGE
, IDS_HINT_LARGE
},
62 {ID_VIEW_SMALL
, IDS_HINT_SMALL
},
63 {ID_VIEW_LIST
, IDS_HINT_LIST
},
64 {ID_VIEW_DETAILS
, IDS_HINT_DETAILS
},
65 {ID_VIEW_CUST
, IDS_HINT_CUST
},
68 {ID_HELP
, IDS_HINT_HELP
},
69 {ID_ABOUT
, IDS_HINT_ABOUT
}
71 /* system menu hints */
72 static const MENU_HINT SystemMenuHintTable
[] = {
73 {SC_RESTORE
, IDS_HINT_SYS_RESTORE
},
74 {SC_MOVE
, IDS_HINT_SYS_MOVE
},
75 {SC_SIZE
, IDS_HINT_SYS_SIZE
},
76 {SC_MINIMIZE
, IDS_HINT_SYS_MINIMIZE
},
77 {SC_MAXIMIZE
, IDS_HINT_SYS_MAXIMIZE
},
78 {SC_CLOSE
, IDS_HINT_SYS_CLOSE
},
83 MainWndMenuHint(PMAIN_WND_INFO Info
,
85 const MENU_HINT
*HintArray
,
90 const MENU_HINT
*LastHint
;
91 UINT HintId
= DefHintId
;
93 LastHint
= HintArray
+ HintsCount
;
94 while (HintArray
!= LastHint
)
96 if (HintArray
->CmdId
== CmdId
)
98 HintId
= HintArray
->HintId
;
105 StatusBarLoadString(Info
->hStatus
,
115 UpdateMainStatusBar(PMAIN_WND_INFO Info
)
117 if (Info
->hStatus
!= NULL
)
119 SendMessage(Info
->hStatus
,
121 (WPARAM
)Info
->bInMenuLoop
,
127 UpdateServiceCount(PMAIN_WND_INFO Info
)
129 LPTSTR lpNumServices
;
131 if (AllocAndLoadString(&lpNumServices
,
135 TCHAR szNumServices
[32];
137 INT NumListedServ
= ListView_GetItemCount(Info
->hListView
);
139 _sntprintf(szNumServices
,
144 SendMessage(Info
->hStatus
,
147 (LPARAM
)szNumServices
);
149 LocalFree(lpNumServices
);
154 VOID
SetMenuAndButtonStates(PMAIN_WND_INFO Info
)
159 /* get handle to menu */
160 hMainMenu
= GetMenu(Info
->hMainWnd
);
162 /* set all to greyed */
163 for (i
= ID_START
; i
<= ID_RESTART
; i
++)
165 EnableMenuItem(hMainMenu
, i
, MF_GRAYED
);
166 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0), i
, MF_GRAYED
);
167 SendMessage(Info
->hTool
, TB_SETSTATE
, i
,
168 (LPARAM
)MAKELONG(TBSTATE_INDETERMINATE
, 0));
171 if (Info
->SelectedItem
!= NO_ITEM_SELECTED
)
173 LPQUERY_SERVICE_CONFIG lpServiceConfig
= NULL
;
176 /* allow user to delete service */
177 if (Info
->bIsUserAnAdmin
)
179 SendMessage(Info
->hTool
, TB_SETSTATE
, ID_DELETE
,
180 (LPARAM
)MAKELONG(TBSTATE_ENABLED
, 0));
181 EnableMenuItem(hMainMenu
, ID_DELETE
, MF_ENABLED
);
182 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0), ID_DELETE
, MF_ENABLED
);
185 Flags
= Info
->pCurrentService
->ServiceStatusProcess
.dwControlsAccepted
;
186 State
= Info
->pCurrentService
->ServiceStatusProcess
.dwCurrentState
;
188 lpServiceConfig
= GetServiceConfig(Info
->pCurrentService
->lpServiceName
);
190 if (lpServiceConfig
&& lpServiceConfig
->dwStartType
!= SERVICE_DISABLED
)
192 if (State
== SERVICE_STOPPED
)
194 EnableMenuItem(hMainMenu
, ID_START
, MF_ENABLED
);
195 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0), ID_START
, MF_ENABLED
);
196 SendMessage(Info
->hTool
, TB_SETSTATE
, ID_START
,
197 (LPARAM
)MAKELONG(TBSTATE_ENABLED
, 0));
200 if ( (Flags
& SERVICE_ACCEPT_STOP
) && (State
== SERVICE_RUNNING
) )
202 EnableMenuItem(hMainMenu
, ID_RESTART
, MF_ENABLED
);
203 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0), ID_RESTART
, MF_ENABLED
);
204 SendMessage(Info
->hTool
, TB_SETSTATE
, ID_RESTART
,
205 (LPARAM
)MAKELONG(TBSTATE_ENABLED
, 0));
208 HeapFree(GetProcessHeap(), 0, lpServiceConfig
);
211 if ( (Flags
& SERVICE_ACCEPT_STOP
) && (State
== SERVICE_RUNNING
) )
213 EnableMenuItem(hMainMenu
, ID_STOP
, MF_ENABLED
);
214 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0), ID_STOP
, MF_ENABLED
);
215 SendMessage(Info
->hTool
, TB_SETSTATE
, ID_STOP
,
216 (LPARAM
)MAKELONG(TBSTATE_ENABLED
, 0));
219 if ( (Flags
& SERVICE_ACCEPT_PAUSE_CONTINUE
) && (State
== SERVICE_RUNNING
) )
221 EnableMenuItem(hMainMenu
, ID_PAUSE
, MF_ENABLED
);
222 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0), ID_PAUSE
, MF_ENABLED
);
223 SendMessage(Info
->hTool
, TB_SETSTATE
, ID_PAUSE
,
224 (LPARAM
)MAKELONG(TBSTATE_ENABLED
, 0));
229 /* disable tools which rely on a selected service */
230 EnableMenuItem(hMainMenu
, ID_PROP
, MF_GRAYED
);
231 EnableMenuItem(hMainMenu
, ID_DELETE
, MF_GRAYED
);
232 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0), ID_PROP
, MF_GRAYED
);
233 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0), ID_DELETE
, MF_GRAYED
);
234 SendMessage(Info
->hTool
, TB_SETSTATE
, ID_PROP
,
235 (LPARAM
)MAKELONG(TBSTATE_INDETERMINATE
, 0));
236 SendMessage(Info
->hTool
, TB_SETSTATE
, ID_DELETE
,
237 (LPARAM
)MAKELONG(TBSTATE_INDETERMINATE
, 0));
244 CompareFunc(LPARAM lParam1
, LPARAM lParam2
, LPARAM lParamSort
)
246 ENUM_SERVICE_STATUS_PROCESS
*Param1
;
247 ENUM_SERVICE_STATUS_PROCESS
*Param2
;
248 // INT iSubItem = (LPARAM)lParamSort;
250 if (bSortAscending
) {
251 Param1
= (ENUM_SERVICE_STATUS_PROCESS
*)lParam1
;
252 Param2
= (ENUM_SERVICE_STATUS_PROCESS
*)lParam2
;
256 Param1
= (ENUM_SERVICE_STATUS_PROCESS
*)lParam2
;
257 Param2
= (ENUM_SERVICE_STATUS_PROCESS
*)lParam1
;
259 return _tcsicmp(Param1
->lpDisplayName
, Param2
->lpDisplayName
);
264 pCreateToolbar(PMAIN_WND_INFO Info
)
266 INT numButtons
= sizeof(Buttons
) / sizeof(Buttons
[0]);
268 Info
->hTool
= CreateWindowEx(0,
271 WS_CHILD
| WS_VISIBLE
| TBSTYLE_FLAT
| TBSTYLE_TOOLTIPS
,
277 if(Info
->hTool
!= NULL
)
279 HIMAGELIST hImageList
;
281 SendMessage(Info
->hTool
,
284 TBSTYLE_EX_HIDECLIPPEDBUTTONS
);
286 SendMessage(Info
->hTool
,
291 hImageList
= InitImageList(IDB_PROP
,
293 GetSystemMetrics(SM_CXSMICON
),
294 GetSystemMetrics(SM_CXSMICON
),
296 if (hImageList
== NULL
)
299 ImageList_Destroy((HIMAGELIST
)SendMessage(Info
->hTool
,
302 (LPARAM
)hImageList
));
304 SendMessage(Info
->hTool
,
316 CreateStatusBar(PMAIN_WND_INFO Info
)
318 INT StatWidths
[] = {110, -1}; /* widths of status bar */
320 Info
->hStatus
= CreateWindowEx(0,
323 WS_CHILD
| WS_VISIBLE
| SBARS_SIZEGRIP
,
326 (HMENU
)IDC_STATUSBAR
,
329 if(Info
->hStatus
== NULL
)
332 SendMessage(Info
->hStatus
,
334 sizeof(StatWidths
) / sizeof(INT
),
342 InitMainWnd(PMAIN_WND_INFO Info
)
344 if (!pCreateToolbar(Info
))
346 DisplayString(_T("error creating toolbar"));
350 if (!CreateListView(Info
))
352 DisplayString(_T("error creating list view"));
356 if (!CreateStatusBar(Info
))
357 DisplayString(_T("error creating status bar"));
359 /* Create Popup Menu */
360 Info
->hShortcutMenu
= LoadMenu(hInstance
,
361 MAKEINTRESOURCE(IDR_POPUP
));
363 Info
->bIsUserAnAdmin
= IsUserAnAdmin();
364 if (Info
->bIsUserAnAdmin
)
366 HMENU hMainMenu
= GetMenu(Info
->hMainWnd
);
368 SendMessage(Info
->hTool
,
371 (LPARAM
)MAKELONG(TBSTATE_ENABLED
, 0));
374 EnableMenuItem(hMainMenu
,
378 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0),
388 MainWndCommand(PMAIN_WND_INFO Info
,
392 UNREFERENCED_PARAMETER(hControl
);
398 if (Info
->SelectedItem
!= NO_ITEM_SELECTED
)
400 Info
->bDlgOpen
= TRUE
;
402 Info
->bDlgOpen
= FALSE
;
403 SetMenuAndButtonStates(Info
);
410 RefreshServiceList(Info
);
411 Info
->SelectedItem
= NO_ITEM_SELECTED
;
413 /* disable menus and buttons */
414 SetMenuAndButtonStates(Info
);
416 /* clear the service in the status bar */
417 SendMessage(Info
->hStatus
,
427 SetFocus(Info
->hListView
);
435 ret
= DialogBoxParam(hInstance
,
436 MAKEINTRESOURCE(IDD_DLG_CREATE
),
441 RefreshServiceList(Info
);
443 SetFocus(Info
->hListView
);
449 if (Info
->pCurrentService
->ServiceStatusProcess
.dwCurrentState
!= SERVICE_RUNNING
)
451 DialogBoxParam(hInstance
,
452 MAKEINTRESOURCE(IDD_DLG_DELETE
),
460 LoadString(hInstance
,
463 sizeof(Buf
) / sizeof(TCHAR
));
467 SetFocus(Info
->hListView
);
474 if (DoStart(Info
, NULL
))
476 UpdateServiceStatus(Info
->pCurrentService
);
477 ChangeListViewText(Info
, Info
->pCurrentService
, LVSTATUS
);
478 SetMenuAndButtonStates(Info
);
479 SetFocus(Info
->hListView
);
487 UpdateServiceStatus(Info
->pCurrentService
);
488 ChangeListViewText(Info
, Info
->pCurrentService
, LVSTATUS
);
489 SetMenuAndButtonStates(Info
);
490 SetFocus(Info
->hListView
);
506 UpdateServiceStatus(Info
->pCurrentService
);
507 ChangeListViewText(Info
, Info
->pCurrentService
, LVSTATUS
);
508 SetMenuAndButtonStates(Info
);
509 SetFocus(Info
->hListView
);
515 _T("Help is not yet implemented\n"),
517 MB_OK
| MB_ICONINFORMATION
);
518 SetFocus(Info
->hListView
);
522 PostMessage(Info
->hMainWnd
,
529 SetListViewStyle(Info
->hListView
,
531 CheckMenuRadioItem(GetMenu(Info
->hMainWnd
),
539 SetListViewStyle(Info
->hListView
,
541 CheckMenuRadioItem(GetMenu(Info
->hMainWnd
),
549 SetListViewStyle(Info
->hListView
,
551 CheckMenuRadioItem(GetMenu(Info
->hMainWnd
),
558 case ID_VIEW_DETAILS
:
559 SetListViewStyle(Info
->hListView
,
561 CheckMenuRadioItem(GetMenu(Info
->hMainWnd
),
573 MAKEINTRESOURCE(IDD_ABOUTBOX
),
576 SetFocus(Info
->hListView
);
584 MainWndResize(PMAIN_WND_INFO Info
,
588 RECT rcClient
, rcTool
, rcStatus
;
589 int lvHeight
, iToolHeight
, iStatusHeight
;
591 /* Size toolbar and get height */
592 SendMessage(Info
->hTool
, TB_AUTOSIZE
, 0, 0);
593 GetWindowRect(Info
->hTool
, &rcTool
);
594 iToolHeight
= rcTool
.bottom
- rcTool
.top
;
596 /* Size status bar and get height */
597 SendMessage(Info
->hStatus
, WM_SIZE
, 0, 0);
598 GetWindowRect(Info
->hStatus
, &rcStatus
);
599 iStatusHeight
= rcStatus
.bottom
- rcStatus
.top
;
601 /* Calculate remaining height and size list view */
602 GetClientRect(Info
->hMainWnd
, &rcClient
);
603 lvHeight
= rcClient
.bottom
- iToolHeight
- iStatusHeight
;
604 SetWindowPos(Info
->hListView
,
614 static LRESULT CALLBACK
615 MainWndProc(HWND hwnd
,
623 /* Get the window context */
624 Info
= (PMAIN_WND_INFO
)GetWindowLongPtr(hwnd
,
626 if (Info
== NULL
&& msg
!= WM_CREATE
)
628 goto HandleDefaultMessage
;
635 Info
= (PMAIN_WND_INFO
)(((LPCREATESTRUCT
)lParam
)->lpCreateParams
);
637 /* Initialize the main window context */
638 Info
->hMainWnd
= hwnd
;
639 Info
->SelectedItem
= NO_ITEM_SELECTED
;
641 SetWindowLongPtr(hwnd
,
645 if (!InitMainWnd(Info
))
648 /* Fill the list-view before showing the main window */
649 RefreshServiceList(Info
);
651 /* Show the window */
655 SetFocus(Info
->hListView
);
669 LPNMHDR pnmhdr
= (LPNMHDR
)lParam
;
671 switch (pnmhdr
->code
)
679 GetWindowRect(Info
->hListView
, &rect
);
681 if (PtInRect(&rect
, pt
))
686 MAKEWPARAM((WORD
)ID_PROP
, (WORD
)0),
690 //OpenPropSheet(Info);
699 MAKEWPARAM((WORD
)ID_PROP
, (WORD
)0),
704 case LVN_COLUMNCLICK
:
706 LPNMLISTVIEW pnmv
= (LPNMLISTVIEW
) lParam
;
708 (void)ListView_SortItems(Info
->hListView
,
711 bSortAscending
= !bSortAscending
;
715 case LVN_ITEMCHANGED
:
717 LPNMLISTVIEW pnmv
= (LPNMLISTVIEW
) lParam
;
719 if (pnmv
->uNewState
!= 0)
721 ListViewSelectionChanged(Info
, pnmv
);
722 SetMenuAndButtonStates(Info
);
727 case TTN_GETDISPINFO
:
732 lpttt
= (LPTOOLTIPTEXT
)lParam
;
734 /* Specify the resource identifier of the descriptive
735 * text for the given button. */
736 idButton
= (UINT
)lpttt
->hdr
.idFrom
;
740 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_PROP
);
744 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_REFRESH
);
748 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_EXPORT
);
752 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_CREATE
);
756 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_DELETE
);
760 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_START
);
764 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_STOP
);
768 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_PAUSE
);
772 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_RESTART
);
786 INT xPos
= GET_X_LPARAM(lParam
);
787 INT yPos
= GET_Y_LPARAM(lParam
);
791 /* display popup when cursor is in the list view */
792 GetWindowRect(Info
->hListView
, &lvRect
);
793 if (PtInRect(&lvRect
, pt
))
795 TrackPopupMenuEx(GetSubMenu(Info
->hShortcutMenu
, 0),
810 goto HandleDefaultMessage
;
815 if (Info
->hStatus
!= NULL
)
817 if (!MainWndMenuHint(Info
,
820 sizeof(MainMenuHintTable
) / sizeof(MainMenuHintTable
[0]),
823 MainWndMenuHint(Info
,
826 sizeof(SystemMenuHintTable
) / sizeof(SystemMenuHintTable
[0]),
833 case WM_ENTERMENULOOP
:
835 Info
->bInMenuLoop
= TRUE
;
836 UpdateMainStatusBar(Info
);
840 case WM_EXITMENULOOP
:
842 Info
->bInMenuLoop
= FALSE
;
843 UpdateMainStatusBar(Info
);
849 HeapFree(ProcessHeap
,
853 DestroyMenu(Info
->hShortcutMenu
);
860 HeapFree(ProcessHeap
,
863 SetWindowLongPtr(hwnd
,
873 HandleDefaultMessage
:
875 Ret
= DefWindowProc(hwnd
,
889 CreateMainWindow(LPCTSTR lpCaption
,
893 HWND hMainWnd
= NULL
;
895 Info
= (MAIN_WND_INFO
*) HeapAlloc(ProcessHeap
,
897 sizeof(MAIN_WND_INFO
));
901 Info
->nCmdShow
= nCmdShow
;
903 hMainWnd
= CreateWindowEx(WS_EX_WINDOWEDGE
,
906 WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
,
915 if (hMainWnd
== NULL
)
918 //ret = GetLastError();
920 HeapFree(ProcessHeap
,
930 InitMainWindowImpl(VOID
)
934 wc
.cbSize
= sizeof(WNDCLASSEX
);
935 wc
.lpfnWndProc
= MainWndProc
;
936 wc
.hInstance
= hInstance
;
937 wc
.hIcon
= LoadIcon(hInstance
,
938 MAKEINTRESOURCE(IDI_SM_ICON
));
939 wc
.hCursor
= LoadCursor(NULL
,
941 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
942 wc
.lpszMenuName
= MAKEINTRESOURCE(IDR_MAINMENU
);
943 wc
.lpszClassName
= szMainWndClass
;
944 wc
.hIconSm
= (HICON
)LoadImage(hInstance
,
945 MAKEINTRESOURCE(IDI_SM_ICON
),
951 return RegisterClassEx(&wc
) != (ATOM
)0;
956 UninitMainWindowImpl(VOID
)
958 UnregisterClass(szMainWndClass
,