2009-09-10 Ramon Novoa <rnovoa@artica.es>

* windows/pandora_windows_info.h,
          windows/pandora_windows_info.cc: Added a new function that searches
          the Windows registry for installed software.

        * windows/pandora_wmi.cc, windows/pandora_wmi.h: Avoid reading numeric
          values from WMI query results into strings.

        * modules/pandora_module_inventory.h,
          modules/pandora_module_inventory.cc,
          modules/pandora_module_factory.cc: Added a new inventory module that
          lists system services. Updated the software module to use the new
          function. Fixed some typos.




git-svn-id: https://svn.code.sf.net/p/pandora/code/trunk@1927 c3f86ba8-e40f-0410-aaad-9ba5e7f4b01f
This commit is contained in:
ramonn 2009-09-10 14:15:39 +00:00
parent 895a958299
commit 6498a6f3bf
8 changed files with 354 additions and 136 deletions

View File

@ -1,3 +1,18 @@
2009-09-10 Ramon Novoa <rnovoa@artica.es>
* windows/pandora_windows_info.h,
windows/pandora_windows_info.cc: Added a new function that searches
the Windows registry for installed software.
* windows/pandora_wmi.cc, windows/pandora_wmi.h: Avoid reading numeric
values from WMI query results into strings.
* modules/pandora_module_inventory.h,
modules/pandora_module_inventory.cc,
modules/pandora_module_factory.cc: Added a new inventory module that
lists system services. Updated the software module to use the new
function. Fixed some typos.
2009-09-02 Pablo de la Concepción <pablo.concepcion@artica.es>
* windows/pandora_wmi.cc, windows/pandora_wmi.h: Added Inventory
functions

View File

