| 1 | /************************************************************************** |
|---|
| 2 | * Copyright (C) 2004-2007 by Michael Medin <michael@medin.name> * |
|---|
| 3 | * * |
|---|
| 4 | * This code is part of NSClient++ - http://trac.nakednuns.org/nscp * |
|---|
| 5 | * * |
|---|
| 6 | * This program is free software; you can redistribute it and/or modify * |
|---|
| 7 | * it under the terms of the GNU General Public License as published by * |
|---|
| 8 | * the Free Software Foundation; either version 2 of the License, or * |
|---|
| 9 | * (at your option) any later version. * |
|---|
| 10 | * * |
|---|
| 11 | * This program is distributed in the hope that it will be useful, * |
|---|
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * |
|---|
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
|---|
| 14 | * GNU General Public License for more details. * |
|---|
| 15 | * * |
|---|
| 16 | * You should have received a copy of the GNU General Public License * |
|---|
| 17 | * along with this program; if not, write to the * |
|---|
| 18 | * Free Software Foundation, Inc., * |
|---|
| 19 | * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * |
|---|
| 20 | ***************************************************************************/ |
|---|
| 21 | #include "stdafx.h" |
|---|
| 22 | #include "trayicon.h" |
|---|
| 23 | #include "resource.h" |
|---|
| 24 | #include <commctrl.h> |
|---|
| 25 | #include <strEx.h> |
|---|
| 26 | #include <ShellAPI.h> |
|---|
| 27 | #include "SysTray.h" |
|---|
| 28 | |
|---|
| 29 | |
|---|
| 30 | extern SysTray gSysTray; |
|---|
| 31 | |
|---|
| 32 | |
|---|
| 33 | unsigned IconWidget_::threadProc(LPVOID lpParameter) |
|---|
| 34 | { |
|---|
| 35 | createDialog(); |
|---|
| 36 | return 0; |
|---|
| 37 | } |
|---|
| 38 | |
|---|
| 39 | |
|---|
| 40 | void IconWidget_::createDialog(void) { |
|---|
| 41 | hDlgWnd = ::CreateDialog(NSCModuleWrapper::getModule(),MAKEINTRESOURCE(IDD_NSTRAYDLG),NULL,TrayIcon::DialogProc); |
|---|
| 42 | |
|---|
| 43 | MSG Msg; |
|---|
| 44 | BOOL bRet; |
|---|
| 45 | while((bRet = ::GetMessage(&Msg, NULL, 0, 0)) != 0) |
|---|
| 46 | { |
|---|
| 47 | if (Msg.message == WM_MY_CLOSE) { |
|---|
| 48 | ::DestroyWindow(hDlgWnd); |
|---|
| 49 | } else if (bRet == -1) { |
|---|
| 50 | // handle the error and possibly exit |
|---|
| 51 | NSC_LOG_ERROR_STD(_T("Wonder what this is... please let me know...")); |
|---|
| 52 | return; |
|---|
| 53 | } else { |
|---|
| 54 | //} else if (!::IsWindow(hDlgWnd) || !::IsDialogMessage(hDlgWnd, &Msg)) { |
|---|
| 55 | ::TranslateMessage(&Msg); |
|---|
| 56 | ::DispatchMessage(&Msg); |
|---|
| 57 | } |
|---|
| 58 | } |
|---|
| 59 | } |
|---|
| 60 | void IconWidget_::exitThread(void) { |
|---|
| 61 | ::PostMessage(hDlgWnd, WM_MY_CLOSE, NULL, NULL); |
|---|
| 62 | } |
|---|
| 63 | |
|---|
| 64 | namespace TrayIcon |
|---|
| 65 | { |
|---|
| 66 | std::wstring defaultCommand; |
|---|
| 67 | } |
|---|
| 68 | |
|---|
| 69 | std::wstring getDlgItemText(HWND hDlg, int nIDDlgItem) { |
|---|
| 70 | #define BUFF_LEN 4096 |
|---|
| 71 | std::wstring ret; |
|---|
| 72 | TCHAR *buffer = new TCHAR[BUFF_LEN+1]; |
|---|
| 73 | if (!GetDlgItemText(hDlg, nIDDlgItem, buffer, BUFF_LEN)) |
|---|
| 74 | buffer[0]=0; |
|---|
| 75 | ret = buffer; |
|---|
| 76 | delete [] buffer; |
|---|
| 77 | return ret; |
|---|
| 78 | } |
|---|
| 79 | void updateDescFromCmd(HWND hDlg, std::wstring cmd) { |
|---|
| 80 | std::wstring result = _T(""); |
|---|
| 81 | try { |
|---|
| 82 | result = NSCModuleHelper::describeCommand(cmd); |
|---|
| 83 | } catch (NSCModuleHelper::NSCMHExcpetion &e) { |
|---|
| 84 | result = _T("Error: ") + e.msg_; |
|---|
| 85 | } catch (...) { |
|---|
| 86 | result = _T("Unknown error!"); |
|---|
| 87 | } |
|---|
| 88 | SetDlgItemText(hDlg, IDC_DESCRIPTION, result.c_str()); |
|---|
| 89 | } |
|---|
| 90 | /* |
|---|
| 91 | INT_PTR CALLBACK DialogProc( HWND hwndDlg, |
|---|
| 92 | UINT uMsg, |
|---|
| 93 | WPARAM wParam, |
|---|
| 94 | LPARAM lParam |
|---|
| 95 | ); |
|---|
| 96 | */ |
|---|
| 97 | INT_PTR CALLBACK TrayIcon::InjectDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam) { |
|---|
| 98 | switch (uMsg) |
|---|
| 99 | { |
|---|
| 100 | case WM_INITDIALOG: |
|---|
| 101 | { |
|---|
| 102 | SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(NSCModuleWrapper::getModule(), MAKEINTRESOURCE(IDI_NSCP))); |
|---|
| 103 | SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(NSCModuleWrapper::getModule(), MAKEINTRESOURCE(IDI_NSCP))); |
|---|
| 104 | SetDlgItemText(hwndDlg, IDC_CMD_BOX, TrayIcon::defaultCommand.c_str()); |
|---|
| 105 | SetDlgItemText(hwndDlg, IDC_DESCRIPTION, _T("Loading commands, please wait...")); |
|---|
| 106 | |
|---|
| 107 | SendDlgItemMessage(hwndDlg, IDC_CMD_BOX, CB_RESETCONTENT, 0, 0); |
|---|
| 108 | std::wstring result = _T(""); |
|---|
| 109 | try { |
|---|
| 110 | std::list<std::wstring> lst = NSCModuleHelper::getAllCommandNames(); |
|---|
| 111 | for (std::list<std::wstring>::const_iterator cit = lst.begin(); cit != lst.end(); ++cit) { |
|---|
| 112 | SendDlgItemMessage(hwndDlg, IDC_CMD_BOX, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>( (*cit).c_str() )); |
|---|
| 113 | } |
|---|
| 114 | } catch (NSCModuleHelper::NSCMHExcpetion &e) { |
|---|
| 115 | result = _T("Error: ") + e.msg_; |
|---|
| 116 | } catch (...) { |
|---|
| 117 | result = _T("Unknown error!"); |
|---|
| 118 | } |
|---|
| 119 | SetDlgItemText(hwndDlg, IDC_DESCRIPTION, result.c_str()); |
|---|
| 120 | } |
|---|
| 121 | break; |
|---|
| 122 | case WM_COMMAND: |
|---|
| 123 | switch (LOWORD(wParam)) |
|---|
| 124 | { |
|---|
| 125 | case IDC_CMD_BOX: |
|---|
| 126 | switch(HIWORD(wParam)) |
|---|
| 127 | { |
|---|
| 128 | case CBN_SELCHANGE: |
|---|
| 129 | { |
|---|
| 130 | std::wstring cmd; |
|---|
| 131 | unsigned int id = SendDlgItemMessage(hwndDlg, IDC_CMD_BOX, CB_GETCURSEL, 0, 0); |
|---|
| 132 | unsigned int len = SendDlgItemMessage(hwndDlg, IDC_CMD_BOX, CB_GETLBTEXTLEN, id, 0); |
|---|
| 133 | TCHAR *buf = new TCHAR[len+2]; |
|---|
| 134 | LRESULT ret; |
|---|
| 135 | ret = SendDlgItemMessage(hwndDlg, IDC_CMD_BOX, CB_GETLBTEXT, id, reinterpret_cast<LPARAM>(buf)); |
|---|
| 136 | if (ret > 0 && ret <= len) { |
|---|
| 137 | cmd = buf; |
|---|
| 138 | updateDescFromCmd(hwndDlg, cmd); |
|---|
| 139 | } |
|---|
| 140 | delete [] buf; |
|---|
| 141 | } |
|---|
| 142 | break; |
|---|
| 143 | case CBN_KILLFOCUS: |
|---|
| 144 | updateDescFromCmd(hwndDlg, getDlgItemText(hwndDlg, IDC_CMD_BOX)); |
|---|
| 145 | break; |
|---|
| 146 | } |
|---|
| 147 | break; |
|---|
| 148 | case IDC_INJECT: |
|---|
| 149 | { |
|---|
| 150 | std::wstring result = _T(""); |
|---|
| 151 | std::wstring cmd = getDlgItemText(hwndDlg, IDC_CMD_BOX); |
|---|
| 152 | std::wstring args = getDlgItemText(hwndDlg, IDC_ARG_BOX); |
|---|
| 153 | std::wstring msg; |
|---|
| 154 | std::wstring perf; |
|---|
| 155 | try { |
|---|
| 156 | NSCAPI::nagiosReturn ret = NSCModuleHelper::InjectSplitAndCommand(cmd, args, ' ', msg, perf); |
|---|
| 157 | if (ret == NSCAPI::returnIgnored) { |
|---|
| 158 | result = _T("Command not found!"); |
|---|
| 159 | } else { |
|---|
| 160 | result = NSCHelper::translateReturn(ret); |
|---|
| 161 | } |
|---|
| 162 | } catch (NSCModuleHelper::NSCMHExcpetion &e) { |
|---|
| 163 | result = _T("Error: ") + e.msg_; |
|---|
| 164 | } catch (...) { |
|---|
| 165 | result = _T("Unknown error!"); |
|---|
| 166 | } |
|---|
| 167 | SetDlgItemText(hwndDlg, IDC_DESCRIPTION, result.c_str()); |
|---|
| 168 | SetDlgItemText(hwndDlg, IDC_MSG, msg.c_str()); |
|---|
| 169 | SetDlgItemText(hwndDlg, IDC_PERF, perf.c_str()); |
|---|
| 170 | } |
|---|
| 171 | break; |
|---|
| 172 | case IDOK: |
|---|
| 173 | { |
|---|
| 174 | TCHAR *c=new TCHAR[1024]; |
|---|
| 175 | if (GetDlgItemText(hwndDlg, IDC_COMMAND, c, 1023)) |
|---|
| 176 | TrayIcon::defaultCommand = c; |
|---|
| 177 | delete [] c; |
|---|
| 178 | } |
|---|
| 179 | |
|---|
| 180 | case IDCANCEL: |
|---|
| 181 | EndDialog(hwndDlg, wParam); |
|---|
| 182 | return TRUE; |
|---|
| 183 | } |
|---|
| 184 | } |
|---|
| 185 | return FALSE; |
|---|
| 186 | } |
|---|
| 187 | |
|---|
| 188 | void insert_logrecord(HWND hwndLV, const SysTray::log_entry &entry) { |
|---|
| 189 | LVITEM item; |
|---|
| 190 | item.mask = LVIF_TEXT; |
|---|
| 191 | std::wstring msg = NSCHelper::translateMessageType(entry.type); |
|---|
| 192 | item.pszText = const_cast<TCHAR*>(msg.c_str()); |
|---|
| 193 | item.iSubItem = 0; |
|---|
| 194 | item.iItem = 0; //ListView_GetItemCount(hwndLV); |
|---|
| 195 | int id = ListView_InsertItem(hwndLV, &item); |
|---|
| 196 | msg = entry.file; |
|---|
| 197 | ListView_SetItemText(hwndLV, id, 1, const_cast<TCHAR*>(msg.c_str())); |
|---|
| 198 | msg = strEx::itos(entry.line); |
|---|
| 199 | ListView_SetItemText(hwndLV, id, 2, const_cast<TCHAR*>(msg.c_str())); |
|---|
| 200 | msg = entry.message; |
|---|
| 201 | ListView_SetItemText(hwndLV, id, 3, const_cast<TCHAR*>(msg.c_str())); |
|---|
| 202 | } |
|---|
| 203 | |
|---|
| 204 | INT_PTR CALLBACK TrayIcon::LogDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam) { |
|---|
| 205 | switch (uMsg) |
|---|
| 206 | { |
|---|
| 207 | case WM_INITDIALOG: |
|---|
| 208 | { |
|---|
| 209 | SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(NSCModuleWrapper::getModule(), MAKEINTRESOURCE(IDI_NSCP))); |
|---|
| 210 | SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(NSCModuleWrapper::getModule(), MAKEINTRESOURCE(IDI_NSCP))); |
|---|
| 211 | gSysTray.setLogWindow(hwndDlg); |
|---|
| 212 | HWND hwndLV = GetDlgItem(hwndDlg, IDC_LOG); |
|---|
| 213 | LVCOLUMN col; |
|---|
| 214 | col.mask = LVCF_TEXT|LVCF_WIDTH; |
|---|
| 215 | col.cx = 10; |
|---|
| 216 | col.pszText = _T("Type"); |
|---|
| 217 | ListView_InsertColumn(hwndLV, 1, &col); |
|---|
| 218 | col.pszText = _T("File"); |
|---|
| 219 | ListView_InsertColumn(hwndLV, 2, &col); |
|---|
| 220 | col.pszText = _T("Line"); |
|---|
| 221 | ListView_InsertColumn(hwndLV, 3, &col); |
|---|
| 222 | col.pszText = _T("Message"); |
|---|
| 223 | ListView_InsertColumn(hwndLV, 4, &col); |
|---|
| 224 | |
|---|
| 225 | SysTray::log_type log = gSysTray.getLog(); |
|---|
| 226 | for (SysTray::log_type::const_iterator cit = log.begin(); cit != log.end(); ++cit) { |
|---|
| 227 | insert_logrecord(hwndLV, *cit); |
|---|
| 228 | } |
|---|
| 229 | |
|---|
| 230 | ListView_SetColumnWidth(hwndLV, 0, LVSCW_AUTOSIZE_USEHEADER); |
|---|
| 231 | ListView_SetColumnWidth(hwndLV, 1, LVSCW_AUTOSIZE_USEHEADER); |
|---|
| 232 | ListView_SetColumnWidth(hwndLV, 2, LVSCW_AUTOSIZE_USEHEADER); |
|---|
| 233 | ListView_SetColumnWidth(hwndLV, 3, LVSCW_AUTOSIZE_USEHEADER); |
|---|
| 234 | } |
|---|
| 235 | return TRUE; |
|---|
| 236 | |
|---|
| 237 | case WM_USER+1: |
|---|
| 238 | { |
|---|
| 239 | HWND hwndLV = GetDlgItem(hwndDlg, IDC_LOG); |
|---|
| 240 | const SysTray::log_entry* record = reinterpret_cast<const SysTray::log_entry*>(wParam); |
|---|
| 241 | insert_logrecord(hwndLV, *record); |
|---|
| 242 | |
|---|
| 243 | } |
|---|
| 244 | return TRUE; |
|---|
| 245 | |
|---|
| 246 | case WM_SIZE: |
|---|
| 247 | if (wParam == SIZE_RESTORED) { |
|---|
| 248 | HWND hwndLV = GetDlgItem(hwndDlg, IDC_LOG); |
|---|
| 249 | ::SetWindowPos(hwndLV, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER); |
|---|
| 250 | } |
|---|
| 251 | return TRUE; |
|---|
| 252 | |
|---|
| 253 | case WM_COMMAND: |
|---|
| 254 | case IDOK: |
|---|
| 255 | case IDCANCEL: |
|---|
| 256 | gSysTray.setLogWindow(NULL); |
|---|
| 257 | EndDialog(hwndDlg, wParam); |
|---|
| 258 | return TRUE; |
|---|
| 259 | } |
|---|
| 260 | return FALSE; |
|---|
| 261 | } |
|---|
| 262 | |
|---|
| 263 | |
|---|
| 264 | INT_PTR CALLBACK TrayIcon::DialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam) |
|---|
| 265 | { |
|---|
| 266 | switch (uMsg) |
|---|
| 267 | { |
|---|
| 268 | case WM_DESTROY: |
|---|
| 269 | TrayIcon::removeIcon(hwndDlg); |
|---|
| 270 | PostQuitMessage(0); |
|---|
| 271 | return 0; |
|---|
| 272 | |
|---|
| 273 | case WM_INITDIALOG: |
|---|
| 274 | addIcon(hwndDlg); |
|---|
| 275 | break; |
|---|
| 276 | |
|---|
| 277 | case WM_ICON_NOTIFY: |
|---|
| 278 | if (lParam==WM_RBUTTONDOWN) { |
|---|
| 279 | HMENU hMenu = LoadMenu(NSCModuleWrapper::getModule(),MAKEINTRESOURCE(IDR_POPUP)); |
|---|
| 280 | HMENU hSubMenu = GetSubMenu(hMenu, 0); |
|---|
| 281 | const RECT r = {0, 0, 0, 0}; |
|---|
| 282 | POINT pt; |
|---|
| 283 | GetCursorPos(&pt); |
|---|
| 284 | SetForegroundWindow(hwndDlg); |
|---|
| 285 | int cmd = TrackPopupMenu(hSubMenu, TPM_LEFTALIGN|TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, &r); |
|---|
| 286 | DestroyMenu(hMenu); |
|---|
| 287 | switch (cmd) { |
|---|
| 288 | case ID_POPUP_STOPSERVICE: |
|---|
| 289 | NSCModuleHelper::StopService(); |
|---|
| 290 | break; |
|---|
| 291 | case ID_POPUP_INJECTCOMMAND: |
|---|
| 292 | //if (TrayIcon::defaultCommand.empty()) |
|---|
| 293 | // TrayIcon::defaultCommand = NSCModuleHelper::getSettingsString(_T("systray"), _T("defaultCommand"), _T("")); |
|---|
| 294 | CreateDialog(NSCModuleWrapper::getModule(),MAKEINTRESOURCE(IDD_INJECTDIALOG),hwndDlg,InjectDialogProc); |
|---|
| 295 | break; |
|---|
| 296 | case ID_POPUP_SHOWLOG: |
|---|
| 297 | CreateDialog(NSCModuleWrapper::getModule(),MAKEINTRESOURCE(IDD_LOGWINDOW),hwndDlg,LogDialogProc); |
|---|
| 298 | } |
|---|
| 299 | return TRUE; |
|---|
| 300 | } |
|---|
| 301 | break; |
|---|
| 302 | } |
|---|
| 303 | return FALSE; |
|---|
| 304 | } |
|---|
| 305 | void TrayIcon::addIcon(HWND hWnd) { |
|---|
| 306 | assert(NSCModuleWrapper::getModule() != NULL); |
|---|
| 307 | assert(hWnd != NULL); |
|---|
| 308 | |
|---|
| 309 | NOTIFYICONDATA ndata; |
|---|
| 310 | ndata.cbSize=sizeof(NOTIFYICONDATA); |
|---|
| 311 | ndata.hWnd=hWnd; |
|---|
| 312 | ndata.uID=2000; |
|---|
| 313 | ndata.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP; |
|---|
| 314 | ndata.uCallbackMessage=WM_ICON_NOTIFY; |
|---|
| 315 | ndata.hIcon=::LoadIcon(NSCModuleWrapper::getModule(),MAKEINTRESOURCE(IDI_NSCP)); |
|---|
| 316 | std::wstring title = NSCModuleHelper::getApplicationName() + _T(" - ") + NSCModuleHelper::getApplicationVersionString(); |
|---|
| 317 | wcsncpy_s(ndata.szTip, 64, title.c_str(), min(64, title.size())); |
|---|
| 318 | Shell_NotifyIcon(NIM_ADD,&ndata); |
|---|
| 319 | } |
|---|
| 320 | |
|---|
| 321 | void TrayIcon::removeIcon(HWND hWnd) { |
|---|
| 322 | NOTIFYICONDATA ndata; |
|---|
| 323 | ndata.cbSize=sizeof(NOTIFYICONDATA); |
|---|
| 324 | ndata.hWnd=hWnd; |
|---|
| 325 | ndata.uID=2000; |
|---|
| 326 | Shell_NotifyIcon(NIM_DELETE,&ndata); |
|---|
| 327 | } |
|---|