source: nscp/service/NSClient++.cpp @ 01a278b

0.4.00.4.10.4.2
Last change on this file since 01a278b was 01a278b, checked in by Michael Medin <michael@…>, 3 years ago

(re)added service support (both w32/*nix) so now it runs as a service again...

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