source: nscp/service/NSClient++.cpp @ 773ad32

0.4.00.4.10.4.2
Last change on this file since 773ad32 was 773ad32, checked in by Michael Medin <michael@…>, 4 years ago

swaped the mutexes for the settings subsysytem to boost

  • Property mode set to 100644
File size: 54.5 KB
Line 
1///////////////////////////////////////////////////////////////////////////
2// NSClient++ Base Service
3//
4// Copyright (c) 2004 MySolutions NORDIC (http://www.medin.name)
5//
6// Date: 2004-03-13
7// Author: Michael Medin (michael@medin.name)
8//
9// Part of this file is based on work by Bruno Vais (bvais@usa.net)
10//
11// This software is provided "AS IS", without a warranty of any kind.
12// You are free to use/modify this code but leave this header intact.
13//
14//////////////////////////////////////////////////////////////////////////
15#include "StdAfx.h"
16#include "NSClient++.h"
17#include <settings/Settings.h>
18#include <charEx.h>
19//#include <Socket.h>
20#include <config.h>
21#include <msvc_wrappers.h>
22#ifdef WIN32
23#include <Userenv.h>
24#include <Lmcons.h>
25//#ifdef DEBUG
26#include <crtdbg.h>
27//#endif
28#endif
29#include <remote_processes.hpp>
30//#include <winsvc.h>
31//#include <Userenv.h>
32//#include <Lmcons.h>
33#include <remote_processes.hpp>
34#include "core_api.h"
35#include "settings_manager_impl.h"
36#include <settings/macros.h>
37#include <NSCHelper.h>
38
39NSClient mainClient(SZSERVICENAME);     // Global core instance.
40bool g_bConsoleLog = false;
41
42#define SETTINGS_GET_BOOL_CORE(key) \
43        settings_manager::get_settings()->get_bool(setting_keys::key ## _PATH, setting_keys::key, setting_keys::key ## _DEFAULT)
44
45#define SETTINGS_GET_STRING_CORE(key) \
46        settings_manager::get_settings()->get_string(setting_keys::key ## _PATH, setting_keys::key, setting_keys::key ## _DEFAULT)
47/*
48#define SETTINGS_SET_STRING_CORE(key, value) \
49        Settings::get_settings()->set_string(setting_keys::key ## _PATH, setting_keys::key, value);
50*/
51/**
52 * START OF Tray starter MERGE HELPER
53 */
54class tray_starter {
55        struct start_block {
56                std::wstring cmd;
57                std::wstring cmd_line;
58                DWORD sessionId;
59        };
60
61public:
62        static LPVOID init(DWORD dwSessionId, std::wstring exe, std::wstring cmdline) {
63                start_block *sb = new start_block;
64                sb->cmd = exe;
65                sb->cmd_line = cmdline;
66                sb->sessionId = dwSessionId;
67                return sb;
68        }
69        DWORD threadProc(LPVOID lpParameter) {
70                start_block* param = static_cast<start_block*>(lpParameter);
71                DWORD dwSessionId = param->sessionId;
72                std::wstring cmd = param->cmd;
73                std::wstring cmdline = param->cmd_line;
74                delete param;
75                for (int i=0;i<10;i++) {
76                        Sleep(1000);
77                        if (startTrayHelper(dwSessionId, cmd, cmdline, false))
78                                break;
79                }
80                return 0;
81        }
82
83        static bool start(unsigned long  dwSessionId) {
84                std::wstring program = mainClient.getBasePath() +  _T("\\") +
85                        SETTINGS_GET_STRING_CORE(settings_def::SYSTRAY_EXE);
86                std::wstring cmdln = _T("\"") + program + _T("\" -channel __") + strEx::itos(dwSessionId) + _T("__");
87                return tray_starter::startTrayHelper(dwSessionId, program, cmdln);
88        }
89
90        static bool startTrayHelper(unsigned long dwSessionId, std::wstring exe, std::wstring cmdline, bool startThread = true) {
91//              HANDLE hToken = NULL;
92//              if (!remote_processes::GetSessionUserToken(dwSessionId, &hToken)) {
93//                      LOG_ERROR_STD(_T("Failed to query user token: ") + error::lookup::last_error());
94//                      return false;
95//              } else {
96//                      STARTUPINFO          StartUPInfo;
97//                      PROCESS_INFORMATION  ProcessInfo;
98//
99//                      ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO));
100//                      ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION));
101//                      StartUPInfo.wShowWindow = SW_HIDE;
102//                      StartUPInfo.lpDesktop = L"Winsta0\\Default";
103//                      StartUPInfo.cb = sizeof(STARTUPINFO);
104//
105//                      wchar_t *buffer = new wchar_t[cmdline.size()+10];
106//                      wcscpy(buffer, cmdline.c_str());
107//                      LOG_MESSAGE_STD(_T("Running: ") + exe);
108//                      LOG_MESSAGE_STD(_T("Running: ") + cmdline);
109//
110//                      LPVOID pEnv =NULL;
111//                      DWORD dwCreationFlags = CREATE_NO_WINDOW; //0; //DETACHED_PROCESS
112//
113//                      if(CreateEnvironmentBlock(&pEnv,hToken,TRUE)) {
114//                              dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT;
115//                      } else {
116//                              LOG_ERROR_STD(_T("Failed to create enviornment: ") + error::lookup::last_error());
117//                              pEnv=NULL;
118//                      }
119//                      /*
120//                      LOG_ERROR_STD(_T("Impersonating user: "));
121//                      if (!ImpersonateLoggedOnUser(hToken)) {
122//                              LOG_ERROR_STD(_T("Failed to impersonate the user: ") + error::lookup::last_error());
123//                      }
124//
125//                      wchar_t pszUname[UNLEN + 1];
126//                      ZeroMemory(pszUname,sizeof(pszUname));
127//                      DWORD dwSize = UNLEN;
128//                      if (!GetUserName(pszUname,&dwSize)) {
129//                              DWORD dwErr = GetLastError();
130//                              if (!RevertToSelf())
131//                                      LOG_ERROR_STD(_T("Failed to revert to self: ") + error::lookup::last_error());
132//                              LOG_ERROR_STD(_T("Failed to get username: ") + error::format::from_system(dwErr));
133//                              return false;
134//                      }
135//                     
136//
137//                      PROFILEINFO info;
138//                      info.dwSize = sizeof(PROFILEINFO);
139//                      info.lpUserName = pszUname;
140//                      if (!LoadUserProfile(hToken, &info)) {
141//                              DWORD dwErr = GetLastError();
142//                              if (!RevertToSelf())
143//                                      LOG_ERROR_STD(_T("Failed to revert to self: ") + error::lookup::last_error());
144//                              LOG_ERROR_STD(_T("Failed to get username: ") + error::format::from_system(dwErr));
145//                              return false;
146//                      }
147//                      */
148//                      if (!CreateProcessAsUser(hToken, exe.c_str(), buffer, NULL, NULL, FALSE, dwCreationFlags, pEnv, NULL, &StartUPInfo, &ProcessInfo)) {
149//                              DWORD dwErr = GetLastError();
150//                              delete [] buffer;
151//                              /*
152//                              if (!RevertToSelf()) {
153//                                      LOG_ERROR_STD(_T("Failed to revert to self: ") + error::lookup::last_error());
154//                              }
155//                              */
156//                              if (startThread && dwErr == ERROR_PIPE_NOT_CONNECTED) {
157//                                      LOG_MESSAGE(_T("Failed to start trayhelper: starting a background thread to do it instead..."));
158//                                      Thread<tray_starter> *pThread = new Thread<tray_starter>(_T("tray-starter-thread"));
159//                                      pThread->createThread(tray_starter::init(dwSessionId, exe, cmdline));
160//                                      return false;
161//                              } else if (dwErr == ERROR_PIPE_NOT_CONNECTED) {
162//                                      LOG_ERROR_STD(_T("Thread failed to start trayhelper (will try again): ") + error::format::from_system(dwErr));
163//                                      return false;
164//                              } else {
165//                                      LOG_ERROR_STD(_T("Failed to start trayhelper: ") + error::format::from_system(dwErr));
166//                                      return true;
167//                              }
168//                      } else {
169//                              delete [] buffer;
170//                              /*
171//                              if (!RevertToSelf()) {
172//                                      LOG_ERROR_STD(_T("Failed to revert to self: ") + error::lookup::last_error());
173//                              }
174//                              */
175//                              LOG_MESSAGE_STD(_T("Started tray in other user session: ") + strEx::itos(dwSessionId));
176//                      }
177//
178//
179//                      CloseHandle(hToken);
180//                      return true;
181//              }
182                return false;
183        }
184};
185
186/**
187 * End of class tray started (MERGE HELP)
188 */
189
190#define XNSC_DEFINE_SETTING_KEY(name, tag) \
191        name ## _SECTION \
192       
193 /**
194 * RANDOM JUNK (MERGE HELP)
195 */
196
197void display(std::wstring title, std::wstring message) {
198        ::MessageBox(NULL, message.c_str(), title.c_str(), MB_OK|MB_ICONERROR);
199}
200
201
202/**
203 * Application startup point
204 *
205 * @param argc Argument count
206 * @param argv[] Argument array
207 * @param envp[] Environment array
208 * @return exit status
209 */
210int wmain(int argc, TCHAR* argv[], TCHAR* envp[])
211{
212        srand( (unsigned)time( NULL ) );
213        int nRetCode = 0;
214        if ( (argc > 1) && ((*argv[1] == '-') || (*argv[1] == '/')) ) {
215                if (false) {
216#ifdef WIN32
217                } if ( _wcsicmp( _T("install"), argv[1]+1 ) == 0 ) {
218                        bool bGui = false;
219                        bool bStart = false;
220                        std::wstring service_name, service_description;
221                        for (int i=2;i<argc;i++) {
222                                if (_wcsicmp( _T("gui"), argv[i]) == 0) {
223                                        bGui = true;
224                                } else if (_wcsicmp( _T("start"), argv[i]) == 0) {
225                                        bStart = true;
226                                } else {
227                                        if (service_name.empty())
228                                                service_name = argv[i];
229                                        else {
230                                                if (!service_description.empty())
231                                                        service_description += _T(" ");
232                                                service_description += argv[i];
233                                        }
234                                }
235                        }
236                        if (service_name.empty())
237                                service_name = SZSERVICENAME;
238                        if (service_description.empty())
239                                service_description = SZSERVICEDISPLAYNAME;
240                        g_bConsoleLog = true;
241                        try {
242                                serviceControll::Install(service_name.c_str(), service_description.c_str(), SZDEPENDENCIES);
243                                if (bStart)
244                                        serviceControll::Start(service_name);
245                        } catch (const serviceControll::SCException& e) {
246                                if (bGui)
247                                        display(_T("Error installing"), _T("Service installation failed; ") + e.error_);
248                                LOG_ERROR_STD(_T("Service installation failed: ") + e.error_);
249                                return -1;
250                        }
251                        try {
252                                serviceControll::SetDescription(service_name, service_description);
253                        } catch (const serviceControll::SCException& e) {
254                                if (bGui)
255                                        display(_T("Error installing"), _T("Service installation failed; ") + e.error_);
256                                LOG_MESSAGE_STD(_T("Couldn't set service description: ") + e.error_);
257                        }
258                        if (bGui)
259                                display(_T("Service installed"), _T("Service installed successfully!"));
260                        LOG_MESSAGE(_T("Service installed!"));
261                        return 0;
262                } else if ( _wcsicmp( _T("uninstall"), argv[1]+1 ) == 0 ) {
263                        bool bGui = false;
264                        bool bStop = false;
265                        std::wstring service_name;
266                        for (int i=2;i<argc;i++) {
267                                if (_wcsicmp( _T("gui"), argv[i]) == 0) {
268                                        bGui = true;
269                                } else if (_wcsicmp( _T("stop"), argv[i]) == 0) {
270                                        bStop = true;
271                                } else {
272                                        service_name = argv[i];
273                                }
274                        }
275                        if (service_name.empty())
276                                service_name = SZSERVICENAME;
277                        g_bConsoleLog = true;
278                        try {
279                                if (bStop)
280                                        serviceControll::Stop(service_name);
281                        } catch (const serviceControll::SCException& e) {
282                                LOG_MESSAGE_STD(_T("Failed to stop service (") + service_name + _T(") failed; ") + e.error_);
283                        }
284                        try {
285                                serviceControll::Uninstall(service_name);
286                        } catch (const serviceControll::SCException& e) {
287                                if (bGui)
288                                        display(_T("Error uninstalling"), _T("Service de-installation (") + service_name + _T(") failed; ") + e.error_ + _T("\nMaybe the service was not previously installed properly?"));
289                                LOG_ERROR_STD(_T("Service deinstallation failed; ") + e.error_);
290                                return 0;
291                        }
292                        if (bGui)
293                                display(_T("Service uninstalled"), _T("Service uninstalled successfully!"));
294                        LOG_MESSAGE(_T("Service uninstalled!"));
295                        return 0;
296                } else if ( _wcsicmp( _T("start"), argv[1]+1 ) == 0 ) {
297                        g_bConsoleLog = true;
298                        bool bGui = false;
299                        std::wstring service_name;
300                        for (int i=2;i<argc;i++) {
301                                if (_wcsicmp( _T("gui"), argv[i]) == 0) {
302                                        bGui = true;
303                                } else {
304                                        service_name = argv[i];
305                                }
306                        }
307                        if (service_name.empty())
308                                service_name = SZSERVICENAME;
309                        try {
310                                serviceControll::Start(service_name.c_str());
311                        } catch (const serviceControll::SCException& e) {
312                                if (bGui)
313                                        display(_T("Service failed to start"), e.error_);
314                                LOG_MESSAGE_STD(_T("Service failed to start: ") + e.error_);
315                                return -1;
316                        }
317                } else if ( _wcsicmp( _T("stop"), argv[1]+1 ) == 0 ) {
318                        g_bConsoleLog = true;
319                        bool bGui = false;
320                        std::wstring service_name;
321                        for (int i=2;i<argc;i++) {
322                                if (_wcsicmp( _T("gui"), argv[i]) == 0) {
323                                        bGui = true;
324                                } else {
325                                        service_name = argv[i];
326                                }
327                        }
328                        if (service_name.empty())
329                                service_name = SZSERVICENAME;
330                        try {
331                                serviceControll::Stop(service_name.c_str());
332                        } catch (const serviceControll::SCException& e) {
333                                if (bGui)
334                                        display(_T("Service failed to stop"), e.error_);
335                                LOG_MESSAGE_STD(_T("Service failed to stop: ") + e.error_);
336                                return -1;
337                        }
338                } else if ( _wcsicmp( _T("svc"), argv[1]+1 ) == 0 ) {
339                        g_bConsoleLog = true;
340                        try {
341                                std::wstring exe = serviceControll::get_exe_path(SZSERVICENAME);
342                                LOG_MESSAGE_STD(_T("The Service uses: ") + exe);
343                        } catch (const serviceControll::SCException& e) {
344                                LOG_ERROR_STD(_T("Failed to find service: ") + e.error_);
345                        }
346#endif
347                } else if ( _wcsicmp( _T("encrypt"), argv[1]+1 ) == 0 ) {
348                        g_bConsoleLog = true;
349                        std::wstring password;
350                        if (!settings_manager::init_settings(mainClient.getBasePath())) {
351                                std::wcout << _T("Could not find settings") << std::endl;;
352                                return 1;
353                        }
354                        std::wcout << _T("Enter password to encrypt (has to be a single word): ");
355                        std::wcin >> password;
356                        std::wstring xor_pwd = Encrypt(password);
357                        std::wcout << _T("obfuscated_password=") << xor_pwd << std::endl;
358                        std::wstring outPasswd = Decrypt(xor_pwd);
359                        if (password != outPasswd)
360                                std::wcout << _T("ERROR: Password did not match: ") << outPasswd<< std::endl;
361                        settings_manager::destroy_settings();
362                        return 0;
363                } else if ( _wcsicmp( _T("about"), argv[1]+1 ) == 0 ) {
364                        g_bConsoleLog = true;
365                        LOG_MESSAGE(SZAPPNAME _T(" (C) Michael Medin - michael<at>medin<dot>name"));
366                        LOG_MESSAGE(_T("Version: ") SZVERSION);
367                        LOG_MESSAGE(_T("Architecture: ") SZARCH);
368
369                        std::wstring pluginPath = mainClient.getBasePath() + _T("modules\\");
370                        LOG_MESSAGE_STD(_T("Looking at plugins in: ") + pluginPath);
371
372                        WIN32_FIND_DATA wfd;
373                        HANDLE hFind = FindFirstFile((pluginPath + _T("*.dll")).c_str(), &wfd);
374                        if (hFind != INVALID_HANDLE_VALUE) {
375                                do {
376                                        std::wstring file = wfd.cFileName;
377                                        NSCPlugin *plugin = new NSCPlugin(pluginPath + _T("\\") + file);
378                                        std::wstring name = _T("<unknown>");
379                                        std::wstring description = _T("<unknown>");
380                                        try {
381                                                plugin->load_dll();
382                                                name = plugin->getName();
383                                                description = plugin->getDescription();
384                                        } catch(const NSPluginException& e) {
385                                                LOG_ERROR_STD(_T("Exception raised: ") + e.error_ + _T(" in module: ") + e.file_);
386                                        } catch (std::exception e) {
387                                                LOG_ERROR_STD(_T("exception loading plugin: ") + strEx::string_to_wstring(e.what()));
388                                        } catch (...) {
389                                                LOG_ERROR_STD(_T("Unknown exception loading plugin"));
390                                        }
391                                        LOG_MESSAGE_STD(_T("* ") + name + _T(" (") + file + _T(")"));
392                                        std::list<std::wstring> list = strEx::splitEx(description, _T("\n"));
393                                        for (std::list<std::wstring>::const_iterator cit = list.begin(); cit != list.end(); ++cit) {
394                                                LOG_MESSAGE_STD(_T("    ") + *cit);
395                                        }
396                                } while (FindNextFile(hFind, &wfd));
397                        } else {
398                                LOG_CRITICAL(_T("No plugin was found!"));
399                        }
400                        FindClose(hFind);
401                } else if ( _wcsicmp( _T("version"), argv[1]+1 ) == 0 ) {
402                        g_bConsoleLog = true;
403                        LOG_MESSAGE(SZAPPNAME _T(" Version: ") SZVERSION _T(", Plattform: ") SZARCH);
404                } else if ( _wcsicmp( _T("d"), argv[1]+1 ) == 0 ) {
405                        // Run command from command line (like NRPE) but with debug enabled
406                } else if ( _wcsicmp( _T("noboot"), argv[1]+1 ) == 0 ) {
407                        g_bConsoleLog = true;
408                        mainClient.enableDebug(false);
409                        mainClient.initCore(false);
410                        if (argc>=4)
411                                nRetCode = mainClient.commandLineExec(argv[2], argv[3], argc-4, &argv[4]);
412                        else
413                                nRetCode = mainClient.commandLineExec(argv[2], argv[3], 0, NULL);
414                        mainClient.exitCore(true);
415                        return nRetCode;
416                } else if ( _wcsicmp( _T("c"), argv[1]+1 ) == 0 ) {
417                        // Run command from command line (like NRPE)
418                        g_bConsoleLog = true;
419                        mainClient.enableDebug(false);
420                        mainClient.initCore(true);
421                        std::wstring command, args, msg, perf;
422                        if (argc > 2)
423                                command = argv[2];
424                        for (int i=3;i<argc;i++) {
425                                if (i!=3) args += _T(" ");
426                                args += argv[i];
427                        }
428                        nRetCode = mainClient.inject(command, args, L' ', true, msg, perf);
429                        std::wcout << msg << _T("|") << perf << std::endl;
430                        mainClient.exitCore(true);
431                        return nRetCode;
432                } else if ( _wcsicmp( _T("test"), argv[1]+1 ) == 0 ) {
433                        bool server = false;
434                        if (argc > 2 && _wcsicmp( _T("server"), argv[2] ) == 0 ) {
435                                server = true;
436                        }
437                        std::wcout << "Launching test mode - " << (server?_T("server mode"):_T("client mode")) << std::endl;
438                        LOG_MESSAGE_STD(_T("Booting: " SZSERVICEDISPLAYNAME ));
439#ifdef WIN32
440                        try {
441                                if (serviceControll::isStarted(SZSERVICENAME)) {
442                                        std::wcerr << "Service seems to be started, this is probably not a good idea..." << std::endl;
443                                }
444                        } catch (const serviceControll::SCException& e) {
445                                e;// Empty by design
446                        }
447#endif
448                        g_bConsoleLog = true;
449                        mainClient.enableDebug(true);
450                        if (!mainClient.initCore(true)) {
451                                LOG_ERROR_STD(_T("Service *NOT* started!"));
452                                return -1;
453                        }
454                        LOG_MESSAGE_STD(_T("Using settings from: ") + settings_manager::get_core()->get_settings_type_desc());
455                        LOG_MESSAGE(_T("Enter command to inject or exit to terminate..."));
456/*
457                        Settings::get_settings()->clear_cache();
458                        LOG_MESSAGE_STD( _T("test 001: ") + SETTINGS_GET_STRING(NSCLIENT_TEST1) );
459                        LOG_MESSAGE_STD( _T("test 002: ") + SETTINGS_GET_STRING(NSCLIENT_TEST2) );
460                        LOG_MESSAGE_STD( _T("test 003: ") + SETTINGS_GET_STRING(NSCLIENT_TEST3) );
461                        LOG_MESSAGE_STD( _T("test 004: ") + SETTINGS_GET_STRING(NSCLIENT_TEST4) );
462
463                        Settings::get_settings()->save_to(_T("test.ini"));
464*/
465                        std::wstring s = _T("");
466                        std::wstring buff = _T("");
467                        while (true) {
468                                std::wcin >> s;
469                                if (s == _T("exit")) {
470                                        std::wcout << _T("Exiting...") << std::endl;
471                                        break;
472                                } else if (s == _T("plugins")) {
473                                        std::wcout << _T("Listing plugins...") << std::endl;
474                                        mainClient.listPlugins();
475                                } else if (s == _T("off") && buff == _T("debug ")) {
476                                        std::wcout << _T("Setting debug log off...") << std::endl;
477                                        mainClient.enableDebug(false);
478                                } else if (s == _T("on") && buff == _T("debug ")) {
479                                        std::wcout << _T("Setting debug log on...") << std::endl;
480                                        mainClient.enableDebug(true);
481                                } else if (s == _T("reattach")) {
482                                        std::wcout << _T("Reattaching to session 0") << std::endl;
483                                        mainClient.startTrayIcon(0);
484//#ifdef DEBUG
485                                } else if (s == _T("assert")) {
486                                        throw "test";
487//#endif
488                                } else if (std::cin.peek() < 15) {
489                                        buff += s;
490                                        strEx::token t = strEx::getToken(buff, ' ');
491                                        std::wstring msg, perf;
492                                        NSCAPI::nagiosReturn ret = mainClient.inject(t.first, t.second, ' ', true, msg, perf);
493                                        if (ret == NSCAPI::returnIgnored) {
494                                                std::wcout << _T("No handler for command: ") << t.first << std::endl;
495                                        } else {
496                                                std::wcout << NSCHelper::translateReturn(ret) << _T(":");
497                                                std::cout << strEx::wstring_to_string(msg);
498                                                if (!perf.empty())
499                                                        std::cout << "|" << strEx::wstring_to_string(perf);
500                                                std::wcout << std::endl;
501                                        }
502                                        buff = _T("");
503                                } else {
504                                        buff += s + _T(" ");
505                                }
506                        }
507                        mainClient.exitCore(true);
508                        return 0;
509                } else {
510                        std::wcerr << _T("Usage: -version, -about, -install, -uninstall, -start, -stop, -encrypt -settings") << std::endl;
511                        std::wcerr << _T("Usage: [-noboot] <ModuleName> <commnd> [arguments]") << std::endl;
512                        return -1;
513                }
514                return nRetCode;
515        } else if (argc > 2) {
516                g_bConsoleLog = true;
517                mainClient.initCore(true);
518                if (argc>=3)
519                        nRetCode = mainClient.commandLineExec(argv[1], argv[2], argc-3, &argv[3]);
520                else
521                        nRetCode = mainClient.commandLineExec(argv[1], argv[2], 0, NULL);
522                mainClient.exitCore(true);
523                return nRetCode;
524        } else if (argc > 1) {
525                g_bConsoleLog = true;
526                mainClient.enableDebug(true);
527                std::wcerr << _T("Invalid command line argument: ") << argv[1] << std::endl;
528                std::wcerr << _T("Usage: -version, -about, -install, -uninstall, -start, -stop, -encrypt") << std::endl;
529                std::wcerr << _T("Usage: [-noboot] <ModuleName> <commnd> [arguments]") << std::endl;
530                return -1;
531        }
532        std::wcout << _T("Running as service...") << std::endl;
533        if (!mainClient.StartServiceCtrlDispatcher()) {
534                LOG_MESSAGE(_T("We failed to start the service"));
535        }
536        return nRetCode;
537}
538
539void migrate() {}
540
541NSClientT::plugin_info_list NSClientT::get_all_plugins() {
542        plugin_info_list ret;
543        std::wstring modPath = getBasePath() + _T("modules\\");
544
545        WIN32_FIND_DATA wfd;
546        HANDLE hFind = FindFirstFile((modPath + _T("*.dll")).c_str(), &wfd);
547        if (hFind != INVALID_HANDLE_VALUE) {
548                do {
549                        plugin_info_type info;
550                        info.dll = wfd.cFileName;
551                        try {
552                                LOG_DEBUG_STD(_T("Attempting to fake load: ") + wfd.cFileName);
553                                NSCPlugin plugin(modPath + wfd.cFileName);
554                                plugin.load_dll();
555                                plugin.load_plugin(NSCAPI::dontStart);
556                                info.name = plugin.getName();
557                                info.description = plugin.getDescription();
558                                plugin.unload();
559                        } catch (NSPluginException e) {
560                                LOG_CRITICAL_STD(_T("Error loading: ") + e.file_ + _T(" root cause: ") + e.error_);
561                        } catch (...) {
562                                LOG_CRITICAL_STD(_T("Unknown Error loading: ") + wfd.cFileName);
563                        }
564                        ret.push_back(info);
565                } while (FindNextFile(hFind, &wfd));
566        }
567        FindClose(hFind);
568        return ret;
569}
570
571
572void NSClientT::load_all_plugins(int mode) {
573        std::wstring modPath = getBasePath() + _T("modules\\");
574
575        WIN32_FIND_DATA wfd;
576        HANDLE hFind = FindFirstFile((modPath + _T("*.dll")).c_str(), &wfd);
577        if (hFind != INVALID_HANDLE_VALUE) {
578                do {
579                        if (settings_manager::get_settings()->has_key(MAIN_MODULES_SECTION, wfd.cFileName)) {
580                                if (settings_manager::get_settings()->get_string(MAIN_MODULES_SECTION, wfd.cFileName) == _T("disabled")) {
581                                        try {
582                                                LOG_DEBUG_STD(_T("Attempting to fake load: ") + wfd.cFileName);
583                                                NSCPlugin plugin(modPath + wfd.cFileName);
584                                                plugin.load_dll();
585                                                plugin.load_plugin(mode);
586                                                plugin.unload();
587                                        } catch (NSPluginException e) {
588                                                LOG_CRITICAL_STD(_T("Error loading: ") + e.file_ + _T(" root cause: ") + e.error_);
589                                        } catch (...) {
590                                                LOG_CRITICAL_STD(_T("Unknown Error loading: ") + wfd.cFileName);
591                                        }
592                                }
593                        } else {
594                                std::wstring desc;
595                                try {
596                                        NSCPlugin plugin(modPath + wfd.cFileName);
597                                        plugin.load_dll();
598                                        plugin.load_plugin(mode);
599                                        desc = plugin.getName() + _T(" - ");
600                                        desc += plugin.getDescription();
601                                        plugin.unload();
602                                } catch (NSPluginException e) {
603                                        desc += _T("unknown module");
604                                        LOG_CRITICAL_STD(_T("Error loading: ") + e.file_ + _T(" root cause: ") + e.error_);
605                                } catch (...) {
606                                        desc += _T("unknown module");
607                                        LOG_CRITICAL_STD(_T("Unknown Error loading: ") + wfd.cFileName);
608                                }
609                                settings_manager::get_core()->register_key(MAIN_MODULES_SECTION, wfd.cFileName, Settings::SettingsCore::key_string, desc, desc, _T("disabled"), false);
610                        }
611                } while (FindNextFile(hFind, &wfd));
612        }
613        FindClose(hFind);
614}
615
616void NSClientT::HandleSettingsCLI(TCHAR* arg, int argc, TCHAR* argv[]) {
617        std::wstring sarg = arg;
618        try {
619                if (sarg == _T("migrate")) {
620                        if (argc == 0) {
621                                LOG_ERROR_STD(_T("In correct syntax: nsclient++ -settings migrate <to>"));
622                                return;
623                        }
624                        std::wstring to = argv[0];
625                        LOG_DEBUG_STD(_T("Migrating to: ") + to);
626                        try {
627                                settings_manager::get_core()->migrate_to(Settings::SettingsCore::string_to_type(to));
628                        } catch (SettingsException e) {
629                                LOG_CRITICAL_STD(_T("Failed to migrate settings: ") + e.getError());
630                        }
631                } else if (sarg == _T("generate")) {
632                        if (argc == 0) {
633                                LOG_ERROR_STD(_T("In correct syntax: nsclient++ -settings generate <what>"));
634                                LOG_ERROR_STD(_T("     where <what> is one of ths following:"));
635                                LOG_ERROR_STD(_T("      trac"));
636                                LOG_ERROR_STD(_T("      default"));
637                                LOG_ERROR_STD(_T("      <type>"));
638                                return;
639                        }
640                        std::wstring arg1 = argv[0];
641                        if (arg1 == _T("default")) {
642                                try {
643                                        load_all_plugins(NSCAPI::dontStart);
644                                        settings_manager::get_core()->update_defaults();
645                                        settings_manager::get_core()->get()->save();
646                                } catch (SettingsException e) {
647                                        LOG_CRITICAL_STD(_T("Failed to migrate settings: ") + e.getError());
648                                }
649                        } else if (arg1 == _T("trac")) {
650                                try {
651                                        load_all_plugins(NSCAPI::dontStart);
652
653                                        Settings::string_list s = settings_manager::get_core()->get_reg_sections();
654                                        for (Settings::string_list::const_iterator cit = s.begin(); cit != s.end(); ++cit) {
655                                                std::wcout << _T("== ") << (*cit) << _T(" ==") << std::endl;
656                                                Settings::string_list k = settings_manager::get_core()->get_reg_keys(*cit);
657                                                bool first = true;
658                                                for (Settings::string_list::const_iterator citk = k.begin(); citk != k.end(); ++citk) {
659                                                        Settings::SettingsCore::key_description desc = settings_manager::get_core()->get_registred_key(*cit, *citk);
660                                                        if (!desc.advanced) {
661                                                                if (first)
662                                                                        std::wcout << _T("'''Normal settings'''") << std::endl;
663                                                                first = false;
664                                                                std::wcout << _T("||") << (*citk) << _T("||") << desc.defValue << _T("||") << desc.title << _T(": ") << desc.description
665                                                                        << std::endl;
666                                                        }
667                                                }
668                                                first = true;
669                                                for (Settings::string_list::const_iterator citk = k.begin(); citk != k.end(); ++citk) {
670                                                        Settings::SettingsCore::key_description desc = settings_manager::get_core()->get_registred_key(*cit, *citk);
671                                                        if (desc.advanced) {
672                                                                if (first)
673                                                                        std::wcout << _T("'''Advanced settings'''") << std::endl;
674                                                                first = false;
675                                                                std::wcout << _T("||") << (*citk) << _T("||") << desc.defValue << _T("||") << desc.title << _T(": ") << desc.description
676                                                                        << std::endl;
677                                                        }
678                                                }
679                                        }
680                                } catch (SettingsException e) {
681                                        LOG_CRITICAL_STD(_T("Failed to migrate settings: ") + e.getError());
682                                }
683                        } else {
684                                try {
685                                        Settings::SettingsCore::settings_type type = settings_manager::get_core()->string_to_type(arg1);
686                                        load_all_plugins(NSCAPI::dontStart);
687                                        settings_manager::get_core()->update_defaults();
688                                        settings_manager::get_core()->get(type)->save();
689                                } catch (SettingsException e) {
690                                        LOG_CRITICAL_STD(_T("Failed to migrate settings: ") + e.getError());
691                                }
692                        }
693                } else {
694                        LOG_ERROR_STD(_T("In correct syntax: nsclient++ -settings <keyword>"));
695                        LOG_ERROR_STD(_T(" <keyword> : "));
696                        LOG_ERROR_STD(_T("   migrate - migrate to a new setings subsystem"));
697                        LOG_ERROR_STD(_T("   copy    - copy settings from one subsystem to another"));
698                        LOG_ERROR_STD(_T("   set     - Set a setting system as the default store"));
699                }
700
701
702        } catch (SettingsException e) {
703                LOG_CRITICAL_STD(_T("Failed to initialize settings: ") + e.getError());
704        } catch (...) {
705                LOG_CRITICAL(_T("FATAL ERROR IN SETTINGS SUBSYTEM"));
706        }
707
708}
709
710void NSClientT::session_error(std::wstring file, unsigned int line, std::wstring msg) {
711        NSAPIMessage(NSCAPI::error, file.c_str(), line, msg.c_str());
712}
713
714void NSClientT::session_info(std::wstring file, unsigned int line, std::wstring msg) {
715        NSAPIMessage(NSCAPI::log, file.c_str(), line, msg.c_str());
716}
717
718
719
720
721//////////////////////////////////////////////////////////////////////////
722// Service functions
723
724/**
725 * Initialize the program
726 * @param boot true if we shall boot all plugins
727 * @param attachIfPossible is true we will attach to a running instance.
728 * @return success
729 * @author mickem
730 */
731bool NSClientT::initCore(bool boot) {
732        LOG_MESSAGE(_T("Attempting to start NSCLient++ - " SZVERSION));
733        if (!settings_manager::init_settings(getBasePath())) {
734                return false;
735        }
736        try {
737                if (debug_)
738                        settings_manager::get_settings()->set_int(_T("log"), _T("debug"), 1);
739                        settings_manager::get_settings()->set_int(_T("Settings"), _T("shared_Session"), 1);
740                enable_shared_session_ = SETTINGS_GET_BOOL_CORE(settings_def::SHARED_SESSION);
741        } catch (SettingsException e) {
742                LOG_ERROR_STD(_T("Could not find settings: ") + e.getMessage());
743        }
744
745        if (enable_shared_session_) {
746                LOG_MESSAGE_STD(_T("Enabling shared session..."));
747                if (boot) {
748                        LOG_MESSAGE_STD(_T("Starting shared session..."));
749//                      try {
750//                              shared_server_.reset(new nsclient_session::shared_server_session(this));
751//                              if (!shared_server_->session_exists()) {
752//                                      shared_server_->create_new_session();
753//                              } else {
754//                                      LOG_ERROR_STD(_T("Session already exists cant create a new one!"));
755//                              }
756//                              startTrayIcons();
757//                      } catch (nsclient_session::session_exception e) {
758//                              LOG_ERROR_STD(_T("Failed to create new session: ") + e.what());
759//                              shared_server_.reset(NULL);
760//                      } catch (...) {
761//                              LOG_ERROR_STD(_T("Failed to create new session: Unknown exception"));
762//                              shared_server_.reset(NULL);
763//                      }
764                } else {
765                        LOG_MESSAGE_STD(_T("Attaching to shared session..."));
766//                      try {
767//                              std::wstring id = _T("_attached_") + strEx::itos(GetCurrentProcessId()) + _T("_");
768//                              shared_client_.reset(new nsclient_session::shared_client_session(id, this));
769//                              if (shared_client_->session_exists()) {
770//                                      shared_client_->attach_to_session(id);
771//                              } else {
772//                                      LOG_ERROR_STD(_T("No session was found cant attach!"));
773//                              }
774//                              LOG_ERROR_STD(_T("Session is: ") + shared_client_->get_client_id());
775//                      } catch (nsclient_session::session_exception e) {
776//                              LOG_ERROR_STD(_T("Failed to attach to session: ") + e.what());
777//                              shared_client_.reset(NULL);
778//                      } catch (...) {
779//                              LOG_ERROR_STD(_T("Failed to attach to session: Unknown exception"));
780//                              shared_client_.reset(NULL);
781//                      }
782                }
783        }
784/*
785        try {
786                simpleSocket::WSAStartup();
787        } catch (simpleSocket::SocketException e) {
788                LOG_ERROR_STD(_T("Socket exception: ") + e.getMessage());
789                return false;
790        } catch (...) {
791                LOG_ERROR_STD(_T("Unknown exception iniating socket..."));
792                return false;
793        }
794*/
795        try {
796                com_helper_.initialize();
797        } catch (com_helper::com_exception e) {
798                LOG_ERROR_STD(_T("COM exception: ") + e.getMessage());
799                return false;
800        } catch (...) {
801                LOG_ERROR_STD(_T("Unknown exception iniating COM..."));
802                return false;
803        }
804        if (boot) {
805                try {
806                        Settings::string_list list = settings_manager::get_settings()->get_keys(MAIN_MODULES_SECTION);
807                        for (Settings::string_list::const_iterator cit = list.begin(); cit != list.end(); ++cit) {
808                                LOG_DEBUG_STD(_T("Processing plugin: " + *cit));
809                                try {
810                                        if (settings_manager::get_settings()->get_string(MAIN_MODULES_SECTION, *cit) == _T("disabled")) {
811                                                LOG_DEBUG_STD(_T("Not booting: " + *cit + _T(" since it is disabled.")));
812                                                continue;
813                                        }
814                                } catch (...) {
815                                        // If we except we load the plugin in as-is
816                                }
817                                try {
818                                        loadPlugin(getBasePath() + _T("modules\\") + (*cit));
819                                } catch(const NSPluginException& e) {
820                                        LOG_ERROR_STD(_T("Exception raised: ") + e.error_ + _T(" in module: ") + e.file_);
821                                        //return false;
822                                } catch (std::exception e) {
823                                        LOG_ERROR_STD(_T("exception loading plugin: ") + (*cit) + strEx::string_to_wstring(e.what()));
824                                        return false;
825                                } catch (...) {
826                                        LOG_ERROR_STD(_T("Unknown exception loading plugin: ") + (*cit));
827                                        return false;
828                                }
829                        }
830                } catch (SettingsException e) {
831                        LOG_ERROR_STD(_T("Failed to set settings file") + e.getMessage());
832                } catch (...) {
833                        LOG_ERROR_STD(_T("Unknown exception when loading plugins"));
834                        return false;
835                }
836                try {
837                        loadPlugins(boot?NSCAPI::normalStart:NSCAPI::dontStart);
838                } catch (...) {
839                        LOG_ERROR_STD(_T("Unknown exception loading plugins"));
840                        return false;
841                }
842                LOG_DEBUG_STD(_T("NSCLient++ - " SZVERSION) + _T(" Started!"));
843        }
844        LOG_MESSAGE_STD(_T("NSCLient++ - " SZVERSION) + _T(" Started!"));
845        return true;
846}
847
848/**
849 * Service control handler startup point.
850 * When the program is started as a service this will be the entry point.
851 */
852bool NSClientT::InitiateService() {
853        if (!initCore(true))
854                return false;
855/*
856        DWORD dwSessionId = remote_processes::getActiveSessionId();
857        if (dwSessionId != 0xFFFFFFFF)
858                tray_starter::start(dwSessionId);
859        else
860                LOG_ERROR_STD(_T("Failed to start tray helper:" ) + error::lookup::last_error());
861                */
862        return true;
863}
864
865void NSClientT::startTrayIcons() {
866//      if (shared_server_.get() == NULL) {
867//              LOG_MESSAGE_STD(_T("No master session so tray icons not started"));
868//              return;
869//      }
870//      remote_processes::PWTS_SESSION_INFO list;
871//      DWORD count;
872//      if (!remote_processes::_WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE , 0, 1, &list, &count)) {
873//              LOG_ERROR_STD(_T("Failed to enumerate sessions:" ) + error::lookup::last_error());
874//      } else {
875//              LOG_DEBUG_STD(_T("Found ") + strEx::itos(count) + _T(" sessions"));
876//              for (DWORD i=0;i<count;i++) {
877//                      LOG_DEBUG_STD(_T("Found session: ") + strEx::itos(list[i].SessionId) + _T(" state: ") + strEx::itos(list[i].State));
878//                      if (list[i].State == remote_processes::_WTS_CONNECTSTATE_CLASS::WTSActive) {
879//                              startTrayIcon(list[i].SessionId);
880//                      }
881//              }
882//      }
883}
884void NSClientT::startTrayIcon(DWORD dwSessionId) {
885//      if (shared_server_.get() == NULL) {
886//              LOG_MESSAGE_STD(_T("No master session so tray icons not started"));
887//              return;
888//      }
889//      if (!shared_server_->re_attach_client(dwSessionId)) {
890//              if (!tray_starter::start(dwSessionId)) {
891//                      LOG_ERROR_STD(_T("Failed to start session (") + strEx::itos(dwSessionId) + _T("): " ) + error::lookup::last_error());
892//              }
893//      }
894}
895
896bool NSClientT::exitCore(bool boot) {
897        plugins_loaded_ = false;
898        LOG_DEBUG(_T("Attempting to stop NSCLient++ - " SZVERSION));
899        if (boot) {
900                try {
901                        LOG_DEBUG_STD(_T("Stopping: NON Message Handling Plugins"));
902                        mainClient.unloadPlugins(false);
903                } catch(NSPluginException e) {
904                        LOG_ERROR_STD(_T("Exception raised when unloading non msg plguins: ") + e.error_ + _T(" in module: ") + e.file_);
905                } catch(...) {
906                        LOG_ERROR_STD(_T("Unknown exception raised when unloading non msg plugins"));
907                }
908        }
909        LOG_DEBUG_STD(_T("Stopping: COM helper"));
910        try {
911                com_helper_.unInitialize();
912        } catch (com_helper::com_exception e) {
913                LOG_ERROR_STD(_T("COM exception: ") + e.getMessage());
914        } catch (...) {
915                LOG_ERROR_STD(_T("Unknown exception uniniating COM..."));
916        }
917        /*
918        LOG_DEBUG_STD(_T("Stopping: Socket Helpers"));
919        try {
920                simpleSocket::WSACleanup();
921        } catch (simpleSocket::SocketException e) {
922                LOG_ERROR_STD(_T("Socket exception: ") + e.getMessage());
923        } catch (...) {
924                LOG_ERROR_STD(_T("Unknown exception uniniating socket..."));
925        }
926        */
927        LOG_DEBUG_STD(_T("Stopping: Settings instance"));
928        settings_manager::destroy_settings();
929//      try {
930//              if (shared_client_.get() != NULL) {
931//                      LOG_DEBUG_STD(_T("Stopping: shared client"));
932//                      shared_client_->set_handler(NULL);
933//                      shared_client_->close_session();
934//              }
935//      } catch(nsclient_session::session_exception &e) {
936//              LOG_ERROR_STD(_T("Exception closing shared client session: ") + e.what());
937//      } catch(...) {
938//              LOG_ERROR_STD(_T("Exception closing shared client session: Unknown exception!"));
939//      }
940        try {
941//              if (shared_server_.get() != NULL) {
942//                      LOG_DEBUG_STD(_T("Stopping: shared server"));
943//                      shared_server_->set_handler(NULL);
944//                      shared_server_->close_session();
945//              }
946        } catch(...) {
947                LOG_ERROR_STD(_T("UNknown exception raised: When closing shared session"));
948        }
949        if (boot) {
950                try {
951                        LOG_DEBUG_STD(_T("Stopping: Message handling Plugins"));
952                        mainClient.unloadPlugins(true);
953                } catch(NSPluginException e) {
954                        LOG_ERROR_STD(_T("Exception raised when unloading msg plugins: ") + e.error_ + _T(" in module: ") + e.file_);
955                } catch(...) {
956                        LOG_ERROR_STD(_T("UNknown exception raised: When stopping message plguins"));
957                }
958        }
959        LOG_MESSAGE_STD(_T("NSCLient++ - " SZVERSION) + _T(" Stopped succcessfully"));
960        return true;
961}
962/**
963 * Service control handler termination point.
964 * When the program is stopped as a service this will be the "exit point".
965 */
966void NSClientT::TerminateService(void) {
967        exitCore(true);
968}
969
970/**
971 * Forward this to the main service dispatcher helper class
972 * @param dwArgc
973 * @param *lpszArgv
974 */
975void WINAPI NSClientT::service_main_dispatch(DWORD dwArgc, LPTSTR *lpszArgv) {
976        try {
977                //WTF!!! mainClient.service_main(dwArgc, lpszArgv);
978        } catch (service_helper::service_exception e) {
979                LOG_ERROR_STD(_T("Unknown service error: ") + e.what());
980        } catch (...) {
981                LOG_ERROR_STD(_T("Unknown service error!"));
982        }
983}
984DWORD WINAPI NSClientT::service_ctrl_dispatch_ex(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext) {
985        return mainClient.service_ctrl_ex(dwControl, dwEventType, lpEventData, lpContext);
986}
987/**
988 * Forward this to the main service dispatcher helper class
989 * @param dwCtrlCode
990 */
991void WINAPI NSClientT::service_ctrl_dispatch(unsigned long dwCtrlCode) {
992        mainClient.service_ctrl_ex(dwCtrlCode, NULL, NULL, NULL);
993}
994
995
996void NSClientT::service_on_session_changed(unsigned long dwSessionId, bool logon, unsigned long dwEventType) {
997//      if (shared_server_.get() == NULL) {
998//              LOG_DEBUG_STD(_T("No shared session: ignoring change event!"));
999//              return;
1000//      }
1001        LOG_DEBUG_STD(_T("Got session change: ") + strEx::itos(dwSessionId));
1002        if (!logon) {
1003                LOG_DEBUG_STD(_T("Not a logon event: ") + strEx::itos(dwEventType));
1004                return;
1005        }
1006        tray_starter::start(dwSessionId);
1007}
1008
1009//////////////////////////////////////////////////////////////////////////
1010// Member functions
1011
1012int NSClientT::commandLineExec(const TCHAR* module, const TCHAR* command, const unsigned int argLen, TCHAR** args) {
1013        std::wstring sModule = module;
1014        std::wstring moduleList = _T("");
1015        {
1016                boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::seconds(5));
1017                if (!readLock.owns_lock()) {
1018                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1019                        return -1;
1020                }
1021                for (pluginList::size_type i=0;i<plugins_.size();++i) {
1022                        NSCPlugin *p = plugins_[i];
1023                        if (!moduleList.empty())
1024                                moduleList += _T(", ");
1025                        moduleList += p->getModule();
1026                        if (p->getModule() == sModule) {
1027                                LOG_DEBUG_STD(_T("Found module: ") + p->getName() + _T("..."));
1028                                try {
1029                                        return p->commandLineExec(command, argLen, args);
1030                                } catch (NSPluginException e) {
1031                                        LOG_ERROR_STD(_T("Could not execute command: ") + e.error_ + _T(" in ") + e.file_);
1032                                        return -1;
1033                                }
1034                        }
1035                }
1036        }
1037        try {
1038                plugin_type plugin = loadPlugin(getBasePath() + _T("modules\\") + module);
1039                LOG_DEBUG_STD(_T("Loading plugin: ") + plugin->getName() + _T("..."));
1040                plugin->load_plugin(NSCAPI::dontStart);
1041                return plugin->commandLineExec(command, argLen, args);
1042        } catch (NSPluginException e) {
1043                LOG_MESSAGE_STD(_T("Module (") + e.file_ + _T(") was not found: ") + e.error_);
1044        }
1045        try {
1046                plugin_type plugin = loadPlugin(getBasePath() + _T("modules\\") + module + _T(".dll"));
1047                LOG_DEBUG_STD(_T("Loading plugin: ") + plugin->getName() + _T("..."));
1048                plugin->load_plugin(NSCAPI::dontStart);
1049                return plugin->commandLineExec(command, argLen, args);
1050        } catch (NSPluginException e) {
1051                LOG_MESSAGE_STD(_T("Module (") + e.file_ + _T(") was not found: ") + e.error_);
1052        }
1053        LOG_ERROR_STD(_T("Module not found: ") + module + _T(" available modules are: ") + moduleList);
1054        return 0;
1055}
1056
1057/**
1058 * Load a list of plug-ins
1059 * @param plugins A list with plug-ins (DLL files) to load
1060 */
1061void NSClientT::addPlugins(const std::list<std::wstring> plugins) {
1062        boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::seconds(10));
1063        if (!readLock.owns_lock()) {
1064                LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1065                return;
1066        }
1067        std::list<std::wstring>::const_iterator it;
1068        for (it = plugins.begin(); it != plugins.end(); ++it) {
1069                loadPlugin(*it);
1070        }
1071}
1072/**
1073 * Unload all plug-ins (in reversed order)
1074 */
1075void NSClientT::unloadPlugins(bool unloadLoggers) {
1076        {
1077                boost::unique_lock<boost::shared_mutex> writeLock(m_mutexRW, boost::get_system_time() + boost::posix_time::seconds(10));
1078                if (!writeLock.owns_lock()) {
1079                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1080                        return;
1081                }
1082                commandHandlers_.clear();
1083                if (unloadLoggers)
1084                        messageHandlers_.clear();
1085        }
1086        {
1087                boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::milliseconds(5000));
1088                if (!readLock.owns_lock()) {
1089                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1090                        return;
1091                }
1092                for (pluginList::reverse_iterator it = plugins_.rbegin(); it != plugins_.rend(); ++it) {
1093                        NSCPlugin *p = *it;
1094                        if (p == NULL)
1095                                continue;
1096                        try {
1097                                if (unloadLoggers || !p->hasMessageHandler()) {
1098                                        LOG_DEBUG_STD(_T("Unloading plugin: ") + p->getModule() + _T("..."));
1099                                        p->unload();
1100                                } else {
1101                                        LOG_DEBUG_STD(_T("Skipping log plugin: ") + p->getModule() + _T("..."));
1102                                }
1103                        } catch(NSPluginException e) {
1104                                LOG_ERROR_STD(_T("Exception raised when unloading plugin: ") + e.error_ + _T(" in module: ") + e.file_);
1105                        } catch(...) {
1106                                LOG_ERROR_STD(_T("Unknown exception raised when unloading plugin"));
1107                        }
1108                }
1109        }
1110        {
1111                boost::unique_lock<boost::shared_mutex> writeLock(m_mutexRW, boost::get_system_time() + boost::posix_time::seconds(10));
1112                if (!writeLock.owns_lock()) {
1113                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1114                        return;
1115                }
1116                for (pluginList::iterator it = plugins_.begin(); it != plugins_.end();) {
1117                        NSCPlugin *p = (*it);
1118                        try {
1119                                if (p != NULL && (unloadLoggers|| !p->isLoaded())) {
1120                                        it = plugins_.erase(it);
1121                                        delete p;
1122                                        continue;
1123                                }
1124                        } catch(NSPluginException e) {
1125                                LOG_ERROR_STD(_T("Exception raised when unloading plugin: ") + e.error_ + _T(" in module: ") + e.file_);
1126                        } catch(...) {
1127                                LOG_ERROR_STD(_T("Unknown exception raised when unloading plugin"));
1128                        }
1129                        it++;
1130                }
1131        }
1132}
1133
1134void NSClientT::loadPlugins(NSCAPI::moduleLoadMode mode) {
1135        bool hasBroken = false;
1136        {
1137                boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::milliseconds(5000));
1138                if (!readLock.owns_lock()) {
1139                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1140                        return;
1141                }
1142                for (pluginList::iterator it=plugins_.begin(); it != plugins_.end();) {
1143                        LOG_DEBUG_STD(_T("Loading plugin: ") + (*it)->getName() + _T("..."));
1144                        try {
1145                                if (!(*it)->load_plugin(NSCAPI::normalStart)) {
1146                                        it = plugins_.erase(it);
1147                                        LOG_ERROR_STD(_T("Plugin refused to load: ") + (*it)->getModule());
1148                                }
1149                                ++it;
1150                        } catch (NSPluginException e) {
1151                                it = plugins_.erase(it);
1152                                LOG_ERROR_STD(_T("Could not load plugin: ") + e.file_ + _T(": ") + e.error_);
1153                        } catch (...) {
1154                                it = plugins_.erase(it);
1155                                LOG_ERROR_STD(_T("Could not load plugin: ") + (*it)->getModule());
1156                        }
1157                }
1158        }
1159        for (pluginList::iterator it=plugins_.begin(); it != plugins_.end();) {
1160                LOG_DEBUG_STD(_T("Loading plugin: ") + (*it)->getName() + _T("..."));
1161                try {
1162                        (*it)->load_plugin(mode);
1163                        ++it;
1164                } catch(NSPluginException e) {
1165                        it = plugins_.erase(it);
1166                        LOG_ERROR_STD(_T("Exception raised when loading plugin: ") + e.error_ + _T(" in module: ") + e.file_ + _T(" plugin has been removed."));
1167                } catch(...) {
1168                        it = plugins_.erase(it);
1169                        LOG_ERROR_STD(_T("Unknown exception raised when unloading plugin plugin has been removed"));
1170                }
1171        }
1172        plugins_loaded_ = true;
1173}
1174/**
1175 * Load a single plug-in using a DLL filename
1176 * @param file The DLL file
1177 */
1178NSClientT::plugin_type NSClientT::loadPlugin(const std::wstring file) {
1179        return addPlugin(new NSCPlugin(file));
1180}
1181/**
1182 * Load and add a plugin to various internal structures
1183 * @param plugin The plug-in instance to load. The pointer is managed by the
1184 */
1185NSClientT::plugin_type NSClientT::addPlugin(plugin_type plugin) {
1186        plugin->load_dll();
1187        {
1188                boost::unique_lock<boost::shared_mutex> writeLock(m_mutexRW, boost::get_system_time() + boost::posix_time::seconds(10));
1189                if (!writeLock.owns_lock()) {
1190                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1191                        return plugin;
1192                }
1193                plugins_.insert(plugins_.end(), plugin);
1194                if (plugin->hasCommandHandler())
1195                        commandHandlers_.insert(commandHandlers_.end(), plugin);
1196                if (plugin->hasMessageHandler())
1197                        messageHandlers_.insert(messageHandlers_.end(), plugin);
1198                settings_manager::get_core()->register_key(_T("/modules"), plugin->getFilename(), Settings::SettingsCore::key_string, plugin->getName(), plugin->getDescription(), _T(""), false);
1199        }
1200        return plugin;
1201}
1202
1203
1204std::wstring NSClientT::describeCommand(std::wstring command) {
1205        boost::shared_lock<boost::shared_mutex> readLock(m_mutexRWcmdDescriptions, boost::get_system_time() + boost::posix_time::seconds(5));
1206        if (!readLock.owns_lock()) {
1207                LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex when trying to get command list."));
1208                return _T("Failed to get mutex when describing command: ") + command;
1209        }
1210        cmdMap::const_iterator cit = cmdDescriptions_.find(command);
1211        if (cit == cmdDescriptions_.end())
1212                return _T("Command not found: ") + command + _T(", maybe it has not been register?");
1213        return (*cit).second;
1214}
1215std::list<std::wstring> NSClientT::getAllCommandNames() {
1216        std::list<std::wstring> lst;
1217        boost::shared_lock<boost::shared_mutex> readLock(m_mutexRWcmdDescriptions, boost::get_system_time() + boost::posix_time::seconds(5));
1218        if (!readLock.owns_lock()) {
1219                LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex when trying to get command list."));
1220                return lst;
1221        }
1222        for (cmdMap::const_iterator cit = cmdDescriptions_.begin(); cit != cmdDescriptions_.end(); ++cit) {
1223                lst.push_back((*cit).first);
1224        }
1225        return lst;
1226}
1227void NSClientT::registerCommand(std::wstring cmd, std::wstring desc) {
1228        boost::unique_lock<boost::shared_mutex> writeLock(m_mutexRWcmdDescriptions, boost::get_system_time() + boost::posix_time::seconds(10));
1229        if (!writeLock.owns_lock()) {
1230                LOG_ERROR_STD(_T("FATAL ERROR: Failed to describe command:") + cmd);
1231                return;
1232        }
1233        cmdDescriptions_[cmd] = desc;
1234}
1235
1236unsigned int NSClientT::getBufferLength() {
1237        static unsigned int len = 0;
1238        if (len == 0) {
1239                try {
1240                        len = settings_manager::get_settings()->get_int(SETTINGS_KEY(settings_def::PAYLOAD_LEN));
1241                } catch (SettingsException &e) {
1242                        LOG_DEBUG_STD(_T("Failed to get length: ") + e.getMessage());
1243                        return setting_keys::settings_def::PAYLOAD_LEN_DEFAULT;
1244                } catch (...) {
1245                        LOG_ERROR(_T("Failed to get length: :("));
1246                        return setting_keys::settings_def::PAYLOAD_LEN_DEFAULT;
1247                }
1248        }
1249        return len;
1250}
1251
1252NSCAPI::nagiosReturn NSClientT::inject(std::wstring command, std::wstring arguments, TCHAR splitter, bool escape, std::wstring &msg, std::wstring & perf) {
1253        /*if (shared_client_.get() != NULL && shared_client_->hasMaster()) {
1254                try {
1255                        return shared_client_->inject(command, arguments, splitter, escape, msg, perf);
1256                } catch (nsclient_session::session_exception &e) {
1257                        LOG_ERROR_STD(_T("Failed to inject remote command: ") + e.what());
1258                        return NSCAPI::returnCRIT;
1259                } catch (...) {
1260                        LOG_ERROR_STD(_T("Failed to inject remote command: Unknown exception"));
1261                        return NSCAPI::returnCRIT;
1262                }
1263        } else */{
1264                unsigned int aLen = 0;
1265                TCHAR ** aBuf = arrayBuffer::split2arrayBuffer(arguments, splitter, aLen, escape);
1266                unsigned int buf_len = getBufferLength();
1267                TCHAR * mBuf = new TCHAR[buf_len+1]; mBuf[0] = '\0';
1268                TCHAR * pBuf = new TCHAR[buf_len+1]; pBuf[0] = '\0';
1269                NSCAPI::nagiosReturn ret = injectRAW(command.c_str(), aLen, aBuf, mBuf, buf_len, pBuf, buf_len);
1270                arrayBuffer::destroyArrayBuffer(aBuf, aLen);
1271                if ( (ret == NSCAPI::returnInvalidBufferLen) || (ret == NSCAPI::returnIgnored) ) {
1272                        delete [] mBuf;
1273                        delete [] pBuf;
1274                        return ret;
1275                }
1276                msg = mBuf;
1277                perf = pBuf;
1278                delete [] mBuf;
1279                delete [] pBuf;
1280                return ret;
1281        }
1282}
1283
1284/**
1285 * Inject a command into the plug-in stack.
1286 *
1287 * @param command Command to inject
1288 * @param argLen Length of argument buffer
1289 * @param **argument Argument buffer
1290 * @param *returnMessageBuffer Message buffer
1291 * @param returnMessageBufferLen Length of returnMessageBuffer
1292 * @param *returnPerfBuffer Performance data buffer
1293 * @param returnPerfBufferLen Length of returnPerfBuffer
1294 * @return The command status
1295 */
1296NSCAPI::nagiosReturn NSClientT::injectRAW(const TCHAR* command, const unsigned int argLen, TCHAR **argument, TCHAR *returnMessageBuffer, unsigned int returnMessageBufferLen, TCHAR *returnPerfBuffer, unsigned int returnPerfBufferLen) {
1297        if (logDebug()) {
1298                LOG_DEBUG_STD(_T("Injecting: ") + (std::wstring) command + _T(": ") + arrayBuffer::arrayBuffer2string(argument, argLen, _T(", ")));
1299        }
1300        /*if (shared_client_.get() != NULL && shared_client_->hasMaster()) {
1301                try {
1302                        std::wstring msg, perf;
1303                        int returnCode = shared_client_->inject(command, arrayBuffer::arrayBuffer2string(argument, argLen, _T(" ")), L' ', true, msg, perf);
1304                        NSCHelper::wrapReturnString(returnMessageBuffer, returnMessageBufferLen, msg, returnCode);
1305                        return NSCHelper::wrapReturnString(returnPerfBuffer, returnPerfBufferLen, perf, returnCode);
1306                } catch (nsclient_session::session_exception &e) {
1307                        LOG_ERROR_STD(_T("Failed to inject remote command: ") + e.what());
1308                        int returnCode = NSCHelper::wrapReturnString(returnMessageBuffer, returnMessageBufferLen, _T("Failed to inject remote command: ") + e.what(), NSCAPI::returnCRIT);
1309                        return NSCHelper::wrapReturnString(returnPerfBuffer, returnPerfBufferLen, _T(""), returnCode);
1310                } catch (...) {
1311                        LOG_ERROR_STD(_T("Failed to inject remote command: Unknown exception"));
1312                        int returnCode = NSCHelper::wrapReturnString(returnMessageBuffer, returnMessageBufferLen, _T("Failed to inject remote command:  + e.what()"), NSCAPI::returnCRIT);
1313                        return NSCHelper::wrapReturnString(returnPerfBuffer, returnPerfBufferLen, _T(""), returnCode);
1314                }
1315        } else */{
1316                boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::milliseconds(5000));
1317                if (!readLock.owns_lock()) {
1318                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1319                        return NSCAPI::returnUNKNOWN;
1320                }
1321                for (pluginList::size_type i = 0; i < commandHandlers_.size(); i++) {
1322                        try {
1323                                NSCAPI::nagiosReturn c = commandHandlers_[i]->handleCommand(command, argLen, argument, returnMessageBuffer, returnMessageBufferLen, returnPerfBuffer, returnPerfBufferLen);
1324                                switch (c) {
1325                                        case NSCAPI::returnInvalidBufferLen:
1326                                                LOG_ERROR(_T("UNKNOWN: Return buffer to small to handle this command."));
1327                                                return c;
1328                                        case NSCAPI::returnIgnored:
1329                                                break;
1330                                        case NSCAPI::returnOK:
1331                                        case NSCAPI::returnWARN:
1332                                        case NSCAPI::returnCRIT:
1333                                        case NSCAPI::returnUNKNOWN:
1334                                                LOG_DEBUG_STD(_T("Injected Result: ") + NSCHelper::translateReturn(c) + _T(" '") + (std::wstring)(returnMessageBuffer) + _T("'"));
1335                                                LOG_DEBUG_STD(_T("Injected Performance Result: '") +(std::wstring)(returnPerfBuffer) + _T("'"));
1336                                                return c;
1337                                        default:
1338                                                LOG_ERROR_STD(_T("Unknown error from handleCommand: ") + strEx::itos(c) + _T(" the injected command was: ") + (std::wstring)command);
1339                                                return c;
1340                                }
1341                        } catch(const NSPluginException& e) {
1342                                LOG_ERROR_STD(_T("Exception raised: ") + e.error_ + _T(" in module: ") + e.file_);
1343                                return NSCAPI::returnCRIT;
1344                        } catch(...) {
1345                                LOG_ERROR_STD(_T("Unknown exception raised in module"));
1346                                return NSCAPI::returnCRIT;
1347                        }
1348                }
1349                LOG_MESSAGE_STD(_T("No handler for command: '") + command + _T("'"));
1350                return NSCAPI::returnIgnored;
1351        }
1352}
1353
1354void NSClientT::listPlugins() {
1355        boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::milliseconds(5000));
1356        if (!readLock.owns_lock()) {
1357                LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1358                return;
1359        }
1360        for (pluginList::iterator it=plugins_.begin(); it != plugins_.end(); ++it) {
1361                try {
1362                        if ((*it)->isBroken()) {
1363                                std::wcout << (*it)->getModule() << _T(": ") << _T("broken") << std::endl;
1364                        } else {
1365                                std::wcout << (*it)->getModule() << _T(": ") << (*it)->getName() << std::endl;
1366                        }
1367                } catch (NSPluginException e) {
1368                        LOG_ERROR_STD(_T("Could not load plugin: ") + e.file_ + _T(": ") + e.error_);
1369                }
1370        }
1371
1372}
1373
1374bool NSClientT::logDebug() {
1375        if (debug_ == log_unknown) {
1376                debug_ = log_looking;
1377                try {
1378                        if (settings_manager::get_settings()->get_int(_T("log"), _T("debug"), 0) == 1)
1379                                debug_ = log_debug;
1380                        else
1381                                debug_ = log_nodebug;
1382                } catch (SettingsException e) {
1383                        return true;
1384                }
1385        } else if (debug_ == log_looking)
1386                return true;
1387        return (debug_ == log_debug);
1388}
1389
1390void log_broken_message(std::wstring msg) {
1391        OutputDebugString(msg.c_str());
1392        std::wcout << msg << std::endl;
1393}
1394/**
1395 * Report a message to all logging enabled modules.
1396 *
1397 * @param msgType Message type
1398 * @param file Filename generally __FILE__
1399 * @param line  Line number, generally __LINE__
1400 * @param message The message as a human readable string.
1401 */
1402void NSClientT::reportMessage(int msgType, const TCHAR* file, const int line, std::wstring message) {
1403        try {
1404                strEx::replace(message, _T("\n"), _T(" "));
1405                strEx::replace(message, _T("\r"), _T(" "));
1406                if ((msgType == NSCAPI::debug)&&(!logDebug())) {
1407                        return;
1408                }
1409//              if (shared_server_.get() != NULL && shared_server_->hasClients()) {
1410//                      try {
1411//                              shared_server_->sendLogMessageToClients(msgType, file, line, message);
1412//                      } catch (nsclient_session::session_exception e) {
1413//                              log_broken_message(_T("Failed to send message to clients: ") + e.what());
1414//                      }
1415//              }
1416                std::wstring file_stl = file;
1417                std::wstring::size_type pos = file_stl.find_last_of(_T("\\"));
1418                if (pos != std::wstring::npos)
1419                        file_stl = file_stl.substr(pos);
1420                {
1421                        boost::shared_lock<boost::shared_mutex> readLock(m_mutexRW, boost::get_system_time() + boost::posix_time::milliseconds(5000));
1422                        if (!readLock.owns_lock()) {
1423                                log_broken_message(_T("Message was lost as the (mutexRW) core was locked: ") + message);
1424                                return;
1425                        }
1426                        boost::unique_lock<boost::timed_mutex> lock(messageMutex, boost::get_system_time() + boost::posix_time::seconds(5));
1427                        if (!lock.owns_lock()) {
1428                                log_broken_message(_T("Message was lost as the core was locked: ") + message);
1429                                return;
1430                        }
1431                        if (g_bConsoleLog) {
1432                                std::string k = "?";
1433                                switch (msgType) {
1434                                case NSCAPI::critical:
1435                                        k ="c";
1436                                        break;
1437                                case NSCAPI::warning:
1438                                        k ="w";
1439                                        break;
1440                                case NSCAPI::error:
1441                                        k ="e";
1442                                        break;
1443                                case NSCAPI::log:
1444                                        k ="l";
1445                                        break;
1446                                case NSCAPI::debug:
1447                                        k ="d";
1448                                        break;
1449                                }       
1450                                std::cout << k << " " << strEx::wstring_to_string(file_stl) << "(" << line << ") " << strEx::wstring_to_string(message) << std::endl;
1451                        }
1452                        if (!plugins_loaded_) {
1453                                log_broken_message(message);
1454                                cached_log_entry entry(msgType, file, line, message);
1455                                log_cache_.push_back(entry);
1456                        } else {
1457                                if (log_cache_.size() > 0) {
1458                                        for (log_cache_type::const_iterator cit=log_cache_.begin();cit!=log_cache_.end();++cit) {
1459                                                for (pluginList::size_type i = 0; i< messageHandlers_.size(); i++) {
1460                                                        try {
1461                                                                messageHandlers_[i]->handleMessage((*cit).msgType, (_T("CACHE") + (*cit).file).c_str(), (*cit).line, (*cit).message.c_str());
1462                                                        } catch(const NSPluginException& e) {
1463                                                                log_broken_message(_T("Caught: ") + e.error_ + _T(" when trying to log a message..."));
1464                                                                return;
1465                                                        } catch(...) {
1466                                                                log_broken_message(_T("Caught: Unknown Exception when trying to log a message..."));
1467                                                                return;
1468                                                        }
1469                                                }
1470                                        }
1471                                        log_cache_.clear();
1472                                }
1473                                for (pluginList::size_type i = 0; i< messageHandlers_.size(); i++) {
1474                                        try {
1475                                                messageHandlers_[i]->handleMessage(msgType, file, line, message.c_str());
1476                                        } catch(const NSPluginException& e) {
1477                                                log_broken_message(_T("Caught: ") + e.error_ + _T(" when trying to log a message..."));
1478                                                return;
1479                                        } catch(...) {
1480                                                log_broken_message(_T("Caught: Unknown Exception when trying to log a message..."));
1481                                                return;
1482                                        }
1483                                }
1484                        }
1485                }
1486        } catch (...) {
1487                log_broken_message(_T("Caught UNKNOWN Exception when trying to log a message: ") + message);
1488        }
1489}
1490std::wstring NSClientT::getBasePath(void) {
1491        boost::unique_lock<boost::timed_mutex> lock(internalVariables, boost::get_system_time() + boost::posix_time::seconds(5));
1492        if (!lock.owns_lock()) {
1493                LOG_ERROR(_T("FATAL ERROR: Could not get mutex."));
1494                return _T("FATAL ERROR");
1495        }
1496        if (!basePath.empty())
1497                return basePath;
1498        unsigned int buf_len = 4096;
1499        TCHAR* buffer = new TCHAR[buf_len+1];
1500        GetModuleFileName(NULL, buffer, buf_len);
1501        std::wstring path = buffer;
1502        std::wstring::size_type pos = path.rfind('\\');
1503        basePath = path.substr(0, pos) + _T("\\");
1504        delete [] buffer;
1505        try {
1506                settings_manager::get_core()->set_base(basePath);
1507        } catch (SettingsException e) {
1508                LOG_ERROR_STD(_T("Failed to set settings file: ") + e.getMessage());
1509        } catch (...) {
1510                LOG_ERROR_STD(_T("Failed to set settings file"));
1511        }
1512        return basePath;
1513}
1514
1515
1516std::wstring Encrypt(std::wstring str, unsigned int algorithm) {
1517        unsigned int len = 0;
1518        NSAPIEncrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), NULL, &len);
1519        len+=2;
1520        TCHAR *buf = new TCHAR[len+1];
1521        NSCAPI::errorReturn ret = NSAPIEncrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), buf, &len);
1522        if (ret == NSCAPI::isSuccess) {
1523                std::wstring ret = buf;
1524                delete [] buf;
1525                return ret;
1526        }
1527        return _T("");
1528}
1529std::wstring Decrypt(std::wstring str, unsigned int algorithm) {
1530        unsigned int len = 0;
1531        NSAPIDecrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), NULL, &len);
1532        len+=2;
1533        TCHAR *buf = new TCHAR[len+1];
1534        NSCAPI::errorReturn ret = NSAPIDecrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), buf, &len);
1535        if (ret == NSCAPI::isSuccess) {
1536                std::wstring ret = buf;
1537                delete [] buf;
1538                return ret;
1539        }
1540        return _T("");
1541}
1542
1543
Note: See TracBrowser for help on using the repository browser.