| 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 <config.h>
|
|---|
| 23 | #include "TrayWidget.h"
|
|---|
| 24 | #include "resource.h"
|
|---|
| 25 | #include <commctrl.h>
|
|---|
| 26 | #include <strEx.h>
|
|---|
| 27 | #include <ShellAPI.h>
|
|---|
| 28 | #include "TrayWidget.h"
|
|---|
| 29 | #include <error.hpp>
|
|---|
| 30 | #include <file_logger.hpp>
|
|---|
| 31 | #include <ServiceCmd.h>
|
|---|
| 32 |
|
|---|
| 33 |
|
|---|
| 34 | logging::file_logger g_log_instance(_T("nsclient++"),_T("systray.log"));
|
|---|
| 35 |
|
|---|
| 36 | #define LOG_ERROR_FILE(x) g_log_instance.log(_T("error"), __FILEW__, __LINE__, std::wstring(x).c_str());
|
|---|
| 37 | #define LOG_MESSAGE_FILE(x) g_log_instance.log(_T("message"), __FILEW__, __LINE__, std::wstring(x).c_str());
|
|---|
| 38 |
|
|---|
| 39 | #define LOG_ERROR_TRAY(x) log(_T("error"), __FILEW__, __LINE__, std::wstring(x).c_str());
|
|---|
| 40 | #define LOG_MESSAGE_TRAY(x) log(_T("message"), __FILEW__, __LINE__, std::wstring(x).c_str());
|
|---|
| 41 |
|
|---|
| 42 | #define LOG_ERROR_TO_TRAY(x) gTrayInstance->log(_T("error"), __FILEW__, __LINE__, std::wstring(x).c_str());
|
|---|
| 43 |
|
|---|
| 44 | #if WINVER < 0x0600
|
|---|
| 45 | #define MSGFLT_ADD 1
|
|---|
| 46 | #define MSGFLT_REMOVE 2
|
|---|
| 47 | typedef BOOL (WINAPI *LPFN_CHANGEWINDOWMESSAGEFILTER) (UINT, DWORD);
|
|---|
| 48 | LPFN_CHANGEWINDOWMESSAGEFILTER fnChangeWindowMessageFilter = NULL;
|
|---|
| 49 | BOOL ChangeWindowMessageFilter(UINT message, DWORD what)
|
|---|
| 50 | {
|
|---|
| 51 | if (fnChangeWindowMessageFilter == NULL) {
|
|---|
| 52 | HMODULE hMod = GetModuleHandle(TEXT("user32"));
|
|---|
| 53 | if (hMod == NULL)
|
|---|
| 54 | return false;
|
|---|
| 55 | fnChangeWindowMessageFilter = (LPFN_CHANGEWINDOWMESSAGEFILTER)GetProcAddress(hMod,"ChangeWindowMessageFilter");
|
|---|
| 56 | }
|
|---|
| 57 | if (fnChangeWindowMessageFilter == NULL) {
|
|---|
| 58 | return true;
|
|---|
| 59 | }
|
|---|
| 60 | return fnChangeWindowMessageFilter(message,what);
|
|---|
| 61 | }
|
|---|
| 62 | #endif
|
|---|
| 63 |
|
|---|
| 64 | std::wstring getArgumentValue(std::wstring key, strEx::splitList list) {
|
|---|
| 65 | for (strEx::splitList::const_iterator cit = list.begin(); cit != list.end(); ++cit) {
|
|---|
| 66 | if ((*cit) == key) {
|
|---|
| 67 | if (++cit == list.end())
|
|---|
| 68 | return _T("");
|
|---|
| 69 | return *cit;
|
|---|
| 70 | }
|
|---|
| 71 | }
|
|---|
| 72 | return _T("");
|
|---|
| 73 | }
|
|---|
| 74 | HINSTANCE ghInstance = NULL;
|
|---|
| 75 | TrayWidget *gTrayInstance = NULL;
|
|---|
| 76 | TrayWidget::TrayWidget(std::wstring cmdLine) {
|
|---|
| 77 | strEx::splitList list = strEx::splitEx(cmdLine, _T(" "));
|
|---|
| 78 | channel_id_ = getArgumentValue(_T("-channel"), list);
|
|---|
| 79 | if (channel_id_.empty()) {
|
|---|
| 80 | channel_id_ = _T("_solo_") + strEx::itos(GetCurrentProcessId()) + _T("_");
|
|---|
| 81 | }
|
|---|
| 82 | LOG_MESSAGE_TRAY(_T("Attempting to launch system tray module for ") + channel_id_);
|
|---|
| 83 | gTrayInstance = this;
|
|---|
| 84 | try {
|
|---|
| 85 | shared_client_.reset(new nsclient_session::shared_client_session(channel_id_, this));
|
|---|
| 86 | if (shared_client_.get() != NULL)
|
|---|
| 87 | shared_client_->attach_to_session(channel_id_);
|
|---|
| 88 | } catch (nsclient_session::session_exception e) {
|
|---|
| 89 | LOG_ERROR_TRAY(_T("Failed to attach to shared session: ") + e.what());
|
|---|
| 90 | }
|
|---|
| 91 | }
|
|---|
| 92 | TrayWidget::~TrayWidget() {
|
|---|
| 93 | gTrayInstance = NULL;
|
|---|
| 94 | try {
|
|---|
| 95 | if (shared_client_.get() != NULL) {
|
|---|
| 96 | LOG_ERROR_FILE(_T("Destroying shared session..."));
|
|---|
| 97 | shared_client_->close_session();
|
|---|
| 98 | }
|
|---|
| 99 | } catch (nsclient_session::session_exception e) {
|
|---|
| 100 | LOG_ERROR_FILE(_T("Failed to close shared session: ") + e.what());
|
|---|
| 101 | } catch (...) {
|
|---|
| 102 | LOG_ERROR_FILE(_T("Failed to close shared session: Unknown Exception"));
|
|---|
| 103 | }
|
|---|
| 104 | shared_client_.reset();
|
|---|
| 105 | }
|
|---|
| 106 | void TrayWidget::connectService() {
|
|---|
| 107 | LOG_MESSAGE_TRAY(_T("Reconnecting to the service..."));
|
|---|
| 108 | try {
|
|---|
| 109 | shared_client_.reset(new nsclient_session::shared_client_session(channel_id_, this));
|
|---|
| 110 | if (shared_client_.get() != NULL)
|
|---|
| 111 | shared_client_->attach_to_session(channel_id_);
|
|---|
| 112 | } catch (nsclient_session::session_exception e) {
|
|---|
| 113 | LOG_ERROR_TRAY(_T("Failed to attach to shared session: ") + e.what());
|
|---|
| 114 | }
|
|---|
| 115 | }
|
|---|
| 116 | int TrayWidget::inject(std::wstring command, std::wstring arguments, TCHAR splitter, bool escape, std::wstring &msg, std::wstring & perf) {
|
|---|
| 117 | if (shared_client_.get() == NULL) {
|
|---|
| 118 | LOG_ERROR_TRAY(_T("No active shared instance!"));
|
|---|
| 119 | return -1;
|
|---|
| 120 | }
|
|---|
| 121 | return shared_client_->inject(command, arguments, splitter, escape, msg, perf);
|
|---|
| 122 | }
|
|---|
| 123 |
|
|---|
| 124 |
|
|---|
| 125 |
|
|---|
| 126 | void TrayWidget::createDialog(HINSTANCE hInstance) {
|
|---|
| 127 | ghInstance = hInstance;
|
|---|
| 128 | hDlgWnd = ::CreateDialog(hInstance,MAKEINTRESOURCE(IDD_NSTRAYDLG),NULL,TrayIcon::DialogProc);
|
|---|
| 129 | if ((hDlgWnd == NULL)||!IsWindow(hDlgWnd)) {
|
|---|
| 130 | LOG_ERROR_TRAY(_T("Failed to create windows: ") + error::lookup::last_error());
|
|---|
| 131 | }
|
|---|
| 132 |
|
|---|
| 133 | UINT UDM_TASKBARCREATED = RegisterWindowMessage(_T("TaskbarCreated"));
|
|---|
| 134 | if (UDM_TASKBARCREATED == 0) {
|
|---|
| 135 | LOG_ERROR_TRAY(_T("Failed to register 'TaskbarCreated': ") + error::lookup::last_error());
|
|---|
| 136 | }
|
|---|
| 137 | if (!ChangeWindowMessageFilter(UDM_TASKBARCREATED, MSGFLT_ADD)) {
|
|---|
| 138 | LOG_ERROR_TRAY(_T("Failed to cchange window filter: ") + error::lookup::last_error());
|
|---|
| 139 | }
|
|---|
| 140 |
|
|---|
| 141 | MSG Msg;
|
|---|
| 142 | BOOL bRet;
|
|---|
| 143 | while((bRet = ::GetMessage(&Msg, NULL, 0, 0)) != 0)
|
|---|
| 144 | {
|
|---|
| 145 | if (Msg.message == WM_MY_CLOSE) {
|
|---|
| 146 | ::DestroyWindow(hDlgWnd);
|
|---|
| 147 | } else if (Msg.message == UDM_TASKBARCREATED) {
|
|---|
| 148 | LOG_MESSAGE_TRAY(_T("Recreating systray icon..."));
|
|---|
| 149 | TrayIcon::addIcon(Msg.hwnd);
|
|---|
| 150 | } else if (bRet == -1) {
|
|---|
| 151 | // handle the error and possibly exit
|
|---|
| 152 | LOG_ERROR_TRAY(_T("Wonder what this is... please let me know..."));
|
|---|
| 153 | return;
|
|---|
| 154 | } else {
|
|---|
| 155 | //} else if (!::IsWindow(hDlgWnd) || !::IsDialogMessage(hDlgWnd, &Msg)) {
|
|---|
| 156 | ::TranslateMessage(&Msg);
|
|---|
| 157 | ::DispatchMessage(&Msg);
|
|---|
| 158 | }
|
|---|
| 159 | }
|
|---|
| 160 | }
|
|---|
| 161 |
|
|---|
| 162 | void TrayWidget::session_error(std::wstring file, unsigned int line, std::wstring msg) {
|
|---|
| 163 | log(_T("error"), file.c_str(), line, msg);
|
|---|
| 164 | }
|
|---|
| 165 |
|
|---|
| 166 | void TrayWidget::session_log_message(int msgType, const TCHAR* file, const int line, std::wstring message) {
|
|---|
| 167 | log(_T("message"), file, line, message);
|
|---|
| 168 | }
|
|---|
| 169 | void TrayWidget::log(std::wstring category, const TCHAR* file, const int line, std::wstring message) {
|
|---|
| 170 | log_entry record(category, file, line, message);
|
|---|
| 171 | g_log_instance.log(_T("error"), record.file.c_str(), record.line, record.message.c_str());
|
|---|
| 172 | HWND hWnd = NULL;
|
|---|
| 173 | {
|
|---|
| 174 | try {
|
|---|
| 175 | MutexLock lock(logLock);
|
|---|
| 176 | if (lock.hasMutex()) {
|
|---|
| 177 | log_.push_back(record);
|
|---|
| 178 | if (log_.size() > 50)
|
|---|
| 179 | log_.pop_front();
|
|---|
| 180 | hWnd = hLogWnd;
|
|---|
| 181 | } else {
|
|---|
| 182 | g_log_instance.log(_T("error"), __FILEW__, __LINE__, _T("Failed to get mutex in logger, message discarded (follows)"));
|
|---|
| 183 | g_log_instance.log(_T("discarded"), record.file.c_str(), record.line, record.message.c_str());
|
|---|
| 184 | }
|
|---|
| 185 | } catch (...) {
|
|---|
| 186 | g_log_instance.log(_T("error"), __FILEW__, __LINE__, _T("Failed to get mutex in logger, message discarded (follows)"));
|
|---|
| 187 | g_log_instance.log(_T("discarded"), record.file.c_str(), record.line, record.message.c_str());
|
|---|
| 188 | }
|
|---|
| 189 | }
|
|---|
| 190 | if (hWnd) {
|
|---|
| 191 | SendMessage(hWnd, WM_USER+1, reinterpret_cast<WPARAM>(&record), NULL);
|
|---|
| 192 | }
|
|---|
| 193 | }
|
|---|
| 194 |
|
|---|
| 195 | TrayWidget::log_type TrayWidget::getLog() {
|
|---|
| 196 | log_type ret;
|
|---|
| 197 | for (log_type::const_iterator cit = log_.begin(); cit != log_.end(); ++cit)
|
|---|
| 198 | ret.push_back(*cit);
|
|---|
| 199 | return ret;
|
|---|
| 200 | }
|
|---|
| 201 |
|
|---|
| 202 | std::wstring getDlgItemText(HWND hDlg, int nIDDlgItem) {
|
|---|
| 203 | #define BUFF_LEN 4096
|
|---|
| 204 | std::wstring ret;
|
|---|
| 205 | TCHAR *buffer = new TCHAR[BUFF_LEN+1];
|
|---|
| 206 | if (!GetDlgItemText(hDlg, nIDDlgItem, buffer, BUFF_LEN))
|
|---|
| 207 | buffer[0]=0;
|
|---|
| 208 | ret = buffer;
|
|---|
| 209 | delete [] buffer;
|
|---|
| 210 | return ret;
|
|---|
| 211 | }
|
|---|
| 212 | void updateDescFromCmd(HWND hDlg, std::wstring cmd) {
|
|---|
| 213 | std::wstring result = _T("");
|
|---|
| 214 | try {
|
|---|
| 215 | result = _T("TODO: re-implement this!"); //NSCModuleHelper::describeCommand(cmd);
|
|---|
| 216 | //} catch (NSCModuleHelper::NSCMHExcpetion &e) {
|
|---|
| 217 | // result = _T("Error: ") + e.msg_;
|
|---|
| 218 | } catch (...) {
|
|---|
| 219 | result = _T("Unknown error!");
|
|---|
| 220 | }
|
|---|
| 221 | SetDlgItemText(hDlg, IDC_DESCRIPTION, result.c_str());
|
|---|
| 222 | }
|
|---|
| 223 |
|
|---|
| 224 |
|
|---|
| 225 | class worker_thread {
|
|---|
| 226 | public:
|
|---|
| 227 | struct start_block {
|
|---|
| 228 | std::wstring cmd;
|
|---|
| 229 | HMENU hMenu;
|
|---|
| 230 | HWND hWnd;
|
|---|
| 231 | };
|
|---|
| 232 |
|
|---|
| 233 | void update(HMENU hMenu, UINT pos, LPTSTR text) {
|
|---|
| 234 | if (!ModifyMenu(hMenu, pos, MF_BYCOMMAND|MF_STRING|MF_GRAYED, pos, text))
|
|---|
| 235 | LOG_ERROR_TO_TRAY(_T("Failed to update menu: ") + error::lookup::last_error());
|
|---|
| 236 | }
|
|---|
| 237 |
|
|---|
| 238 | DWORD threadProc(LPVOID lpParameter) {
|
|---|
| 239 | start_block* param = static_cast<start_block*>(lpParameter);
|
|---|
| 240 | std::wstring cmd = param->cmd;
|
|---|
| 241 | HMENU hMenu = param->hMenu;
|
|---|
| 242 | HWND hWnd = param->hWnd;
|
|---|
| 243 | delete param;
|
|---|
| 244 | if (cmd == _T("update-status")) {
|
|---|
| 245 | update(hMenu, ID_SERVICE_STATUS, _T("getting..."));
|
|---|
| 246 | try {
|
|---|
| 247 | if (serviceControll::isStarted(SZSERVICENAME)) {
|
|---|
| 248 | update(hMenu, ID_SERVICE_STATUS, _T("Started"));
|
|---|
| 249 | } else {
|
|---|
| 250 | update(hMenu, ID_SERVICE_STATUS, _T("Stopped"));
|
|---|
| 251 | }
|
|---|
| 252 | } catch (serviceControll::SCException &e) {
|
|---|
| 253 | LOG_ERROR_TO_TRAY(_T("Failed to get service information: ") + e.error_);
|
|---|
| 254 | } catch (...) {
|
|---|
| 255 | LOG_ERROR_TO_TRAY(_T("Failed to get service information: Unknown error"));
|
|---|
| 256 | }
|
|---|
| 257 | } else if (cmd == _T("start-service")) {
|
|---|
| 258 | update(hMenu, ID_SERVICE_STATUS, _T("Starting"));
|
|---|
| 259 | try {
|
|---|
| 260 | serviceControll::Start(SZSERVICENAME);
|
|---|
| 261 | update(hMenu, ID_SERVICE_STATUS, _T("Started"));
|
|---|
| 262 | } catch (serviceControll::SCException &e) {
|
|---|
| 263 | update(hMenu, ID_SERVICE_STATUS, _T("Unknown (failed to start)"));
|
|---|
| 264 | LOG_ERROR_TO_TRAY(_T("Failed to get service information: ") + e.error_);
|
|---|
| 265 | } catch (...) {
|
|---|
| 266 | update(hMenu, ID_SERVICE_STATUS, _T("Unknown (failed to start)"));
|
|---|
| 267 | LOG_ERROR_TO_TRAY(_T("Failed to get service information: Unknown error"));
|
|---|
| 268 | }
|
|---|
| 269 | } else if (cmd == _T("stop-service")) {
|
|---|
| 270 | update(hMenu, ID_SERVICE_STATUS, _T("Stopped"));
|
|---|
| 271 | try {
|
|---|
| 272 | serviceControll::Stop(SZSERVICENAME);
|
|---|
| 273 | update(hMenu, ID_SERVICE_STATUS, _T("Stopped"));
|
|---|
| 274 | } catch (serviceControll::SCException &e) {
|
|---|
| 275 | update(hMenu, ID_SERVICE_STATUS, _T("Unknown (failed to stop)"));
|
|---|
| 276 | LOG_ERROR_TO_TRAY(_T("Failed to get service information: ") + e.error_);
|
|---|
| 277 | } catch (...) {
|
|---|
| 278 | update(hMenu, ID_SERVICE_STATUS, _T("Unknown (failed to stop)"));
|
|---|
| 279 | LOG_ERROR_TO_TRAY(_T("Failed to get service information: Unknown error"));
|
|---|
| 280 | }
|
|---|
| 281 | } else if (cmd == _T("inject-button-pressed")) {
|
|---|
| 282 | std::wstring result = _T("");
|
|---|
| 283 | std::wstring cmd = getDlgItemText(hWnd, IDC_CMD_BOX);
|
|---|
| 284 | std::wstring args = getDlgItemText(hWnd, IDC_ARG_BOX);
|
|---|
| 285 | std::wstring msg;
|
|---|
| 286 | std::wstring perf;
|
|---|
| 287 | try {
|
|---|
| 288 | int ret = gTrayInstance->inject(cmd, args, L' ', true, msg, perf);
|
|---|
| 289 | //NSCAPI::nagiosReturn ret = NSCModuleHelper::InjectSplitAndCommand(cmd, args, ' ', msg, perf);
|
|---|
| 290 | /*
|
|---|
| 291 | if (ret == NSCAPI::returnIgnored) {
|
|---|
| 292 | result = _T("Command not found!");
|
|---|
| 293 | } else {
|
|---|
| 294 | result = NSCHelper::translateReturn(ret);
|
|---|
| 295 | }
|
|---|
| 296 | */
|
|---|
| 297 | result = _T("TODO: re-implement this: ") + strEx::itos(ret);
|
|---|
| 298 | //} catch (NSCModuleHelper::NSCMHExcpetion &e) {
|
|---|
| 299 | // result = _T("Error: ") + e.msg_;
|
|---|
| 300 | } catch (...) {
|
|---|
| 301 | result = _T("Unknown error!");
|
|---|
| 302 | }
|
|---|
| 303 | SetDlgItemText(hWnd, IDC_DESCRIPTION, result.c_str());
|
|---|
| 304 | SetDlgItemText(hWnd, IDC_MSG, msg.c_str());
|
|---|
| 305 | SetDlgItemText(hWnd, IDC_PERF, perf.c_str());
|
|---|
| 306 | }
|
|---|
| 307 | return 0;
|
|---|
| 308 | }
|
|---|
| 309 | static LPVOID init(std::wstring command, HMENU hMenu, HWND hWnd = NULL) {
|
|---|
| 310 | start_block *sb = new start_block;
|
|---|
| 311 | sb->cmd = command;
|
|---|
| 312 | sb->hMenu = hMenu;
|
|---|
| 313 | sb->hWnd = hWnd;
|
|---|
| 314 | return sb;
|
|---|
| 315 | }
|
|---|
| 316 |
|
|---|
| 317 | static void updateServiceStatus(HMENU hMenu) {
|
|---|
| 318 | Thread<worker_thread> *pThread = new Thread<worker_thread>(_T("tray-worker-thread"));
|
|---|
| 319 | pThread->createThread(worker_thread::init(_T("update-status"), hMenu));
|
|---|
| 320 | }
|
|---|
| 321 | static void startService(HMENU hMenu) {
|
|---|
| 322 | Thread<worker_thread> *pThread = new Thread<worker_thread>(_T("tray-worker-thread"));
|
|---|
| 323 | pThread->createThread(worker_thread::init(_T("start-service"), hMenu));
|
|---|
| 324 | }
|
|---|
| 325 | static void stopService(HMENU hMenu) {
|
|---|
| 326 | Thread<worker_thread> *pThread = new Thread<worker_thread>(_T("tray-worker-thread"));
|
|---|
| 327 | pThread->createThread(worker_thread::init(_T("stop-service"), hMenu));
|
|---|
| 328 | }
|
|---|
| 329 | static void injectDialog(HWND hWnd) {
|
|---|
| 330 | Thread<worker_thread> *pThread = new Thread<worker_thread>(_T("tray-worker-thread"));
|
|---|
| 331 | pThread->createThread(worker_thread::init(_T("inject-button-pressed"), NULL, hWnd));
|
|---|
| 332 | }
|
|---|
| 333 | };
|
|---|
| 334 |
|
|---|
| 335 |
|
|---|
| 336 |
|
|---|
| 337 | namespace TrayIcon
|
|---|
| 338 | {
|
|---|
| 339 | std::wstring defaultCommand;
|
|---|
| 340 | }
|
|---|
| 341 |
|
|---|
| 342 | /*
|
|---|
| 343 | INT_PTR CALLBACK DialogProc( HWND hwndDlg,
|
|---|
| 344 | UINT uMsg,
|
|---|
| 345 | WPARAM wParam,
|
|---|
| 346 | LPARAM lParam
|
|---|
| 347 | );
|
|---|
| 348 | */
|
|---|
| 349 | INT_PTR CALLBACK TrayIcon::InjectDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam) {
|
|---|
| 350 | switch (uMsg)
|
|---|
| 351 | {
|
|---|
| 352 | case WM_INITDIALOG:
|
|---|
| 353 | {
|
|---|
| 354 | SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_NSCP)));
|
|---|
| 355 | SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_NSCP)));
|
|---|
| 356 | SetDlgItemText(hwndDlg, IDC_CMD_BOX, TrayIcon::defaultCommand.c_str());
|
|---|
| 357 | SetDlgItemText(hwndDlg, IDC_DESCRIPTION, _T("Loading commands, please wait..."));
|
|---|
| 358 |
|
|---|
| 359 | SendDlgItemMessage(hwndDlg, IDC_CMD_BOX, CB_RESETCONTENT, 0, 0);
|
|---|
| 360 | std::wstring result = _T("");
|
|---|
| 361 | /*
|
|---|
| 362 | TODO! re-implement this!
|
|---|
| 363 | try {
|
|---|
| 364 | std::list<std::wstring> lst = NSCModuleHelper::getAllCommandNames();
|
|---|
| 365 | for (std::list<std::wstring>::const_iterator cit = lst.begin(); cit != lst.end(); ++cit) {
|
|---|
| 366 | SendDlgItemMessage(hwndDlg, IDC_CMD_BOX, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>( (*cit).c_str() ));
|
|---|
| 367 | }
|
|---|
| 368 | } catch (NSCModuleHelper::NSCMHExcpetion &e) {
|
|---|
| 369 | result = _T("Error: ") + e.msg_;
|
|---|
| 370 | } catch (...) {
|
|---|
| 371 | result = _T("Unknown error!");
|
|---|
| 372 | }
|
|---|
| 373 | */
|
|---|
| 374 | SetDlgItemText(hwndDlg, IDC_DESCRIPTION, result.c_str());
|
|---|
| 375 | }
|
|---|
| 376 | break;
|
|---|
| 377 | case WM_COMMAND:
|
|---|
| 378 | switch (LOWORD(wParam))
|
|---|
| 379 | {
|
|---|
| 380 | case IDC_CMD_BOX:
|
|---|
| 381 | switch(HIWORD(wParam))
|
|---|
| 382 | {
|
|---|
| 383 | case CBN_SELCHANGE:
|
|---|
| 384 | {
|
|---|
| 385 | std::wstring cmd;
|
|---|
| 386 | unsigned int id = SendDlgItemMessage(hwndDlg, IDC_CMD_BOX, CB_GETCURSEL, 0, 0);
|
|---|
| 387 | unsigned int len = SendDlgItemMessage(hwndDlg, IDC_CMD_BOX, CB_GETLBTEXTLEN, id, 0);
|
|---|
| 388 | TCHAR *buf = new TCHAR[len+2];
|
|---|
| 389 | LRESULT ret;
|
|---|
| 390 | ret = SendDlgItemMessage(hwndDlg, IDC_CMD_BOX, CB_GETLBTEXT, id, reinterpret_cast<LPARAM>(buf));
|
|---|
| 391 | if (ret > 0 && ret <= len) {
|
|---|
| 392 | cmd = buf;
|
|---|
| 393 | updateDescFromCmd(hwndDlg, cmd);
|
|---|
| 394 | }
|
|---|
| 395 | delete [] buf;
|
|---|
| 396 | }
|
|---|
| 397 | break;
|
|---|
| 398 | case CBN_KILLFOCUS:
|
|---|
| 399 | updateDescFromCmd(hwndDlg, getDlgItemText(hwndDlg, IDC_CMD_BOX));
|
|---|
| 400 | break;
|
|---|
| 401 | }
|
|---|
| 402 | break;
|
|---|
| 403 | case IDC_INJECT:
|
|---|
| 404 | worker_thread::injectDialog(hwndDlg);
|
|---|
| 405 | /*
|
|---|
| 406 | {
|
|---|
| 407 | std::wstring result = _T("");
|
|---|
| 408 | std::wstring cmd = getDlgItemText(hwndDlg, IDC_CMD_BOX);
|
|---|
| 409 | std::wstring args = getDlgItemText(hwndDlg, IDC_ARG_BOX);
|
|---|
| 410 | std::wstring msg;
|
|---|
| 411 | std::wstring perf;
|
|---|
| 412 | try {
|
|---|
| 413 | int ret = gTrayInstance->inject(cmd, args, _T(" "), true, msg, perf);
|
|---|
| 414 | //NSCAPI::nagiosReturn ret = NSCModuleHelper::InjectSplitAndCommand(cmd, args, ' ', msg, perf);
|
|---|
| 415 | / *
|
|---|
| 416 | if (ret == NSCAPI::returnIgnored) {
|
|---|
| 417 | result = _T("Command not found!");
|
|---|
| 418 | } else {
|
|---|
| 419 | result = NSCHelper::translateReturn(ret);
|
|---|
| 420 | }
|
|---|
| 421 | * /
|
|---|
| 422 | result = _T("TODO: re-implement this: ") + strEx::itos(ret);
|
|---|
| 423 | //} catch (NSCModuleHelper::NSCMHExcpetion &e) {
|
|---|
| 424 | // result = _T("Error: ") + e.msg_;
|
|---|
| 425 | } catch (...) {
|
|---|
| 426 | result = _T("Unknown error!");
|
|---|
| 427 | }
|
|---|
| 428 | SetDlgItemText(hwndDlg, IDC_DESCRIPTION, result.c_str());
|
|---|
| 429 | SetDlgItemText(hwndDlg, IDC_MSG, msg.c_str());
|
|---|
| 430 | SetDlgItemText(hwndDlg, IDC_PERF, perf.c_str());
|
|---|
| 431 | }
|
|---|
| 432 | */
|
|---|
| 433 | break;
|
|---|
| 434 | case IDOK:
|
|---|
| 435 | {
|
|---|
| 436 | TCHAR *c=new TCHAR[1024];
|
|---|
| 437 | if (GetDlgItemText(hwndDlg, IDC_COMMAND, c, 1023))
|
|---|
| 438 | TrayIcon::defaultCommand = c;
|
|---|
| 439 | delete [] c;
|
|---|
| 440 | }
|
|---|
| 441 |
|
|---|
| 442 | case IDCANCEL:
|
|---|
| 443 | EndDialog(hwndDlg, wParam);
|
|---|
| 444 | return TRUE;
|
|---|
| 445 | }
|
|---|
| 446 | }
|
|---|
| 447 | return FALSE;
|
|---|
| 448 | }
|
|---|
| 449 |
|
|---|
| 450 |
|
|---|
| 451 |
|
|---|
| 452 | void insert_logrecord(HWND hwndLV, const TrayWidget::log_entry &entry) {
|
|---|
| 453 | LVITEM item;
|
|---|
| 454 | item.mask = LVIF_TEXT;
|
|---|
| 455 | std::wstring msg = entry.category;
|
|---|
| 456 | item.pszText = const_cast<TCHAR*>(msg.c_str());
|
|---|
| 457 | item.iSubItem = 0;
|
|---|
| 458 | item.iItem = 0; //ListView_GetItemCount(hwndLV);
|
|---|
| 459 | int id = ListView_InsertItem(hwndLV, &item);
|
|---|
| 460 | msg = entry.file;
|
|---|
| 461 |
|
|---|
| 462 | std::wstring::size_type pos = msg.find_last_of(_T("\\"));
|
|---|
| 463 | if (pos != std::wstring::npos)
|
|---|
| 464 | msg = msg.substr(pos);
|
|---|
| 465 | ListView_SetItemText(hwndLV, id, 1, const_cast<TCHAR*>(msg.c_str()));
|
|---|
| 466 | msg = strEx::itos(entry.line);
|
|---|
| 467 | ListView_SetItemText(hwndLV, id, 2, const_cast<TCHAR*>(msg.c_str()));
|
|---|
| 468 | msg = entry.message;
|
|---|
| 469 | ListView_SetItemText(hwndLV, id, 3, const_cast<TCHAR*>(msg.c_str()));
|
|---|
| 470 | }
|
|---|
| 471 |
|
|---|
| 472 | INT_PTR CALLBACK TrayIcon::LogDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam) {
|
|---|
| 473 | switch (uMsg)
|
|---|
| 474 | {
|
|---|
| 475 | case WM_INITDIALOG:
|
|---|
| 476 | {
|
|---|
| 477 | SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_NSCP)));
|
|---|
| 478 | SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_NSCP)));
|
|---|
| 479 | gTrayInstance->setLogWindow(hwndDlg);
|
|---|
| 480 | HWND hwndLV = GetDlgItem(hwndDlg, IDC_LOG);
|
|---|
| 481 | LVCOLUMN col;
|
|---|
| 482 | col.mask = LVCF_TEXT|LVCF_WIDTH;
|
|---|
| 483 | col.cx = 10;
|
|---|
| 484 | col.pszText = _T("Type");
|
|---|
| 485 | ListView_InsertColumn(hwndLV, 1, &col);
|
|---|
| 486 | col.pszText = _T("File");
|
|---|
| 487 | ListView_InsertColumn(hwndLV, 2, &col);
|
|---|
| 488 | col.pszText = _T("Line");
|
|---|
| 489 | ListView_InsertColumn(hwndLV, 3, &col);
|
|---|
| 490 | col.pszText = _T("Message");
|
|---|
| 491 | ListView_InsertColumn(hwndLV, 4, &col);
|
|---|
| 492 | TrayWidget::log_type log = gTrayInstance->getLog();
|
|---|
| 493 | for (TrayWidget::log_type::const_iterator cit = log.begin(); cit != log.end(); ++cit) {
|
|---|
| 494 | insert_logrecord(hwndLV, *cit);
|
|---|
| 495 | }
|
|---|
| 496 |
|
|---|
| 497 | ListView_SetColumnWidth(hwndLV, 0, LVSCW_AUTOSIZE_USEHEADER);
|
|---|
| 498 | ListView_SetColumnWidth(hwndLV, 1, LVSCW_AUTOSIZE_USEHEADER);
|
|---|
| 499 | ListView_SetColumnWidth(hwndLV, 2, LVSCW_AUTOSIZE_USEHEADER);
|
|---|
| 500 | ListView_SetColumnWidth(hwndLV, 3, LVSCW_AUTOSIZE_USEHEADER);
|
|---|
| 501 | }
|
|---|
| 502 | return TRUE;
|
|---|
| 503 |
|
|---|
| 504 | case WM_USER+1:
|
|---|
| 505 | {
|
|---|
| 506 | HWND hwndLV = GetDlgItem(hwndDlg, IDC_LOG);
|
|---|
| 507 | const TrayWidget::log_entry* record = reinterpret_cast<const TrayWidget::log_entry*>(wParam);
|
|---|
| 508 | insert_logrecord(hwndLV, *record);
|
|---|
| 509 |
|
|---|
| 510 | }
|
|---|
| 511 | return TRUE;
|
|---|
| 512 |
|
|---|
| 513 | case WM_SIZE:
|
|---|
| 514 | if (wParam == SIZE_RESTORED) {
|
|---|
| 515 | HWND hwndLV = GetDlgItem(hwndDlg, IDC_LOG);
|
|---|
| 516 | ::SetWindowPos(hwndLV, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER);
|
|---|
| 517 | }
|
|---|
| 518 | return TRUE;
|
|---|
| 519 |
|
|---|
| 520 | case WM_COMMAND:
|
|---|
| 521 | case IDOK:
|
|---|
| 522 | case IDCANCEL:
|
|---|
| 523 | gTrayInstance->setLogWindow(NULL);
|
|---|
| 524 | EndDialog(hwndDlg, wParam);
|
|---|
| 525 | return TRUE;
|
|---|
| 526 | }
|
|---|
| 527 | return FALSE;
|
|---|
| 528 | }
|
|---|
| 529 | namespace TrayIcon
|
|---|
| 530 | {
|
|---|
| 531 | HMENU hPopupMenu_ = NULL;
|
|---|
| 532 | }
|
|---|
| 533 | INT_PTR CALLBACK TrayIcon::DialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
|
|---|
| 534 | {
|
|---|
| 535 | switch (uMsg)
|
|---|
| 536 | {
|
|---|
| 537 | case WM_DESTROY:
|
|---|
| 538 | if (hPopupMenu_ != NULL)
|
|---|
| 539 | DestroyMenu(hPopupMenu_);
|
|---|
| 540 | TrayIcon::removeIcon(hwndDlg);
|
|---|
| 541 | PostQuitMessage(0);
|
|---|
| 542 | return 0;
|
|---|
| 543 |
|
|---|
| 544 | case WM_INITDIALOG:
|
|---|
| 545 | addIcon(hwndDlg);
|
|---|
| 546 | break;
|
|---|
| 547 |
|
|---|
| 548 | case WM_COMMAND:
|
|---|
| 549 | if (HIWORD(wParam) == 0) {
|
|---|
| 550 | switch (wParam)
|
|---|
| 551 | {
|
|---|
| 552 | case ID_POPUP_CONNECT:
|
|---|
| 553 | gTrayInstance->connectService();
|
|---|
| 554 | break;
|
|---|
| 555 | case ID_POPUP_CLOSE:
|
|---|
| 556 | ::PostMessage(hwndDlg, WM_MY_CLOSE, NULL, NULL);
|
|---|
| 557 | break;
|
|---|
| 558 | case ID_SERVICE_STATUS:
|
|---|
| 559 | worker_thread::updateServiceStatus(GetSubMenu(hPopupMenu_, 0));
|
|---|
| 560 | break;
|
|---|
| 561 | case ID_SERVICE_START:
|
|---|
| 562 | worker_thread::startService(GetSubMenu(hPopupMenu_, 0));
|
|---|
| 563 | break;
|
|---|
| 564 | case ID_SERVICE_STOP:
|
|---|
| 565 | worker_thread::stopService(GetSubMenu(hPopupMenu_, 0));
|
|---|
| 566 | break;
|
|---|
| 567 | case ID_POPUP_SHOWLOG:
|
|---|
| 568 | if (IsWindow(gTrayInstance->getLogWindow())) {
|
|---|
| 569 | ::ShowWindow(gTrayInstance->getLogWindow(), SW_SHOW);
|
|---|
| 570 | ::SetForegroundWindow(gTrayInstance->getLogWindow());
|
|---|
| 571 | }
|
|---|
| 572 | else
|
|---|
| 573 | CreateDialog(ghInstance,MAKEINTRESOURCE(IDD_LOGWINDOW),hwndDlg,LogDialogProc);
|
|---|
| 574 | break;
|
|---|
| 575 | case ID_POPUP_INJECTCOMMAND:
|
|---|
| 576 | //if (TrayIcon::defaultCommand.empty())
|
|---|
| 577 | // TrayIcon::defaultCommand = NSCModuleHelper::getSettingsString(_T("systray"), _T("defaultCommand"), _T(""));
|
|---|
| 578 | CreateDialog(ghInstance,MAKEINTRESOURCE(IDD_INJECTDIALOG),hwndDlg,InjectDialogProc);
|
|---|
| 579 | break;
|
|---|
| 580 | }
|
|---|
| 581 | }
|
|---|
| 582 | break;
|
|---|
| 583 |
|
|---|
| 584 | case WM_ICON_NOTIFY:
|
|---|
| 585 | if (lParam==WM_RBUTTONDOWN) {
|
|---|
| 586 | bool created = false;
|
|---|
| 587 | if (hPopupMenu_ == NULL) {
|
|---|
| 588 | hPopupMenu_ = LoadMenu(ghInstance,MAKEINTRESOURCE(IDR_POPUP));
|
|---|
| 589 | created = true;
|
|---|
| 590 | }
|
|---|
| 591 | HMENU hSubMenu = GetSubMenu(hPopupMenu_, 0);
|
|---|
| 592 | POINT pt;
|
|---|
| 593 | GetCursorPos(&pt);
|
|---|
| 594 | SetForegroundWindow(hwndDlg);
|
|---|
| 595 | TrackPopupMenu(hSubMenu, TPM_LEFTALIGN, pt.x, pt.y, 0, hwndDlg, NULL);
|
|---|
| 596 | PostMessage(hwndDlg, WM_NULL, 0, 0);
|
|---|
| 597 | if (created)
|
|---|
| 598 | worker_thread::updateServiceStatus(GetSubMenu(hPopupMenu_, 0));
|
|---|
| 599 | return TRUE;
|
|---|
| 600 | }
|
|---|
| 601 | break;
|
|---|
| 602 | }
|
|---|
| 603 | return FALSE;
|
|---|
| 604 | }
|
|---|
| 605 | void TrayIcon::addIcon(HWND hWnd) {
|
|---|
| 606 | NOTIFYICONDATA ndata;
|
|---|
| 607 | ndata.cbSize=sizeof(NOTIFYICONDATA);
|
|---|
| 608 | ndata.hWnd=hWnd;
|
|---|
| 609 | ndata.uID=2000;
|
|---|
| 610 | ndata.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP;
|
|---|
| 611 | ndata.uCallbackMessage=WM_ICON_NOTIFY;
|
|---|
| 612 | ndata.hIcon=::LoadIcon(ghInstance,MAKEINTRESOURCE(IDI_NSCP));
|
|---|
| 613 | std::wstring title = _T("NSClient++ SystemTray (TODO)"); //NSCModuleHelper::getApplicationName() + _T(" - ") + NSCModuleHelper::getApplicationVersionString();
|
|---|
| 614 | wcsncpy_s(ndata.szTip, 64, title.c_str(), min(64, title.size()));
|
|---|
| 615 | Shell_NotifyIcon(NIM_ADD,&ndata);
|
|---|
| 616 | }
|
|---|
| 617 |
|
|---|
| 618 | void TrayIcon::removeIcon(HWND hWnd) {
|
|---|
| 619 | NOTIFYICONDATA ndata;
|
|---|
| 620 | ndata.cbSize=sizeof(NOTIFYICONDATA);
|
|---|
| 621 | ndata.hWnd=hWnd;
|
|---|
| 622 | ndata.uID=2000;
|
|---|
| 623 | Shell_NotifyIcon(NIM_DELETE,&ndata);
|
|---|
| 624 | } |
|---|