diff --git a/pandora_agents/win32/ChangeLog b/pandora_agents/win32/ChangeLog index 50fef03bce..0d3415496f 100644 --- a/pandora_agents/win32/ChangeLog +++ b/pandora_agents/win32/ChangeLog @@ -1,3 +1,21 @@ +2008-12-01 Esteban Sanchez + + * 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 * modules/pandora_module.[cc,h]: Added an async property. Added diff --git a/pandora_agents/win32/modules/pandora_module.cc b/pandora_agents/win32/modules/pandora_module.cc index d18a38c63a..7235a7588a 100644 --- a/pandora_agents/win32/modules/pandora_module.cc +++ b/pandora_agents/win32/modules/pandora_module.cc @@ -184,12 +184,7 @@ Pandora_Module::getModuleKind () const { */ string Pandora_Module::getLatestOutput () const { - list::iterator iter; - - if (this->data_list == NULL) - return ""; - iter = this->data_list->begin (); - return (*iter)->getValue (); + return this->latest_output; } /** @@ -256,7 +251,8 @@ Pandora_Module::setOutput (string output) { if (this->data_list == NULL) this->data_list = new list (); data = new Pandora_Data (output); - this->data_list->push_back (data); + this->data_list->push_back (data); + this->latest_output = output; } /** diff --git a/pandora_agents/win32/modules/pandora_module.h b/pandora_agents/win32/modules/pandora_module.h index 213641eb23..03f42d9346 100644 --- a/pandora_agents/win32/modules/pandora_module.h +++ b/pandora_agents/win32/modules/pandora_module.h @@ -117,7 +117,8 @@ namespace Pandora_Modules { Module_Type module_type; string module_kind_str; Module_Kind module_kind; - list *data_list; + list *data_list; + string latest_output; string getDataOutput (Pandora_Data *data); void cleanDataList (); diff --git a/pandora_agents/win32/modules/pandora_module_proc.cc b/pandora_agents/win32/modules/pandora_module_proc.cc index 1a2fa13cc2..983d40d13d 100644 --- a/pandora_agents/win32/modules/pandora_module_proc.cc +++ b/pandora_agents/win32/modules/pandora_module_proc.cc @@ -18,15 +18,19 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "pandora_module_proc.h" -#include "../windows/pandora_wmi.h" -#include "../pandora_strutils.h" +#include "pandora_module_proc.h" +#include "pandora_module_list.h" +#include "../windows/pandora_wmi.h" +#include "../windows/pandora_windows_info.h" +#include "../pandora_strutils.h" +#include "../pandora_windows_service.h" #include #include using namespace Pandora; using namespace Pandora_Modules; -using namespace Pandora_Strutils; +using namespace Pandora_Strutils; +using namespace Pandora_Windows_Info; /** * Creates a Pandora_Module_Proc object. @@ -43,6 +47,73 @@ Pandora_Module_Proc::Pandora_Module_Proc (string name, string process_name) 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 Pandora_Module_Proc::run () { @@ -52,9 +123,16 @@ Pandora_Module_Proc::run () { Pandora_Module::run (); } catch (Interval_Not_Fulfilled e) { return; - } - + } + 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; + } } diff --git a/pandora_agents/win32/modules/pandora_module_proc.h b/pandora_agents/win32/modules/pandora_module_proc.h index 126c97370c..96d1baab81 100644 --- a/pandora_agents/win32/modules/pandora_module_proc.h +++ b/pandora_agents/win32/modules/pandora_module_proc.h @@ -29,11 +29,14 @@ namespace Pandora_Modules { */ class Pandora_Module_Proc : public Pandora_Module { private: - string process_name; + string process_name; + HANDLE thread; public: - Pandora_Module_Proc (string name, string process_name); + Pandora_Module_Proc (string name, string process_name); + + string getProcessName () const; - void run (); + void run (); }; } diff --git a/pandora_agents/win32/modules/pandora_module_service.cc b/pandora_agents/win32/modules/pandora_module_service.cc index 6364434cc1..aa06de51d3 100644 --- a/pandora_agents/win32/modules/pandora_module_service.cc +++ b/pandora_agents/win32/modules/pandora_module_service.cc @@ -58,19 +58,19 @@ Pandora_Module_Service::getServiceName () const { 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; + 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 (); @@ -87,35 +87,41 @@ async_run (Pandora_Module_Service *module) { NotifyChangeEventLog (event_log, event); result = WaitForSingleObject (event, 10000); - if (result == 0) { - service_event = false; - record = (EVENTLOGRECORD *) buffer; + /* No event happened */ + if (result != WAIT_OBJECT_0) { + CloseHandle (event); + CloseEventLog (event_log); + continue; + } + + /* An event happened */ + service_event = false; + record = (EVENTLOGRECORD *) buffer; + + /* Read events and check if any was relative to service */ + while (ReadEventLog (event_log, + EVENTLOG_FORWARDS_READ | EVENTLOG_SEQUENTIAL_READ, + 0, record, BUFFER_SIZE, &read, &needed)) { - 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 (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); - } + } + + /* A start/stop action was thrown */ + 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; + Pandora_Windows_Service::getInstance ()->sendXml (modules); } } CloseHandle (event); diff --git a/pandora_agents/win32/pandora.cc b/pandora_agents/win32/pandora.cc index dca3fd74fb..5015451df8 100644 --- a/pandora_agents/win32/pandora.cc +++ b/pandora_agents/win32/pandora.cc @@ -50,24 +50,24 @@ Key_Value::parseLine (string str) { list tokens; list::iterator iter; string trimmedstr; - + trimmedstr = trim (str); - -/* Check if the string has " */ + + /* 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 */ + + /* 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 */ + /* Check if the line has only one token */ if (iter != tokens.begin ()) { value = trim (*iter); } else { @@ -102,16 +102,16 @@ pandoraWriteLog (string filename, string line) { 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); - + 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 ()); @@ -132,11 +132,11 @@ 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); } @@ -154,11 +154,11 @@ 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; diff --git a/pandora_agents/win32/pandora_windows_service.cc b/pandora_agents/win32/pandora_windows_service.cc index 61c304dda3..2284f232b4 100644 --- a/pandora_agents/win32/pandora_windows_service.cc +++ b/pandora_agents/win32/pandora_windows_service.cc @@ -641,10 +641,10 @@ Pandora_Windows_Service::sendXml (Pandora_Module_List *modules) { 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) { @@ -686,7 +686,7 @@ Pandora_Windows_Service::sendXml (Pandora_Module_List *modules) { } 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->InsertEndChild (*decl); doc->InsertEndChild (*agent); @@ -696,7 +696,8 @@ Pandora_Windows_Service::sendXml (Pandora_Module_List *modules) { if (!saved) { pandoraLog ("Error when saving the XML in %s", - tmp_filepath.c_str ()); + tmp_filepath.c_str ()); + ReleaseMutex (mutex); return; } diff --git a/pandora_agents/win32/windows/pandora_windows_info.cc b/pandora_agents/win32/windows/pandora_windows_info.cc index e3ea5bbe38..35c7b20696 100644 --- a/pandora_agents/win32/windows/pandora_windows_info.cc +++ b/pandora_agents/win32/windows/pandora_windows_info.cc @@ -19,7 +19,8 @@ */ #include "pandora_windows_info.h" -#include "../pandora_strutils.h" +#include "../pandora_strutils.h" +#include #define MAX_KEY_LENGTH 255 @@ -80,4 +81,52 @@ Pandora_Windows_Info::getSystemPath () { string str_path = buffer; str_path = trim (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; +} diff --git a/pandora_agents/win32/windows/pandora_windows_info.h b/pandora_agents/win32/windows/pandora_windows_info.h index f348199fde..1fb4b4b101 100644 --- a/pandora_agents/win32/windows/pandora_windows_info.h +++ b/pandora_agents/win32/windows/pandora_windows_info.h @@ -34,10 +34,11 @@ using namespace std; * Windows information functions. */ namespace Pandora_Windows_Info { - string getOSName (); - string getOSVersion (); - string getOSBuild (); - string getSystemName (); - string getSystemPath (); + string getOSName (); + string getOSVersion (); + string getOSBuild (); + string getSystemName (); + string getSystemPath (); + HANDLE *getProcessHandles (string name); } #endif