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));
210 HeapFree(GetProcessHeap(), 0, lpServiceConfig
);
212 if ( (Flags
& SERVICE_ACCEPT_STOP
) && (State
== SERVICE_RUNNING
) )
214 EnableMenuItem(hMainMenu
, ID_STOP
, MF_ENABLED
);
215 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0), ID_STOP
, MF_ENABLED
);
216 SendMessage(Info
->hTool
, TB_SETSTATE
, ID_STOP
,
217 (LPARAM
)MAKELONG(TBSTATE_ENABLED
, 0));
220 if ( (Flags
& SERVICE_ACCEPT_PAUSE_CONTINUE
) && (State
== SERVICE_RUNNING
) )
222 EnableMenuItem(hMainMenu
, ID_PAUSE
, MF_ENABLED
);
223 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0), ID_PAUSE
, MF_ENABLED
);
224 SendMessage(Info
->hTool
, TB_SETSTATE
, ID_PAUSE
,
225 (LPARAM
)MAKELONG(TBSTATE_ENABLED
, 0));
230 /* disable tools which rely on a selected service */
231 EnableMenuItem(hMainMenu
, ID_PROP
, MF_GRAYED
);
232 EnableMenuItem(hMainMenu
, ID_DELETE
, MF_GRAYED
);
233 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0), ID_PROP
, MF_GRAYED
);
234 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0), ID_DELETE
, MF_GRAYED
);
235 SendMessage(Info
->hTool
, TB_SETSTATE
, ID_PROP
,
236 (LPARAM
)MAKELONG(TBSTATE_INDETERMINATE
, 0));
237 SendMessage(Info
->hTool
, TB_SETSTATE
, ID_DELETE
,
238 (LPARAM
)MAKELONG(TBSTATE_INDETERMINATE
, 0));
245 CompareFunc(LPARAM lParam1
, LPARAM lParam2
, LPARAM lParamSort
)
247 ENUM_SERVICE_STATUS_PROCESS
*Param1
;
248 ENUM_SERVICE_STATUS_PROCESS
*Param2
;
249 // INT iSubItem = (LPARAM)lParamSort;
251 if (bSortAscending
) {
252 Param1
= (ENUM_SERVICE_STATUS_PROCESS
*)lParam1
;
253 Param2
= (ENUM_SERVICE_STATUS_PROCESS
*)lParam2
;
257 Param1
= (ENUM_SERVICE_STATUS_PROCESS
*)lParam2
;
258 Param2
= (ENUM_SERVICE_STATUS_PROCESS
*)lParam1
;
260 return _tcsicmp(Param1
->lpDisplayName
, Param2
->lpDisplayName
);
265 pCreateToolbar(PMAIN_WND_INFO Info
)
267 INT numButtons
= sizeof(Buttons
) / sizeof(Buttons
[0]);
269 Info
->hTool
= CreateWindowEx(0,
272 WS_CHILD
| WS_VISIBLE
| TBSTYLE_FLAT
| TBSTYLE_TOOLTIPS
,
278 if(Info
->hTool
!= NULL
)
280 HIMAGELIST hImageList
;
282 SendMessage(Info
->hTool
,
285 TBSTYLE_EX_HIDECLIPPEDBUTTONS
);
287 SendMessage(Info
->hTool
,
292 hImageList
= InitImageList(IDB_PROP
,
294 GetSystemMetrics(SM_CXSMICON
),
295 GetSystemMetrics(SM_CXSMICON
),
297 if (hImageList
== NULL
)
300 ImageList_Destroy((HIMAGELIST
)SendMessage(Info
->hTool
,
303 (LPARAM
)hImageList
));
305 SendMessage(Info
->hTool
,
317 CreateStatusBar(PMAIN_WND_INFO Info
)
319 INT StatWidths
[] = {110, -1}; /* widths of status bar */
321 Info
->hStatus
= CreateWindowEx(0,
324 WS_CHILD
| WS_VISIBLE
| SBARS_SIZEGRIP
,
327 (HMENU
)IDC_STATUSBAR
,
330 if(Info
->hStatus
== NULL
)
333 SendMessage(Info
->hStatus
,
335 sizeof(StatWidths
) / sizeof(INT
),
343 InitMainWnd(PMAIN_WND_INFO Info
)
345 if (!pCreateToolbar(Info
))
347 DisplayString(_T("error creating toolbar"));
351 if (!CreateListView(Info
))
353 DisplayString(_T("error creating list view"));
357 if (!CreateStatusBar(Info
))
358 DisplayString(_T("error creating status bar"));
360 /* Create Popup Menu */
361 Info
->hShortcutMenu
= LoadMenu(hInstance
,
362 MAKEINTRESOURCE(IDR_POPUP
));
364 Info
->bIsUserAnAdmin
= IsUserAnAdmin();
365 if (Info
->bIsUserAnAdmin
)
367 HMENU hMainMenu
= GetMenu(Info
->hMainWnd
);
369 SendMessage(Info
->hTool
,
372 (LPARAM
)MAKELONG(TBSTATE_ENABLED
, 0));
375 EnableMenuItem(hMainMenu
,
379 EnableMenuItem(GetSubMenu(Info
->hShortcutMenu
, 0),
389 MainWndCommand(PMAIN_WND_INFO Info
,
393 UNREFERENCED_PARAMETER(hControl
);
399 if (Info
->SelectedItem
!= NO_ITEM_SELECTED
)
401 Info
->bDlgOpen
= TRUE
;
403 Info
->bDlgOpen
= FALSE
;
404 SetMenuAndButtonStates(Info
);
411 RefreshServiceList(Info
);
412 Info
->SelectedItem
= NO_ITEM_SELECTED
;
414 /* disable menus and buttons */
415 SetMenuAndButtonStates(Info
);
417 /* clear the service in the status bar */
418 SendMessage(Info
->hStatus
,
428 SetFocus(Info
->hListView
);
436 ret
= DialogBoxParam(hInstance
,
437 MAKEINTRESOURCE(IDD_DLG_CREATE
),
442 RefreshServiceList(Info
);
444 SetFocus(Info
->hListView
);
450 if (Info
->pCurrentService
->ServiceStatusProcess
.dwCurrentState
!= SERVICE_RUNNING
)
452 DialogBoxParam(hInstance
,
453 MAKEINTRESOURCE(IDD_DLG_DELETE
),
461 LoadString(hInstance
,
464 sizeof(Buf
) / sizeof(TCHAR
));
468 SetFocus(Info
->hListView
);
475 if (DoStart(Info
, NULL
))
477 UpdateServiceStatus(Info
->pCurrentService
);
478 ChangeListViewText(Info
, Info
->pCurrentService
, LVSTATUS
);
479 SetMenuAndButtonStates(Info
);
480 SetFocus(Info
->hListView
);
488 UpdateServiceStatus(Info
->pCurrentService
);
489 ChangeListViewText(Info
, Info
->pCurrentService
, LVSTATUS
);
490 SetMenuAndButtonStates(Info
);
491 SetFocus(Info
->hListView
);
507 UpdateServiceStatus(Info
->pCurrentService
);
508 ChangeListViewText(Info
, Info
->pCurrentService
, LVSTATUS
);
509 SetMenuAndButtonStates(Info
);
510 SetFocus(Info
->hListView
);
516 _T("Help is not yet implemented\n"),
518 MB_OK
| MB_ICONINFORMATION
);
519 SetFocus(Info
->hListView
);
523 PostMessage(Info
->hMainWnd
,
530 SetListViewStyle(Info
->hListView
,
532 CheckMenuRadioItem(GetMenu(Info
->hMainWnd
),
540 SetListViewStyle(Info
->hListView
,
542 CheckMenuRadioItem(GetMenu(Info
->hMainWnd
),
550 SetListViewStyle(Info
->hListView
,
552 CheckMenuRadioItem(GetMenu(Info
->hMainWnd
),
559 case ID_VIEW_DETAILS
:
560 SetListViewStyle(Info
->hListView
,
562 CheckMenuRadioItem(GetMenu(Info
->hMainWnd
),
574 MAKEINTRESOURCE(IDD_ABOUTBOX
),
577 SetFocus(Info
->hListView
);
585 MainWndResize(PMAIN_WND_INFO Info
,
589 RECT rcClient
, rcTool
, rcStatus
;
590 int lvHeight
, iToolHeight
, iStatusHeight
;
592 /* Size toolbar and get height */
593 SendMessage(Info
->hTool
, TB_AUTOSIZE
, 0, 0);
594 GetWindowRect(Info
->hTool
, &rcTool
);
595 iToolHeight
= rcTool
.bottom
- rcTool
.top
;
597 /* Size status bar and get height */
598 SendMessage(Info
->hStatus
, WM_SIZE
, 0, 0);
599 GetWindowRect(Info
->hStatus
, &rcStatus
);
600 iStatusHeight
= rcStatus
.bottom
- rcStatus
.top
;
602 /* Calculate remaining height and size list view */
603 GetClientRect(Info
->hMainWnd
, &rcClient
);
604 lvHeight
= rcClient
.bottom
- iToolHeight
- iStatusHeight
;
605 SetWindowPos(Info
->hListView
,
615 static LRESULT CALLBACK
616 MainWndProc(HWND hwnd
,
624 /* Get the window context */
625 Info
= (PMAIN_WND_INFO
)GetWindowLongPtr(hwnd
,
627 if (Info
== NULL
&& msg
!= WM_CREATE
)
629 goto HandleDefaultMessage
;
636 Info
= (PMAIN_WND_INFO
)(((LPCREATESTRUCT
)lParam
)->lpCreateParams
);
638 /* Initialize the main window context */
639 Info
->hMainWnd
= hwnd
;
640 Info
->SelectedItem
= NO_ITEM_SELECTED
;
642 SetWindowLongPtr(hwnd
,
646 if (!InitMainWnd(Info
))
649 /* Fill the list-view before showing the main window */
650 RefreshServiceList(Info
);
652 /* Show the window */
656 SetFocus(Info
->hListView
);
670 LPNMHDR pnmhdr
= (LPNMHDR
)lParam
;
672 switch (pnmhdr
->code
)
680 GetWindowRect(Info
->hListView
, &rect
);
682 if (PtInRect(&rect
, pt
))
687 MAKEWPARAM((WORD
)ID_PROP
, (WORD
)0),
691 //OpenPropSheet(Info);
700 MAKEWPARAM((WORD
)ID_PROP
, (WORD
)0),
705 case LVN_COLUMNCLICK
:
707 LPNMLISTVIEW pnmv
= (LPNMLISTVIEW
) lParam
;
709 (void)ListView_SortItems(Info
->hListView
,
712 bSortAscending
= !bSortAscending
;
716 case LVN_ITEMCHANGED
:
718 LPNMLISTVIEW pnmv
= (LPNMLISTVIEW
) lParam
;
720 if (pnmv
->uNewState
!= 0)
722 ListViewSelectionChanged(Info
, pnmv
);
723 SetMenuAndButtonStates(Info
);
728 case TTN_GETDISPINFO
:
733 lpttt
= (LPTOOLTIPTEXT
)lParam
;
735 /* Specify the resource identifier of the descriptive
736 * text for the given button. */
737 idButton
= (UINT
)lpttt
->hdr
.idFrom
;
741 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_PROP
);
745 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_REFRESH
);
749 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_EXPORT
);
753 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_CREATE
);
757 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_DELETE
);
761 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_START
);
765 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_STOP
);
769 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_PAUSE
);
773 lpttt
->lpszText
= MAKEINTRESOURCE(IDS_TOOLTIP_RESTART
);
787 INT xPos
= GET_X_LPARAM(lParam
);
788 INT yPos
= GET_Y_LPARAM(lParam
);
792 /* display popup when cursor is in the list view */
793 GetWindowRect(Info
->hListView
, &lvRect
);
794 if (PtInRect(&lvRect
, pt
))
796 TrackPopupMenuEx(GetSubMenu(Info
->hShortcutMenu
, 0),
811 goto HandleDefaultMessage
;
816 if (Info
->hStatus
!= NULL
)
818 if (!MainWndMenuHint(Info
,
821 sizeof(MainMenuHintTable
) / sizeof(MainMenuHintTable
[0]),
824 MainWndMenuHint(Info
,
827 sizeof(SystemMenuHintTable
) / sizeof(SystemMenuHintTable
[0]),
834 case WM_ENTERMENULOOP
:
836 Info
->bInMenuLoop
= TRUE
;
837 UpdateMainStatusBar(Info
);
841 case WM_EXITMENULOOP
:
843 Info
->bInMenuLoop
= FALSE
;
844 UpdateMainStatusBar(Info
);
850 HeapFree(ProcessHeap
,
854 DestroyMenu(Info
->hShortcutMenu
);
861 HeapFree(ProcessHeap
,
864 SetWindowLongPtr(hwnd
,
874 HandleDefaultMessage
:
876 Ret
= DefWindowProc(hwnd
,
890 CreateMainWindow(LPCTSTR lpCaption
,
894 HWND hMainWnd
= NULL
;
896 Info
= (MAIN_WND_INFO
*) HeapAlloc(ProcessHeap
,
898 sizeof(MAIN_WND_INFO
));
902 Info
->nCmdShow
= nCmdShow
;
904 hMainWnd
= CreateWindowEx(WS_EX_WINDOWEDGE
,
907 WS_OVERLAPPEDWINDOW
| WS_CLIPCHILDREN
| WS_CLIPSIBLINGS
,
916 if (hMainWnd
== NULL
)
919 //ret = GetLastError();
921 HeapFree(ProcessHeap
,
931 InitMainWindowImpl(VOID
)
935 wc
.cbSize
= sizeof(WNDCLASSEX
);
936 wc
.lpfnWndProc
= MainWndProc
;
937 wc
.hInstance
= hInstance
;
938 wc
.hIcon
= LoadIcon(hInstance
,
939 MAKEINTRESOURCE(IDI_SM_ICON
));
940 wc
.hCursor
= LoadCursor(NULL
,
942 wc
.hbrBackground
= (HBRUSH
)(COLOR_BTNFACE
+ 1);
943 wc
.lpszMenuName
= MAKEINTRESOURCE(IDR_MAINMENU
);
944 wc
.lpszClassName
= szMainWndClass
;
945 wc
.hIconSm
= (HICON
)LoadImage(hInstance
,
946 MAKEINTRESOURCE(IDI_SM_ICON
),
952 return RegisterClassEx(&wc
) != (ATOM
)0;
957 UninitMainWindowImpl(VOID
)
959 UnregisterClass(szMainWndClass
,