From 5a63e70b7b74befdf9627a10a41ced4f3c4adfae Mon Sep 17 00:00:00 2001
From: Esteban Sanchez <esteban.sanchez@gmail.com>
Date: Fri, 28 Nov 2008 10:51:03 +0000
Subject: [PATCH] 2008-11-28  Esteban Sanchez  <estebans@artica.es>

	* modules/pandora_module.[cc,h]: Added an async property. Added
	getLatestOutput() to get the latest output of a module.

	* modules/pandora_module_factory.cc: Parse async token in modules.

	* modules/pandora_module_list.[cc,h]: It can create empty lists now
	and add modules using new addModule() function.

	* modules/pandora_module_service.[cc,h]: Added an async thread to
	watch services events and track services status changes quickly and
	asynchronously.

	* windows/pandora_wmi.cc: Style correction.

	* pandora_windows_service.[cc,h]: Pandora Windows service object is
	now single instance, so the instance to the running service can be
	accessed anywhere (useful in async threads). The XML generation and
	sending process has been moved to a new function called sendXml()
	which is thread-safe.

	* windows_service.h: Some properties are now protected instead of
	public to make it easier the singleton pattern in child classes.

	* main.cc: Adopted to singleton pattern in Pandora windows service.



git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@1268 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
---
 pandora_agents/win32/ChangeLog                |  27 +
 pandora_agents/win32/main.cc                  | 260 ++++-----
 .../win32/modules/pandora_module.cc           |  64 +-
 pandora_agents/win32/modules/pandora_module.h |  46 +-
 .../win32/modules/pandora_module_factory.cc   |  51 +-
 .../win32/modules/pandora_module_list.cc      |  22 +-
 .../win32/modules/pandora_module_list.h       |   6 +-
 .../win32/modules/pandora_module_service.cc   |  94 ++-
 .../win32/modules/pandora_module_service.h    |   6 +-
 pandora_agents/win32/pandora.cc               | 548 +++++++++---------
 .../win32/pandora_windows_service.cc          | 216 ++++---
 .../win32/pandora_windows_service.h           |  23 +-
 pandora_agents/win32/windows/pandora_wmi.cc   |   4 +-
 pandora_agents/win32/windows_service.h        |   5 +-
 14 files changed, 804 insertions(+), 568 deletions(-)

diff --git a/pandora_agents/win32/ChangeLog b/pandora_agents/win32/ChangeLog
index d33ba58b63..50fef03bce 100644
--- a/pandora_agents/win32/ChangeLog
+++ b/pandora_agents/win32/ChangeLog
@@ -1,3 +1,30 @@
+2008-11-28  Esteban Sanchez  <estebans@artica.es>
+
+	* modules/pandora_module.[cc,h]: Added an async property. Added
+	getLatestOutput() to get the latest output of a module.
+
+	* modules/pandora_module_factory.cc: Parse async token in modules.
+
+	* modules/pandora_module_list.[cc,h]: It can create empty lists now
+	and add modules using new addModule() function.
+
+	* modules/pandora_module_service.[cc,h]: Added an async thread to
+	watch services events and track services status changes quickly and
+	asynchronously.
+
+	* windows/pandora_wmi.cc: Style correction.
+
+	* pandora_windows_service.[cc,h]: Pandora Windows service object is
+	now single instance, so the instance to the running service can be
+	accessed anywhere (useful in async threads). The XML generation and
+	sending process has been moved to a new function called sendXml()
+	which is thread-safe.
+
+	* windows_service.h: Some properties are now protected instead of
+	public to make it easier the singleton pattern in child classes.
+
+	* main.cc: Adopted to singleton pattern in Pandora windows service.
+
 2008-11-26  Esteban Sanchez  <estebans@artica.es>
 
 	* pandora_strutils.cc, pandora_strutils.h, ftp/pandora_ftp_client.cc,
