source: nscp/NSClient++.cpp @ a0528c4

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

Initial release

  • Property mode set to 100644
File size: 10.8 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
21NSClient mainClient;    // Global core instance.
22
23//////////////////////////////////////////////////////////////////////////
24// Startup code
25
26/**
27 * Application startup point
28 *
29 * @param argc Argument count
30 * @param argv[] Argument array
31 * @param envp[] Environment array
32 * @return exit status
33 */
34int main(int argc, TCHAR* argv[], TCHAR* envp[])
35{
36        int nRetCode = 0;
37
38        if ( (argc > 1) && ((*argv[1] == '-') || (*argv[1] == '/')) ) {
39                if ( _stricmp( "install", argv[1]+1 ) == 0 ) {
40                        try {
41                                serviceControll::Install(SZSERVICENAME, SZSERVICEDISPLAYNAME, SZDEPENDENCIES);
42                        } catch (const serviceControll::SCException& e) {
43                                LOG_MESSAGE_STD("Service installation failed: " + e.error_);
44                                return -1;
45                        }
46                        LOG_MESSAGE("Service installed!");
47                } else if ( _stricmp( "uninstall", argv[1]+1 ) == 0 ) {
48                        try {
49                                serviceControll::Uninstall(SZSERVICENAME);
50                        } catch (const serviceControll::SCException& e) {
51                                LOG_MESSAGE_STD("Service deinstallation failed; " + e.error_);
52                                return -1;
53                        }
54                } else if ( _stricmp( "start", argv[1]+1 ) == 0 ) {
55                        serviceControll::Start(SZSERVICENAME);
56                } else if ( _stricmp( "stop", argv[1]+1 ) == 0 ) {
57                        serviceControll::Stop(SZSERVICENAME);
58                } else if ( _stricmp( "about", argv[1]+1 ) == 0 ) {
59                        LOG_MESSAGE(SZAPPNAME " (C) Michael Medin");
60                        LOG_MESSAGE("Version " SZVERSION);
61                } else if ( _stricmp( "version", argv[1]+1 ) == 0 ) {
62                        LOG_MESSAGE(SZAPPNAME " Version: " SZVERSION);
63                } else if ( _stricmp( "test", argv[1]+1 ) == 0 ) {
64                        mainClient.InitiateService();
65                        LOG_MESSAGE("Enter command to inject or exit to terminate...");
66                        std::string s = "";
67                        while (s != "exit") {
68                                std::cin >> s;
69                                mainClient.inject(s);
70                        }
71                        mainClient.TerminateService();
72                        return 0;
73                } else {
74                        LOG_MESSAGE("Usage: -version, -about, -install, -uninstall, -start, -stop");
75                }
76                return nRetCode;
77        }
78        mainClient.StartServiceCtrlDispatcher();
79        return nRetCode;
80}
81
82//////////////////////////////////////////////////////////////////////////
83// Service functions
84
85/**
86 * Service control handler startup point.
87 * When the program is started as a service this will be the entry point.
88 */
89void NSClientT::InitiateService(void) {
90        char* buffer = new char[1024];
91        GetModuleFileName(NULL, buffer, 1023);
92        std::string path = buffer;
93        std::string::size_type pos = path.rfind('\\');
94        basePath = path.substr(0, pos) + "\\";
95        LOG_DEBUG_STD("Base path is: " + basePath);
96        delete [] buffer;
97        Settings::getInstance()->setFile(basePath + "NSC.ini");
98
99        SettingsT::sectionList list = Settings::getInstance()->getSection("modules");
100        for (SettingsT::sectionList::iterator it = list.begin(); it != list.end(); it++) {
101                try {
102                        LOG_DEBUG_STD("Loading: " + basePath + "modules\\" + (*it));
103                        loadPlugin(basePath + "modules\\" + (*it));
104                } catch(const NSPluginException& e) {
105                        LOG_ERROR_STD("Exception raised: " + e.error_ + " in module: " + e.file_);
106                }
107        }
108        socketThread.createThread();
109}
110/**
111 * Service control handler termination point.
112 * When the program is stopped as a service this will be the "exit point".
113 */
114void NSClientT::TerminateService(void) {
115        if (!socketThread.exitThread())
116                LOG_ERROR("Could not exit socket listener thread");
117        try {
118                mainClient.unloadPlugins();
119        } catch(NSPluginException *e) {
120                LOG_ERROR_STD("Exception raised: " + e->error_ + " in module: " + e->file_);
121        }
122        Settings::destroyInstance();
123}
124
125/**
126 * Forward this to the main service dispatcher helper class
127 * @param dwArgc
128 * @param *lpszArgv
129 */
130void WINAPI NSClientT::service_main_dispatch(DWORD dwArgc, LPTSTR *lpszArgv) {
131        mainClient.service_main(dwArgc, lpszArgv);
132}
133/**
134 * Forward this to the main service dispatcher helper class
135 * @param dwCtrlCode
136 */
137void WINAPI NSClientT::service_ctrl_dispatch(DWORD dwCtrlCode) {
138        mainClient.service_ctrl(dwCtrlCode);
139}
140
141//////////////////////////////////////////////////////////////////////////
142// Member functions
143
144
145/**
146 * Load a list of plug-ins
147 * @param plugins A list with plug-ins (DLL files) to load
148 */
149void NSClientT::loadPlugins(std::list<std::string> plugins) {
150        std::list<std::string>::const_iterator it;
151        for (it = plugins.begin(); it != plugins.end(); ++it) {
152                loadPlugin(*it);
153        }
154}
155/**
156 * Unload all plug-ins (in reversed order)
157 */
158void NSClientT::unloadPlugins() {
159        messageHandlers_.clear();
160        commandHandlers_.clear();
161        pluginList::reverse_iterator it;
162        for (it = plugins_.rbegin(); it != plugins_.rend(); ++it) {
163                LOG_DEBUG_STD("---\n\n\nUnloading: " + (*it)->getName());
164                (*it)->unload();
165                delete (*it);
166        }
167        plugins_.clear();
168}
169/**
170 * Load a single plug-in using a DLL filename
171 * @param file The DLL file
172 */
173void NSClientT::loadPlugin(std::string file) {
174        addPlugin(NSCPlugin::loadPlugin(file));
175}
176/**
177 * Load and add a plugin to various internal structures
178 * @param *plugin The plug-ininstance to load. The pointer is managed by the
179 */
180void NSClientT::addPlugin(NSCPlugin *plugin) {
181        plugin->load();
182        LOG_DEBUG_STD("Loading: " + plugin->getName());
183        // @todo Catch here and unload if we fail perhaps ?
184        plugins_.push_back(plugin);
185        if (plugin->hasCommandHandler())
186                commandHandlers_.push_back(plugin);
187        if (plugin->hasMessageHandler())
188                messageHandlers_.push_back(plugin);
189}
190/**
191 * Inject a command into the plug-in stack.
192 *
193 * @param buffer A command string to inject. This should be a unparsed command string such as command&arg1&arg2&arg...
194 * @return The result, empty string if no result
195 */
196std::string NSClientT::inject(std::string buffer) {
197        std::list<std::string> args = charEx::split(buffer.c_str(), '&');
198        if (args.size() < 2) {
199                LOG_MESSAGE("Insufficient arguments!");
200        }
201        std::string command = args.front(); args.pop_front();
202        LOG_MESSAGE_STD("Injecting: " + command);
203        std::string ret = execute(NSClientT::getPassword(), command, args);
204        LOG_MESSAGE_STD("Injected Result: " + ret);
205        return ret;
206
207}
208/**
209 * Helper function to return the current password (perhaps this should be static ?)
210 *
211 * @return The current password
212 */
213std::string NSClientT::getPassword() {
214        return Settings::getInstance()->getString("generic", "password", "");
215}
216/**
217 * Execute a command.
218 *
219 * @param password The password
220 * @param cmd The command
221 * @param args Arguments as a list<string>
222 * @return The result if any, empty string if no result.
223 *
224 * @todo Make an int return value to set critical/warning/ok/unknown status.
225 * ie. pair<int,string>
226 */
227std::string NSClientT::execute(std::string password, std::string cmd, std::list<std::string> args) {
228        static unsigned int bufferSize = 0;
229        if (bufferSize == 0)
230                bufferSize = static_cast<unsigned int>(Settings::getInstance()->getInt("main", "bufferSize", 4096));
231
232        if (password != getPassword())
233                return "INVALID PASSWORD";
234
235        // Pack the argument as a char** buffer
236        std::string ret;
237        int len = args.size();
238        char **arguments = new char*[len];
239        std::list<std::string>::iterator it = args.begin();
240        for (int i=0;it!=args.end();++it,i++) {
241                int alen = (*it).size();
242                arguments[i] = new char[alen+2];
243                strncpy(arguments[i], (*it).c_str(), alen+1);
244        }
245        // Allocate return buffer
246        char* returnbuffer = new char[bufferSize+1];
247        pluginList::const_iterator plit;
248        for (plit = commandHandlers_.begin(); plit != commandHandlers_.end(); ++plit) {
249                try {
250                        int c = (*plit)->handleCommand(cmd.c_str(), len, arguments, returnbuffer, bufferSize);
251                        if (c == NSCAPI::handled) {                                     // module handled the message "we are done..."
252                                ret = returnbuffer;
253                                break;
254                        } else if (c == NSCAPI::isfalse) {                      // Module ignored the message
255                        } else if (c == NSCAPI::invalidBufferLen) {     // Buffer is to small
256                                LOG_ERROR("Return buffer to small, need to increase it in the ini file.");
257                        } else {                                                                        // Something else went wrong...
258                                LOG_ERROR("Unknown error from handleCommand");
259                        }
260                } catch(const NSPluginException& e) {
261                        LOG_ERROR_STD("Exception raised: " + e.error_ + " in module: " + e.file_);
262                }
263        }
264        // delete buffers
265        delete [] returnbuffer;
266        for (int i=0;i<len;i++) {
267                delete [] arguments[i];
268        }
269        delete [] arguments;
270        return ret;
271}
272/**
273 * Report a message to all logging enabled modules.
274 *
275 * @param msgType Message type
276 * @param file Filename generally __FILE__
277 * @param line  Line number, generaly __LINE__
278 * @param message The message as a human readable string.
279 */
280void NSClientT::reportMessage(int msgType, const char* file, const int line, std::string message) {
281        MutexLock lock(messageMutex);
282        pluginList::const_iterator plit;
283        for (plit = messageHandlers_.begin(); plit != messageHandlers_.end(); ++plit) {
284                try {
285                        (*plit)->handleMessage(msgType, file, line, message.c_str());
286                } catch(const NSPluginException& e) {
287                        // Here we are pretty much fucked! (as logging this might cause a loop :)
288                        throw "This shouldn't have happened...";
289                }
290        }
291}
292
293int NSAPIGetSettingsString(const char* section, const char* key, const char* defaultValue, char* buffer, unsigned int bufLen) {
294        return NSCHelper::wrapReturnString(buffer, bufLen, Settings::getInstance()->getString(section, key, defaultValue));
295}
296int NSAPIGetSettingsInt(const char* section, const char* key, int defaultValue) {
297        return Settings::getInstance()->getInt(section, key, defaultValue);
298}
299
300int NSAPIGetApplicationName(char*buffer, unsigned int bufLen) {
301        return NSCHelper::wrapReturnString(buffer, bufLen, SZAPPNAME);
302}
303int NSAPIGetApplicationVersionStr(char*buffer, unsigned int bufLen) {
304        return NSCHelper::wrapReturnString(buffer, bufLen, SZVERSION);
305}
306void NSAPIMessage(int msgType, const char* file, const int line, const char* message) {
307        mainClient.reportMessage(msgType, file, line, message);
308}
309void NSAPIStopServer(void) {
310        serviceControll::Stop(SZSERVICENAME);
311}
312int NSAPIInject(const char* command, char* buffer, unsigned int bufLen) {
313        return NSCHelper::wrapReturnString(buffer, bufLen, mainClient.inject(command));
314}
315
316LPVOID NSAPILoader(char*buffer) {
317        if (stricmp(buffer, "NSAPIGetApplicationName") == 0)
318                return &NSAPIGetApplicationName;
319        if (stricmp(buffer, "NSAPIGetApplicationVersionStr") == 0)
320                return &NSAPIGetApplicationVersionStr;
321        if (stricmp(buffer, "NSAPIGetSettingsString") == 0)
322                return &NSAPIGetSettingsString;
323        if (stricmp(buffer, "NSAPIGetSettingsInt") == 0)
324                return &NSAPIGetSettingsInt;
325        if (stricmp(buffer, "NSAPIMessage") == 0)
326                return &NSAPIMessage;
327        if (stricmp(buffer, "NSAPIStopServer") == 0)
328                return &NSAPIStopServer;
329        if (stricmp(buffer, "NSAPIInject") == 0)
330                return &NSAPIInject;
331        return NULL;
332}
Note: See TracBrowser for help on using the repository browser.