2008-12-01 Esteban Sanchez <estebans@artica.es>

* pandora_windows_service.cc: Removed debug output. Release mutex on
        sendXml()

        * modules/pandora_module.[cc,h]: Save latest output in a new property.
        It's used on generic_proc modules to check the value better.

        * modules/pandora_module_proc.[cc,h]: Added support for asynchronous
        mode. It checks process in a separeted thread and report the status
        quicker. Added getProcessName()

        * modules/pandora_module_service.cc: Style correction. Removed an
        indentation level.

        * windows/pandora_windows_info.[cc,h]: Added getProcessHandles() to
        get a list of handles of a running process, giving the process name.




git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@1270 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
This commit is contained in:
Esteban Sanchez 2008-12-01 13:40:19 +00:00
parent 9843334767
commit 0059aad758
10 changed files with 239 additions and 86 deletions

View File

@ -1,3 +1,21 @@
2008-12-01 Esteban Sanchez <estebans@artica.es>
* pandora_windows_service.cc: Removed debug output. Release mutex on
sendXml()
* modules/pandora_module.[cc,h]: Save latest output in a new property.
It's used on generic_proc modules to check the value better.
* modules/pandora_module_proc.[cc,h]: Added support for asynchronous
mode. It checks process in a separeted thread and report the status
quicker. Added getProcessName()
* modules/pandora_module_service.cc: Style correction. Removed an
indentation level.
* windows/pandora_windows_info.[cc,h]: Added getProcessHandles() to
get a list of handles of a running process, giving the process name.
2008-11-28 Esteban Sanchez <estebans@artica.es> 2008-11-28 Esteban Sanchez <estebans@artica.es>
* modules/pandora_module.[cc,h]: Added an async property. Added * modules/pandora_module.[cc,h]: Added an async property. Added

View File

@ -184,12 +184,7 @@ Pandora_Module::getModuleKind () const {
*/ */
string string
Pandora_Module::getLatestOutput () const { Pandora_Module::getLatestOutput () const {
list<Pandora_Data *>::iterator iter; return this->latest_output;
if (this->data_list == NULL)
return "";
iter = this->data_list->begin ();
return (*iter)->getValue ();
} }
/** /**
@ -257,6 +252,7 @@ Pandora_Module::setOutput (string output) {
this->data_list = new list<Pandora_Data *> (); this->data_list = new list<Pandora_Data *> ();
data = new Pandora_Data (output); data = new Pandora_Data (output);
this->data_list->push_back (data); this->data_list->push_back (data);
this->latest_output = output;
} }
/** /**

View File

@ -118,6 +118,7 @@ namespace Pandora_Modules {
string module_kind_str; string module_kind_str;
Module_Kind module_kind; Module_Kind module_kind;
list<Pandora_Data *> *data_list; list<Pandora_Data *> *data_list;
string latest_output;
string getDataOutput (Pandora_Data *data); string getDataOutput (Pandora_Data *data);
void cleanDataList (); void cleanDataList ();

View File

@ -19,14 +19,18 @@
*/ */
#include "pandora_module_proc.h" #include "pandora_module_proc.h"
#include "pandora_module_list.h"
#include "../windows/pandora_wmi.h" #include "../windows/pandora_wmi.h"
#include "../windows/pandora_windows_info.h"
#include "../pandora_strutils.h" #include "../pandora_strutils.h"
#include "../pandora_windows_service.h"
#include <algorithm> #include <algorithm>
#include <cctype> #include <cctype>
using namespace Pandora; using namespace Pandora;
using namespace Pandora_Modules; using namespace Pandora_Modules;
using namespace Pandora_Strutils; using namespace Pandora_Strutils;
using namespace Pandora_Windows_Info;
/** /**
* Creates a Pandora_Module_Proc object. * Creates a Pandora_Module_Proc object.
@ -44,6 +48,73 @@ Pandora_Module_Proc::Pandora_Module_Proc (string name, string process_name)
this->setKind (module_proc_str); this->setKind (module_proc_str);
} }
string
Pandora_Module_Proc::getProcessName () const {
return this->process_name;
}
void
async_run (Pandora_Module_Proc *module) {
HANDLE *processes = NULL;
int nprocess;
DWORD result;
Pandora_Module_List *modules;
string str_res;
string prev_res;
int res;
int i;
prev_res = module->getLatestOutput ();
modules = new Pandora_Module_List ();
modules->addModule (module);
Sleep (2000);
while (1) {
processes = getProcessHandles (module->getProcessName ());
if (processes == NULL) {
Sleep (2000);
continue;
}
/* There are opened processes */
res = Pandora_Wmi::isProcessRunning (module->getProcessName ());
str_res = inttostr (res);
if (str_res != prev_res) {
module->setOutput (str_res);
prev_res = str_res;
Pandora_Windows_Service::getInstance ()->sendXml (modules);
}
/* Wait for this processes */
nprocess = res;
result = WaitForMultipleObjects (nprocess, processes, FALSE, 10000);
if (result > (WAIT_OBJECT_0 + nprocess - 1)) {
/* No event happened */
for (i = 0; i < nprocess; i++)
CloseHandle (processes[i]);
pandoraFree (processes);
continue;
}
/* Some event happened, probably the process was closed */
res = Pandora_Wmi::isProcessRunning (module->getProcessName ());
str_res = inttostr (res);
if (str_res != prev_res) {
module->setOutput (str_res);
prev_res = str_res;
Pandora_Windows_Service::getInstance ()->sendXml (modules);
}
/* Free handles */
for (i = 0; i < nprocess; i++)
CloseHandle (processes[i]);
pandoraFree (processes);
}
delete modules;
}
void void
Pandora_Module_Proc::run () { Pandora_Module_Proc::run () {
int res; int res;
@ -55,6 +126,13 @@ Pandora_Module_Proc::run () {
} }
res = Pandora_Wmi::isProcessRunning (this->process_name); res = Pandora_Wmi::isProcessRunning (this->process_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;
}
} }

