source: nscp/service/NSClient++.cpp @ f0eb62d

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

Refactored service into its own project

  • Property mode set to 100644
File size: 71.9 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 <winsvc.h>
17#include "NSClient++.h"
18#include <settings/Settings.h>
19#include <charEx.h>
20#include <Socket.h>
21#include <b64/b64.h>
22#include <config.h>
23#include <msvc_wrappers.h>
24#include <Userenv.h>
25#include <remote_processes.hpp>
26#include <Lmcons.h>
27//#ifdef DEBUG
28#include <crtdbg.h>
29//#endif
30#include <settings/settings_ini.hpp>
31#include <settings/settings_registry.hpp>
32#include <settings/settings_old.hpp>
33#include <Userenv.h>
34#include <remote_processes.hpp>
35#include <Lmcons.h>
36
37NSClient mainClient(SZSERVICENAME);     // Global core instance.
38bool g_bConsoleLog = false;
39
40/**
41 * START OF Tray starter MERGE HELPER
42 */
43class tray_starter {
44        struct start_block {
45                std::wstring cmd;
46                std::wstring cmd_line;
47                DWORD sessionId;
48        };
49
50public:
51        static LPVOID init(DWORD dwSessionId, std::wstring exe, std::wstring cmdline) {
52                start_block *sb = new start_block;
53                sb->cmd = exe;
54                sb->cmd_line = cmdline;
55                sb->sessionId = dwSessionId;
56                return sb;
57        }
58        DWORD threadProc(LPVOID lpParameter) {
59                start_block* param = static_cast<start_block*>(lpParameter);
60                DWORD dwSessionId = param->sessionId;
61                std::wstring cmd = param->cmd;
62                std::wstring cmdline = param->cmd_line;
63                delete param;
64                for (int i=0;i<10;i++) {
65                        Sleep(1000);
66                        if (startTrayHelper(dwSessionId, cmd, cmdline, false))
67                                break;
68                }
69                return 0;
70        }
71
72        static bool start(DWORD dwSessionId) {
73                std::wstring program = mainClient.getBasePath() +  _T("\\") + SETTINGS_GET_STRING(nsclient::SYSTRAY_EXE);
74                std::wstring cmdln = _T("\"") + program + _T("\" -channel __") + strEx::itos(dwSessionId) + _T("__");
75                return tray_starter::startTrayHelper(dwSessionId, program, cmdln);
76        }
77
78        static bool startTrayHelper(DWORD dwSessionId, std::wstring exe, std::wstring cmdline, bool startThread = true) {
79                HANDLE hToken = NULL;
80                if (!remote_processes::GetSessionUserToken(dwSessionId, &hToken)) {
81                        LOG_ERROR_STD(_T("Failed to query user token: ") + error::lookup::last_error());
82                        return false;
83                } else {
84                        STARTUPINFO          StartUPInfo;
85                        PROCESS_INFORMATION  ProcessInfo;
86
87                        ZeroMemory(&StartUPInfo,sizeof(STARTUPINFO));
88                        ZeroMemory(&ProcessInfo,sizeof(PROCESS_INFORMATION));
89                        StartUPInfo.wShowWindow = SW_HIDE;
90                        StartUPInfo.lpDesktop = L"Winsta0\\Default";
91                        StartUPInfo.cb = sizeof(STARTUPINFO);
92
93                        wchar_t *buffer = new wchar_t[cmdline.size()+10];
94                        wcscpy(buffer, cmdline.c_str());
95                        LOG_MESSAGE_STD(_T("Running: ") + exe);
96                        LOG_MESSAGE_STD(_T("Running: ") + cmdline);
97
98                        LPVOID pEnv =NULL;
99                        DWORD dwCreationFlags = CREATE_NO_WINDOW; //0; //DETACHED_PROCESS
100
101                        if(CreateEnvironmentBlock(&pEnv,hToken,TRUE)) {
102                                dwCreationFlags|=CREATE_UNICODE_ENVIRONMENT;
103                        } else {
104                                LOG_ERROR_STD(_T("Failed to create enviornment: ") + error::lookup::last_error());
105                                pEnv=NULL;
106                        }
107                        /*
108                        LOG_ERROR_STD(_T("Impersonating user: "));
109                        if (!ImpersonateLoggedOnUser(hToken)) {
110                                LOG_ERROR_STD(_T("Failed to impersonate the user: ") + error::lookup::last_error());
111                        }
112
113                        wchar_t pszUname[UNLEN + 1];
114                        ZeroMemory(pszUname,sizeof(pszUname));
115                        DWORD dwSize = UNLEN;
116                        if (!GetUserName(pszUname,&dwSize)) {
117                                DWORD dwErr = GetLastError();
118                                if (!RevertToSelf())
119                                        LOG_ERROR_STD(_T("Failed to revert to self: ") + error::lookup::last_error());
120                                LOG_ERROR_STD(_T("Failed to get username: ") + error::format::from_system(dwErr));
121                                return false;
122                        }
123                       
124
125                        PROFILEINFO info;
126                        info.dwSize = sizeof(PROFILEINFO);
127                        info.lpUserName = pszUname;
128                        if (!LoadUserProfile(hToken, &info)) {
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                        if (!CreateProcessAsUser(hToken, exe.c_str(), buffer, NULL, NULL, FALSE, dwCreationFlags, pEnv, NULL, &StartUPInfo, &ProcessInfo)) {
137                                DWORD dwErr = GetLastError();
138                                delete [] buffer;
139                                /*
140                                if (!RevertToSelf()) {
141                                        LOG_ERROR_STD(_T("Failed to revert to self: ") + error::lookup::last_error());
142                                }
143                                */
144                                if (startThread && dwErr == ERROR_PIPE_NOT_CONNECTED) {
145                                        LOG_MESSAGE(_T("Failed to start trayhelper: starting a background thread to do it instead..."));
146                                        Thread<tray_starter> *pThread = new Thread<tray_starter>(_T("tray-starter-thread"));
147                                        pThread->createThread(tray_starter::init(dwSessionId, exe, cmdline));
148                                        return false;
149                                } else if (dwErr == ERROR_PIPE_NOT_CONNECTED) {
150                                        LOG_ERROR_STD(_T("Thread failed to start trayhelper (will try again): ") + error::format::from_system(dwErr));
151                                        return false;
152                                } else {
153                                        LOG_ERROR_STD(_T("Failed to start trayhelper: ") + error::format::from_system(dwErr));
154                                        return true;
155                                }
156                        } else {
157                                delete [] buffer;
158                                /*
159                                if (!RevertToSelf()) {
160                                        LOG_ERROR_STD(_T("Failed to revert to self: ") + error::lookup::last_error());
161                                }
162                                */
163                                LOG_MESSAGE_STD(_T("Started tray in other user session: ") + strEx::itos(dwSessionId));
164                        }
165
166
167                        CloseHandle(hToken);
168                        return true;
169                }
170        }
171};
172
173/**
174 * End of class tray started (MERGE HELP)
175 */
176
177#define XNSC_DEFINE_SETTING_KEY(name, tag) \
178        name ## _SECTION \
179       
180 /**
181 * RANDOM JUNK (MERGE HELP)
182 */
183
184void display(std::wstring title, std::wstring message) {
185        ::MessageBox(NULL, message.c_str(), title.c_str(), MB_OK|MB_ICONERROR);
186}
187
188class NSC_logger : public Settings::LoggerInterface {
189public:
190        //////////////////////////////////////////////////////////////////////////
191        /// Log an ERROR message.
192        ///
193        /// @param file the file where the event happened
194        /// @param line the line where the event happened
195        /// @param message the message to log
196        ///
197        /// @author mickem
198        void err(std::wstring file, int line, std::wstring message) {
199                NSAPIMessage(NSCAPI::error, file.c_str(), line, message.c_str());
200        }
201        //////////////////////////////////////////////////////////////////////////
202        /// Log an WARNING message.
203        ///
204        /// @param file the file where the event happened
205        /// @param line the line where the event happened
206        /// @param message the message to log
207        ///
208        /// @author mickem
209        void warn(std::wstring file, int line, std::wstring message) {
210                NSAPIMessage(NSCAPI::warning, file.c_str(), line, message.c_str());
211        }
212        //////////////////////////////////////////////////////////////////////////
213        /// Log an INFO message.
214        ///
215        /// @param file the file where the event happened
216        /// @param line the line where the event happened
217        /// @param message the message to log
218        ///
219        /// @author mickem
220        void info(std::wstring file, int line, std::wstring message) {
221                NSAPIMessage(NSCAPI::log, file.c_str(), line, message.c_str());
222        }
223        //////////////////////////////////////////////////////////////////////////
224        /// Log an DEBUG message.
225        ///
226        /// @param file the file where the event happened
227        /// @param line the line where the event happened
228        /// @param message the message to log
229        ///
230        /// @author mickem
231        void debug(std::wstring file, int line, std::wstring message) {
232                NSAPIMessage(NSCAPI::debug, file.c_str(), line, message.c_str());
233        }
234};
235
236#define SETTINGS_GET_BOOL(key) \
237        settings_manager::get_settings()->get_bool(settings::key ## _PATH, settings::key, settings::key ## _DEFAULT)
238
239namespace settings_manager {
240        class NSCSettingsImpl : public Settings::SettingsHandlerImpl {
241        private:
242                std::wstring boot_;
243                bool old_;
244        public:
245                NSCSettingsImpl() : old_(false) {}
246                //////////////////////////////////////////////////////////////////////////
247                /// Get a string form the boot file.
248                ///
249                /// @param section section to read a value from.
250                /// @param key the key to read.
251                /// @param def a default value.
252                /// @return the value of the key or the default value.
253                ///
254                /// @author mickem
255                std::wstring get_boot_string(std::wstring section, std::wstring key, std::wstring def) {
256                        TCHAR* buffer = new TCHAR[1024];
257                        GetPrivateProfileString(section.c_str(), key.c_str(), def.c_str(), buffer, 1023, boot_.c_str());
258                        std::wstring ret = buffer;
259                        delete [] buffer;
260                        return ret;
261                }
262                //////////////////////////////////////////////////////////////////////////
263                /// Boot the settings subsystem from the given file (boot.ini).
264                ///
265                /// @param file the file to use when booting.
266                ///
267                /// @author mickem
268                void boot(std::wstring file = _T("boot.ini")) {
269                        boot_ = get_base() + _T("\\") + file;
270                        std::wstring subsystem = get_boot_string(_T("settings"), _T("type"), _T("old"));
271                        get_logger()->debug(__FILEW__, __LINE__, _T("Trying to boot: ") + subsystem);
272                        settings_type type = string_to_type(subsystem);
273                        std::wstring context = get_boot_string(_T("settings"), _T("context"), subsystem);
274                        Settings::SettingsInterface *impl = create_instance(type, context);
275                        if (impl == NULL)
276                                throw Settings::SettingsException(_T("Could not create settings instance: ") + subsystem);
277                        add_type_impl(type, create_instance(type, context));
278                        set_type(type);
279                        if (old_)
280                                get()->set_bool(settings::settings_def::COMPATIBLITY_PATH, settings::settings_def::COMPATIBLITY, true);
281                }
282                //////////////////////////////////////////////////////////////////////////
283                /// Create an instance of a given type.
284                /// Used internally to create instances of various settings types.
285                ///
286                /// @param type the type to create
287                /// @param context the context to use
288                /// @return a new instance of given type.
289                ///
290                /// @author mickem
291                Settings::SettingsInterface* create_instance(settings_type type, std::wstring context) {
292                        get_logger()->debug(__FILEW__, __LINE__, _T("Trying to create: ") + SettingsCore::type_to_string(type) + _T(": ") + context);
293                        if (type == SettingsCore::old_ini_file) {
294                                old_ = true;
295                                return new Settings::OLDSettings(this, context);
296                        }
297                        if (type == SettingsCore::ini_file)
298                                return new Settings::INISettings(this, context);
299                        if (type == SettingsCore::registry)
300                                return new Settings::REGSettings(this, context);
301                        throw SettingsException(_T("Undefined settings type: ") + SettingsCore::type_to_string(type));
302                }
303
304        };
305
306        typedef Singleton<NSCSettingsImpl> SettingsHandler;
307
308        // Alias to make handling "compatible" with old syntax
309        Settings::SettingsInterface* get_settings() {
310                return SettingsHandler::getInstance()->get();
311        }
312        Settings::SettingsCore* get_core() {
313                return SettingsHandler::getInstance();
314        }
315        void destroy_settings() {
316                SettingsHandler::destroyInstance();
317        }
318
319
320        bool init_settings() {
321                try {
322                        get_core()->set_logger(new NSC_logger());
323                        get_core()->set_base(mainClient.getBasePath());
324                        get_core()->boot(_T("boot.ini"));
325                        get_core()->register_key(SETTINGS_REG_KEY_I_GEN(settings_def::PAYLOAD_LEN, Settings::SettingsCore::key_integer));
326                        get_core()->register_key(SETTINGS_REG_KEY_S_GEN(protocol_def::ALLOWED_HOSTS, Settings::SettingsCore::key_string));
327                        get_core()->register_key(SETTINGS_REG_KEY_B_GEN(protocol_def::CACHE_ALLOWED, Settings::SettingsCore::key_bool));
328                        get_core()->register_key(SETTINGS_REG_KEY_S_GEN(protocol_def::MASTER_KEY, Settings::SettingsCore::key_string));
329                        get_core()->register_key(SETTINGS_REG_KEY_S_GEN(protocol_def::PWD, Settings::SettingsCore::key_string));
330                        get_core()->register_key(SETTINGS_REG_KEY_S_GEN(protocol_def::OBFUSCATED_PWD, Settings::SettingsCore::key_string));
331
332                } catch (SettingsException e) {
333                        LOG_CRITICAL_STD(_T("Failed to initialize settings: ") + e.getError());
334                        return false;
335                } catch (...) {
336                        LOG_CRITICAL(_T("FATAL ERROR IN SETTINGS SUBSYTEM"));
337                        return false;
338                }
339                return true;
340        }
341
342}
343
344#define SETTINGS_GET_STRING(key) \
345        Settings::get_settings()->get_string(key ## _PATH, key, key ## _DEFAULT)
346#define SETTINGS_SET_STRING(key, value) \
347        Settings::get_settings()->set_string(key ## _PATH, key, value);
348
349/**
350 * Application startup point
351 *
352 * @param argc Argument count
353 * @param argv[] Argument array
354 * @param envp[] Environment array
355 * @return exit status
356 */
357int wmain(int argc, TCHAR* argv[], TCHAR* envp[])
358{
359        srand( (unsigned)time( NULL ) );
360        int nRetCode = 0;
361        if ( (argc > 1) && ((*argv[1] == '-') || (*argv[1] == '/')) ) {
362                if ( _wcsicmp( _T("install"), argv[1]+1 ) == 0 ) {
363                        bool bGui = false;
364                        bool bStart = false;
365                        std::wstring service_name, service_description;
366                        for (int i=2;i<argc;i++) {
367                                if (_wcsicmp( _T("gui"), argv[i]) == 0) {
368                                        bGui = true;
369                                } else if (_wcsicmp( _T("start"), argv[i]) == 0) {
370                                        bStart = true;
371                                } else {
372                                        if (service_name.empty())
373                                                service_name = argv[i];
374                                        else {
375                                                if (!service_description.empty())
376                                                        service_description += _T(" ");
377                                                service_description += argv[i];
378                                        }
379                                }
380                        }
381                        if (service_name.empty())
382                                service_name = SZSERVICENAME;
383                        if (service_description.empty())
384                                service_description = SZSERVICEDISPLAYNAME;
385                        g_bConsoleLog = true;
386                        try {
387                                serviceControll::Install(service_name.c_str(), service_description.c_str(), SZDEPENDENCIES);
388                                if (bStart)
389                                        serviceControll::Start(service_name);
390                        } catch (const serviceControll::SCException& e) {
391                                if (bGui)
392                                        display(_T("Error installing"), _T("Service installation failed; ") + e.error_);
393                                LOG_ERROR_STD(_T("Service installation failed: ") + e.error_);
394                                return -1;
395                        }
396                        try {
397                                serviceControll::SetDescription(service_name, service_description);
398                        } catch (const serviceControll::SCException& e) {
399                                if (bGui)
400                                        display(_T("Error installing"), _T("Service installation failed; ") + e.error_);
401                                LOG_MESSAGE_STD(_T("Couldn't set service description: ") + e.error_);
402                        }
403                        if (bGui)
404                                display(_T("Service installed"), _T("Service installed successfully!"));
405                        LOG_MESSAGE(_T("Service installed!"));
406                        return 0;
407                } else if ( _wcsicmp( _T("uninstall"), argv[1]+1 ) == 0 ) {
408                        bool bGui = false;
409                        bool bStop = false;
410                        std::wstring service_name;
411                        for (int i=2;i<argc;i++) {
412                                if (_wcsicmp( _T("gui"), argv[i]) == 0) {
413                                        bGui = true;
414                                } else if (_wcsicmp( _T("stop"), argv[i]) == 0) {
415                                        bStop = true;
416                                } else {
417                                        service_name = argv[i];
418                                }
419                        }
420                        if (service_name.empty())
421                                service_name = SZSERVICENAME;
422                        g_bConsoleLog = true;
423                        try {
424                                if (bStop)
425                                        serviceControll::Stop(service_name);
426                        } catch (const serviceControll::SCException& e) {
427                                LOG_MESSAGE_STD(_T("Failed to stop service (") + service_name + _T(") failed; ") + e.error_);
428                        }
429                        try {
430                                serviceControll::Uninstall(service_name);
431                        } catch (const serviceControll::SCException& e) {
432                                if (bGui)
433                                        display(_T("Error uninstalling"), _T("Service de-installation (") + service_name + _T(") failed; ") + e.error_ + _T("\nMaybe the service was not previously installed properly?"));
434                                LOG_ERROR_STD(_T("Service deinstallation failed; ") + e.error_);
435                                return 0;
436                        }
437                        if (bGui)
438                                display(_T("Service uninstalled"), _T("Service uninstalled successfully!"));
439                        LOG_MESSAGE(_T("Service uninstalled!"));
440                        return 0;
441                } else if ( _wcsicmp( _T("encrypt"), argv[1]+1 ) == 0 ) {
442                        g_bConsoleLog = true;
443                        std::wstring password;
444                        if (!settings_manager::init_settings()) {
445                                std::wcout << _T("Could not find settings") << std::endl;;
446                                return 1;
447                        }
448                        std::wcout << _T("Enter password to encrypt (has to be a single word): ");
449                        std::wcin >> password;
450                        std::wstring xor_pwd = Encrypt(password);
451                        std::wcout << _T("obfuscated_password=") << xor_pwd << std::endl;
452                        std::wstring outPasswd = Decrypt(xor_pwd);
453                        if (password != outPasswd)
454                                std::wcout << _T("ERROR: Password did not match: ") << outPasswd<< std::endl;
455                        settings_manager::destroy_settings();
456                        return 0;
457                } else if ( _wcsicmp( _T("start"), argv[1]+1 ) == 0 ) {
458                        g_bConsoleLog = true;
459                        bool bGui = false;
460                        std::wstring service_name;
461                        for (int i=2;i<argc;i++) {
462                                if (_wcsicmp( _T("gui"), argv[i]) == 0) {
463                                        bGui = true;
464                                } else {
465                                        service_name = argv[i];
466                                }
467                        }
468                        if (service_name.empty())
469                                service_name = SZSERVICENAME;
470                        try {
471                                serviceControll::Start(service_name.c_str());
472                        } catch (const serviceControll::SCException& e) {
473                                if (bGui)
474                                        display(_T("Service failed to start"), e.error_);
475                                LOG_MESSAGE_STD(_T("Service failed to start: ") + e.error_);
476                                return -1;
477                        }
478                } else if ( _wcsicmp( _T("stop"), argv[1]+1 ) == 0 ) {
479                        g_bConsoleLog = true;
480                        bool bGui = false;
481                        std::wstring service_name;
482                        for (int i=2;i<argc;i++) {
483                                if (_wcsicmp( _T("gui"), argv[i]) == 0) {
484                                        bGui = true;
485                                } else {
486                                        service_name = argv[i];
487                                }
488                        }
489                        if (service_name.empty())
490                                service_name = SZSERVICENAME;
491                        try {
492                                serviceControll::Stop(service_name.c_str());
493                        } catch (const serviceControll::SCException& e) {
494                                if (bGui)
495                                        display(_T("Service failed to stop"), e.error_);
496                                LOG_MESSAGE_STD(_T("Service failed to stop: ") + e.error_);
497                                return -1;
498                        }
499                } else if ( _wcsicmp( _T("about"), argv[1]+1 ) == 0 ) {
500                        g_bConsoleLog = true;
501                        LOG_MESSAGE(SZAPPNAME _T(" (C) Michael Medin - michael<at>medin<dot>name"));
502                        LOG_MESSAGE(_T("Version: ") SZVERSION);
503                        LOG_MESSAGE(_T("Architecture: ") SZARCH);
504
505                        std::wstring pluginPath = mainClient.getBasePath() + _T("modules\\");
506                        LOG_MESSAGE_STD(_T("Looking at plugins in: ") + pluginPath);
507
508                        WIN32_FIND_DATA wfd;
509                        HANDLE hFind = FindFirstFile((pluginPath + _T("*.dll")).c_str(), &wfd);
510                        if (hFind != INVALID_HANDLE_VALUE) {
511                                do {
512                                        std::wstring file = wfd.cFileName;
513                                        NSCPlugin *plugin = new NSCPlugin(pluginPath + _T("\\") + file);
514                                        std::wstring name = _T("<unknown>");
515                                        std::wstring description = _T("<unknown>");
516                                        try {
517                                                plugin->load_dll();
518                                                name = plugin->getName();
519                                                description = plugin->getDescription();
520                                        } catch(const NSPluginException& e) {
521                                                LOG_ERROR_STD(_T("Exception raised: ") + e.error_ + _T(" in module: ") + e.file_);
522                                        } catch (std::exception e) {
523                                                LOG_ERROR_STD(_T("exception loading plugin: ") + strEx::string_to_wstring(e.what()));
524                                        } catch (...) {
525                                                LOG_ERROR_STD(_T("Unknown exception loading plugin"));
526                                        }
527                                        LOG_MESSAGE_STD(_T("* ") + name + _T(" (") + file + _T(")"));
528                                        std::list<std::wstring> list = strEx::splitEx(description, _T("\n"));
529                                        for (std::list<std::wstring>::const_iterator cit = list.begin(); cit != list.end(); ++cit) {
530                                                LOG_MESSAGE_STD(_T("    ") + *cit);
531                                        }
532                                } while (FindNextFile(hFind, &wfd));
533                        } else {
534                                LOG_CRITICAL(_T("No plugin was found!"));
535                        }
536                        FindClose(hFind);
537                } else if ( _wcsicmp( _T("version"), argv[1]+1 ) == 0 ) {
538                        g_bConsoleLog = true;
539                        LOG_MESSAGE(SZAPPNAME _T(" Version: ") SZVERSION _T(", Plattform: ") SZARCH);
540                } else if ( _wcsicmp( _T("d"), argv[1]+1 ) == 0 ) {
541                        // Run command from command line (like NRPE) but with debug enabled
542                } else if ( _wcsicmp( _T("noboot"), argv[1]+1 ) == 0 ) {
543                        g_bConsoleLog = true;
544                        mainClient.enableDebug(true);
545                        mainClient.initCore(true);
546                        std::wstring command, args, msg, perf;
547                        if (argc > 2)
548                                command = argv[2];
549                        for (int i=3;i<argc;i++) {
550                                if (i!=3) args += _T(" ");
551                                args += argv[i];
552                        }
553                        nRetCode = mainClient.inject(command, args, L' ', true, msg, perf);
554                        std::wcout << msg << _T("|") << perf << std::endl;
555                        mainClient.exitCore(true);
556                        return nRetCode;
557                } else if ( _wcsicmp( _T("c"), argv[1]+1 ) == 0 ) {
558                        // Run command from command line (like NRPE)
559                        g_bConsoleLog = true;
560                        mainClient.enableDebug(false);
561                        mainClient.initCore(true);
562                        std::wstring command, args, msg, perf;
563                        if (argc > 2)
564                                command = argv[2];
565                        for (int i=3;i<argc;i++) {
566                                if (i!=3) args += _T(" ");
567                                args += argv[i];
568                        }
569                        nRetCode = mainClient.inject(command, args, L' ', true, msg, perf);
570                        std::wcout << msg << _T("|") << perf << std::endl;
571                        mainClient.exitCore(true);
572                        return nRetCode;
573                        g_bConsoleLog = true;
574                        mainClient.enableDebug(false);
575                        mainClient.initCore(false);
576                        int nRetCode = -1;
577                        if (argc>=4)
578                                nRetCode = mainClient.commandLineExec(argv[2], argv[3], argc-4, &argv[4]);
579                        else if (argc>=3)
580                                nRetCode = mainClient.commandLineExec(argv[2], argv[3], 0, NULL);
581                        mainClient.exitCore(false);
582                        return nRetCode;
583                } else if ( _wcsicmp( _T("svc"), argv[1]+1 ) == 0 ) {
584                        g_bConsoleLog = true;
585                        try {
586                                std::wstring exe = serviceControll::get_exe_path(SZSERVICENAME);
587                                LOG_MESSAGE_STD(_T("The Service uses: ") + exe);
588                        } catch (const serviceControll::SCException& e) {
589                                LOG_ERROR_STD(_T("Failed to find service: ") + e.error_);
590                        }
591                } else if ( _wcsicmp( _T("test"), argv[1]+1 ) == 0 ) {
592                        bool server = false;
593                        if (argc > 2 && _wcsicmp( _T("server"), argv[2] ) == 0 ) {
594                                server = true;
595                        }
596                        std::wcout << "Launching test mode - " << (server?_T("server mode"):_T("client mode")) << std::endl;
597                        LOG_MESSAGE_STD(_T("Booting: " SZSERVICEDISPLAYNAME ));
598                        try {
599                                if (serviceControll::isStarted(SZSERVICENAME)) {
600                                        std::wcerr << "Service seems to be started, this is probably not a good idea..." << std::endl;
601                                }
602                        } catch (const serviceControll::SCException& e) {
603                                e;// Empty by design
604                        }
605                        g_bConsoleLog = true;
606                        mainClient.enableDebug(true);
607                        if (!mainClient.initCore(true)) {
608                                LOG_ERROR_STD(_T("Service *NOT* started!"));
609                                return -1;
610                        }
611                        LOG_MESSAGE_STD(_T("Using settings from: ") + settings_manager::get_core()->get_settings_type_desc());
612                        LOG_MESSAGE(_T("Enter command to inject or exit to terminate..."));
613/*
614                        Settings::get_settings()->clear_cache();
615                        LOG_MESSAGE_STD( _T("test 001: ") + SETTINGS_GET_STRING(NSCLIENT_TEST1) );
616                        LOG_MESSAGE_STD( _T("test 002: ") + SETTINGS_GET_STRING(NSCLIENT_TEST2) );
617                        LOG_MESSAGE_STD( _T("test 003: ") + SETTINGS_GET_STRING(NSCLIENT_TEST3) );
618                        LOG_MESSAGE_STD( _T("test 004: ") + SETTINGS_GET_STRING(NSCLIENT_TEST4) );
619
620                        Settings::get_settings()->save_to(_T("test.ini"));
621*/
622                        std::wstring s = _T("");
623                        std::wstring buff = _T("");
624                        while (true) {
625                                std::wcin >> s;
626                                if (s == _T("exit")) {
627                                        std::wcout << _T("Exiting...") << std::endl;
628                                        break;
629                                } else if (s == _T("plugins")) {
630                                        std::wcout << _T("Listing plugins...") << std::endl;
631                                        mainClient.listPlugins();
632                                } else if (s == _T("off") && buff == _T("debug ")) {
633                                        std::wcout << _T("Setting debug log off...") << std::endl;
634                                        mainClient.enableDebug(false);
635                                } else if (s == _T("on") && buff == _T("debug ")) {
636                                        std::wcout << _T("Setting debug log on...") << std::endl;
637                                        mainClient.enableDebug(true);
638                                } else if (s == _T("reattach")) {
639                                        std::wcout << _T("Reattaching to session 0") << std::endl;
640                                        mainClient.startTrayIcon(0);
641//#ifdef DEBUG
642                                } else if (s == _T("assert")) {
643                                        throw "test";
644//#endif
645                                } else if (std::cin.peek() < 15) {
646                                        buff += s;
647                                        strEx::token t = strEx::getToken(buff, ' ');
648                                        std::wstring msg, perf;
649                                        NSCAPI::nagiosReturn ret = mainClient.inject(t.first, t.second, ' ', true, msg, perf);
650                                        if (ret == NSCAPI::returnIgnored) {
651                                                std::wcout << _T("No handler for command: ") << t.first << std::endl;
652                                        } else {
653                                                std::wcout << NSCHelper::translateReturn(ret) << _T(":");
654                                                std::cout << strEx::wstring_to_string(msg);
655                                                if (!perf.empty())
656                                                        std::cout << "|" << strEx::wstring_to_string(perf);
657                                                std::wcout << std::endl;
658                                        }
659                                        buff = _T("");
660                                } else {
661                                        buff += s + _T(" ");
662                                }
663                        }
664                        mainClient.exitCore(true);
665                        return 0;
666                } else {
667                        std::wcerr << _T("Usage: -version, -about, -install, -uninstall, -start, -stop, -encrypt -settings") << std::endl;
668                        std::wcerr << _T("Usage: [-noboot] <ModuleName> <commnd> [arguments]") << std::endl;
669                        return -1;
670                }
671                return nRetCode;
672        } else if (argc > 2) {
673                g_bConsoleLog = true;
674                mainClient.initCore(true);
675                if (argc>=3)
676                        nRetCode = mainClient.commandLineExec(argv[1], argv[2], argc-3, &argv[3]);
677                else
678                        nRetCode = mainClient.commandLineExec(argv[1], argv[2], 0, NULL);
679                mainClient.exitCore(true);
680                return nRetCode;
681        } else if (argc > 1) {
682                g_bConsoleLog = true;
683                mainClient.enableDebug(true);
684                std::wcerr << _T("Invalid command line argument: ") << argv[1] << std::endl;
685                std::wcerr << _T("Usage: -version, -about, -install, -uninstall, -start, -stop, -encrypt") << std::endl;
686                std::wcerr << _T("Usage: [-noboot] <ModuleName> <commnd> [arguments]") << std::endl;
687                return -1;
688        }
689        std::wcout << _T("Running as service...") << std::endl;
690        if (!mainClient.StartServiceCtrlDispatcher()) {
691                LOG_MESSAGE(_T("We failed to start the service"));
692        }
693        return nRetCode;
694}
695
696void migrate() {}
697
698NSClientT::plugin_info_list NSClientT::get_all_plugins() {
699        plugin_info_list ret;
700        std::wstring modPath = getBasePath() + _T("modules\\");
701
702        WIN32_FIND_DATA wfd;
703        HANDLE hFind = FindFirstFile((modPath + _T("*.dll")).c_str(), &wfd);
704        if (hFind != INVALID_HANDLE_VALUE) {
705                do {
706                        plugin_info_type info;
707                        info.dll = wfd.cFileName;
708                        try {
709                                LOG_DEBUG_STD(_T("Attempting to fake load: ") + wfd.cFileName);
710                                NSCPlugin plugin(modPath + wfd.cFileName);
711                                plugin.load_dll();
712                                plugin.load_plugin(NSCAPI::dontStart);
713                                info.name = plugin.getName();
714                                info.description = plugin.getDescription();
715                                plugin.unload();
716                        } catch (NSPluginException e) {
717                                LOG_CRITICAL_STD(_T("Error loading: ") + e.file_ + _T(" root cause: ") + e.error_);
718                        } catch (...) {
719                                LOG_CRITICAL_STD(_T("Unknown Error loading: ") + wfd.cFileName);
720                        }
721                        ret.push_back(info);
722                } while (FindNextFile(hFind, &wfd));
723        }
724        FindClose(hFind);
725        return ret;
726}
727
728
729void NSClientT::load_all_plugins(int mode) {
730        std::wstring modPath = getBasePath() + _T("modules\\");
731
732        WIN32_FIND_DATA wfd;
733        HANDLE hFind = FindFirstFile((modPath + _T("*.dll")).c_str(), &wfd);
734        if (hFind != INVALID_HANDLE_VALUE) {
735                do {
736                        if (settings_manager::get_settings()->has_key(MAIN_MODULES_SECTION, wfd.cFileName)) {
737                                if (settings_manager::get_settings()->get_string(MAIN_MODULES_SECTION, wfd.cFileName) == _T("disabled")) {
738                                        try {
739                                                LOG_DEBUG_STD(_T("Attempting to fake load: ") + wfd.cFileName);
740                                                NSCPlugin plugin(modPath + wfd.cFileName);
741                                                plugin.load_dll();
742                                                plugin.load_plugin(mode);
743                                                plugin.unload();
744                                        } catch (NSPluginException e) {
745                                                LOG_CRITICAL_STD(_T("Error loading: ") + e.file_ + _T(" root cause: ") + e.error_);
746                                        } catch (...) {
747                                                LOG_CRITICAL_STD(_T("Unknown Error loading: ") + wfd.cFileName);
748                                        }
749                                }
750                        } else {
751                                std::wstring desc;
752                                try {
753                                        NSCPlugin plugin(modPath + wfd.cFileName);
754                                        plugin.load_dll();
755                                        plugin.load_plugin(mode);
756                                        desc = plugin.getName() + _T(" - ");
757                                        desc += plugin.getDescription();
758                                        plugin.unload();
759                                } catch (NSPluginException e) {
760                                        desc += _T("unknown module");
761                                        LOG_CRITICAL_STD(_T("Error loading: ") + e.file_ + _T(" root cause: ") + e.error_);
762                                } catch (...) {
763                                        desc += _T("unknown module");
764                                        LOG_CRITICAL_STD(_T("Unknown Error loading: ") + wfd.cFileName);
765                                }
766                                settings_manager::get_core()->register_key(MAIN_MODULES_SECTION, wfd.cFileName, Settings::SettingsCore::key_string, desc, desc, _T("disabled"), false);
767                        }
768                } while (FindNextFile(hFind, &wfd));
769        }
770        FindClose(hFind);
771}
772
773void NSClientT::HandleSettingsCLI(TCHAR* arg, int argc, TCHAR* argv[]) {
774        std::wstring sarg = arg;
775        try {
776                if (sarg == _T("migrate")) {
777                        if (argc == 0) {
778                                LOG_ERROR_STD(_T("In correct syntax: nsclient++ -settings migrate <to>"));
779                                return;
780                        }
781                        std::wstring to = argv[0];
782                        LOG_DEBUG_STD(_T("Migrating to: ") + to);
783                        try {
784                                settings_manager::get_core()->migrate_to(Settings::SettingsCore::string_to_type(to));
785                        } catch (SettingsException e) {
786                                LOG_CRITICAL_STD(_T("Failed to migrate settings: ") + e.getError());
787                        }
788                } else if (sarg == _T("generate")) {
789                        if (argc == 0) {
790                                LOG_ERROR_STD(_T("In correct syntax: nsclient++ -settings generate <what>"));
791                                LOG_ERROR_STD(_T("     where <what> is one of ths following:"));
792                                LOG_ERROR_STD(_T("      trac"));
793                                LOG_ERROR_STD(_T("      default"));
794                                LOG_ERROR_STD(_T("      <type>"));
795                                return;
796                        }
797                        std::wstring arg1 = argv[0];
798                        if (arg1 == _T("default")) {
799                                try {
800                                        load_all_plugins(NSCAPI::dontStart);
801                                        settings_manager::get_core()->update_defaults();
802                                        settings_manager::get_core()->get()->save();
803                                } catch (SettingsException e) {
804                                        LOG_CRITICAL_STD(_T("Failed to migrate settings: ") + e.getError());
805                                }
806                        } else if (arg1 == _T("trac")) {
807                                try {
808                                        load_all_plugins(NSCAPI::dontStart);
809
810                                        Settings::string_list s = settings_manager::get_core()->get_reg_sections();
811                                        for (Settings::string_list::const_iterator cit = s.begin(); cit != s.end(); ++cit) {
812                                                std::wcout << _T("== ") << (*cit) << _T(" ==") << std::endl;
813                                                Settings::string_list k = settings_manager::get_core()->get_reg_keys(*cit);
814                                                bool first = true;
815                                                for (Settings::string_list::const_iterator citk = k.begin(); citk != k.end(); ++citk) {
816                                                        Settings::SettingsCore::key_description desc = settings_manager::get_core()->get_registred_key(*cit, *citk);
817                                                        if (!desc.advanced) {
818                                                                if (first)
819                                                                        std::wcout << _T("'''Normal settings'''") << std::endl;
820                                                                first = false;
821                                                                std::wcout << _T("||") << (*citk) << _T("||") << desc.defValue << _T("||") << desc.title << _T(": ") << desc.description
822                                                                        << std::endl;
823                                                        }
824                                                }
825                                                first = true;
826                                                for (Settings::string_list::const_iterator citk = k.begin(); citk != k.end(); ++citk) {
827                                                        Settings::SettingsCore::key_description desc = settings_manager::get_core()->get_registred_key(*cit, *citk);
828                                                        if (desc.advanced) {
829                                                                if (first)
830                                                                        std::wcout << _T("'''Advanced settings'''") << std::endl;
831                                                                first = false;
832                                                                std::wcout << _T("||") << (*citk) << _T("||") << desc.defValue << _T("||") << desc.title << _T(": ") << desc.description
833                                                                        << std::endl;
834                                                        }
835                                                }
836                                        }
837                                } catch (SettingsException e) {
838                                        LOG_CRITICAL_STD(_T("Failed to migrate settings: ") + e.getError());
839                                }
840                        } else {
841                                try {
842                                        Settings::SettingsCore::settings_type type = settings_manager::get_core()->string_to_type(arg1);
843                                        load_all_plugins(NSCAPI::dontStart);
844                                        settings_manager::get_core()->update_defaults();
845                                        settings_manager::get_core()->get(type)->save();
846                                } catch (SettingsException e) {
847                                        LOG_CRITICAL_STD(_T("Failed to migrate settings: ") + e.getError());
848                                }
849                        }
850                } else {
851                        LOG_ERROR_STD(_T("In correct syntax: nsclient++ -settings <keyword>"));
852                        LOG_ERROR_STD(_T(" <keyword> : "));
853                        LOG_ERROR_STD(_T("   migrate - migrate to a new setings subsystem"));
854                        LOG_ERROR_STD(_T("   copy    - copy settings from one subsystem to another"));
855                        LOG_ERROR_STD(_T("   set     - Set a setting system as the default store"));
856                }
857
858
859        } catch (SettingsException e) {
860                LOG_CRITICAL_STD(_T("Failed to initialize settings: ") + e.getError());
861        } catch (...) {
862                LOG_CRITICAL(_T("FATAL ERROR IN SETTINGS SUBSYTEM"));
863        }
864
865}
866
867void NSClientT::session_error(std::wstring file, unsigned int line, std::wstring msg) {
868        NSAPIMessage(NSCAPI::error, file.c_str(), line, msg.c_str());
869}
870
871void NSClientT::session_info(std::wstring file, unsigned int line, std::wstring msg) {
872        NSAPIMessage(NSCAPI::log, file.c_str(), line, msg.c_str());
873}
874
875
876
877
878//////////////////////////////////////////////////////////////////////////
879// Service functions
880
881/**
882 * Initialize the program
883 * @param boot true if we shall boot all plugins
884 * @param attachIfPossible is true we will attach to a running instance.
885 * @return success
886 * @author mickem
887 */
888bool NSClientT::initCore(bool boot) {
889        LOG_MESSAGE(_T("Attempting to start NSCLient++ - " SZVERSION));
890        if (!settings_manager::init_settings()) {
891                return false;
892        }
893        try {
894                if (debug_)
895                        settings_manager::get_settings()->set_int(_T("log"), _T("debug"), 1);
896                        settings_manager::get_settings()->set_int(_T("Settings"), _T("shared_Session"), 1);
897                enable_shared_session_ = SETTINGS_GET_BOOL(settings_def::SHARED_SESSION);
898        } catch (SettingsException e) {
899                LOG_ERROR_STD(_T("Could not find settings: ") + e.getMessage());
900        }
901
902        if (enable_shared_session_) {
903                LOG_MESSAGE_STD(_T("Enabling shared session..."));
904                if (boot) {
905                        LOG_MESSAGE_STD(_T("Starting shared session..."));
906                        try {
907                                shared_server_.reset(new nsclient_session::shared_server_session(this));
908                                if (!shared_server_->session_exists()) {
909                                        shared_server_->create_new_session();
910                                } else {
911                                        LOG_ERROR_STD(_T("Session already exists cant create a new one!"));
912                                }
913                                startTrayIcons();
914                        } catch (nsclient_session::session_exception e) {
915                                LOG_ERROR_STD(_T("Failed to create new session: ") + e.what());
916                                shared_server_.reset(NULL);
917                        } catch (...) {
918                                LOG_ERROR_STD(_T("Failed to create new session: Unknown exception"));
919                                shared_server_.reset(NULL);
920                        }
921                } else {
922                        LOG_MESSAGE_STD(_T("Attaching to shared session..."));
923                        try {
924                                std::wstring id = _T("_attached_") + strEx::itos(GetCurrentProcessId()) + _T("_");
925                                shared_client_.reset(new nsclient_session::shared_client_session(id, this));
926                                if (shared_client_->session_exists()) {
927                                        shared_client_->attach_to_session(id);
928                                } else {
929                                        LOG_ERROR_STD(_T("No session was found cant attach!"));
930                                }
931                                LOG_ERROR_STD(_T("Session is: ") + shared_client_->get_client_id());
932                        } catch (nsclient_session::session_exception e) {
933                                LOG_ERROR_STD(_T("Failed to attach to session: ") + e.what());
934                                shared_client_.reset(NULL);
935                        } catch (...) {
936                                LOG_ERROR_STD(_T("Failed to attach to session: Unknown exception"));
937                                shared_client_.reset(NULL);
938                        }
939                }
940        }
941
942        try {
943                simpleSocket::WSAStartup();
944        } catch (simpleSocket::SocketException e) {
945                LOG_ERROR_STD(_T("Socket exception: ") + e.getMessage());
946                return false;
947        } catch (...) {
948                LOG_ERROR_STD(_T("Unknown exception iniating socket..."));
949                return false;
950        }
951
952        try {
953                com_helper_.initialize();
954        } catch (com_helper::com_exception e) {
955                LOG_ERROR_STD(_T("COM exception: ") + e.getMessage());
956                return false;
957        } catch (...) {
958                LOG_ERROR_STD(_T("Unknown exception iniating COM..."));
959                return false;
960        }
961        if (boot) {
962                try {
963                        Settings::string_list list = settings_manager::get_settings()->get_keys(MAIN_MODULES_SECTION);
964                        for (Settings::string_list::const_iterator cit = list.begin(); cit != list.end(); ++cit) {
965                                try {
966                                        if (settings_manager::get_settings()->get_string(MAIN_MODULES_SECTION, *cit) == _T("disabled")) {
967                                                LOG_DEBUG_STD(_T("Not booting: " + *cit + _T(" since it is disabled.")));
968                                                continue;
969                                        }
970                                } catch (...) {
971                                        // If we except we load the plugin in as-is
972                                }
973                                try {
974                                        loadPlugin(getBasePath() + _T("modules\\") + (*cit));
975                                } catch(const NSPluginException& e) {
976                                        LOG_ERROR_STD(_T("Exception raised: ") + e.error_ + _T(" in module: ") + e.file_);
977                                        //return false;
978                                } catch (std::exception e) {
979                                        LOG_ERROR_STD(_T("exception loading plugin: ") + (*cit) + strEx::string_to_wstring(e.what()));
980                                        return false;
981                                } catch (...) {
982                                        LOG_ERROR_STD(_T("Unknown exception loading plugin: ") + (*cit));
983                                        return false;
984                                }
985                        }
986                } catch (SettingsException e) {
987                        LOG_ERROR_STD(_T("Failed to set settings file") + e.getMessage());
988                } catch (...) {
989                        LOG_ERROR_STD(_T("Unknown exception when loading plugins"));
990                        return false;
991                }
992                try {
993                        loadPlugins(boot?NSCAPI::normalStart:NSCAPI::dontStart);
994                } catch (...) {
995                        LOG_ERROR_STD(_T("Unknown exception loading plugins"));
996                        return false;
997                }
998                LOG_DEBUG_STD(_T("NSCLient++ - " SZVERSION) + _T(" Started!"));
999        }
1000        LOG_MESSAGE_STD(_T("NSCLient++ - " SZVERSION) + _T(" Started!"));
1001        return true;
1002}
1003
1004/**
1005 * Service control handler startup point.
1006 * When the program is started as a service this will be the entry point.
1007 */
1008bool NSClientT::InitiateService() {
1009        if (!initCore(true))
1010                return false;
1011/*
1012        DWORD dwSessionId = remote_processes::getActiveSessionId();
1013        if (dwSessionId != 0xFFFFFFFF)
1014                tray_starter::start(dwSessionId);
1015        else
1016                LOG_ERROR_STD(_T("Failed to start tray helper:" ) + error::lookup::last_error());
1017                */
1018        return true;
1019}
1020
1021void NSClientT::startTrayIcons() {
1022        if (shared_server_.get() == NULL) {
1023                LOG_MESSAGE_STD(_T("No master session so tray icons not started"));
1024                return;
1025        }
1026        remote_processes::PWTS_SESSION_INFO list;
1027        DWORD count;
1028        if (!remote_processes::_WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE , 0, 1, &list, &count)) {
1029                LOG_ERROR_STD(_T("Failed to enumerate sessions:" ) + error::lookup::last_error());
1030        } else {
1031                LOG_DEBUG_STD(_T("Found ") + strEx::itos(count) + _T(" sessions"));
1032                for (DWORD i=0;i<count;i++) {
1033                        LOG_DEBUG_STD(_T("Found session: ") + strEx::itos(list[i].SessionId) + _T(" state: ") + strEx::itos(list[i].State));
1034                        if (list[i].State == remote_processes::_WTS_CONNECTSTATE_CLASS::WTSActive) {
1035                                startTrayIcon(list[i].SessionId);
1036                        }
1037                }
1038        }
1039}
1040void NSClientT::startTrayIcon(DWORD dwSessionId) {
1041        if (shared_server_.get() == NULL) {
1042                LOG_MESSAGE_STD(_T("No master session so tray icons not started"));
1043                return;
1044        }
1045        if (!shared_server_->re_attach_client(dwSessionId)) {
1046                if (!tray_starter::start(dwSessionId)) {
1047                        LOG_ERROR_STD(_T("Failed to start session (") + strEx::itos(dwSessionId) + _T("): " ) + error::lookup::last_error());
1048                }
1049        }
1050}
1051
1052bool NSClientT::exitCore(bool boot) {
1053        plugins_loaded_ = false;
1054        LOG_DEBUG(_T("Attempting to stop NSCLient++ - " SZVERSION));
1055        if (boot) {
1056                try {
1057                        LOG_DEBUG_STD(_T("Stopping: NON Message Handling Plugins"));
1058                        mainClient.unloadPlugins(false);
1059                } catch(NSPluginException e) {
1060                        LOG_ERROR_STD(_T("Exception raised when unloading non msg plguins: ") + e.error_ + _T(" in module: ") + e.file_);
1061                } catch(...) {
1062                        LOG_ERROR_STD(_T("Unknown exception raised when unloading non msg plugins"));
1063                }
1064        }
1065        LOG_DEBUG_STD(_T("Stopping: COM helper"));
1066        try {
1067                com_helper_.unInitialize();
1068        } catch (com_helper::com_exception e) {
1069                LOG_ERROR_STD(_T("COM exception: ") + e.getMessage());
1070        } catch (...) {
1071                LOG_ERROR_STD(_T("Unknown exception uniniating COM..."));
1072        }
1073        LOG_DEBUG_STD(_T("Stopping: Socket Helpers"));
1074        try {
1075                simpleSocket::WSACleanup();
1076        } catch (simpleSocket::SocketException e) {
1077                LOG_ERROR_STD(_T("Socket exception: ") + e.getMessage());
1078        } catch (...) {
1079                LOG_ERROR_STD(_T("Unknown exception uniniating socket..."));
1080        }
1081        LOG_DEBUG_STD(_T("Stopping: Settings instance"));
1082        settings_manager::destroy_settings();
1083        try {
1084                if (shared_client_.get() != NULL) {
1085                        LOG_DEBUG_STD(_T("Stopping: shared client"));
1086                        shared_client_->set_handler(NULL);
1087                        shared_client_->close_session();
1088                }
1089        } catch(nsclient_session::session_exception &e) {
1090                LOG_ERROR_STD(_T("Exception closing shared client session: ") + e.what());
1091        } catch(...) {
1092                LOG_ERROR_STD(_T("Exception closing shared client session: Unknown exception!"));
1093        }
1094        try {
1095                if (shared_server_.get() != NULL) {
1096                        LOG_DEBUG_STD(_T("Stopping: shared server"));
1097                        shared_server_->set_handler(NULL);
1098                        shared_server_->close_session();
1099                }
1100        } catch(...) {
1101                LOG_ERROR_STD(_T("UNknown exception raised: When closing shared session"));
1102        }
1103        if (boot) {
1104                try {
1105                        LOG_DEBUG_STD(_T("Stopping: Message handling Plugins"));
1106                        mainClient.unloadPlugins(true);
1107                } catch(NSPluginException e) {
1108                        LOG_ERROR_STD(_T("Exception raised when unloading msg plugins: ") + e.error_ + _T(" in module: ") + e.file_);
1109                } catch(...) {
1110                        LOG_ERROR_STD(_T("UNknown exception raised: When stopping message plguins"));
1111                }
1112        }
1113        LOG_MESSAGE_STD(_T("NSCLient++ - " SZVERSION) + _T(" Stopped succcessfully"));
1114        return true;
1115}
1116/**
1117 * Service control handler termination point.
1118 * When the program is stopped as a service this will be the "exit point".
1119 */
1120void NSClientT::TerminateService(void) {
1121        exitCore(true);
1122}
1123
1124/**
1125 * Forward this to the main service dispatcher helper class
1126 * @param dwArgc
1127 * @param *lpszArgv
1128 */
1129void WINAPI NSClientT::service_main_dispatch(DWORD dwArgc, LPTSTR *lpszArgv) {
1130        try {
1131                mainClient.service_main(dwArgc, lpszArgv);
1132        } catch (service_helper::service_exception e) {
1133                LOG_ERROR_STD(_T("Unknown service error: ") + e.what());
1134        } catch (...) {
1135                LOG_ERROR_STD(_T("Unknown service error!"));
1136        }
1137}
1138DWORD WINAPI NSClientT::service_ctrl_dispatch_ex(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext) {
1139        return mainClient.service_ctrl_ex(dwControl, dwEventType, lpEventData, lpContext);
1140}
1141/**
1142 * Forward this to the main service dispatcher helper class
1143 * @param dwCtrlCode
1144 */
1145void WINAPI NSClientT::service_ctrl_dispatch(DWORD dwCtrlCode) {
1146        mainClient.service_ctrl_ex(dwCtrlCode, NULL, NULL, NULL);
1147}
1148
1149
1150void NSClientT::service_on_session_changed(DWORD dwSessionId, bool logon, DWORD dwEventType) {
1151        if (shared_server_.get() == NULL) {
1152                LOG_DEBUG_STD(_T("No shared session: ignoring change event!"));
1153                return;
1154        }
1155        LOG_DEBUG_STD(_T("Got session change: ") + strEx::itos(dwSessionId));
1156        if (!logon) {
1157                LOG_DEBUG_STD(_T("Not a logon event: ") + strEx::itos(dwEventType));
1158                return;
1159        }
1160        tray_starter::start(dwSessionId);
1161}
1162
1163//////////////////////////////////////////////////////////////////////////
1164// Member functions
1165
1166int NSClientT::commandLineExec(const TCHAR* module, const TCHAR* command, const unsigned int argLen, TCHAR** args) {
1167        std::wstring sModule = module;
1168        std::wstring moduleList = _T("");
1169        {
1170                ReadLock readLock(&m_mutexRW, true, 10000);
1171                if (!readLock.IsLocked()) {
1172                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1173                        return -1;
1174                }
1175                for (pluginList::size_type i=0;i<plugins_.size();++i) {
1176                        NSCPlugin *p = plugins_[i];
1177                        if (!moduleList.empty())
1178                                moduleList += _T(", ");
1179                        moduleList += p->getModule();
1180                        if (p->getModule() == sModule) {
1181                                LOG_DEBUG_STD(_T("Found module: ") + p->getName() + _T("..."));
1182                                try {
1183                                        return p->commandLineExec(command, argLen, args);
1184                                } catch (NSPluginException e) {
1185                                        LOG_ERROR_STD(_T("Could not execute command: ") + e.error_ + _T(" in ") + e.file_);
1186                                        return -1;
1187                                }
1188                        }
1189                }
1190        }
1191        try {
1192                plugin_type plugin = loadPlugin(getBasePath() + _T("modules\\") + module);
1193                LOG_DEBUG_STD(_T("Loading plugin: ") + plugin->getName() + _T("..."));
1194                plugin->load_plugin(NSCAPI::dontStart);
1195                return plugin->commandLineExec(command, argLen, args);
1196        } catch (NSPluginException e) {
1197                LOG_MESSAGE_STD(_T("Module (") + e.file_ + _T(") was not found: ") + e.error_);
1198        }
1199        try {
1200                plugin_type plugin = loadPlugin(getBasePath() + _T("modules\\") + module + _T(".dll"));
1201                LOG_DEBUG_STD(_T("Loading plugin: ") + plugin->getName() + _T("..."));
1202                plugin->load_plugin(NSCAPI::dontStart);
1203                return plugin->commandLineExec(command, argLen, args);
1204        } catch (NSPluginException e) {
1205                LOG_MESSAGE_STD(_T("Module (") + e.file_ + _T(") was not found: ") + e.error_);
1206        }
1207        LOG_ERROR_STD(_T("Module not found: ") + module + _T(" available modules are: ") + moduleList);
1208        return 0;
1209}
1210
1211/**
1212 * Load a list of plug-ins
1213 * @param plugins A list with plug-ins (DLL files) to load
1214 */
1215void NSClientT::addPlugins(const std::list<std::wstring> plugins) {
1216        ReadLock readLock(&m_mutexRW, true, 10000);
1217        if (!readLock.IsLocked()) {
1218                LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1219                return;
1220        }
1221        std::list<std::wstring>::const_iterator it;
1222        for (it = plugins.begin(); it != plugins.end(); ++it) {
1223                loadPlugin(*it);
1224        }
1225}
1226/**
1227 * Unload all plug-ins (in reversed order)
1228 */
1229void NSClientT::unloadPlugins(bool unloadLoggers) {
1230        {
1231                WriteLock writeLock(&m_mutexRW, true, 10000);
1232                if (!writeLock.IsLocked()) {
1233                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1234                        return;
1235                }
1236                commandHandlers_.clear();
1237                if (unloadLoggers)
1238                        messageHandlers_.clear();
1239        }
1240        {
1241                ReadLock readLock(&m_mutexRW, true, 10000);
1242                if (!readLock.IsLocked()) {
1243                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1244                        return;
1245                }
1246                for (pluginList::reverse_iterator it = plugins_.rbegin(); it != plugins_.rend(); ++it) {
1247                        NSCPlugin *p = *it;
1248                        if (p == NULL)
1249                                continue;
1250                        try {
1251                                if (unloadLoggers || !p->hasMessageHandler()) {
1252                                        LOG_DEBUG_STD(_T("Unloading plugin: ") + p->getModule() + _T("..."));
1253                                        p->unload();
1254                                } else {
1255                                        LOG_DEBUG_STD(_T("Skipping log plugin: ") + p->getModule() + _T("..."));
1256                                }
1257                        } catch(NSPluginException e) {
1258                                LOG_ERROR_STD(_T("Exception raised when unloading plugin: ") + e.error_ + _T(" in module: ") + e.file_);
1259                        } catch(...) {
1260                                LOG_ERROR_STD(_T("Unknown exception raised when unloading plugin"));
1261                        }
1262                }
1263        }
1264        {
1265                WriteLock writeLock(&m_mutexRW, true, 10000);
1266                if (!writeLock.IsLocked()) {
1267                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1268                        return;
1269                }
1270                for (pluginList::iterator it = plugins_.begin(); it != plugins_.end();) {
1271                        NSCPlugin *p = (*it);
1272                        try {
1273                                if (p != NULL && (unloadLoggers|| !p->isLoaded())) {
1274                                        it = plugins_.erase(it);
1275                                        delete p;
1276                                        continue;
1277                                }
1278                        } catch(NSPluginException e) {
1279                                LOG_ERROR_STD(_T("Exception raised when unloading plugin: ") + e.error_ + _T(" in module: ") + e.file_);
1280                        } catch(...) {
1281                                LOG_ERROR_STD(_T("Unknown exception raised when unloading plugin"));
1282                        }
1283                        it++;
1284                }
1285        }
1286}
1287
1288void NSClientT::loadPlugins(NSCAPI::moduleLoadMode mode) {
1289        bool hasBroken = false;
1290        {
1291                ReadLock readLock(&m_mutexRW, true, 10000);
1292                if (!readLock.IsLocked()) {
1293                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1294                        return;
1295                }
1296                for (pluginList::iterator it=plugins_.begin(); it != plugins_.end();) {
1297                        LOG_DEBUG_STD(_T("Loading plugin: ") + (*it)->getName() + _T("..."));
1298                        try {
1299                                if (!(*it)->load_plugin(NSCAPI::normalStart)) {
1300                                        it = plugins_.erase(it);
1301                                        LOG_ERROR_STD(_T("Plugin refused to load: ") + (*it)->getModule());
1302                                }
1303                                ++it;
1304                        } catch (NSPluginException e) {
1305                                it = plugins_.erase(it);
1306                                LOG_ERROR_STD(_T("Could not load plugin: ") + e.file_ + _T(": ") + e.error_);
1307                        } catch (...) {
1308                                it = plugins_.erase(it);
1309                                LOG_ERROR_STD(_T("Could not load plugin: ") + (*it)->getModule());
1310                        }
1311                }
1312        }
1313        for (pluginList::iterator it=plugins_.begin(); it != plugins_.end();) {
1314                LOG_DEBUG_STD(_T("Loading plugin: ") + (*it)->getName() + _T("..."));
1315                try {
1316                        (*it)->load_plugin(mode);
1317                        ++it;
1318                } catch(NSPluginException e) {
1319                        it = plugins_.erase(it);
1320                        LOG_ERROR_STD(_T("Exception raised when loading plugin: ") + e.error_ + _T(" in module: ") + e.file_ + _T(" plugin has been removed."));
1321                } catch(...) {
1322                        it = plugins_.erase(it);
1323                        LOG_ERROR_STD(_T("Unknown exception raised when unloading plugin plugin has been removed"));
1324                }
1325        }
1326        plugins_loaded_ = true;
1327}
1328/**
1329 * Load a single plug-in using a DLL filename
1330 * @param file The DLL file
1331 */
1332NSClientT::plugin_type NSClientT::loadPlugin(const std::wstring file) {
1333        return addPlugin(new NSCPlugin(file));
1334}
1335/**
1336 * Load and add a plugin to various internal structures
1337 * @param plugin The plug-in instance to load. The pointer is managed by the
1338 */
1339NSClientT::plugin_type NSClientT::addPlugin(plugin_type plugin) {
1340        plugin->load_dll();
1341        {
1342                WriteLock writeLock(&m_mutexRW, true, 10000);
1343                if (!writeLock.IsLocked()) {
1344                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1345                        return plugin;
1346                }
1347                plugins_.insert(plugins_.end(), plugin);
1348                if (plugin->hasCommandHandler())
1349                        commandHandlers_.insert(commandHandlers_.end(), plugin);
1350                if (plugin->hasMessageHandler())
1351                        messageHandlers_.insert(messageHandlers_.end(), plugin);
1352                settings_manager::get_core()->register_key(_T("/modules"), plugin->getFilename(), Settings::SettingsCore::key_string, plugin->getName(), plugin->getDescription(), _T(""), false);
1353        }
1354        return plugin;
1355}
1356
1357
1358std::wstring NSClientT::describeCommand(std::wstring command) {
1359        ReadLock readLock(&m_mutexRWcmdDescriptions, true, 5000);
1360        if (!readLock.IsLocked()) {
1361                LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex when trying to get command list."));
1362                return _T("Failed to get mutex when describing command: ") + command;
1363        }
1364        cmdMap::const_iterator cit = cmdDescriptions_.find(command);
1365        if (cit == cmdDescriptions_.end())
1366                return _T("Command not found: ") + command + _T(", maybe it has not been register?");
1367        return (*cit).second;
1368}
1369std::list<std::wstring> NSClientT::getAllCommandNames() {
1370        std::list<std::wstring> lst;
1371        ReadLock readLock(&m_mutexRWcmdDescriptions, true, 5000);
1372        if (!readLock.IsLocked()) {
1373                LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex when trying to get command list."));
1374                return lst;
1375        }
1376        for (cmdMap::const_iterator cit = cmdDescriptions_.begin(); cit != cmdDescriptions_.end(); ++cit) {
1377                lst.push_back((*cit).first);
1378        }
1379        return lst;
1380}
1381void NSClientT::registerCommand(std::wstring cmd, std::wstring desc) {
1382        WriteLock writeLock(&m_mutexRWcmdDescriptions, true, 10000);
1383        if (!writeLock.IsLocked()) {
1384                LOG_ERROR_STD(_T("FATAL ERROR: Failed to describe command:") + cmd);
1385                return;
1386        }
1387        cmdDescriptions_[cmd] = desc;
1388}
1389
1390unsigned int NSClientT::getBufferLength() {
1391        static unsigned int len = 0;
1392        if (len == 0) {
1393                try {
1394                        len = settings_manager::get_settings()->get_int(SETTINGS_KEY(settings_def::PAYLOAD_LEN));
1395                } catch (SettingsException &e) {
1396                        LOG_DEBUG_STD(_T("Failed to get length: ") + e.getMessage());
1397                        return settings::settings_def::PAYLOAD_LEN_DEFAULT;
1398                } catch (...) {
1399                        LOG_ERROR(_T("Failed to get length: :("));
1400                        return settings::settings_def::PAYLOAD_LEN_DEFAULT;
1401                }
1402        }
1403        return len;
1404}
1405
1406NSCAPI::nagiosReturn NSClientT::inject(std::wstring command, std::wstring arguments, TCHAR splitter, bool escape, std::wstring &msg, std::wstring & perf) {
1407        if (shared_client_.get() != NULL && shared_client_->hasMaster()) {
1408                try {
1409                        return shared_client_->inject(command, arguments, splitter, escape, msg, perf);
1410                } catch (nsclient_session::session_exception &e) {
1411                        LOG_ERROR_STD(_T("Failed to inject remote command: ") + e.what());
1412                        return NSCAPI::returnCRIT;
1413                } catch (...) {
1414                        LOG_ERROR_STD(_T("Failed to inject remote command: Unknown exception"));
1415                        return NSCAPI::returnCRIT;
1416                }
1417        } else {
1418                unsigned int aLen = 0;
1419                TCHAR ** aBuf = arrayBuffer::split2arrayBuffer(arguments, splitter, aLen, escape);
1420                unsigned int buf_len = getBufferLength();
1421                TCHAR * mBuf = new TCHAR[buf_len+1]; mBuf[0] = '\0';
1422                TCHAR * pBuf = new TCHAR[buf_len+1]; pBuf[0] = '\0';
1423                NSCAPI::nagiosReturn ret = injectRAW(command.c_str(), aLen, aBuf, mBuf, buf_len, pBuf, buf_len);
1424                arrayBuffer::destroyArrayBuffer(aBuf, aLen);
1425                if ( (ret == NSCAPI::returnInvalidBufferLen) || (ret == NSCAPI::returnIgnored) ) {
1426                        delete [] mBuf;
1427                        delete [] pBuf;
1428                        return ret;
1429                }
1430                msg = mBuf;
1431                perf = pBuf;
1432                delete [] mBuf;
1433                delete [] pBuf;
1434                return ret;
1435        }
1436}
1437
1438/**
1439 * Inject a command into the plug-in stack.
1440 *
1441 * @param command Command to inject
1442 * @param argLen Length of argument buffer
1443 * @param **argument Argument buffer
1444 * @param *returnMessageBuffer Message buffer
1445 * @param returnMessageBufferLen Length of returnMessageBuffer
1446 * @param *returnPerfBuffer Performance data buffer
1447 * @param returnPerfBufferLen Length of returnPerfBuffer
1448 * @return The command status
1449 */
1450NSCAPI::nagiosReturn NSClientT::injectRAW(const TCHAR* command, const unsigned int argLen, TCHAR **argument, TCHAR *returnMessageBuffer, unsigned int returnMessageBufferLen, TCHAR *returnPerfBuffer, unsigned int returnPerfBufferLen) {
1451        if (logDebug()) {
1452                LOG_DEBUG_STD(_T("Injecting: ") + (std::wstring) command + _T(": ") + arrayBuffer::arrayBuffer2string(argument, argLen, _T(", ")));
1453        }
1454        if (shared_client_.get() != NULL && shared_client_->hasMaster()) {
1455                try {
1456                        std::wstring msg, perf;
1457                        int returnCode = shared_client_->inject(command, arrayBuffer::arrayBuffer2string(argument, argLen, _T(" ")), L' ', true, msg, perf);
1458                        NSCHelper::wrapReturnString(returnMessageBuffer, returnMessageBufferLen, msg, returnCode);
1459                        return NSCHelper::wrapReturnString(returnPerfBuffer, returnPerfBufferLen, perf, returnCode);
1460                } catch (nsclient_session::session_exception &e) {
1461                        LOG_ERROR_STD(_T("Failed to inject remote command: ") + e.what());
1462                        int returnCode = NSCHelper::wrapReturnString(returnMessageBuffer, returnMessageBufferLen, _T("Failed to inject remote command: ") + e.what(), NSCAPI::returnCRIT);
1463                        return NSCHelper::wrapReturnString(returnPerfBuffer, returnPerfBufferLen, _T(""), returnCode);
1464                } catch (...) {
1465                        LOG_ERROR_STD(_T("Failed to inject remote command: Unknown exception"));
1466                        int returnCode = NSCHelper::wrapReturnString(returnMessageBuffer, returnMessageBufferLen, _T("Failed to inject remote command:  + e.what()"), NSCAPI::returnCRIT);
1467                        return NSCHelper::wrapReturnString(returnPerfBuffer, returnPerfBufferLen, _T(""), returnCode);
1468                }
1469        } else {
1470                ReadLock readLock(&m_mutexRW, true, 5000);
1471                if (!readLock.IsLocked()) {
1472                        LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1473                        return NSCAPI::returnUNKNOWN;
1474                }
1475                for (pluginList::size_type i = 0; i < commandHandlers_.size(); i++) {
1476                        try {
1477                                NSCAPI::nagiosReturn c = commandHandlers_[i]->handleCommand(command, argLen, argument, returnMessageBuffer, returnMessageBufferLen, returnPerfBuffer, returnPerfBufferLen);
1478                                switch (c) {
1479                                        case NSCAPI::returnInvalidBufferLen:
1480                                                LOG_ERROR(_T("UNKNOWN: Return buffer to small to handle this command."));
1481                                                return c;
1482                                        case NSCAPI::returnIgnored:
1483                                                break;
1484                                        case NSCAPI::returnOK:
1485                                        case NSCAPI::returnWARN:
1486                                        case NSCAPI::returnCRIT:
1487                                        case NSCAPI::returnUNKNOWN:
1488                                                LOG_DEBUG_STD(_T("Injected Result: ") + NSCHelper::translateReturn(c) + _T(" '") + (std::wstring)(returnMessageBuffer) + _T("'"));
1489                                                LOG_DEBUG_STD(_T("Injected Performance Result: '") +(std::wstring)(returnPerfBuffer) + _T("'"));
1490                                                return c;
1491                                        default:
1492                                                LOG_ERROR_STD(_T("Unknown error from handleCommand: ") + strEx::itos(c) + _T(" the injected command was: ") + (std::wstring)command);
1493                                                return c;
1494                                }
1495                        } catch(const NSPluginException& e) {
1496                                LOG_ERROR_STD(_T("Exception raised: ") + e.error_ + _T(" in module: ") + e.file_);
1497                                return NSCAPI::returnCRIT;
1498                        } catch(...) {
1499                                LOG_ERROR_STD(_T("Unknown exception raised in module"));
1500                                return NSCAPI::returnCRIT;
1501                        }
1502                }
1503                LOG_MESSAGE_STD(_T("No handler for command: '") + command + _T("'"));
1504                return NSCAPI::returnIgnored;
1505        }
1506}
1507
1508void NSClientT::listPlugins() {
1509        ReadLock readLock(&m_mutexRW, true, 10000);
1510        if (!readLock.IsLocked()) {
1511                LOG_ERROR(_T("FATAL ERROR: Could not get read-mutex."));
1512                return;
1513        }
1514        for (pluginList::iterator it=plugins_.begin(); it != plugins_.end(); ++it) {
1515                try {
1516                        if ((*it)->isBroken()) {
1517                                std::wcout << (*it)->getModule() << _T(": ") << _T("broken") << std::endl;
1518                        } else {
1519                                std::wcout << (*it)->getModule() << _T(": ") << (*it)->getName() << std::endl;
1520                        }
1521                } catch (NSPluginException e) {
1522                        LOG_ERROR_STD(_T("Could not load plugin: ") + e.file_ + _T(": ") + e.error_);
1523                }
1524        }
1525
1526}
1527
1528bool NSClientT::logDebug() {
1529        if (debug_ == log_unknown) {
1530                try {
1531                        if (settings_manager::get_settings()->get_int(_T("log"), _T("debug"), 0) == 1)
1532                                debug_ = log_debug;
1533                        else
1534                                debug_ = log_nodebug;
1535                } catch (SettingsException e) {
1536                        return true;
1537                }
1538        }
1539        return (debug_ == log_debug);
1540}
1541
1542void log_broken_message(std::wstring msg) {
1543        OutputDebugString(msg.c_str());
1544        std::wcout << msg << std::endl;
1545}
1546/**
1547 * Report a message to all logging enabled modules.
1548 *
1549 * @param msgType Message type
1550 * @param file Filename generally __FILE__
1551 * @param line  Line number, generally __LINE__
1552 * @param message The message as a human readable string.
1553 */
1554void NSClientT::reportMessage(int msgType, const TCHAR* file, const int line, std::wstring message) {
1555        if ((msgType == NSCAPI::debug)&&(!logDebug())) {
1556                return;
1557        }
1558        if (shared_server_.get() != NULL && shared_server_->hasClients()) {
1559                try {
1560                        shared_server_->sendLogMessageToClients(msgType, file, line, message);
1561                } catch (nsclient_session::session_exception e) {
1562                        log_broken_message(_T("Failed to send message to clients: ") + e.what());
1563                }
1564        }
1565        std::wstring file_stl = file;
1566        std::wstring::size_type pos = file_stl.find_last_of(_T("\\"));
1567        if (pos != std::wstring::npos)
1568                file_stl = file_stl.substr(pos);
1569        {
1570                ReadLock readLock(&m_mutexRW, true, 5000);
1571                if (!readLock.IsLocked()) {
1572                        log_broken_message(_T("Message was lost as the (mutexRW) core was locked: ") + message);
1573                        return;
1574                }
1575                MutexLock lock(messageMutex);
1576                if (!lock.hasMutex()) {
1577                        log_broken_message(_T("Message was lost as the core was locked: ") + message);
1578                        return;
1579                }
1580                if (g_bConsoleLog) {
1581                        std::string k = "?";
1582                        switch (msgType) {
1583                        case NSCAPI::critical:
1584                                k ="c";
1585                                break;
1586                        case NSCAPI::warning:
1587                                k ="w";
1588                                break;
1589                        case NSCAPI::error:
1590                                k ="e";
1591                                break;
1592                        case NSCAPI::log:
1593                                k ="l";
1594                                break;
1595                        case NSCAPI::debug:
1596                                k ="d";
1597                                break;
1598                        }       
1599                        std::cout << k << " " << strEx::wstring_to_string(file_stl) << "(" << line << ") " << strEx::wstring_to_string(message) << std::endl;
1600                }
1601                if (!plugins_loaded_) {
1602                        OutputDebugString(message.c_str());
1603                        log_cache_.push_back(cached_log_entry(msgType, file, line, message));
1604                } else {
1605                        if (log_cache_.size() > 0) {
1606                                for (log_cache_type::const_iterator cit=log_cache_.begin();cit!=log_cache_.end();++cit) {
1607                                        for (pluginList::size_type i = 0; i< messageHandlers_.size(); i++) {
1608                                                try {
1609                                                        messageHandlers_[i]->handleMessage((*cit).msgType, (_T("CACHE") + (*cit).file).c_str(), (*cit).line, (*cit).message.c_str());
1610                                                } catch(const NSPluginException& e) {
1611                                                        log_broken_message(_T("Caught: ") + e.error_ + _T(" when trying to log a message..."));
1612                                                        return;
1613                                                } catch(...) {
1614                                                        log_broken_message(_T("Caught: Unknown Exception when trying to log a message..."));
1615                                                        return;
1616                                                }
1617                                        }
1618                                }
1619                                log_cache_.clear();
1620                        }
1621                        for (pluginList::size_type i = 0; i< messageHandlers_.size(); i++) {
1622                                try {
1623                                        messageHandlers_[i]->handleMessage(msgType, file, line, message.c_str());
1624                                } catch(const NSPluginException& e) {
1625                                        log_broken_message(_T("Caught: ") + e.error_ + _T(" when trying to log a message..."));
1626                                        return;
1627                                } catch(...) {
1628                                        log_broken_message(_T("Caught: Unknown Exception when trying to log a message..."));
1629                                        return;
1630                                }
1631                        }
1632                }
1633        }
1634}
1635std::wstring NSClientT::getBasePath(void) {
1636        MutexLock lock(internalVariables);
1637        if (!lock.hasMutex()) {
1638                LOG_ERROR(_T("FATAL ERROR: Could not get mutex."));
1639                return _T("FATAL ERROR");
1640        }
1641        if (!basePath.empty())
1642                return basePath;
1643        unsigned int buf_len = 4096;
1644        TCHAR* buffer = new TCHAR[buf_len+1];
1645        GetModuleFileName(NULL, buffer, buf_len);
1646        std::wstring path = buffer;
1647        std::wstring::size_type pos = path.rfind('\\');
1648        basePath = path.substr(0, pos) + _T("\\");
1649        delete [] buffer;
1650        try {
1651                settings_manager::get_core()->set_base(basePath);
1652        } catch (SettingsException e) {
1653                LOG_ERROR_STD(_T("Failed to set settings file: ") + e.getMessage());
1654        } catch (...) {
1655                LOG_ERROR_STD(_T("Failed to set settings file"));
1656        }
1657        return basePath;
1658}
1659
1660
1661NSCAPI::errorReturn NSAPIGetSettingsString(const TCHAR* section, const TCHAR* key, const TCHAR* defaultValue, TCHAR* buffer, unsigned int bufLen) {
1662        try {
1663                return NSCHelper::wrapReturnString(buffer, bufLen, settings_manager::get_settings()->get_string(section, key, defaultValue), NSCAPI::isSuccess);
1664        } catch (...) {
1665                LOG_ERROR_STD(_T("Failed to getString: ") + key);
1666                return NSCAPI::hasFailed;
1667        }
1668}
1669int NSAPIGetSettingsInt(const TCHAR* section, const TCHAR* key, int defaultValue) {
1670        try {
1671                return settings_manager::get_settings()->get_int(section, key, defaultValue);
1672        } catch (SettingsException e) {
1673                LOG_ERROR_STD(_T("Failed to set settings file") + e.getMessage());
1674                return defaultValue;
1675        }
1676}
1677NSCAPI::errorReturn NSAPIGetBasePath(TCHAR*buffer, unsigned int bufLen) {
1678        return NSCHelper::wrapReturnString(buffer, bufLen, mainClient.getBasePath(), NSCAPI::isSuccess);
1679}
1680NSCAPI::errorReturn NSAPIGetApplicationName(TCHAR*buffer, unsigned int bufLen) {
1681        return NSCHelper::wrapReturnString(buffer, bufLen, SZAPPNAME, NSCAPI::isSuccess);
1682}
1683NSCAPI::errorReturn NSAPIGetApplicationVersionStr(TCHAR*buffer, unsigned int bufLen) {
1684        return NSCHelper::wrapReturnString(buffer, bufLen, SZVERSION, NSCAPI::isSuccess);
1685}
1686void NSAPIMessage(int msgType, const TCHAR* file, const int line, const TCHAR* message) {
1687        mainClient.reportMessage(msgType, file, line, message);
1688}
1689void NSAPIStopServer(void) {
1690        serviceControll::StopNoWait(SZSERVICENAME);
1691}
1692NSCAPI::nagiosReturn NSAPIInject(const TCHAR* command, const unsigned int argLen, TCHAR **argument, TCHAR *returnMessageBuffer, unsigned int returnMessageBufferLen, TCHAR *returnPerfBuffer, unsigned int returnPerfBufferLen) {
1693        return mainClient.injectRAW(command, argLen, argument, returnMessageBuffer, returnMessageBufferLen, returnPerfBuffer, returnPerfBufferLen);
1694}
1695NSCAPI::errorReturn NSAPIGetSettingsSection(const TCHAR* section, TCHAR*** aBuffer, unsigned int * bufLen) {
1696        try {
1697                unsigned int len = 0;
1698                *aBuffer = arrayBuffer::list2arrayBuffer(settings_manager::get_settings()->get_keys(section), len);
1699                *bufLen = len;
1700                return NSCAPI::isSuccess;
1701        } catch (SettingsException e) {
1702                LOG_ERROR_STD(_T("Failed to get section: ") + e.getMessage());
1703        } catch (...) {
1704                LOG_ERROR_STD(_T("Failed to getSection: ") + section);
1705        }
1706        return NSCAPI::hasFailed;
1707}
1708NSCAPI::errorReturn NSAPIReleaseSettingsSectionBuffer(TCHAR*** aBuffer, unsigned int * bufLen) {
1709        arrayBuffer::destroyArrayBuffer(*aBuffer, *bufLen);
1710        *bufLen = 0;
1711        *aBuffer = NULL;
1712        return NSCAPI::isSuccess;
1713}
1714
1715NSCAPI::boolReturn NSAPICheckLogMessages(int messageType) {
1716        if (mainClient.logDebug())
1717                return NSCAPI::istrue;
1718        return NSCAPI::isfalse;
1719}
1720
1721std::wstring Encrypt(std::wstring str, unsigned int algorithm) {
1722        unsigned int len = 0;
1723        NSAPIEncrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), NULL, &len);
1724        len+=2;
1725        TCHAR *buf = new TCHAR[len+1];
1726        NSCAPI::errorReturn ret = NSAPIEncrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), buf, &len);
1727        if (ret == NSCAPI::isSuccess) {
1728                std::wstring ret = buf;
1729                delete [] buf;
1730                return ret;
1731        }
1732        return _T("");
1733}
1734std::wstring Decrypt(std::wstring str, unsigned int algorithm) {
1735        unsigned int len = 0;
1736        NSAPIDecrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), NULL, &len);
1737        len+=2;
1738        TCHAR *buf = new TCHAR[len+1];
1739        NSCAPI::errorReturn ret = NSAPIDecrypt(algorithm, str.c_str(), static_cast<unsigned int>(str.size()), buf, &len);
1740        if (ret == NSCAPI::isSuccess) {
1741                std::wstring ret = buf;
1742                delete [] buf;
1743                return ret;
1744        }
1745        return _T("");
1746}
1747
1748NSCAPI::errorReturn NSAPIEncrypt(unsigned int algorithm, const TCHAR* inBuffer, unsigned int inBufLen, TCHAR* outBuf, unsigned int *outBufLen) {
1749        if (algorithm != NSCAPI::xor) {
1750                LOG_ERROR(_T("Unknown algortihm requested."));
1751                return NSCAPI::hasFailed;
1752        }
1753        std::wstring key = settings_manager::get_settings()->get_string(SETTINGS_KEY(protocol_def::MASTER_KEY));
1754        int tcharInBufLen = 0;
1755        char *c = charEx::tchar_to_char(inBuffer, inBufLen, tcharInBufLen);
1756        std::wstring::size_type j=0;
1757        for (int i=0;i<tcharInBufLen;i++,j++) {
1758                if (j > key.size())
1759                        j = 0;
1760                c[i] ^= key[j];
1761        }
1762        size_t cOutBufLen = b64::b64_encode(reinterpret_cast<void*>(c), tcharInBufLen, NULL, NULL);
1763        if (!outBuf) {
1764                *outBufLen = static_cast<unsigned int>(cOutBufLen*2); // TODO: Guessing wildly here but no proper way to tell without a lot of extra work
1765                return NSCAPI::isSuccess;
1766        }
1767        char *cOutBuf = new char[cOutBufLen+1];
1768        size_t len = b64::b64_encode(reinterpret_cast<void*>(c), tcharInBufLen, cOutBuf, cOutBufLen);
1769        delete [] c;
1770        if (len == 0) {
1771                LOG_ERROR(_T("Invalid out buffer length."));
1772                return NSCAPI::isInvalidBufferLen;
1773        }
1774        int realOutLen;
1775        TCHAR *realOut = charEx::char_to_tchar(cOutBuf, cOutBufLen, realOutLen);
1776        if (static_cast<unsigned int>(realOutLen) >= *outBufLen) {
1777                LOG_ERROR_STD(_T("Invalid out buffer length: ") + strEx::itos(realOutLen) + _T(" was needed but only ") + strEx::itos(*outBufLen) + _T(" was allocated."));
1778                return NSCAPI::isInvalidBufferLen;
1779        }
1780        wcsncpy_s(outBuf, *outBufLen, realOut, realOutLen);
1781        delete [] realOut;
1782        outBuf[realOutLen] = 0;
1783        *outBufLen = static_cast<unsigned int>(realOutLen);
1784        return NSCAPI::isSuccess;
1785}
1786
1787NSCAPI::errorReturn NSAPIDecrypt(unsigned int algorithm, const TCHAR* inBuffer, unsigned int inBufLen, TCHAR* outBuf, unsigned int *outBufLen) {
1788        if (algorithm != NSCAPI::xor) {
1789                LOG_ERROR(_T("Unknown algortihm requested."));
1790                return NSCAPI::hasFailed;
1791        }
1792        int inBufLenC = 0;
1793        char *inBufferC = charEx::tchar_to_char(inBuffer, inBufLen, inBufLenC);
1794        size_t cOutLen =  b64::b64_decode(inBufferC, inBufLenC, NULL, NULL);
1795        if (!outBuf) {
1796                *outBufLen = static_cast<unsigned int>(cOutLen*2); // TODO: Guessing wildly here but no proper way to tell without a lot of extra work
1797                return NSCAPI::isSuccess;
1798        }
1799        char *cOutBuf = new char[cOutLen+1];
1800        size_t len = b64::b64_decode(inBufferC, inBufLenC, reinterpret_cast<void*>(cOutBuf), cOutLen);
1801        delete [] inBufferC;
1802        if (len == 0) {
1803                LOG_ERROR(_T("Invalid out buffer length."));
1804                return NSCAPI::isInvalidBufferLen;
1805        }
1806        int realOutLen;
1807
1808        std::wstring key = settings_manager::get_settings()->get_string(SETTINGS_KEY(protocol_def::MASTER_KEY));
1809        std::wstring::size_type j=0;
1810        for (int i=0;i<cOutLen;i++,j++) {
1811                if (j > key.size())
1812                        j = 0;
1813                cOutBuf[i] ^= key[j];
1814        }
1815
1816        TCHAR *realOut = charEx::char_to_tchar(cOutBuf, cOutLen, realOutLen);
1817        if (static_cast<unsigned int>(realOutLen) >= *outBufLen) {
1818                LOG_ERROR_STD(_T("Invalid out buffer length: ") + strEx::itos(realOutLen) + _T(" was needed but only ") + strEx::itos(*outBufLen) + _T(" was allocated."));
1819                return NSCAPI::isInvalidBufferLen;
1820        }
1821        wcsncpy_s(outBuf, *outBufLen, realOut, realOutLen);
1822        delete [] realOut;
1823        outBuf[realOutLen] = 0;
1824        *outBufLen = static_cast<unsigned int>(realOutLen);
1825        return NSCAPI::isSuccess;
1826}
1827
1828NSCAPI::errorReturn NSAPISetSettingsString(const TCHAR* section, const TCHAR* key, const TCHAR* value) {
1829        try {
1830                settings_manager::get_settings()->set_string(section, key, value);
1831        } catch (...) {
1832                LOG_ERROR_STD(_T("Failed to setString: ") + key);
1833                return NSCAPI::hasFailed;
1834        }
1835        return NSCAPI::isSuccess;
1836}
1837NSCAPI::errorReturn NSAPISetSettingsInt(const TCHAR* section, const TCHAR* key, int value) {
1838        try {
1839                settings_manager::get_settings()->set_int(section, key, value);
1840        } catch (...) {
1841                LOG_ERROR_STD(_T("Failed to setInt: ") + key);
1842                return NSCAPI::hasFailed;
1843        }
1844        return NSCAPI::isSuccess;
1845}
1846NSCAPI::errorReturn NSAPIWriteSettings(int type) {
1847        try {
1848                if (type == NSCAPI::settings_registry)
1849                        settings_manager::get_core()->migrate_to(Settings::SettingsCore::registry);
1850                else if (type == NSCAPI::settings_inifile)
1851                        settings_manager::get_core()->migrate_to(Settings::SettingsCore::ini_file);
1852                else
1853                        settings_manager::get_settings()->save();
1854        } catch (SettingsException e) {
1855                LOG_ERROR_STD(_T("Failed to write settings: ") + e.getMessage());
1856                return NSCAPI::hasFailed;
1857        } catch (...) {
1858                LOG_ERROR_STD(_T("Failed to write settings"));
1859                return NSCAPI::hasFailed;
1860        }
1861        return NSCAPI::isSuccess;
1862}
1863NSCAPI::errorReturn NSAPIReadSettings(int type) {
1864        try {
1865                if (type == NSCAPI::settings_registry)
1866                        settings_manager::get_core()->migrate_from(Settings::SettingsCore::registry);
1867                else if (type == NSCAPI::settings_inifile)
1868                        settings_manager::get_core()->migrate_from(Settings::SettingsCore::ini_file);
1869                else
1870                        settings_manager::get_settings()->reload();
1871        } catch (SettingsException e) {
1872                LOG_ERROR_STD(_T("Failed to read settings: ") + e.getMessage());
1873                return NSCAPI::hasFailed;
1874        } catch (...) {
1875                LOG_ERROR_STD(_T("Failed to read settings"));
1876                return NSCAPI::hasFailed;
1877        }
1878        return NSCAPI::isSuccess;
1879}
1880NSCAPI::errorReturn NSAPIRehash(int flag) {
1881        return NSCAPI::hasFailed;
1882}
1883NSCAPI::errorReturn NSAPIDescribeCommand(const TCHAR* command, TCHAR* buffer, unsigned int bufLen) {
1884        return NSCHelper::wrapReturnString(buffer, bufLen, mainClient.describeCommand(command), NSCAPI::isSuccess);
1885}
1886NSCAPI::errorReturn NSAPIGetAllCommandNames(arrayBuffer::arrayBuffer* aBuffer, unsigned int *bufLen) {
1887        unsigned int len = 0;
1888        *aBuffer = arrayBuffer::list2arrayBuffer(mainClient.getAllCommandNames(), len);
1889        *bufLen = len;
1890        return NSCAPI::isSuccess;
1891}
1892NSCAPI::errorReturn NSAPIReleaseAllCommandNamessBuffer(TCHAR*** aBuffer, unsigned int * bufLen) {
1893        arrayBuffer::destroyArrayBuffer(*aBuffer, *bufLen);
1894        *bufLen = 0;
1895        *aBuffer = NULL;
1896        return NSCAPI::isSuccess;
1897}
1898NSCAPI::errorReturn NSAPIRegisterCommand(const TCHAR* cmd,const TCHAR* desc) {
1899        mainClient.registerCommand(cmd, desc);
1900        return NSCAPI::isSuccess;
1901}
1902NSCAPI::errorReturn NSAPISettingsRegKey(const TCHAR* path, const TCHAR* key, int type, const TCHAR* title, const TCHAR* description, const TCHAR* defVal, int advanced) {
1903        try {
1904                if (type == NSCAPI::key_string)
1905                        settings_manager::get_core()->register_key(path, key, Settings::SettingsCore::key_string, title, description, defVal, advanced);
1906                if (type == NSCAPI::key_bool)
1907                        settings_manager::get_core()->register_key(path, key, Settings::SettingsCore::key_bool, title, description, defVal, advanced);
1908                if (type == NSCAPI::key_integer)
1909                        settings_manager::get_core()->register_key(path, key, Settings::SettingsCore::key_integer, title, description, defVal, advanced);
1910                return NSCAPI::hasFailed;
1911        } catch (SettingsException e) {
1912                LOG_ERROR_STD(_T("Failed register key: ") + e.getMessage());
1913                return NSCAPI::hasFailed;
1914        } catch (...) {
1915                LOG_ERROR_STD(_T("Failed register key"));
1916                return NSCAPI::hasFailed;
1917        }
1918        return NSCAPI::isSuccess;
1919}
1920
1921
1922NSCAPI::errorReturn NSAPISettingsRegPath(const TCHAR* path, const TCHAR* title, const TCHAR* description, int advanced) {
1923        try {
1924                settings_manager::get_core()->register_path(path, title, description, advanced);
1925        } catch (SettingsException e) {
1926                LOG_ERROR_STD(_T("Failed register path: ") + e.getMessage());
1927                return NSCAPI::hasFailed;
1928        } catch (...) {
1929                LOG_ERROR_STD(_T("Failed register path"));
1930                return NSCAPI::hasFailed;
1931        }
1932        return NSCAPI::isSuccess;
1933}
1934
1935//int wmain(int argc, TCHAR* argv[], TCHAR* envp[])
1936TCHAR* copyString(const std::wstring &str) {
1937        int sz = str.size();
1938        TCHAR *tc = new TCHAR[sz+2];
1939        wcsncpy_s(tc, sz+1, str.c_str(), sz);
1940        return tc;
1941}
1942NSCAPI::errorReturn NSAPIGetPluginList(int *len, NSCAPI::plugin_info *list[]) {
1943        NSClientT::plugin_info_list plugList= mainClient.get_all_plugins();
1944        *len = plugList.size();
1945
1946        *list = new NSCAPI::plugin_info[*len+1];
1947        int i=0;
1948        for(NSClientT::plugin_info_list::const_iterator cit = plugList.begin(); cit != plugList.end(); ++cit,i++) {
1949                (*list)[i].dll = copyString((*cit).dll);
1950                (*list)[i].name = copyString((*cit).name);
1951                (*list)[i].version = copyString((*cit).version);
1952                (*list)[i].description = copyString((*cit).description);
1953        }
1954        return NSCAPI::isSuccess;
1955}
1956NSCAPI::errorReturn NSAPIReleasePluginList(int len, NSCAPI::plugin_info *list[]) {
1957        for (int i=0;i<len;i++) {
1958                delete [] (*list)[i].dll;
1959                delete [] (*list)[i].name;
1960                delete [] (*list)[i].version;
1961                delete [] (*list)[i].description;
1962        }
1963        delete [] *list;
1964        return NSCAPI::isSuccess;
1965}
1966
1967
1968NSCAPI::errorReturn NSAPISettingsSave(void) {
1969        try {
1970                settings_manager::get_settings()->save();
1971        } catch (SettingsException e) {
1972                LOG_ERROR_STD(_T("Failed to save: ") + e.getMessage());
1973                return NSCAPI::hasFailed;
1974        } catch (...) {
1975                LOG_ERROR_STD(_T("Failed to save"));
1976                return NSCAPI::hasFailed;
1977        }
1978        return NSCAPI::isSuccess;
1979}
1980
1981
1982
1983LPVOID NSAPILoader(TCHAR*buffer) {
1984        if (_wcsicmp(buffer, _T("NSAPIGetApplicationName")) == 0)
1985                return &NSAPIGetApplicationName;
1986        if (_wcsicmp(buffer, _T("NSAPIGetApplicationVersionStr")) == 0)
1987                return &NSAPIGetApplicationVersionStr;
1988        if (_wcsicmp(buffer, _T("NSAPIGetSettingsString")) == 0)
1989                return &NSAPIGetSettingsString;
1990        if (_wcsicmp(buffer, _T("NSAPIGetSettingsSection")) == 0)
1991                return &NSAPIGetSettingsSection;
1992        if (_wcsicmp(buffer, _T("NSAPIReleaseSettingsSectionBuffer")) == 0)
1993                return &NSAPIReleaseSettingsSectionBuffer;
1994        if (_wcsicmp(buffer, _T("NSAPIGetSettingsInt")) == 0)
1995                return &NSAPIGetSettingsInt;
1996        if (_wcsicmp(buffer, _T("NSAPIMessage")) == 0)
1997                return &NSAPIMessage;
1998        if (_wcsicmp(buffer, _T("NSAPIStopServer")) == 0)
1999                return &NSAPIStopServer;
2000        if (_wcsicmp(buffer, _T("NSAPIInject")) == 0)
2001                return &NSAPIInject;
2002        if (_wcsicmp(buffer, _T("NSAPIGetBasePath")) == 0)
2003                return &NSAPIGetBasePath;
2004        if (_wcsicmp(buffer, _T("NSAPICheckLogMessages")) == 0)
2005                return &NSAPICheckLogMessages;
2006        if (_wcsicmp(buffer, _T("NSAPIEncrypt")) == 0)
2007                return &NSAPIEncrypt;
2008        if (_wcsicmp(buffer, _T("NSAPIDecrypt")) == 0)
2009                return &NSAPIDecrypt;
2010        if (_wcsicmp(buffer, _T("NSAPISetSettingsString")) == 0)
2011                return &NSAPISetSettingsString;
2012        if (_wcsicmp(buffer, _T("NSAPISetSettingsInt")) == 0)
2013                return &NSAPISetSettingsInt;
2014        if (_wcsicmp(buffer, _T("NSAPIWriteSettings")) == 0)
2015                return &NSAPIWriteSettings;
2016        if (_wcsicmp(buffer, _T("NSAPIReadSettings")) == 0)
2017                return &NSAPIReadSettings;
2018        if (_wcsicmp(buffer, _T("NSAPIRehash")) == 0)
2019                return &NSAPIRehash;
2020        if (_wcsicmp(buffer, _T("NSAPIDescribeCommand")) == 0)
2021                return &NSAPIDescribeCommand;
2022        if (_wcsicmp(buffer, _T("NSAPIGetAllCommandNames")) == 0)
2023                return &NSAPIGetAllCommandNames;
2024        if (_wcsicmp(buffer, _T("NSAPIReleaseAllCommandNamessBuffer")) == 0)
2025                return &NSAPIReleaseAllCommandNamessBuffer;
2026        if (_wcsicmp(buffer, _T("NSAPIRegisterCommand")) == 0)
2027                return &NSAPIRegisterCommand;
2028        if (_wcsicmp(buffer, _T("NSAPISettingsRegKey")) == 0)
2029                return &NSAPISettingsRegKey;
2030        if (_wcsicmp(buffer, _T("NSAPISettingsRegPath")) == 0)
2031                return &NSAPISettingsRegPath;
2032        if (_wcsicmp(buffer, _T("NSAPIGetPluginList")) == 0)
2033                return &NSAPIGetPluginList;
2034        if (_wcsicmp(buffer, _T("NSAPIReleasePluginList")) == 0)
2035                return &NSAPIReleasePluginList;
2036        if (_wcsicmp(buffer, _T("NSAPISettingsSave")) == 0)
2037                return &NSAPISettingsSave;
2038
2039        LOG_ERROR_STD(_T("Function not found: ") + buffer);
2040        return NULL;
2041}
2042
2043
Note: See TracBrowser for help on using the repository browser.