source: nscp/service/NSClient++.cpp @ 6672c56

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