@ -111,7 +111,7 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
string module_name, module_type, module_exec;
string module_min, module_max, module_description;
string module_interval, module_proc, module_service;
string module_freedisk, module_cpuusage, module_inventory, module_inventory_interval, module_odbc;
string module_freedisk, module_cpuusage, module_inventory, module_odbc;
string module_freedisk_percent, module_freememory_percent;
string module_odbc_query, module_dsn, module_freememory;
string module_logevent, module_source, module_eventtype, module_eventcode;
@ -344,11 +344,10 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
} else if (module_inventory != "") {
module = new Pandora_Module_Inventory (module_name, module_inventory);
if (module_inventory_interval != "") {
if (module_interval != "") {
try {
// Convert the interval to seconds...
int interval = strtoint (module_inventory_interval) *60 *60 *24 ;
pandoraDebug("Inventory_interval = %d", interval);
int interval = strtoint (module_interval) *60 *60 *24 ;
module->setInterval(interval);
} catch (Invalid_Conversion e) {
pandoraLog("Error in conversion of module_inventory_interval");
@ -450,9 +449,6 @@ Pandora_Module_Factory::getModuleFromDefinition (string definition) {
module_name.c_str ());
}
}
if (module != NULL)
{
pandoraDebug("Parsed Moudle: %s\n",module->getName().c_str());
}
return module;
}

View File

@ -21,6 +21,7 @@ the agent is instaled.
#include "pandora_module_inventory.h"
#include "../windows/pandora_wmi.h"
#include "../windows/pandora_windows_info.h"
#include "../pandora_strutils.h"
using namespace Pandora;
@ -60,157 +61,167 @@ Pandora_Module_Inventory::run () {
// Until no data data is gathered there will be no output
this->has_output = false;
pandoraLog("At Inventory - Run\n");
try {
Pandora_Module::run ();
} catch (Interval_Not_Fulfilled e) {
return;
}
found = this->options.find(module_invenory_cdrom_str);
found = this->options.find(module_inventory_cdrom_str);
if (found != string::npos){
pandoraDebug(" Launching CDRom Query WMI ... \n");
num_results = Pandora_Wmi::getCdRomInfo(rows);
pandoraLog("Setting Outuput: found %d items\n",num_results);
pandoraDebug("Setting Outuput: found %d items\n",num_results);
try {
for (row = rows.begin (); row != rows.end(); ++row) {
this->setOutput (*row,module_invenory_cdrom_str);
this->setOutput (*row,module_inventory_cdrom_str);
this->has_output = true;
}
} catch (Pandora_Wmi::Pandora_Wmi_Exception e) {
pandoraLog("Output Error at Moudle Inventory\n");
pandoraLog("Output Error at Module Inventory\n");
this->has_output = false;
}
rows.clear();
}
found = this->options.find(module_invenory_video_str);
found = this->options.find(module_inventory_video_str);
if (found != string::npos){
pandoraDebug(" Launching Video Query WMI\n");
num_results = Pandora_Wmi::getVideoInfo(rows);
pandoraLog("Setting Outuput: found %d items\n",num_results);
pandoraDebug("Setting Outuput: found %d items\n",num_results);
try {
for (row = rows.begin (); row != rows.end(); ++row) {
this->setOutput (*row,module_invenory_video_str);
this->setOutput (*row,module_inventory_video_str);
this->has_output = true;
}
} catch (Pandora_Wmi::Pandora_Wmi_Exception e) {
pandoraLog("Output Error at Moudle Inventory\n");
pandoraLog("Output Error at Module Inventory\n");
this->has_output = (this->has_output || false);
}
rows.clear();
}
found = this->options.find(module_invenory_hds_str);
found = this->options.find(module_inventory_hds_str);
if (found != string::npos){
pandoraDebug(" Launching HD Query WMI\n");
num_results = Pandora_Wmi::getHDsInfo(rows);
pandoraLog("Setting Outuput: found %d items\n",num_results);
pandoraDebug("Setting Outuput: found %d items\n",num_results);
try {
for (row = rows.begin (); row != rows.end(); ++row) {
this->setOutput (*row,module_invenory_hds_str);
this->setOutput (*row,module_inventory_hds_str);
this->has_output = true;
}
} catch (Pandora_Wmi::Pandora_Wmi_Exception e) {
pandoraLog("Output Error at Moudle Inventory\n");
pandoraLog("Output Error at Module Inventory\n");
this->has_output = (this->has_output || false);
}
rows.clear();
}
found = this->options.find(module_invenory_cpu_str);
found = this->options.find(module_inventory_cpu_str);
if (found != string::npos){
pandoraDebug(" Launching CPUs Query WMI\n");
pandoraDebug(" Launching CPUs Query WMI\n");
num_results = Pandora_Wmi::getCPUsInfo(rows);
pandoraLog("Setting Outuput: found %d items\n",num_results);
pandoraDebug("Setting Outuput: found %d items\n",num_results);
try {
for (row = rows.begin (); row != rows.end(); ++row) {
this->setOutput (*row,module_invenory_cpu_str);
this->setOutput (*row,module_inventory_cpu_str);
this->has_output = true;
}
} catch (Pandora_Wmi::Pandora_Wmi_Exception e) {
pandoraLog("Output Error at Moudle Inventory\n");
pandoraLog("Output Error at Module Inventory\n");
this->has_output = (this->has_output || false);
}
rows.clear();
}
found = this->options.find(module_invenory_nics_str);
found = this->options.find(module_inventory_nics_str);
if (found != string::npos){
pandoraDebug(" Launching NICs Query WMI\n");
pandoraDebug(" Launching NICs Query WMI\n");
num_results = Pandora_Wmi::getNICsInfo(rows);
pandoraLog("Setting Outuput: found %d items\n",num_results);
pandoraDebug("Setting Outuput: found %d items\n",num_results);
try {
for (row = rows.begin (); row != rows.end(); ++row) {
this->setOutput (*row,module_invenory_nics_str);
this->setOutput (*row,module_inventory_nics_str);
this->has_output = true;
}
} catch (Pandora_Wmi::Pandora_Wmi_Exception e) {
pandoraLog("Output Error at Moudle Inventory\n");
pandoraLog("Output Error at Module Inventory\n");
this->has_output = (this->has_output || false);
}
rows.clear();
}
found = this->options.find(module_invenory_patches_str);
found = this->options.find(module_inventory_patches_str);
if (found != string::npos){
pandoraDebug(" Launching Patch Query WMI\n");
pandoraDebug(" Launching Patch Query WMI\n");
num_results = Pandora_Wmi::getPatchInfo(rows);
pandoraLog("Setting Outuput: found %d items\n",num_results);
pandoraDebug("Setting Outuput: found %d items\n",num_results);
try {
for (row = rows.begin (); row != rows.end(); ++row) {
this->setOutput (*row,module_invenory_patches_str);
this->setOutput (*row,module_inventory_patches_str);
this->has_output = true;
}
} catch (Pandora_Wmi::Pandora_Wmi_Exception e) {
pandoraLog("Output Error at Moudle Inventory\n");
pandoraLog("Output Error at Module Inventory\n");
this->has_output = (this->has_output || false);
}
rows.clear();
}
found = this->options.find(module_invenory_ram_str);
found = this->options.find(module_inventory_ram_str);
if (found != string::npos){
pandoraDebug(" Launching RAM Query WMI\n");
pandoraDebug(" Launching RAM Query WMI\n");
num_results = Pandora_Wmi::getRAMInfo(rows);
pandoraLog("Setting Outuput: found %d items\n",num_results);
pandoraDebug("Setting Outuput: found %d items\n",num_results);
try {
for (row = rows.begin (); row != rows.end(); ++row) {
this->setOutput (*row,module_invenory_ram_str);
this->setOutput (*row,module_inventory_ram_str);
this->has_output = true;
}
} catch (Pandora_Wmi::Pandora_Wmi_Exception e) {
pandoraLog("Output Error at Moudle Inventory\n");
pandoraLog("Output Error at Module Inventory\n");
this->has_output = (this->has_output || false);
}
rows.clear();
}
found = this->options.find(module_invenory_software_str);
found = this->options.find(module_inventory_software_str);
if (found != string::npos){
pandoraDebug(" Launching Software Query WMI\n");
num_results = Pandora_Wmi::getSoftware(rows);
pandoraLog("Setting Outuput: found %d items\n",num_results);
num_results = Pandora_Windows_Info::getSoftware(rows, Pandora_Wmi::inventory_field_separator);
pandoraDebug("Setting Outuput: found %d items\n",num_results);
try {
for (row = rows.begin (); row != rows.end(); ++row) {
this->setOutput (*row,module_invenory_software_str);
this->setOutput (*row,module_inventory_software_str);
}
} catch (Pandora_Wmi::Pandora_Wmi_Exception e) {
pandoraLog("Output Error at Moudle Inventory\n");
pandoraLog("Output Error at Module Inventory\n");
this->has_output = false;
}
rows.clear();
}
found = this->options.find(module_inventory_software_str);
if (found != string::npos){
pandoraDebug(" Launching Services Query WMI\n");
num_results = Pandora_Wmi::getServices(rows);
pandoraDebug("Setting Outuput: found %d items\n",num_results);
try {
for (row = rows.begin (); row != rows.end(); ++row) {
this->setOutput (*row,module_inventory_services_str);
}
} catch (Pandora_Wmi::Pandora_Wmi_Exception e) {
pandoraLog("Output Error at Module Inventory\n");
this->has_output = false;
}
rows.clear();
}
//pandoraLog("Inventory - Run finish\n");
}

View File

@ -26,14 +26,15 @@ the agent is instaled.
namespace Pandora_Modules {
const string module_invenory_cpu_str = "CPU";
const string module_invenory_cdrom_str = "CDROM";
const string module_invenory_video_str = "Video";
const string module_invenory_hds_str = "HD";
const string module_invenory_nics_str = "NIC";
const string module_invenory_patches_str = "Patches";
const string module_invenory_software_str = "Software";
const string module_invenory_ram_str = "RAM";
const string module_inventory_cpu_str = "CPU";
const string module_inventory_cdrom_str = "CDROM";
const string module_inventory_video_str = "Video";
const string module_inventory_hds_str = "HD";
const string module_inventory_nics_str = "NIC";
const string module_inventory_patches_str = "Patches";
const string module_inventory_software_str = "Software";
const string module_inventory_ram_str = "RAM";
const string module_inventory_services_str = "Services";
/**
* Module to retrieve the Inventory of the machine.

View File

@ -19,7 +19,7 @@
*/
#include "pandora_windows_info.h"
#include "../pandora_strutils.h"
#include "../pandora_strutils.h"
#include <psapi.h>
#define MAX_KEY_LENGTH 255
@ -81,52 +81,208 @@ 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;
}
}
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;
}
/**
* Get the value of the given registry key
*
* @return The system name of the operating system.
*/
string
Pandora_Windows_Info::getRegistryValue (HKEY root, const string treepath,
const string keyname) {
long reg_result;
list<string> tokens;
HKEY prev, current;
DWORD data_type;
DWORD buffer_size = 1024;
BYTE *buffer;
string result = "";
stringtok (tokens, treepath, "\\");
// Go through the registry path
prev = root;
list<string>::const_iterator i = tokens.begin();
while (i != tokens.end()) {
reg_result = RegOpenKeyEx (prev, (*i).c_str (), 0, KEY_READ, &current);
if (reg_result != ERROR_SUCCESS) {
RegCloseKey (prev);
return "";
}
reg_result = RegCloseKey (prev);
if (reg_result != ERROR_SUCCESS) {
RegCloseKey (current);
return "";
}
prev = current;
i++;
}
buffer = (BYTE *) malloc (buffer_size * sizeof (BYTE));
if (buffer == NULL) {
RegCloseKey (current);
return "";
}
reg_result = RegQueryValueEx (current, keyname.c_str (), NULL,
&data_type, buffer, &buffer_size);
// The buffer is not large enough
while (reg_result == ERROR_MORE_DATA) {
buffer_size *= 2;
buffer = (BYTE *) realloc (buffer, buffer_size * sizeof (BYTE));
if (buffer == NULL) {
RegCloseKey (current);
return "";
}
reg_result = RegQueryValueEx (current, keyname.c_str (), NULL,
&data_type, buffer, &buffer_size);
}
// The key could not be read
if (reg_result != ERROR_SUCCESS) {
RegCloseKey (current);
free ((void *)buffer);
return "";
}
switch (data_type) {
/* String value */
case REG_EXPAND_SZ:
case REG_MULTI_SZ:
case REG_SZ:
result = (char *) buffer;
break;
/* Numeric value */
default:
for (int i = 0; i < (int) buffer_size; i++) {
string hex = longtohex (buffer[i]);
if (hex == "0") {
hex = "0" + hex;
}
result = hex + result;
}
int result_int = strtoint (result);
result = inttostr (result_int);
break;
}
RegCloseKey (current);
free ((void *)buffer);
return result;
}
/**
* Get a list of installed software
*
* @param rows Result list.
* @param rows Field separator.
* @return Result list length.
*/
int
Pandora_Windows_Info::getSoftware (list<string> &rows, string separator) {
int num_objects = 0;
string tree;
HKEY key;
DWORD sub_keys, ret, name_len;
TCHAR sub_key_name[MAX_KEY_LENGTH];
string app_name, system, version, reg_path;
tree = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall";
ret = RegOpenKeyEx (HKEY_LOCAL_MACHINE, TEXT (tree.c_str ()), 0, KEY_READ, &key);
if (ret != ERROR_SUCCESS) {
return 0;
}
RegQueryInfoKey (key, NULL, NULL, NULL, &sub_keys, NULL, NULL,
NULL, NULL, NULL, NULL,NULL);
for (int i = 0; i < (int) sub_keys; i++) {
name_len = MAX_KEY_LENGTH;
ret = RegEnumKeyEx (key, i, sub_key_name, &name_len,
NULL, NULL, NULL, NULL);
if (ret != ERROR_SUCCESS) {
continue;
}
/* Get application name */
reg_path = tree + "\\" + sub_key_name;
app_name = getRegistryValue (HKEY_LOCAL_MACHINE, reg_path, "DisplayName");
if (app_name == "") {
continue;
}
/* Skip system components */
system = getRegistryValue (HKEY_LOCAL_MACHINE, reg_path, "SystemComponent");
if (system != "") {
continue;
}
/* Get application version */
version = getRegistryValue (HKEY_LOCAL_MACHINE, reg_path, "DisplayVersion");
if (version != "") {
app_name += separator + version;
}
rows.push_back (app_name);
num_objects++;
}
RegCloseKey (key);
return num_objects;
}

