source: nscp/helpers/systray_helper/TrayWidget.cpp @ bc97cd8

0.4.00.4.10.4.2stable
Last change on this file since bc97cd8 was bc97cd8, checked in by Michael Medin <michael@…>, 5 years ago

2008-09-06 MickeM

  • Improved error reporting in the eventlogchecker
  • *BREAKING CHANGE* filter=new is now the default so unless you use the new filtering you need to specify filter=old instead! I Recommend everyone to stop using the "old" filtering.

2008-09-04 MickeM

  • Fixed issues with new service stuff on NT4 and W2K (should work fine now) + Added some DebugOutput? to service handling features so if you experience tropubel try using sysinternals DebugView? too se logging before the agent startes.
  • Fixed a memory leak in the error formating code

2008-08-24 MickeM

  • Changed NSCA "general problem" error message to be more descriptive.
  • Fixed issue with CheckCPU not returning a valid performance unit (%) see issue #219 for details.
  • Property mode set to 100644
File size: 21.5 KB
Line 
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
34logging::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
47typedef BOOL (WINAPI *LPFN_CHANGEWINDOWMESSAGEFILTER) (UINT, DWORD);
48LPFN_CHANGEWINDOWMESSAGEFILTER fnChangeWindowMessageFilter = NULL;
49BOOL 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
64std::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}
74HINSTANCE ghInstance = NULL;
75TrayWidget *gTrayInstance = NULL;
76TrayWidget::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}
92TrayWidget::~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}
106void 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}
116int 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
126void 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
162void TrayWidget::session_error(std::wstring file, unsigned int line, std::wstring msg) {
163        log(_T("error"), file.c_str(), line, msg);
164}
165
166void TrayWidget::session_log_message(int msgType, const TCHAR* file, const int line, std::wstring message) {
167        log(_T("message"), file, line, message);
168}
169void 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
195TrayWidget::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
202std::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}
212void 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
225class worker_thread {
226public:
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
337namespace TrayIcon
338{
339        std::wstring defaultCommand;
340}
341
342/*
343INT_PTR CALLBACK DialogProc(          HWND hwndDlg,
344    UINT uMsg,
345    WPARAM wParam,
346    LPARAM lParam
347);
348*/
349INT_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
452void 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
472INT_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}
529namespace TrayIcon
530{
531        HMENU hPopupMenu_ = NULL;
532}
533INT_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}
605void 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
618void 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}
Note: See TracBrowser for help on using the repository browser.