source: nscp/modules/SysTray/TrayIcon.cpp

0.4.1
Last change on this file was 1d53fe0, checked in by Michael Medin <michael@…>, 4 years ago

2009-02-11 MickeM

  • Fixed so that performance data is always(?) renderd regardless of if we have bounds or not. This was primarily to fix issues where we have might not "unexpectedly" get performance data (might still be some issues here so let me know).

2009-02-06 MickeM

2009-02-05 MickeM

  • Fixed so the error message for "to small eventlog buffer" specifies the required size.
  • Changed so that event log buffer problems are "ignored in the result" (still logged in the error log).

2009-02-03 MickeM

  • Added support for changing the time when using NSCA with the time_delay in NSC.ini time_delay=+4h or time_delay=-1h etc should can now be used when system time not the same as NSCA time.

2009-01-30 MickeM

  • Added support for changing name and description of service from the /install command line NSClient++ /install [gui] [start] [service name] [description] NSClient++ /uninstall [gui] [stop] [service name] NSClient++ /start [gui] [service name] NSClient++ /stop [gui] [service name]

2009-01-28 MickeM

  • Slightly improved error handling around socket creation
  • Fixed some pretty minor issues with the SysTray module (uncreation as well as new boost build).

2009-01-25 MickeM

  • Fixed issue with checkVersion (#242)
  • Fixed spelling error (#244)
  • Fixed crash in CheckFile when a file was locked in exclusive mode (#254) + Improved error handling in all CheckDIsk/CheckFile checks. Should report errors better now.
  • Updated the config file a bit: remving "beta" from a bunch of modules no longer in beta. (#270) + Added more filter operatos to all numeric filters so they accept eq:, ne:, gt:, lt: in addition to =, >, <, <>, !, !=, in: (#269)

2009-01-23 MickeM

+ Added better support for numerical hit matching in the eventlog module. You can now use exact and detailed matching.

You can now use the following syntax:
CheckEventLog ... warn=ne:1 crit=eq:0 ...
To generate a warning if the number of hits are != 1 and a critical if the number of hits are = 0.
Other operators avalible are: =, >, <, <>, !, !=, eq:, ne:, gt:, lt:

  • Property mode set to 100644
File size: 13.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 "trayicon.h"
23#include "resource.h"
24#include <commctrl.h>
25#include <strEx.h>
26#include <ShellAPI.h>
27#include "SysTray.h"
28#include <error.hpp>
29
30
31extern SysTray gSysTray;
32
33//BOOL ChangeWindowMessageFilter(UINT message,DWORD dwFlag);
34
35unsigned IconWidget_::threadProc(LPVOID lpParameter)
36{
37        createDialog();
38        return 0;
39}
40
41#ifdef WINVER < 0x0600
42#define MSGFLT_ADD 1
43#define MSGFLT_REMOVE 2
44typedef BOOL (WINAPI *LPFN_CHANGEWINDOWMESSAGEFILTER) (UINT, DWORD);
45#endif
46
47LPFN_CHANGEWINDOWMESSAGEFILTER fnChangeWindowMessageFilter = NULL;
48BOOL ChangeWindowMessageFilter_(UINT message, DWORD what)
49{
50        if (fnChangeWindowMessageFilter == NULL)
51                fnChangeWindowMessageFilter = (LPFN_CHANGEWINDOWMESSAGEFILTER)GetProcAddress(GetModuleHandle(TEXT("user32")),"ChangeWindowMessageFilter");
52        if (fnChangeWindowMessageFilter == NULL) {
53                NSC_DEBUG_MSG(_T("Failed to load: ChangeWindowMessageFilter aparently we are not on Vista..."));
54                return true;
55        }
56        NSC_DEBUG_MSG(_T("Chaning window message filters..."));
57        return fnChangeWindowMessageFilter(message,what);
58}
59
60void test() {
61/* error
62WTSQueryUserToken(dwSessionId, &hToken);
63DuplicateTokenEx(hTokenNew,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hTokenDup);
64*/
65/*
66        HANDLE hToken = NULL, hTokenDup = NULL;
67        HMODULE  hmod = LoadLibrary("kernel32.dll");
68        WTSGETACTIVECONSOLESESSIONID lpfnWTSGetActiveConsoleSessionId = (WTSGETACTIVECONSOLESESSIONID)GetProcAddress(hmod,"WTSGetActiveConsoleSessionId");
69        DWORD dwSessionId = lpfnWTSGetActiveConsoleSessionId();
70        WTSQueryUserToken(dwSessionId, &hToken);
71        //DuplicateTokenEx(hTokenNew,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hTokenDup);
72        //
73        WriteToLog("Calling lpfnCreateEnvironmentBlock");
74        ZeroMemory( &si, sizeof( STARTUPINFO ) );
75        si.cb = sizeof( STARTUPINFO );
76        si.lpDesktop = "winsta0\\default";
77
78
79        LPVOID  pEnv = NULL;
80        DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
81        HMODULE hModule = LoadLibrary("Userenv.dll");
82        if(hModule )
83        {
84                LPFN_CreateEnvironmentBlock lpfnCreateEnvironmentBlock = (LPFN_CreateEnvironmentBlock)GetProcAddress( hModule, "CreateEnvironmentBlock" );
85                if( lpfnCreateEnvironmentBlock != NULL )
86                {
87                        if(lpfnCreateEnvironmentBlock(&pEnv, hTokenDup, FALSE))
88                        {
89                                WriteToLog("CreateEnvironmentBlock Ok");
90                                dwCreationFlag |= CREATE_UNICODE_ENVIRONMENT;   
91                        }
92                        else
93                        {
94                                pEnv = NULL;
95                        }
96                }
97        }
98        //
99        ZeroMemory( &pi,sizeof(pi));
100
101        if ( !CreateProcessAsUser(
102                hTokenDup,
103                NULL,
104                ( char * )pszCmd, 
105                NULL,
106                NULL,
107                FALSE,
108                dwCreationFlag,
109                pEnv,
110                NULL,
111                &si,
112                &pi
113                ) )
114        {
115
116                goto RESTORE;
117        }
118*/
119
120}
121
122void IconWidget_::createDialog(void) {
123        hDlgWnd = ::CreateDialog(NSCModuleWrapper::getModule(),MAKEINTRESOURCE(IDD_NSTRAYDLG),NULL,TrayIcon::DialogProc);
124        if (hDlgWnd == NULL || !IsWindow(hDlgWnd)) {
125                NSC_LOG_ERROR_STD(_T("Failed to create windows: ") + error::lookup::last_error());
126        }
127
128        UINT UDM_TASKBARCREATED = RegisterWindowMessage(_T("TaskbarCreated"));
129        if (UDM_TASKBARCREATED == 0) {
130                NSC_LOG_ERROR_STD(_T("Failed to register 'TaskbarCreated': ") + error::lookup::last_error());
131        }
132        if (!ChangeWindowMessageFilter_(UDM_TASKBARCREATED, MSGFLT_ADD)) {
133                NSC_LOG_ERROR_STD(_T("Failed to cchange window filter: ") + error::lookup::last_error());
134        }
135
136        MSG Msg;
137        BOOL bRet;
138        while((bRet = ::GetMessage(&Msg, NULL, 0, 0)) != 0)
139        {
140                if (Msg.message == WM_MY_CLOSE) {
141                        TrayIcon::removeIcon(Msg.hwnd);
142                        ::DestroyWindow(hDlgWnd);
143//              } else if (Msg.message == WM_QUERYENDSESSION) {
144//                      NSC_LOG_ERROR_STD(_T("Got WM_QUERYENDSESSION thingy..."));
145                } else if (Msg.message == UDM_TASKBARCREATED) {
146                        NSC_LOG_MESSAGE_STD(_T("Recreating systray icon..."));
147                        TrayIcon::addIcon(Msg.hwnd);
148                } else if (bRet == -1) {
149                        // handle the error and possibly exit
150                        NSC_LOG_ERROR_STD(_T("Wonder what this is... please let me know..."));
151                        return;
152                } else {
153                //} else if (!::IsWindow(hDlgWnd) || !::IsDialogMessage(hDlgWnd, &Msg)) {
154                        ::TranslateMessage(&Msg);
155                        ::DispatchMessage(&Msg);
156                }
157        }
158}
159void IconWidget_::exitThread(void) {
160        ::PostMessage(hDlgWnd, WM_MY_CLOSE, NULL, NULL);
161}
162
163namespace TrayIcon
164{
165        std::wstring defaultCommand;
166}
167
168std::wstring getDlgItemText(HWND hDlg, int nIDDlgItem) {
169#define BUFF_LEN 4096
170        std::wstring ret;
171        TCHAR *buffer = new TCHAR[BUFF_LEN+1];
172        if (!GetDlgItemText(hDlg, nIDDlgItem, buffer, BUFF_LEN))
173                buffer[0]=0;
174        ret = buffer;
175        delete [] buffer;
176        return ret;
177}
178void updateDescFromCmd(HWND hDlg, std::wstring cmd) {
179        std::wstring result = _T("");
180        try {
181                result = NSCModuleHelper::describeCommand(cmd);
182        } catch (NSCModuleHelper::NSCMHExcpetion &e) {
183                result = _T("Error: ") + e.msg_;
184        } catch (...) {
185                result = _T("Unknown error!");
186        }
187        SetDlgItemText(hDlg, IDC_DESCRIPTION, result.c_str());
188}
189/*
190INT_PTR CALLBACK DialogProc(          HWND hwndDlg,
191    UINT uMsg,
192    WPARAM wParam,
193    LPARAM lParam
194);
195*/
196INT_PTR CALLBACK TrayIcon::InjectDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam) {
197        switch (uMsg)
198        {
199        case WM_INITDIALOG:
200                {
201                        SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(NSCModuleWrapper::getModule(), MAKEINTRESOURCE(IDI_NSCP)));
202                        SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(NSCModuleWrapper::getModule(), MAKEINTRESOURCE(IDI_NSCP)));
203                        SetDlgItemText(hwndDlg, IDC_CMD_BOX, TrayIcon::defaultCommand.c_str());
204                        SetDlgItemText(hwndDlg, IDC_DESCRIPTION, _T("Loading commands, please wait..."));
205
206                        SendDlgItemMessage(hwndDlg, IDC_CMD_BOX, CB_RESETCONTENT, 0, 0);
207                        std::wstring result = _T("");
208                        try {
209                                std::list<std::wstring> lst = NSCModuleHelper::getAllCommandNames();
210                                for (std::list<std::wstring>::const_iterator cit = lst.begin(); cit != lst.end(); ++cit) {
211                                        SendDlgItemMessage(hwndDlg, IDC_CMD_BOX, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>( (*cit).c_str() ));
212                                }
213                        } catch (NSCModuleHelper::NSCMHExcpetion &e) {
214                                result = _T("Error: ") + e.msg_;
215                        } catch (...) {
216                                result = _T("Unknown error!");
217                        }
218                        SetDlgItemText(hwndDlg, IDC_DESCRIPTION, result.c_str());
219                }
220                break;
221        case WM_COMMAND:
222                switch (LOWORD(wParam))
223                {
224                case IDC_CMD_BOX:
225                        switch(HIWORD(wParam))
226                        {
227                        case CBN_SELCHANGE:
228                                {
229                                        std::wstring cmd;
230                                        unsigned int id = SendDlgItemMessage(hwndDlg, IDC_CMD_BOX, CB_GETCURSEL, 0, 0);
231                                        unsigned int len = SendDlgItemMessage(hwndDlg, IDC_CMD_BOX, CB_GETLBTEXTLEN, id, 0);
232                                        TCHAR *buf = new TCHAR[len+2];
233                                        LRESULT ret;
234                                        ret = SendDlgItemMessage(hwndDlg, IDC_CMD_BOX, CB_GETLBTEXT, id, reinterpret_cast<LPARAM>(buf));
235                                        if (ret > 0 && ret <= len) {
236                                                cmd = buf;
237                                                updateDescFromCmd(hwndDlg, cmd);
238                                        }
239                                        delete [] buf;
240                                }
241                                break;
242                        case CBN_KILLFOCUS:
243                                updateDescFromCmd(hwndDlg, getDlgItemText(hwndDlg, IDC_CMD_BOX));
244                                break;
245                        }
246                        break;
247                case IDC_INJECT:
248                        {
249                                std::wstring result = _T("");
250                                std::wstring cmd = getDlgItemText(hwndDlg, IDC_CMD_BOX);
251                                std::wstring args = getDlgItemText(hwndDlg, IDC_ARG_BOX);
252                                std::wstring msg;
253                                std::wstring perf;
254                                try {
255                                        NSCAPI::nagiosReturn ret = NSCModuleHelper::InjectSplitAndCommand(cmd, args, ' ', msg, perf);
256                                        if (ret == NSCAPI::returnIgnored) {
257                                                result = _T("Command not found!");
258                                        } else {
259                                                result = NSCHelper::translateReturn(ret);
260                                        }
261                                } catch (NSCModuleHelper::NSCMHExcpetion &e) {
262                                        result = _T("Error: ") + e.msg_;
263                                } catch (...) {
264                                        result = _T("Unknown error!");
265                                }
266                                SetDlgItemText(hwndDlg, IDC_DESCRIPTION, result.c_str());
267                                SetDlgItemText(hwndDlg, IDC_MSG, msg.c_str());
268                                SetDlgItemText(hwndDlg, IDC_PERF, perf.c_str());
269                        }
270                        break;
271                case IDOK:
272                        {
273                                TCHAR *c=new TCHAR[1024];
274                                if (GetDlgItemText(hwndDlg, IDC_COMMAND, c, 1023))
275                                        TrayIcon::defaultCommand = c;
276                                delete [] c;
277                        }
278
279                case IDCANCEL:
280                        EndDialog(hwndDlg, wParam);
281                        return TRUE;
282                }
283        }
284        return FALSE;
285}
286
287
288
289void insert_logrecord(HWND hwndLV, const SysTray::log_entry &entry) {
290        LVITEM item;
291        item.mask = LVIF_TEXT;
292        std::wstring msg = NSCHelper::translateMessageType(entry.type);
293        item.pszText = const_cast<TCHAR*>(msg.c_str());
294        item.iSubItem = 0;
295        item.iItem = 0; //ListView_GetItemCount(hwndLV);
296        int id = ListView_InsertItem(hwndLV, &item);
297        msg = entry.file;
298        ListView_SetItemText(hwndLV, id, 1, const_cast<TCHAR*>(msg.c_str()));
299        msg = strEx::itos(entry.line);
300        ListView_SetItemText(hwndLV, id, 2, const_cast<TCHAR*>(msg.c_str()));
301        msg = entry.message;
302        ListView_SetItemText(hwndLV, id, 3, const_cast<TCHAR*>(msg.c_str()));
303}
304
305INT_PTR CALLBACK TrayIcon::LogDialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam) {
306        switch (uMsg)
307        {
308        case WM_INITDIALOG:
309                {
310                        SendMessage(hwndDlg, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(NSCModuleWrapper::getModule(), MAKEINTRESOURCE(IDI_NSCP)));
311                        SendMessage(hwndDlg, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(NSCModuleWrapper::getModule(), MAKEINTRESOURCE(IDI_NSCP)));
312                        gSysTray.setLogWindow(hwndDlg);
313                        HWND hwndLV = GetDlgItem(hwndDlg, IDC_LOG);
314                        LVCOLUMN col;
315                        col.mask = LVCF_TEXT|LVCF_WIDTH;
316                        col.cx = 10;
317                        col.pszText = _T("Type");
318                        ListView_InsertColumn(hwndLV, 1, &col);
319                        col.pszText = _T("File");
320                        ListView_InsertColumn(hwndLV, 2, &col);
321                        col.pszText = _T("Line");
322                        ListView_InsertColumn(hwndLV, 3, &col);
323                        col.pszText = _T("Message");
324                        ListView_InsertColumn(hwndLV, 4, &col);
325
326                        SysTray::log_type log = gSysTray.getLog();
327                        for (SysTray::log_type::const_iterator cit = log.begin(); cit != log.end(); ++cit) {
328                                insert_logrecord(hwndLV, *cit);
329                        }
330
331                        ListView_SetColumnWidth(hwndLV, 0, LVSCW_AUTOSIZE_USEHEADER);
332                        ListView_SetColumnWidth(hwndLV, 1, LVSCW_AUTOSIZE_USEHEADER);
333                        ListView_SetColumnWidth(hwndLV, 2, LVSCW_AUTOSIZE_USEHEADER);
334                        ListView_SetColumnWidth(hwndLV, 3, LVSCW_AUTOSIZE_USEHEADER);
335                }
336                return TRUE;
337
338        case WM_USER+1:
339                {
340                        HWND hwndLV = GetDlgItem(hwndDlg, IDC_LOG);
341                        const SysTray::log_entry* record = reinterpret_cast<const SysTray::log_entry*>(wParam);
342                        insert_logrecord(hwndLV, *record);
343
344                }
345                return TRUE;
346
347        case WM_SIZE:
348                if (wParam == SIZE_RESTORED) {
349                        HWND hwndLV = GetDlgItem(hwndDlg, IDC_LOG);
350                        ::SetWindowPos(hwndLV, NULL, 0, 0, LOWORD(lParam), HIWORD(lParam), SWP_NOZORDER);
351                }
352                return TRUE;
353
354        case WM_COMMAND:
355                case IDOK:
356                case IDCANCEL:
357                        gSysTray.setLogWindow(NULL);
358                        EndDialog(hwndDlg, wParam);
359                        return TRUE;
360        }
361        return FALSE;
362}
363
364
365INT_PTR CALLBACK TrayIcon::DialogProc(HWND hwndDlg,UINT uMsg,WPARAM wParam,LPARAM lParam)
366{
367        switch (uMsg)
368        {
369        case WM_DESTROY:
370                TrayIcon::removeIcon(hwndDlg);
371                PostQuitMessage(0);
372                return 0;
373
374        case WM_INITDIALOG:
375                addIcon(hwndDlg);
376                break;
377
378        case WM_ICON_NOTIFY:
379                if (lParam==WM_RBUTTONDOWN) {
380                        HMENU hMenu = LoadMenu(NSCModuleWrapper::getModule(),MAKEINTRESOURCE(IDR_POPUP));
381                        HMENU hSubMenu = GetSubMenu(hMenu, 0);
382                        const RECT r = {0, 0, 0, 0};
383                        POINT pt;
384                        GetCursorPos(&pt);
385                        SetForegroundWindow(hwndDlg);
386                        int cmd = TrackPopupMenu(hSubMenu, TPM_LEFTALIGN|TPM_RETURNCMD, pt.x, pt.y, 0, hwndDlg, &r);
387                        DestroyMenu(hMenu);
388                        switch (cmd) {
389                        case ID_POPUP_STOPSERVICE:
390                                NSCModuleHelper::Exit();
391                                break;
392                        case ID_POPUP_INJECTCOMMAND:
393                                //if (TrayIcon::defaultCommand.empty())
394                                //      TrayIcon::defaultCommand = NSCModuleHelper::getSettingsString(_T("systray"), _T("defaultCommand"), _T(""));
395                                CreateDialog(NSCModuleWrapper::getModule(),MAKEINTRESOURCE(IDD_INJECTDIALOG),hwndDlg,InjectDialogProc);
396                                break;
397                        case ID_POPUP_SHOWLOG:
398                                CreateDialog(NSCModuleWrapper::getModule(),MAKEINTRESOURCE(IDD_LOGWINDOW),hwndDlg,LogDialogProc);
399                        }
400                        return TRUE;
401                }
402                break;
403        }
404        return FALSE;
405}
406void TrayIcon::addIcon(HWND hWnd) {
407        assert(NSCModuleWrapper::getModule() != NULL);
408        assert(hWnd != NULL);
409
410        NOTIFYICONDATA ndata;
411        ndata.cbSize=sizeof(NOTIFYICONDATA);
412        ndata.hWnd=hWnd;
413        ndata.uID=2000;
414        ndata.uFlags=NIF_ICON|NIF_MESSAGE|NIF_TIP;
415        ndata.uCallbackMessage=WM_ICON_NOTIFY;
416        ndata.hIcon=::LoadIcon(NSCModuleWrapper::getModule(),MAKEINTRESOURCE(IDI_NSCP));
417        std::wstring title = NSCModuleHelper::getApplicationName() + _T(" - ") + NSCModuleHelper::getApplicationVersionString();
418        wcsncpy_s(ndata.szTip, 64, title.c_str(), min(64, title.size()));
419        Shell_NotifyIcon(NIM_ADD,&ndata);
420}
421
422void TrayIcon::removeIcon(HWND hWnd) {
423        NOTIFYICONDATA ndata;
424        ndata.cbSize=sizeof(NOTIFYICONDATA);
425        ndata.hWnd=hWnd;
426        ndata.uID=2000;
427        Shell_NotifyIcon(NIM_DELETE,&ndata);
428}
Note: See TracBrowser for help on using the repository browser.