diff --git a/pandora_agents/win32/main.cc b/pandora_agents/win32/main.cc
index 4be38cc6b2..3bf8dc20c5 100644
--- a/pandora_agents/win32/main.cc
+++ b/pandora_agents/win32/main.cc
@@ -1,129 +1,131 @@
-/* Pandora Windows agent main file.
-
-   Copyright (C) 2006 Artica ST.
-   Written by Esteban Sanchez.
-
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-
-   You should have received a copy of the GNU General Public License along
-   with this program; if not, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include "pandora.h"
-#include "pandora_windows_service.h"
-#include "ssh/pandora_ssh_test.h"
-#include "ftp/pandora_ftp_test.h"
-
-#define PATH_SIZE                         _MAX_PATH+1
-#define SERVICE_INSTALL_CMDLINE_PARAM    "--install"
-#define SERVICE_UNINSTALL_CMDLINE_PARAM  "--uninstall"
-#define SSH_TEST_CMDLINE_PARAM           "--test-ssh"
-#define FTP_TEST_CMDLINE_PARAM           "--test-ftp"
-#define HELP_CMDLINE_PARAM               "--help"
-
-int
-main (int argc, char *argv[]) {
-	Pandora_Windows_Service *service;
-	char                     buffer[PATH_SIZE];
-	string                   aux;
-	unsigned int             pos;
-
-	service = new Pandora_Windows_Service (Pandora::name, Pandora::display_name,
-					       Pandora::description);
-
-	GetModuleFileName (NULL, buffer, MAX_PATH);
-	aux = buffer;
-	Pandora::setPandoraInstallPath (aux);
-	pos = aux.rfind ("\\");
-	aux.erase (pos + 1);
-	Pandora::setPandoraInstallDir (aux);
-
-	/* Check the parameters */
-	for (int i = 1; i < argc; i++) {
-		if (_stricmp(argv[i], SERVICE_INSTALL_CMDLINE_PARAM) == 0) {
-			/* Install parameter */
-			service->install (Pandora::getPandoraInstallPath ().c_str ());
-		
-			delete service;
-		
-			return 0;
-		} else if (_stricmp(argv[i], SERVICE_UNINSTALL_CMDLINE_PARAM) == 0) {
-			/* Uninstall parameter */
-			service->uninstall ();
-		
-			delete service;
-		
-			return 0;
-		} else if (_stricmp(argv[i], SSH_TEST_CMDLINE_PARAM) == 0) {
-			/* SSH test parameter */
-			SSH::Pandora_SSH_Test ssh_test;
-		
-			delete service;
-		
-			try {
-				ssh_test.test ();
-			} catch (Pandora_Exception e) {
-				return 1;
-			}
-			
-			return 0;
-		} else if (_stricmp(argv[i], FTP_TEST_CMDLINE_PARAM) == 0) {
-			/* SSH test parameter */
-			FTP::Pandora_FTP_Test ftp_test;
-			
-			delete service;
-		
-			try {
-				ftp_test.test ();
-			} catch (Pandora_Exception e) {
-				return 1;
-			}
-		
-			return 0;
-		
-		}  else if (_stricmp(argv[i], HELP_CMDLINE_PARAM) == 0) {
-			/* Help parameter */
-			cout << "Pandora agent for Windows. ";
-			cout << "Version " << getPandoraAgentVersion () << endl;
-			cout << "Usage: " << argv[0] << " [OPTION]" << endl << endl;
-			cout << "Available options are:" << endl;
-			cout << "\t" << SERVICE_INSTALL_CMDLINE_PARAM;
-			cout <<	":   Install the Pandora Agent service." << endl;
-			cout << "\t" << SERVICE_UNINSTALL_CMDLINE_PARAM;
-			cout << ": Uninstall the Pandora Agent service." << endl;
-			cout << "\t" << SSH_TEST_CMDLINE_PARAM;
-			cout << ":  Test the SSH Pandora Agent configuration." << endl;
-			cout << "\t" << FTP_TEST_CMDLINE_PARAM;
-			cout << ":  Test the FTP Pandora Agent configuration." << endl;
-		
-			return 0;
-		} else {
-			/* No parameter recognized */
-			cout << "Pandora agent for Windows. ";
-			cout << "Version " << getPandoraAgentVersion () << endl;
-			cout << "Usage: " << argv[0] << " [" << SERVICE_INSTALL_CMDLINE_PARAM;
-			cout << "] [" << SERVICE_UNINSTALL_CMDLINE_PARAM;
-			cout << "] [" << SSH_TEST_CMDLINE_PARAM;
-			cout << "] [" << FTP_TEST_CMDLINE_PARAM << "]";
-			cout << endl << endl;
-			cout << "Run " << argv[0] << " with " << HELP_CMDLINE_PARAM;
-			cout << " parameter for more info." << endl;
-		
-			return 1;
-		}
-	}
-	service->run ();
-
-	delete service;
-
-	return 0;
-}
+/* Pandora Windows agent main file.
+
+   Copyright (C) 2006 Artica ST.
+   Written by Esteban Sanchez.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include "pandora.h"
+#include "pandora_windows_service.h"
+#include "ssh/pandora_ssh_test.h"
+#include "ftp/pandora_ftp_test.h"
+
+#define PATH_SIZE                         _MAX_PATH+1
+#define SERVICE_INSTALL_CMDLINE_PARAM    "--install"
+#define SERVICE_UNINSTALL_CMDLINE_PARAM  "--uninstall"
+#define SSH_TEST_CMDLINE_PARAM           "--test-ssh"
+#define FTP_TEST_CMDLINE_PARAM           "--test-ftp"
+#define HELP_CMDLINE_PARAM               "--help"
+
+int
+main (int argc, char *argv[]) {
+	Pandora_Windows_Service *service;
+	char                     buffer[PATH_SIZE];
+	string                   aux;
+	unsigned int             pos;
+
+	service = Pandora_Windows_Service::getInstance ();
+	service->setValues (Pandora::name, Pandora::display_name,
+			    Pandora::description);
+	service->start ();
+	
+	GetModuleFileName (NULL, buffer, MAX_PATH);
+	aux = buffer;
+	Pandora::setPandoraInstallPath (aux);
+	pos = aux.rfind ("\\");
+	aux.erase (pos + 1);
+	Pandora::setPandoraInstallDir (aux);
+
+	/* Check the parameters */
+	for (int i = 1; i < argc; i++) {
+		if (_stricmp(argv[i], SERVICE_INSTALL_CMDLINE_PARAM) == 0) {
+			/* Install parameter */
+			service->install (Pandora::getPandoraInstallPath ().c_str ());
+		
+			delete service;
+		
+			return 0;
+		} else if (_stricmp(argv[i], SERVICE_UNINSTALL_CMDLINE_PARAM) == 0) {
+			/* Uninstall parameter */
+			service->uninstall ();
+		
+			delete service;
+		
+			return 0;
+		} else if (_stricmp(argv[i], SSH_TEST_CMDLINE_PARAM) == 0) {
+			/* SSH test parameter */
+			SSH::Pandora_SSH_Test ssh_test;
+		
+			delete service;
+		
+			try {
+				ssh_test.test ();
+			} catch (Pandora_Exception e) {
+				return 1;
+			}
+			
+			return 0;
+		} else if (_stricmp(argv[i], FTP_TEST_CMDLINE_PARAM) == 0) {
+			/* SSH test parameter */
+			FTP::Pandora_FTP_Test ftp_test;
+			
+			delete service;
+		
+			try {
+				ftp_test.test ();
+			} catch (Pandora_Exception e) {
+				return 1;
+			}
+		
+			return 0;
+		
+		}  else if (_stricmp(argv[i], HELP_CMDLINE_PARAM) == 0) {
+			/* Help parameter */
+			cout << "Pandora agent for Windows. ";
+			cout << "Version " << getPandoraAgentVersion () << endl;
+			cout << "Usage: " << argv[0] << " [OPTION]" << endl << endl;
+			cout << "Available options are:" << endl;
+			cout << "\t" << SERVICE_INSTALL_CMDLINE_PARAM;
+			cout <<	":   Install the Pandora Agent service." << endl;
+			cout << "\t" << SERVICE_UNINSTALL_CMDLINE_PARAM;
+			cout << ": Uninstall the Pandora Agent service." << endl;
+			cout << "\t" << SSH_TEST_CMDLINE_PARAM;
+			cout << ":  Test the SSH Pandora Agent configuration." << endl;
+			cout << "\t" << FTP_TEST_CMDLINE_PARAM;
+			cout << ":  Test the FTP Pandora Agent configuration." << endl;
+		
+			return 0;
+		} else {
+			/* No parameter recognized */
+			cout << "Pandora agent for Windows. ";
+			cout << "Version " << getPandoraAgentVersion () << endl;
+			cout << "Usage: " << argv[0] << " [" << SERVICE_INSTALL_CMDLINE_PARAM;
+			cout << "] [" << SERVICE_UNINSTALL_CMDLINE_PARAM;
+			cout << "] [" << SSH_TEST_CMDLINE_PARAM;
+			cout << "] [" << FTP_TEST_CMDLINE_PARAM << "]";
+			cout << endl << endl;
+			cout << "Run " << argv[0] << " with " << HELP_CMDLINE_PARAM;
+			cout << " parameter for more info." << endl;
+		
+			return 1;
+		}
+	}
+	service->run ();
+
+	delete service;
+
+	return 0;
+}
diff --git a/pandora_agents/win32/modules/pandora_module.cc b/pandora_agents/win32/modules/pandora_module.cc
index f264617c4f..d18a38c63a 100644
--- a/pandora_agents/win32/modules/pandora_module.cc
+++ b/pandora_agents/win32/modules/pandora_module.cc
@@ -39,7 +39,8 @@ Pandora_Module::Pandora_Module (string name) {
 	this->module_interval = 1;
 	this->max             = 0;
 	this->min             = 0;
-	this->has_limits      = false;
+	this->has_limits      = false;
+	this->async           = false;
 	this->data_list       = NULL;
 }
 