View File

@ -30,10 +30,13 @@ namespace Pandora_Modules {
class Pandora_Module_Proc : public Pandora_Module { class Pandora_Module_Proc : public Pandora_Module {
private: private:
string process_name; string process_name;
HANDLE thread;
public: public:
Pandora_Module_Proc (string name, string process_name); Pandora_Module_Proc (string name, string process_name);
void run (); string getProcessName () const;
void run ();
}; };
} }

View File

@ -58,19 +58,19 @@ Pandora_Module_Service::getServiceName () const {
void void
async_run (Pandora_Module_Service *module) { async_run (Pandora_Module_Service *module) {
HANDLE event_log; HANDLE event_log;
HANDLE event; HANDLE event;
DWORD result; DWORD result;
int res; int res;
string str_res; string str_res;
BYTE buffer[BUFFER_SIZE]; BYTE buffer[BUFFER_SIZE];
EVENTLOGRECORD *record; EVENTLOGRECORD *record;
DWORD read; DWORD read;
DWORD needed; DWORD needed;
int event_id; int event_id;
bool service_event; bool service_event;
string prev_res; string prev_res;
Pandora_Module_List *modules; Pandora_Module_List *modules;
prev_res = module->getLatestOutput (); prev_res = module->getLatestOutput ();
modules = new Pandora_Module_List (); modules = new Pandora_Module_List ();
@ -87,35 +87,41 @@ async_run (Pandora_Module_Service *module) {
NotifyChangeEventLog (event_log, event); NotifyChangeEventLog (event_log, event);
result = WaitForSingleObject (event, 10000); result = WaitForSingleObject (event, 10000);
if (result == 0) { /* No event happened */
service_event = false; if (result != WAIT_OBJECT_0) {
record = (EVENTLOGRECORD *) buffer; CloseHandle (event);
CloseEventLog (event_log);
continue;
}
while (ReadEventLog (event_log, /* An event happened */
EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ, service_event = false;
0, record, BUFFER_SIZE, &read, &needed)) { record = (EVENTLOGRECORD *) buffer;
if (record->EventType != EVENTLOG_INFORMATION_TYPE) /* Read events and check if any was relative to service */
continue; while (ReadEventLog (event_log,
event_id = record->EventID & 0x0000ffff; EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ,
0, record, BUFFER_SIZE, &read, &needed)) {
/* Those numbers are the code for service start/stopping */ if (record->EventType != EVENTLOG_INFORMATION_TYPE)
if (event_id == 7035 || event_id == 7036) { continue;
service_event = true; event_id = record->EventID & 0x0000ffff;
break;
} /* Those numbers are the code for service start/stopping */
if (event_id == 7035 || event_id == 7036) {
service_event = true;
break;
} }
}
if (service_event) { /* A start/stop action was thrown */
res = Pandora_Wmi::isServiceRunning (module->getServiceName ()); if (service_event) {
str_res = inttostr (res); res = Pandora_Wmi::isServiceRunning (module->getServiceName ());
if (str_res != prev_res) { str_res = inttostr (res);
module->setOutput (str_res); if (str_res != prev_res) {
prev_res = str_res; module->setOutput (str_res);
pandoraLog ("Service \"%s\" changed status to: %d", prev_res = str_res;
module->getServiceName ().c_str (), res); Pandora_Windows_Service::getInstance ()->sendXml (modules);
Pandora_Windows_Service::getInstance ()->sendXml (modules);
}
} }
} }
CloseHandle (event); CloseHandle (event);

View File

@ -53,7 +53,7 @@ Key_Value::parseLine (string str) {
trimmedstr = trim (str); trimmedstr = trim (str);
/* Check if the string has " */ /* Check if the string has " */
pos = trimmedstr.find ("\""); pos = trimmedstr.find ("\"");
if (pos == string::npos) { if (pos == string::npos) {
stringtok (tokens, trimmedstr, " \t"); stringtok (tokens, trimmedstr, " \t");
@ -61,13 +61,13 @@ Key_Value::parseLine (string str) {
stringtok (tokens, trimmedstr, "\""); stringtok (tokens, trimmedstr, "\"");
} }
/* Pick the first and the last value of the token list */ /* Pick the first and the last value of the token list */
iter = tokens.begin (); iter = tokens.begin ();
key = trim (*iter); key = trim (*iter);
transform (key.begin(), key.end(), key.begin(), (int(*)(int)) tolower); transform (key.begin(), key.end(), key.begin(), (int(*)(int)) tolower);
iter = tokens.end (); iter = tokens.end ();
iter--; iter--;
/* Check if the line has only one token */ /* Check if the line has only one token */
if (iter != tokens.begin ()) { if (iter != tokens.begin ()) {
value = trim (*iter); value = trim (*iter);
} else { } else {
@ -104,8 +104,8 @@ pandoraWriteLog (string filename, string line) {
SYSTEMTIME st; SYSTEMTIME st;
GetSystemTime(&st); GetSystemTime(&st);
sprintf (str_time, "%d-%02d-%02d %02d:%02d:%02d ", st.wYear, st.wMonth, st.wDay, sprintf (str_time, "%d-%02d-%02d %02d:%02d:%02d ", st.wYear, st.wMonth, st.wDay,
st.wHour, st.wMinute, st.wSecond); st.wHour, st.wMinute, st.wSecond);
buffer = (char *) str_time; buffer = (char *) str_time;
buffer += line; buffer += line;

View File

@ -641,10 +641,10 @@ Pandora_Windows_Service::sendXml (Pandora_Module_List *modules) {
if (mutex == 0) { if (mutex == 0) {
mutex = CreateMutex (NULL, FALSE, NULL); mutex = CreateMutex (NULL, FALSE, NULL);
} }
/* Wait for the mutex to be opened */ /* Wait for the mutex to be opened */
WaitForSingleObject (mutex, INFINITE); WaitForSingleObject (mutex, INFINITE);
pandoraLog ("aasdfasdf");
agent = getXmlHeader (); agent = getXmlHeader ();
if (modules != NULL) { if (modules != NULL) {
@ -686,7 +686,7 @@ Pandora_Windows_Service::sendXml (Pandora_Module_List *modules) {
} }
pandoraDebug ("Copying XML on %s", tmp_filepath.c_str ()); pandoraDebug ("Copying XML on %s", tmp_filepath.c_str ());
decl = new TiXmlDeclaration( "1.0", encoding.c_str(), "" ); decl = new TiXmlDeclaration ("1.0", encoding.c_str(), "");
doc = new TiXmlDocument (tmp_filepath); doc = new TiXmlDocument (tmp_filepath);
doc->InsertEndChild (*decl); doc->InsertEndChild (*decl);
doc->InsertEndChild (*agent); doc->InsertEndChild (*agent);
@ -697,6 +697,7 @@ Pandora_Windows_Service::sendXml (Pandora_Module_List *modules) {
if (!saved) { if (!saved) {
pandoraLog ("Error when saving the XML in %s", pandoraLog ("Error when saving the XML in %s",
tmp_filepath.c_str ()); tmp_filepath.c_str ());
ReleaseMutex (mutex);
return; return;
} }

View File

@ -20,6 +20,7 @@
#include "pandora_windows_info.h" #include "pandora_windows_info.h"
#include "../pandora_strutils.h" #include "../pandora_strutils.h"
#include <psapi.h>
#define MAX_KEY_LENGTH 255 #define MAX_KEY_LENGTH 255
@ -81,3 +82,51 @@ Pandora_Windows_Info::getSystemPath () {
str_path = trim (str_path); str_path = trim (str_path);
return str_path; return str_path;
} }
HANDLE *
Pandora_Windows_Info::getProcessHandles (string name) {
HANDLE handle;
HANDLE handles[128];
HANDLE *retval;
DWORD pids[1024], needed, npids;
int i;
int count;
HMODULE modules;
bool success;
TCHAR process_name[MAX_PATH];
if (! EnumProcesses (pids, sizeof (pids), &needed))
return NULL;
count = 0;
npids = needed / sizeof (DWORD);
for (i = 0; i < npids; i++) {
if (pids[i] == 0)
continue;
/* Open process handle and find module base name (which is
supposed to be process name) */
handle = OpenProcess (PROCESS_ALL_ACCESS, FALSE, pids[i]);
if (handle == NULL)
continue;
success = EnumProcessModules (handle, &modules, sizeof (modules), &needed);
if (! success) {
CloseHandle (handle);
continue;
}
GetModuleBaseName (handle, modules, process_name, sizeof (process_name) / sizeof (TCHAR));
if (stricmp (process_name, name.c_str ()) == 0) {
/* Process found */
handles[count++] = handle;
}
}
if (count == 0)
return NULL;
retval = (HANDLE *) malloc (count * sizeof (HANDLE));
for (i = 0; i < count; i++)
retval[i] = handles[i];
return retval;
}

View File

@ -34,10 +34,11 @@ using namespace std;
* Windows information functions. * Windows information functions.
*/ */
namespace Pandora_Windows_Info { namespace Pandora_Windows_Info {
string getOSName (); string getOSName ();
string getOSVersion (); string getOSVersion ();
string getOSBuild (); string getOSBuild ();
string getSystemName (); string getSystemName ();
string getSystemPath (); string getSystemPath ();
HANDLE *getProcessHandles (string name);
} }
#endif #endif