source: nscp/NSClient++.cpp @ 79f191a

stable
Last change on this file since 79f191a was 79f191a, checked in by Michael Medin <michael@…>, 23 months ago

Release of 0.3.9

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