@@ -175,6 +176,21 @@ Module_Kind
 Pandora_Module::getModuleKind () const {
 	return this->module_kind;
 }
+
+/** 
+ * Get the output of the module.
+ * 
+ * @return The module output in a string value.
+ */
+string
+Pandora_Module::getLatestOutput () const {
+	list<Pandora_Data *>::iterator iter;
+	
+	if (this->data_list == NULL)
+		return "";
+	iter = this->data_list->begin ();
+	return (*iter)->getValue ();
+}
 
 /** 
  * Get the type of the module in a integer_value.
@@ -222,7 +238,7 @@ Pandora_Module::getDataOutput (Pandora_Data *data) {
 		}
 	}
 	
-	return trim(data->getValue ());
+	return trim (data->getValue ());
 }
 
 /** 
@@ -351,15 +367,16 @@ Pandora_Module::getXml () {
 			data_element = new TiXmlElement ("data");
 			element = new TiXmlElement ("value");
 			try {
-		data_clean = strreplace (this->getDataOutput (data), "%", "%%" );
-	    } catch (Output_Error e) {
-	       		delete element;
-		continue;
-	    }
-
-	    text = new TiXmlText (data_clean);
-	    element->InsertEndChild (*text);
-	    data_element->InsertEndChild (*element);
+				data_clean = strreplace (this->getDataOutput (data),
+							 "%", "%%" );
+			} catch (Output_Error e) {
+		 		delete element;
+				continue;
+			}
+			
+			text = new TiXmlText (data_clean);
+			element->InsertEndChild (*text);
+			data_element->InsertEndChild (*element);
 			delete text;
 			delete element;
 			
@@ -379,11 +396,11 @@ Pandora_Module::getXml () {
 		data = data_list->front ();
 		element = new TiXmlElement ("data");
 		try {
-	    data_clean = strreplace (this->getDataOutput (data), "%", "%%" );
-	    text = new TiXmlText (data_clean);
-	    element->InsertEndChild (*text);
-	    root->InsertEndChild (*element);
-	    delete text;
+		data_clean = strreplace (this->getDataOutput (data), "%", "%%" );
+		text = new TiXmlText (data_clean);
+		element->InsertEndChild (*text);
+		root->InsertEndChild (*element);
+		delete text;
 	} catch (Output_Error e) {
 	}
 		delete element;
@@ -412,7 +429,7 @@ void
 Pandora_Module::setMax (int value) {
 	this->has_limits = true;
 	this->max        = value;
-}
+}
 
 /** 
  * Set the min value the module can have.
@@ -426,6 +443,19 @@ Pandora_Module::setMin (int value) {
 	this->has_limits = true;
 	this->min        = value;
 }
+
+/** 
+ * Set the async flag to the module.
+ *
+ * If a module is set to be async, it would try to works only when the
+ * events happen. Note that not all the modules can work in async mode.
+ *
+ * @param async Flag to set.
+ */
+void
+Pandora_Module::setAsync (bool async) {
+	this->async = async;
+}
 
 /** 
  * Set the module type from a string type.
diff --git a/pandora_agents/win32/modules/pandora_module.h b/pandora_agents/win32/modules/pandora_module.h
index 261e289155..213641eb23 100644
--- a/pandora_agents/win32/modules/pandora_module.h
+++ b/pandora_agents/win32/modules/pandora_module.h
@@ -80,7 +80,7 @@ namespace Pandora_Modules {
 	const string module_freememory_str = "module_freememory";
 	const string module_cpuusage_str   = "module_cpuusage";
 	const string module_odbc_str       = "module_odbc";
-	const string module_logevent_str       = "module_logevent";	
+	const string module_logevent_str   = "module_logevent";	
 
 	/**
 	 * Pandora module super-class exception.
@@ -134,7 +134,12 @@ namespace Pandora_Modules {
 		/**
 		 * The description of the module.
 		 */
-		string      module_description;
+		string      module_description;
+		
+		/**
+		 * Flag to set a module as asynchronous
+		 */
+		bool                  async;
 	public:
 		Pandora_Module                    (string name);
 		virtual ~Pandora_Module           ();
@@ -145,29 +150,32 @@ namespace Pandora_Modules {
 		static Module_Kind
 			parseModuleKindFromString (string kind);
 		
-		void               setInterval    (int interval);
-		int                getInterval    ();
+		void         setInterval   (int interval);
+		int          getInterval   ();
 		
-		TiXmlElement      *getXml         ();
+		TiXmlElement *getXml       ();
 		
-		virtual void       run            ();
+		virtual void run           ();
 		
-		virtual void       setOutput      (string output);
-	virtual void       setOutput      (string output, SYSTEMTIME *system_time);
+		virtual void setOutput     (string output);
+		virtual void setOutput     (string output,
+					    SYSTEMTIME *system_time);
 
 		
-		string             getName        () const;
-		string             getDescription () const;
-		string             getTypeString  () const;
-		Module_Type        getTypeInt     () const;
-		Module_Type        getModuleType  () const;
-		Module_Kind        getModuleKind  () const;
+		string      getName        () const;
+		string      getDescription () const;
+		string      getTypeString  () const;
+		string      getLatestOutput () const;
+		Module_Type getTypeInt     () const;
+		Module_Type getModuleType  () const;
+		Module_Kind getModuleKind  () const;
 		
-		void               setType        (string type);
-		void               setKind        (string kind);
-		void               setDescription (string description);
-		void               setMax         (int value);
-		void               setMin         (int value);
+		void        setType        (string type);
+		void        setKind        (string kind);
+		void        setDescription (string description);
+		void        setMax         (int value);
+		void        setMin         (int value);
+		void        setAsync       (bool async);
 	};
 }
 
diff --git a/pandora_agents/win32/modules/pandora_module_factory.cc b/pandora_agents/win32/modules/pandora_module_factory.cc
index 5e189fc8c1..004bef94cd 100644
--- a/pandora_agents/win32/modules/pandora_module_factory.cc
+++ b/pandora_agents/win32/modules/pandora_module_factory.cc
@@ -52,7 +52,8 @@ using namespace Pandora_Strutils;
 #define TOKEN_LOGEVENT    ("module_logevent")
 #define TOKEN_SOURCE      ("module_source ")
 #define TOKEN_EVENTTYPE   ("module_eventtype ")
