source: nscp/service/NSClient++.cpp @ 818b54e

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

First version which builds on Linux!!! (though 99% of all features are still disabled).
All it does is build and tell you there is no settings subsystem (which there isn't as simpleini does not support wchar_t on unix :(

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