View File

@ -38,7 +38,9 @@ namespace Pandora_Windows_Info {
string getOSVersion ();
string getOSBuild ();
string getSystemName ();
string getSystemPath ();
string getSystemPath ();
HANDLE *getProcessHandles (string name);
string getRegistryValue (HKEY root, const string treepath, const string keyname);
int getSoftware (list<string> &rows, string separator);
}
#endif

View File

@ -139,8 +139,7 @@ unsigned long
Pandora_Wmi::getDiskFreeSpace (string disk_id) {
CDhInitialize init;
CDispPtr wmi_svc, quickfixes;
unsigned long long space = 0;
string space_str;
double free_space = 0;
string query;
query = "SELECT FreeSpace FROM Win32_LogicalDisk WHERE DeviceID = \"" + disk_id + "\"";
@ -156,24 +155,11 @@ Pandora_Wmi::getDiskFreeSpace (string disk_id) {
query.c_str ()));
FOR_EACH (quickfix, quickfixes, NULL) {
QFix fix = { 0 };
dhGetValue (L"%s", &fix.free_space, quickfix,
dhGetValue (L"%e", &free_space, quickfix,
L".FreeSpace");
if (fix.free_space == NULL)
return 0;
space_str = fix.free_space;
dhFreeString (name);
try {
space = Pandora_Strutils::strtoulong (space_str);
} catch (Pandora_Exception e) {
throw Pandora_Wmi_Exception ();
}
return space / 1024 / 1024;
// 1048576 = 1024 * 1024
return (unsigned long) free_space / 1048576;
} NEXT_THROW (quickfix);
} catch (string errstr) {
pandoraLog ("getDiskFreeSpace error. %s", errstr.c_str ());
@ -196,8 +182,8 @@ unsigned long
Pandora_Wmi::getDiskFreeSpacePercent (string disk_id) {
CDhInitialize init;
CDispPtr wmi_svc, quickfixes;
unsigned long free_space = 0, size = 0;
unsigned long total_free_space = 0, total_size = 0;
double free_space = 0, size = 0;
double total_free_space = 0, total_size = 0;
string query, free_str, size_str;
query = "SELECT Size, FreeSpace FROM Win32_LogicalDisk WHERE DeviceID = \"" + disk_id + "\"";
@ -209,9 +195,9 @@ Pandora_Wmi::getDiskFreeSpacePercent (string disk_id) {
query.c_str ()));
FOR_EACH (quickfix, quickfixes, NULL) {
dhGetValue (L"%s", &free_str, quickfix,
dhGetValue (L"%e", &free_space, quickfix,
L".FreeSpace");
dhGetValue (L"%s", &size_str, quickfix,
dhGetValue (L"%e", &size, quickfix,
L".Size");
free_space = Pandora_Strutils::strtoulong (free_str);
@ -224,7 +210,7 @@ Pandora_Wmi::getDiskFreeSpacePercent (string disk_id) {
return 0;
}
return total_free_space * 100 / total_size;
return (unsigned long) (total_free_space * 100 / total_size);
} catch (string errstr) {
pandoraLog ("getDiskFreeSpace error. %s", errstr.c_str ());
}
@ -1151,3 +1137,51 @@ Pandora_Wmi::getRAMInfo (list<string> &rows) {
}
return num_objects;
}
/**
* Get a list of running system services
*
* @param rows Result list.
* @return Result list length.
*/
int
Pandora_Wmi::getServices (list<string> &rows) {
CDhInitialize init;
CDispPtr wmi_svc = NULL, services = NULL;
char *name = NULL, *path_name = NULL, *state = NULL;
string ret = "";
int num_objects = 0;
try {
dhCheck (dhGetObject (getWmiStr (L"."), NULL, &wmi_svc));
dhCheck (dhGetValue (L"%o", &services, wmi_svc,
L".ExecQuery(%S)",
L"SELECT Name, PathName, State FROM Win32_Service"));
FOR_EACH (service, services, NULL) {
num_objects++;
dhGetValue (L"%s", &name, service, L".Name");
if (name != NULL) {
ret += name;
}
ret += inventory_field_separator;
dhFreeString(name);
dhGetValue (L"%s", &path_name, service, L".PathName");
if (path_name != NULL) {
ret += path_name;
}
ret += inventory_field_separator;
dhFreeString (path_name);
dhGetValue (L"%s", &state, service, L".State");
if (state != NULL) {
ret += state;
}
dhFreeString(state);
rows.push_back(ret);
ret.clear();
} NEXT_THROW (service_item);
} catch (string errstr) {
pandoraLog ("runWMIQuery error. %s", errstr.c_str ());
}
return num_objects;
}

View File

@ -22,6 +22,8 @@
#ifndef __PANDORA_WMI_H__
#define __PANDORA_WMI_H__
#define MAX_KEY_LENGTH 255
#include "../pandora.h"
#include "wmi/disphelper.h"
#include <list>
@ -64,6 +66,7 @@ namespace Pandora_Wmi {
int getNICsInfo (list<string> &rows);
int getPatchInfo (list<string> &rows);
int getRAMInfo (list<string> &rows);
int getServices (list<string> &rows);
};