-#define TOKEN_PATTERN     ("module_pattern ")
+#define TOKEN_PATTERN     ("module_pattern ")
+#define TOKEN_ASYNC       ("module_async")
 
 string
 parseLine (string line, string token) {
@@ -87,7 +88,8 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
 	string                 module_interval, module_proc, module_service;
 	string                 module_freedisk, module_cpuusage, module_odbc;
 	string                 module_odbc_query, module_dsn, module_freememory;
-    string                 module_logevent, module_source, module_eventtype, module_pattern;
+	string                 module_logevent, module_source, module_eventtype;
+	string                 module_pattern, module_async;
 	Pandora_Module        *module;
 	bool                   numeric;
 	Module_Type            type;
@@ -104,10 +106,10 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
 	module_odbc        = "";
 	module_odbc_query  = "";
 	module_odbc        = "";
-    module_logevent    = "";
-    module_source      = "";
-    module_eventtype   = "";
-    module_pattern     = "";
+	module_logevent    = "";
+	module_source      = "";
+	module_eventtype   = "";
+	module_pattern     = "";
 
 	stringtok (tokens, definition, "\n");
 	
@@ -160,18 +162,21 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
 		if (module_odbc_query == "") {
 			module_odbc_query = parseLine (line, TOKEN_ODBC_QUERY);
 		}
-	if (module_logevent == "") {
-	    module_logevent = parseLine (line, TOKEN_LOGEVENT);
-	}                
-	if (module_source == "") {
-	    module_source = parseLine (line, TOKEN_SOURCE);
-	}                
-	if (module_eventtype == "") {
-	    module_eventtype = parseLine (line, TOKEN_EVENTTYPE);
-	}                
-	if (module_pattern == "") {
-	    module_pattern = parseLine (line, TOKEN_PATTERN);
-	}                
+		if (module_logevent == "") {
+			module_logevent = parseLine (line, TOKEN_LOGEVENT);
+		}
+		if (module_source == "") {
+			module_source = parseLine (line, TOKEN_SOURCE);
+		}
+		if (module_eventtype == "") {
+			module_eventtype = parseLine (line, TOKEN_EVENTTYPE);
+		}
+		if (module_pattern == "") {
+			module_pattern = parseLine (line, TOKEN_PATTERN);
+		}
+		if (module_async == "") {
+			module_async = parseLine (line, TOKEN_ASYNC);
+		}
 		
 		iter++;
 	}
@@ -220,8 +225,12 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
 
 	if (module_description != "") {
 		module->setDescription (module_description);
-	}
-
+	}
+	
+	if (module_async != "") {
+		module->setAsync (true);
+	}
+	
 	type = Pandora_Module::parseModuleTypeFromString (module_type);
 	switch (type) {
 	case TYPE_GENERIC_DATA:
@@ -258,7 +267,7 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
 			}
 		}
 		if (module_min != "") {
-		       try {
+			try {
 				int value = strtoint (module_min);
 				
 				module->setMin (value);
diff --git a/pandora_agents/win32/modules/pandora_module_list.cc b/pandora_agents/win32/modules/pandora_module_list.cc
index 34bc06e3de..d3122c5952 100644
--- a/pandora_agents/win32/modules/pandora_module_list.cc
+++ b/pandora_agents/win32/modules/pandora_module_list.cc
@@ -80,8 +80,26 @@ Pandora_Modules::Pandora_Module_List::Pandora_Module_List (string filename) {
 	file.close ();
 	
 	current = new std::list<Pandora_Module *>::iterator ();
-	*current = modules->begin ();
-}
+	(*current) = modules->begin ();
+}
+
+/** 
+ * Creates an empty module list object.
+ */
+Pandora_Modules::Pandora_Module_List::Pandora_Module_List () {
+	this->modules = new list<Pandora_Module *> ();
+	current = new std::list<Pandora_Module *>::iterator ();
+	(*current) = modules->begin ();
+}
+
+/** 
+ * Adds a module object to a list object.
+ */
+void
+Pandora_Modules::Pandora_Module_List::addModule (Pandora_Module *module) {
+	modules->push_back (module);
+}
+
 
 /** 
  * Destroy the list.
diff --git a/pandora_agents/win32/modules/pandora_module_list.h b/pandora_agents/win32/modules/pandora_module_list.h
index 6c83289ae5..68c92ebdc8 100644
--- a/pandora_agents/win32/modules/pandora_module_list.h
+++ b/pandora_agents/win32/modules/pandora_module_list.h
@@ -42,11 +42,15 @@ namespace Pandora_Modules {
 		list<Pandora_Module *>::iterator *current;
 		void             parseModuleDefinition (string definition);
 	public:
-		Pandora_Module_List                    (string filename);
+		Pandora_Module_List                    (string filename);
+		Pandora_Module_List                    ();
 		
 		~Pandora_Module_List                   ();
 		
 		Pandora_Module * getCurrentValue       ();
+		
+		/* Add a module to the list */
+		void             addModule             (Pandora_Module *module);
 		
 		/* Move to the first element of the list */
 		void             goFirst               ();
diff --git a/pandora_agents/win32/modules/pandora_module_service.cc b/pandora_agents/win32/modules/pandora_module_service.cc
index 06166b249e..6364434cc1 100644
--- a/pandora_agents/win32/modules/pandora_module_service.cc
+++ b/pandora_agents/win32/modules/pandora_module_service.cc
@@ -19,9 +19,11 @@
    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */
 
-#include "pandora_module_service.h"
+#include "pandora_module_service.h"
+#include "pandora_module_list.h"
 #include "../windows/pandora_wmi.h"
-#include "../pandora_strutils.h"
+#include "../pandora_strutils.h"
+#include "../pandora_windows_service.h"
 #include <algorithm>
 #include <cctype>
 
@@ -43,8 +45,84 @@ Pandora_Module_Service::Pandora_Module_Service (string name, string service_name
 	transform (service_name.begin (), service_name.end (),
 		   this->service_name.begin (), (int (*) (int)) tolower);
 	
-	this->setKind (module_service_str);
+	this->setKind (module_service_str);
+	this->thread = 0;
 }
+
+string
+Pandora_Module_Service::getServiceName () const {
+	return this->service_name;
+}
+
+#define BUFFER_SIZE (16384)
+
+void
+async_run (Pandora_Module_Service *module) {
+	HANDLE                   event_log;
+	HANDLE                   event;
+	DWORD                    result;
+	int                      res;
+	string                   str_res;
+	BYTE                     buffer[BUFFER_SIZE];
+	EVENTLOGRECORD          *record;
+	DWORD                    read;
+	DWORD                    needed;
+	int                     event_id;
+	bool                     service_event;
+	string                   prev_res;
+	Pandora_Module_List     *modules;
+	
+	prev_res = module->getLatestOutput ();
+	modules = new Pandora_Module_List ();
+	modules->addModule (module);
+	
+	while (1) {
+		event_log = OpenEventLog (NULL, "Service Control Manager");
+		if (event_log == NULL) {
+			pandoraLog ("Could not open event log for %s.",
+				    module->getServiceName ().c_str ());
+			return;
+		}
+		event = CreateEvent (NULL, FALSE, FALSE, NULL);
+		NotifyChangeEventLog (event_log, event);
+		result = WaitForSingleObject (event, 10000);
+		
+		if (result == 0) {
+			service_event = false;
+			record = (EVENTLOGRECORD *) buffer;
+			
+			while (ReadEventLog (event_log,	
+				EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ,
+				0, record, BUFFER_SIZE, &read, &needed)) {
+				
+				if (record->EventType != EVENTLOG_INFORMATION_TYPE)
+					continue;
+				event_id = record->EventID & 0x0000ffff;
+				
+				/* Those numbers are the code for service start/stopping */
+				if (event_id == 7035 || event_id == 7036) {
+					service_event = true;
+					break;
+				}
+			}
+			
+			if (service_event) {
+				res = Pandora_Wmi::isServiceRunning (module->getServiceName ());
+				str_res = inttostr (res);
+				if (str_res != prev_res) {
+					module->setOutput (str_res);
+					prev_res = str_res;
+					pandoraLog ("Service \"%s\" changed status to: %d",
+						module->getServiceName ().c_str (), res);
+					Pandora_Windows_Service::getInstance ()->sendXml (modules);
+				}
+			}
+		}
+		CloseHandle (event);
+		CloseEventLog (event_log);
+	}
+	delete modules;
+}
 
 void
 Pandora_Module_Service::run () {
@@ -57,5 +135,13 @@ Pandora_Module_Service::run () {
 	}
 	
 	res = Pandora_Wmi::isServiceRunning (this->service_name);
-	this->setOutput (inttostr (res));
+	this->setOutput (inttostr (res));
+	
+	/* Launch thread if it's asynchronous */
+	if (this->async) {
+		this->thread = CreateThread (NULL, 0,
+					     (LPTHREAD_START_ROUTINE) async_run,
+					     this, 0, NULL);
+		this->async = false;
+	}
 }
diff --git a/pandora_agents/win32/modules/pandora_module_service.h b/pandora_agents/win32/modules/pandora_module_service.h
index 8506eba091..3cb1101a91 100644
--- a/pandora_agents/win32/modules/pandora_module_service.h
+++ b/pandora_agents/win32/modules/pandora_module_service.h
@@ -31,11 +31,13 @@ namespace Pandora_Modules {
 	 */
 	class Pandora_Module_Service : public Pandora_Module {
 	private:
-		string service_name;
+		string service_name;
+		HANDLE thread;
 	public:
 		Pandora_Module_Service (string name, string service_name);
 		
-		void   run             ();
+		void   run               ();
+		string getServiceName    () const;
 	};
 }
 
diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc
index 7a74a88d03..dca3fd74fb 100644
--- a/pandora_agents/win32/pandora.cc
+++ b/pandora_agents/win32/pandora.cc
@@ -1,274 +1,274 @@
-/* Common functions to any Pandora program.
-   Copyright (C) 2006 Artica ST.
-   Written by Esteban Sanchez.
-   
-   This program is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-  
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
-  
-   You should have received a copy of the GNU General Public License along
-   with this program; if not, write to the Free Software Foundation,
-   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-
-#include <stdio.h>
-#include <iostream>
-#include <cctype>
-#include <string>
-#include <algorithm>
-#include "pandora.h"
-#include "pandora_strutils.h"
-
-using namespace std;
-using namespace Pandora;
-using namespace Pandora_Strutils;
-
-#define PATH_SIZE    _MAX_PATH+1
-#define PANDORA_VERSION ("2.0(Build 080610)")
-
-string pandora_path;
-string pandora_dir;
-bool   pandora_debug;
-string pandora_version = PANDORA_VERSION;
-
-/**
- * Parses a string and initialize the key and the value.
- * 
- * The string should be in the format:
- *  - <code>key value</code>
- *  - <code>key "value with blankspaces"</code>
- */
-void
-Key_Value::parseLine (string str) {
-	unsigned int           pos;
-	list<string>           tokens;
-	list<string>::iterator iter;
-	string                 trimmedstr;
-        
-	trimmedstr = trim (str);
-        
-/* Check if the string has " */
-	pos = trimmedstr.find ("\"");
-	if (pos == string::npos) {
-		stringtok (tokens, trimmedstr, " \t");
-	} else {
-		stringtok (tokens, trimmedstr, "\"");
-	}
-        
-/* Pick the first and the last value of the token list */
-	iter = tokens.begin ();
-	key = trim (*iter);
-	transform (key.begin(), key.end(), key.begin(), (int(*)(int)) tolower);
-	iter = tokens.end ();
-	iter--;
-/* Check if the line has only one token */
-	if (iter != tokens.begin ()) {
-		value = trim (*iter);
-	} else {
-		value = "";
-	}
-}
-
-/**
- * Get the key of the object.
- * 
- * @return The key
- */
-string
-Key_Value::getKey () {
-	return key;
-}
-
-/**
- * Get the value of the object.
- * 
- * @return The value
- */
-string
-Key_Value::getValue () {
-	return value;
-}
-
-void
-pandoraWriteLog (string filename, string line) {
-	string     buffer; 
-	char       str_time[25];
-	FILE      *file;
-	string     filepath;
-	SYSTEMTIME st;
-        
-	GetSystemTime(&st);
-    sprintf (str_time, "%d-%02d-%02d %02d:%02d:%02d ", st.wYear, st.wMonth, st.wDay,
-             st.wHour, st.wMinute, st.wSecond);
-        
-	buffer = (char *) str_time;
-	buffer += line;
-        
-	filepath = pandora_dir + filename;
-        
-	file = fopen (filepath.c_str (), "a+");
-	if (file != NULL) {
-		fprintf (file, "%s\n", buffer.c_str ());
-		fclose (file);
-	}
-}
-
-/**
- * Write a message in the log file.
- *
- * The log file is used to write the output of errors and problems of the
- * agent.
- *
- * @param format String output format (like printf).
- * @param ... Variable argument list
- */
-void
-Pandora::pandoraLog (char *format, ...) {
-	va_list    args;
-	char       msg[5000];
-        
-	va_start (args, format);
-	vsprintf (msg, format, args);
-	va_end (args);
-        
-	pandoraWriteLog ("pandora_agent.log", (char *) msg);
-}
-
-/**
- * Write a message in the debug file.
- *
- * The log file is used to write the output of debugging information of the
- * agent.
- *
- * @param format String output format.
- * @param ... Variable argument list
- */
-void
-Pandora::pandoraDebug (char *format, ...) {
-	if (pandora_debug) {
-		va_list    args;
-		char       msg[5000];
-                
-		va_start (args, format);
-		vsprintf (msg, format, args);
-		va_end (args);
-                
-		pandoraWriteLog ("pandora_debug.log", (char *) msg);
-	}
-	return;
-}
-
-/**
- * Secure free of a pointer.
- *
- * @param pointer pointer to free.
- */
-void
-Pandora::pandoraFree (void * pointer) {
-	if (pointer != NULL)
-		free (pointer);
-	return;       
-}
-
-/**
- * Set the installation directory of the application.
- *
- * This directory is the path to the directory which holds
- * the binary file.
- *
- * @param dir The path to the directory. 
- *
- * @see getPandoraInstallDir
- */
-void
-Pandora::setPandoraInstallDir (string dir) {
-	pandora_dir = dir;
-}
-
-/**
- * Get the installation directory of the application.
- *
- * This directory is the path to the directory which holds
- * the binary file.
- *
- * @return The path to the directory.
- *
- * @see setPandoraInstallDir
- */
-string
-Pandora::getPandoraInstallDir () {
-	return pandora_dir;
-}
-
-/**
- * Set the installation path of the application.
- *
- * This the complete path to the binary file.
- *
- * @param path The path to the binary file. 
- *
- * @see getPandoraInstallPath
- */
-void
-Pandora::setPandoraInstallPath (string path) {
-	pandora_path = path;
-}
-
-/**
- * Get the installation path of the application.
- *
- * This the complete path to the binary file.
- *
- * @return The path.
- *
- * @see setPandoraInstallPath
- */
-string
-Pandora::getPandoraInstallPath () {
-	return pandora_path;
-}
-
-/**
- * Set the debug flag.
- *
- * If the flag is true output wil be generated and XML files will not be deleted.
- *
- * @param dbg Turns the debug flag on/off.
- * 
- * @see getPandoraDebug
- * @see pandoraDebug
- */
-void
-Pandora::setPandoraDebug  (bool dbg) {
-	pandora_debug = dbg;
-}
-
-/**
- * Get the debug flag value.
- *
- * If the flag is truee output wil be generated and XML files will not be deleted.
- *
- * @see setPandoraDebug
- * @see pandoraDebug
- */
-bool
-Pandora::getPandoraDebug  () {
-	return pandora_debug;
-}
-
-
-/**
- * Get the version of the agent.
- *
- * @return The version.
- */
-string
-Pandora::getPandoraAgentVersion () {
-	return pandora_version;
-}
+/* Common functions to any Pandora program.
+   Copyright (C) 2006 Artica ST.
+   Written by Esteban Sanchez.
+   
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2, or (at your option)
+   any later version.
+  
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+  
+   You should have received a copy of the GNU General Public License along
+   with this program; if not, write to the Free Software Foundation,
+   Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+#include <stdio.h>
+#include <iostream>
+#include <cctype>
+#include <string>
+#include <algorithm>
+#include "pandora.h"
+#include "pandora_strutils.h"
+
+using namespace std;
+using namespace Pandora;
+using namespace Pandora_Strutils;
+
+#define PATH_SIZE    _MAX_PATH+1
+#define PANDORA_VERSION ("2.0(Build 080610)")
+
+string pandora_path;
+string pandora_dir;
+bool   pandora_debug;
+string pandora_version = PANDORA_VERSION;
+
+/**
+ * Parses a string and initialize the key and the value.
+ * 
+ * The string should be in the format:
+ *  - <code>key value</code>
+ *  - <code>key "value with blankspaces"</code>
+ */
+void
+Key_Value::parseLine (string str) {
+	unsigned int           pos;
+	list<string>           tokens;
+	list<string>::iterator iter;
+	string                 trimmedstr;
+        
+	trimmedstr = trim (str);
+        
+/* Check if the string has " */
+	pos = trimmedstr.find ("\"");
+	if (pos == string::npos) {
+		stringtok (tokens, trimmedstr, " \t");
+	} else {
+		stringtok (tokens, trimmedstr, "\"");
+	}
+        
+/* Pick the first and the last value of the token list */
+	iter = tokens.begin ();
+	key = trim (*iter);
+	transform (key.begin(), key.end(), key.begin(), (int(*)(int)) tolower);
+	iter = tokens.end ();
+	iter--;
+/* Check if the line has only one token */
+	if (iter != tokens.begin ()) {
+		value = trim (*iter);
+	} else {
+		value = "";
+	}
+}
+
+/**
+ * Get the key of the object.
+ * 
+ * @return The key
+ */
+string
+Key_Value::getKey () {
+	return key;
+}
+
+/**
+ * Get the value of the object.
+ * 
+ * @return The value
+ */
+string
+Key_Value::getValue () {
+	return value;
+}
+
+void
+pandoraWriteLog (string filename, string line) {
+	string     buffer; 
+	char       str_time[25];
+	FILE      *file;
+	string     filepath;
+	SYSTEMTIME st;
+        
+	GetSystemTime(&st);
+    sprintf (str_time, "%d-%02d-%02d %02d:%02d:%02d ", st.wYear, st.wMonth, st.wDay,
+             st.wHour, st.wMinute, st.wSecond);
+        
+	buffer = (char *) str_time;
+	buffer += line;
+        
+	filepath = pandora_dir + filename;
+        
+	file = fopen (filepath.c_str (), "a+");
+	if (file != NULL) {
+		fprintf (file, "%s\n", buffer.c_str ());
+		fclose (file);
+	}
+}
+
+/**
+ * Write a message in the log file.
+ *
+ * The log file is used to write the output of errors and problems of the
+ * agent.
+ *
+ * @param format String output format (like printf).
+ * @param ... Variable argument list
+ */
+void
+Pandora::pandoraLog (char *format, ...) {
+	va_list    args;
+	char       msg[5000];
+        
+	va_start (args, format);
+	vsprintf (msg, format, args);
+	va_end (args);
+        
+	pandoraWriteLog ("pandora_agent.log", (char *) msg);
+}
+
+/**
+ * Write a message in the debug file.
+ *
+ * The log file is used to write the output of debugging information of the
+ * agent.
+ *
+ * @param format String output format.
+ * @param ... Variable argument list
+ */
+void
+Pandora::pandoraDebug (char *format, ...) {
+	if (pandora_debug) {
+		va_list    args;
+		char       msg[5000];
+                
+		va_start (args, format);
+		vsprintf (msg, format, args);
+		va_end (args);
+                
+		pandoraWriteLog ("pandora_debug.log", (char *) msg);
+	}
+	return;
+}
+
+/**
+ * Secure free of a pointer.
+ *
+ * @param pointer pointer to free.
+ */
+void
+Pandora::pandoraFree (void * pointer) {
+	if (pointer != NULL)
+		free (pointer);
+	return;       
+}
+
+/**
+ * Set the installation directory of the application.
+ *
+ * This directory is the path to the directory which holds
+ * the binary file.
+ *
+ * @param dir The path to the directory. 
+ *
+ * @see getPandoraInstallDir
+ */
+void
+Pandora::setPandoraInstallDir (string dir) {
+	pandora_dir = dir;
+}
+
+/**
+ * Get the installation directory of the application.
+ *
+ * This directory is the path to the directory which holds
+ * the binary file.
+ *
+ * @return The path to the directory.
+ *
+ * @see setPandoraInstallDir
+ */
+string
+Pandora::getPandoraInstallDir () {
+	return pandora_dir;
+}
+
+/**
+ * Set the installation path of the application.
+ *
+ * This the complete path to the binary file.
+ *
+ * @param path The path to the binary file. 
+ *
+ * @see getPandoraInstallPath
+ */
+void
+Pandora::setPandoraInstallPath (string path) {
+	pandora_path = path;
+}
+
+/**
+ * Get the installation path of the application.
+ *
+ * This the complete path to the binary file.
+ *
+ * @return The path.
+ *
+ * @see setPandoraInstallPath
+ */
+string
+Pandora::getPandoraInstallPath () {
+	return pandora_path;
+}
+
+/**
+ * Set the debug flag.
+ *
+ * If the flag is true output wil be generated and XML files will not be deleted.
+ *
+ * @param dbg Turns the debug flag on/off.
+ * 
+ * @see getPandoraDebug
+ * @see pandoraDebug
+ */
+void
+Pandora::setPandoraDebug  (bool dbg) {
+	pandora_debug = dbg;
+}
+
+/**
+ * Get the debug flag value.
+ *
+ * If the flag is truee output wil be generated and XML files will not be deleted.
+ *
+ * @see setPandoraDebug
+ * @see pandoraDebug
+ */
+bool
+Pandora::getPandoraDebug  () {
+	return pandora_debug;
+}
+
+
+/**
+ * Get the version of the agent.
+ *
+ * @return The version.
+ */
+string
+Pandora::getPandoraAgentVersion () {
+	return pandora_version;
+}
diff --git a/pandora_agents/win32/pandora_windows_service.cc b/pandora_agents/win32/pandora_windows_service.cc
index bad9f92c5c..61c304dda3 100644
--- a/pandora_agents/win32/pandora_windows_service.cc
+++ b/pandora_agents/win32/pandora_windows_service.cc
@@ -39,24 +39,31 @@ using namespace Pandora_Modules;
 using namespace Pandora_Strutils;
 
 string enabled_values[] = {"enabled", "1", "on", "yes", "si", "sí", "ok", ""};
+
+Pandora_Windows_Service::Pandora_Windows_Service ()
+  : Windows_Service (NULL, NULL, NULL) {
+	this->setInitFunction ((void (Windows_Service::*) ())
+			       &Pandora_Windows_Service::pandora_init);
+	this->setRunFunction ((void (Windows_Service::*) ())
+			      &Pandora_Windows_Service::pandora_run);
+	this->started = false;
+}
 
 /** 
- * Creates a new Pandora_Windows_Service.
+ * Set Pandora service Windows properties.
  * 
  * @param svc_name Internal service name
  * @param svc_display_name Service name that will appear in the
  *        Windows service administration tool.
  * @param svc_description Long description of the service.
- */
-Pandora_Windows_Service::Pandora_Windows_Service (const char * svc_name,
-						  const char * svc_display_name,
-						  const char * svc_description)
-  : Windows_Service (svc_name, svc_display_name, svc_description) {
-	this->setInitFunction ((void (Windows_Service::*) ())
-			       &Pandora_Windows_Service::pandora_init);
-	this->setRunFunction ((void (Windows_Service::*) ())
-			      &Pandora_Windows_Service::pandora_run);
-	
+ */
+void
+Pandora_Windows_Service::setValues (const char * svc_name,
+				    const char * svc_display_name,
+				    const char * svc_description) {
+	this->service_name          = (char *) svc_name;
+	this->service_display_name  = (char *) svc_display_name;
+	this->service_description   = (char *) svc_description;
 	execution_number            = 0;
 	this->modules               = NULL;
 	this->conf                  = NULL;
@@ -78,6 +85,23 @@ Pandora_Windows_Service::~Pandora_Windows_Service () {
 	}
 	pandoraLog ("Pandora agent stopped");
 }
+
+Pandora_Windows_Service *
+Pandora_Windows_Service::getInstance () {
+	static Pandora_Windows_Service *service = NULL;
+	
+	if (service != NULL)
+		return service;
+	
+	service = new Pandora_Windows_Service ();
+	
+	return service;
+}
+
+void
+Pandora_Windows_Service::start () {
+	this->started = true;
+}
 
 bool
 is_enabled (string value) {
@@ -161,7 +185,7 @@ Pandora_Windows_Service::getXmlHeader () {
 	
 	// Get current time
 	ctime = time(0);
-    ctime_tm = localtime(&ctime);
+	ctime_tm = localtime(&ctime);
 
 	sprintf (timestamp, "%d-%02d-%02d %02d:%02d:%02d", ctime_tm->tm_year + 1900,
 		ctime_tm->tm_mon + 1,	ctime_tm->tm_mday, ctime_tm->tm_hour,
@@ -589,7 +613,7 @@ Pandora_Windows_Service::checkConfig () {
 		Pandora_File::removeFile (tmp);
 		/* Save new configuration */
 		Pandora_File::writeBinFile (conf_file, conf_str, conf_size);
-	} catch (...) {		
+	} catch (...) {
 		pandoraDebug("Pandora_Windows_Service::checkConfig: Error retrieving configuration file from server");
 		if (conf_str != NULL) {
 			delete[] conf_str;
@@ -602,17 +626,95 @@ Pandora_Windows_Service::checkConfig () {
 	/* Reload configuration */
 	this->pandora_init ();
 }
+
+void
+Pandora_Windows_Service::sendXml (Pandora_Module_List *modules) {
+	TiXmlDeclaration *decl;
+	TiXmlDocument    *doc;
+	TiXmlElement     *local_xml, *agent;
+	string            xml_filename, random_integer;
+	string            tmp_filename, tmp_filepath;
+	string            encoding;
+	bool              saved;
+	static HANDLE     mutex = 0; 
+	
+	if (mutex == 0) {
+		mutex = CreateMutex (NULL, FALSE, NULL);
+	}
+	/* Wait for the mutex to be opened */
+	WaitForSingleObject (mutex, INFINITE);
+
+	pandoraLog ("aasdfasdf");
+	agent = getXmlHeader ();
+	
+	if (modules != NULL) {
+		modules->goFirst ();
+	
+		while (! modules->isLast ()) {
+			Pandora_Module *module;
+			
+			module = modules->getCurrentValue ();
+			
+			local_xml = module->getXml ();
+			if (local_xml != NULL) {
+				agent->InsertEndChild (*local_xml);
+			
+				delete local_xml;
+			}
+			modules->goNext ();
+		}
+	}
+	
+	/* Generate temporal filename */
+	random_integer = inttostr (rand());
+	tmp_filename = conf->getValue ("agent_name");
+	if (tmp_filename == "") {
+		tmp_filename = Pandora_Windows_Info::getSystemName ();
+	}
+	tmp_filename += "." + random_integer + ".data";
+
+	xml_filename = conf->getValue ("temporal");
+	if (xml_filename[xml_filename.length () - 1] != '\\') {
+		xml_filename += "\\";
+	}
+	tmp_filepath = xml_filename + tmp_filename;
+
+	/* Copy the XML to temporal file */
+	encoding = conf->getValue ("encoding");
+	if (encoding == "") {
+		encoding = "ISO-8859-1";
+	}
+
+	pandoraDebug ("Copying XML on %s", tmp_filepath.c_str ());
+	decl = new TiXmlDeclaration( "1.0", encoding.c_str(), "" );
+	doc = new TiXmlDocument (tmp_filepath);
+	doc->InsertEndChild (*decl);
+	doc->InsertEndChild (*agent);
+	saved = doc->SaveFile();
+	delete doc;
+	delete agent;
+
+	if (!saved) {
+		pandoraLog ("Error when saving the XML in %s",
+			    tmp_filepath.c_str ());
+		return;
+	}
+
+	/* Only send if debug is not activated */
+	if (getPandoraDebug () == false) {
+		this->copyDataFile (tmp_filename);
+	
+		try {
+			Pandora_File::removeFile (tmp_filepath);
+		} catch (Pandora_File::Delete_Error e) {
+		}
+	}
+	
+	ReleaseMutex (mutex);
+}
 
 void
 Pandora_Windows_Service::pandora_run () {
-	TiXmlDeclaration *decl;    
-	TiXmlDocument *doc;
-	TiXmlElement  *local_xml, *agent;
-	string         xml_filename, random_integer;
-	string         tmp_filename, tmp_filepath;
-	string encoding;
-	bool           saved;
-
 	pandoraDebug ("Run begin");
 	
 	/* Check for configuration changes */
@@ -635,74 +737,12 @@ Pandora_Windows_Service::pandora_run () {
 		}
 	}
 
-	this->elapsed_transfer_time += interval;
-
+	this->elapsed_transfer_time += this->interval;
+	
 	if (this->elapsed_transfer_time >= this->transfer_interval) {
-		agent = getXmlHeader ();
-	
-		if (this->modules != NULL) {
-			this->modules->goFirst ();
-		
-			while (! this->modules->isLast ()) {
-				Pandora_Module *module;
-			
-				module = this->modules->getCurrentValue ();
-			
-				local_xml = module->getXml ();
-				if (local_xml != NULL) {
-					agent->InsertEndChild (*local_xml);
-				
-					delete local_xml;
-				}
-				this->modules->goNext ();
-			}
-		}
-	
-		this->elapsed_transfer_time = 0;
-		/* Generate temporal filename */
-		random_integer = inttostr (rand());
-		tmp_filename = conf->getValue ("agent_name");
-		if (tmp_filename == "") {
-			tmp_filename = Pandora_Windows_Info::getSystemName ();
-		}
-		tmp_filename += "." + random_integer + ".data";
-	
-		xml_filename = conf->getValue ("temporal");
-		if (xml_filename[xml_filename.length () - 1] != '\\') {
-			xml_filename += "\\";
-		}
-		tmp_filepath = xml_filename + tmp_filename;
-	
-		/* Copy the XML to temporal file */
-		encoding = conf->getValue ("encoding");
-		if (encoding == "") {
-			encoding = "ISO-8859-1";
-		}
-	
-		pandoraDebug ("Copying XML on %s", tmp_filepath.c_str ());
-		decl = new TiXmlDeclaration( "1.0", encoding.c_str(), "" );
-		doc = new TiXmlDocument (tmp_filepath);
-		doc->InsertEndChild (*decl);			
-		doc->InsertEndChild (*agent);
-		saved = doc->SaveFile();
-		delete doc;
-		delete agent;
-	
-		if (!saved) {
-			pandoraLog ("Error when saving the XML in %s",
-				    tmp_filepath.c_str ());
-			return;
-		}
-	
-		/* Only send if debug is not activated */
-		if (getPandoraDebug () == false) {
-			this->copyDataFile (tmp_filename);
-		
-			try {
-				Pandora_File::removeFile (tmp_filepath);
-			} catch (Pandora_File::Delete_Error e) {
-			}
-		}
+		this->elapsed_transfer_time = 0;
+		
+		this->sendXml (this->modules);
 	}
 	
 	/* Get the interval value (in minutes) */
diff --git a/pandora_agents/win32/pandora_windows_service.h b/pandora_agents/win32/pandora_windows_service.h
index e5119c0f2d..3e6d29f3bf 100644
--- a/pandora_agents/win32/pandora_windows_service.h
+++ b/pandora_agents/win32/pandora_windows_service.h
@@ -43,7 +43,8 @@ namespace Pandora {
 		string               agent_name;
 		long                 interval;
 		long                 elapsed_transfer_time;
-		long                 transfer_interval;
+		long                 transfer_interval;
+		bool                 started;
 		
 		TiXmlElement  *getXmlHeader    ();
 		void           copyDataFile    (string filename);
@@ -58,15 +59,23 @@ namespace Pandora {
 		void           recvDataFile (string filename);
 		void           recvTentacleDataFile (string host,
 						     string filename);
-		void           checkConfig ();
+		void           checkConfig ();
+		
+		Pandora_Windows_Service     ();
 	public:
 		void           pandora_run  ();
 		void           pandora_init ();
-	public:
-		Pandora_Windows_Service     (const char * svc_name,
-					     const char * svc_display_name,
-					     const char * svc_description);
-		~Pandora_Windows_Service    ();
+	public:
+		static Pandora_Windows_Service *getInstance ();
+		
+		~Pandora_Windows_Service    ();
+		
+		void           setValues    (const char *svc_name,
+					     const char *svc_display_name,
+					     const char *svc_description);
+		
+		void           start        ();
+		void           sendXml      (Pandora_Module_List *modules);
 	};
 }
 
diff --git a/pandora_agents/win32/windows/pandora_wmi.cc b/pandora_agents/win32/windows/pandora_wmi.cc
index 736ac071e7..e60c9411cd 100644
--- a/pandora_agents/win32/windows/pandora_wmi.cc
+++ b/pandora_agents/win32/windows/pandora_wmi.cc
@@ -64,7 +64,7 @@ Pandora_Wmi::isProcessRunning (string process_name) {
 
 	query = "SELECT * FROM Win32_Process WHERE Name=\"" + process_name + "\"";
 	
-	try {	
+	try {
 		dhCheck (dhGetObject (getWmiStr (L"."), NULL, &wmi_svc));
 		dhCheck (dhGetValue (L"%o", &quickfixes, wmi_svc,
 				     L".ExecQuery(%T)",
@@ -99,7 +99,7 @@ Pandora_Wmi::isServiceRunning (string service_name) {
 
 	query = "SELECT * FROM Win32_Service WHERE Name = \"" + service_name + "\"";
 
-	try {	
+	try {
 		dhCheck (dhGetObject (getWmiStr (L"."), NULL, &wmi_svc));
 		dhCheck (dhGetValue (L"%o", &quickfixes, wmi_svc,
 				     L".ExecQuery(%T)",
diff --git a/pandora_agents/win32/windows_service.h b/pandora_agents/win32/windows_service.h
index 20b499e81a..38c1a77a7b 100644
--- a/pandora_agents/win32/windows_service.h
+++ b/pandora_agents/win32/windows_service.h
@@ -35,10 +35,11 @@
  * Notice: A program should have only one object of this class.
  */
 class Windows_Service {
-private:
+protected:
 	char     *service_name;
 	char     *service_display_name;
-	char     *service_description;
+	char     *service_description;
+private:
 	HANDLE    stop_event;
 	int       sleep_time;
 	SC_HANDLE sc_service;