alias support in config class; agent core configuration section can be changed with...
authorVictor Kirhenshtein <victor@netxms.org>
Wed, 25 Jan 2017 14:26:16 +0000 (16:26 +0200)
committerVictor Kirhenshtein <victor@netxms.org>
Wed, 25 Jan 2017 14:26:16 +0000 (16:26 +0200)
ChangeLog
include/nms_util.h
include/nxconfig.h
src/agent/core/ctrl.cpp
src/agent/core/extagent.cpp
src/agent/core/nxagentd.cpp
src/agent/core/push.cpp
src/agent/core/sd.cpp
src/libnetxms/config.cpp
src/libnetxms/tools.cpp

index a247677..1e08900 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,7 +3,9 @@
 *
 
 - Improved the usability of the Server Configuration, by adding descriptions and recognition for data types and possible values
--Fixed issues: NX-630, NX-916, NX-1151
+- Alternative core configuration section can be set for nxagentd using -G command line option
+- Implicit external subagent registartion using EXT:* sections in agent configuration file
+- Fixed issues: NX-630, NX-916, NX-1151
 
 
 *
index da4f5a1..d036f4d 100644 (file)
@@ -1811,8 +1811,8 @@ void LIBNETXMS_EXPORTABLE RemoveTrailingCRLFW(WCHAR *str);
 #define RemoveTrailingCRLF RemoveTrailingCRLFA
 #endif
 
-BOOL LIBNETXMS_EXPORTABLE RegexpMatchA(const char *str, const char *expr, bool matchCase);
-BOOL LIBNETXMS_EXPORTABLE RegexpMatchW(const WCHAR *str, const WCHAR *expr, bool matchCase);
+bool LIBNETXMS_EXPORTABLE RegexpMatchA(const char *str, const char *expr, bool matchCase);
+bool LIBNETXMS_EXPORTABLE RegexpMatchW(const WCHAR *str, const WCHAR *expr, bool matchCase);
 #ifdef UNICODE
 #define RegexpMatch RegexpMatchW
 #else
index d5ea4b4..f06d339 100644 (file)
@@ -27,6 +27,8 @@
 #include <nms_util.h>
 #include <uuid.h>
 
+class Config;
+
 /**
  * Config entry
  */
@@ -44,12 +46,13 @@ private:
        int m_line;
        int m_id;
    StringMap m_attributes;
+   const Config *m_owner;
 
        void addEntry(ConfigEntry *entry);
        void linkEntry(ConfigEntry *entry) { entry->m_next = m_next; m_next = entry; }
 
 public:
-       ConfigEntry(const TCHAR *name, ConfigEntry *parent, const TCHAR *file, int line, int id);
+       ConfigEntry(const TCHAR *name, ConfigEntry *parent, const Config *owner, const TCHAR *file, int line, int id);
        ~ConfigEntry();
 
        ConfigEntry *getNext() { return m_next; }
@@ -119,6 +122,7 @@ private:
        ConfigEntry *m_root;
        int m_errorCount;
        MUTEX m_mutex;
+   StringMap m_aliases;
 
 protected:
        virtual void onError(const TCHAR *errorMessage);
@@ -165,10 +169,13 @@ public:
 
        bool parseTemplate(const TCHAR *section, NX_CFG_TEMPLATE *cfgTemplate);
 
-       int getErrorCount() { return m_errorCount; }
+       int getErrorCount() const { return m_errorCount; }
 
        void print(FILE *file);
        String createXml();
+
+   void setAlias(const TCHAR *alias, const TCHAR *value) { if (alias != NULL) m_aliases.set(alias, value); else m_aliases.remove(alias); }
+   const TCHAR *getAlias(const TCHAR *alias) const { return m_aliases.get(alias); }
 };
 
 
index 1fc252c..2fb5815 100644 (file)
@@ -75,7 +75,7 @@ static THREAD_RESULT THREAD_CALL ControlConnector(void *arg)
        ea.grfAccessPermissions = (FILE_GENERIC_READ | FILE_GENERIC_WRITE) & ~FILE_CREATE_PIPE_INSTANCE;
        ea.grfAccessMode = SET_ACCESS;
        ea.grfInheritance = NO_INHERITANCE;
-       const TCHAR *user = g_config->getValue(_T("/agent/ControlUser"), _T("*"));
+       const TCHAR *user = g_config->getValue(_T("/%agent/ControlUser"), _T("*"));
        if ((user[0] == 0) || !_tcscmp(user, _T("*")))
        {
                ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
index 3486404..ec51669 100644 (file)
@@ -467,7 +467,8 @@ static THREAD_RESULT THREAD_CALL ExternalSubagentConnector(void *arg)
        // Create a well-known SID for the Everyone group.
        if(!AllocateAndInitializeSid(&sidAuthWorld, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &sidEveryone))
        {
-               AgentWriteDebugLog(2, _T("ExternalSubagentConnector: AllocateAndInitializeSid failed (%s)"), GetSystemErrorText(GetLastError(), errorText, 1024));
+               nxlog_debug(2, _T("ExternalSubagentConnector(%s): AllocateAndInitializeSid failed (%s)"), 
+         subagent->getName(), GetSystemErrorText(GetLastError(), errorText, 1024));
                goto cleanup;
        }
 
@@ -483,38 +484,44 @@ static THREAD_RESULT THREAD_CALL ExternalSubagentConnector(void *arg)
                ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
                ea.Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP;
                ea.Trustee.ptstrName  = (LPTSTR)sidEveryone;
+               nxlog_debug(2, _T("ExternalSubagentConnector(%s): using \"Everyone\" group"), subagent->getName());
        }
        else
        {
                ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME;
                ea.Trustee.TrusteeType = TRUSTEE_IS_USER;
                ea.Trustee.ptstrName  = (LPTSTR)user;
+               nxlog_debug(2, _T("ExternalSubagentConnector(%s): using \"%s\" user"), subagent->getName(), user);
        }
 
        // Create a new ACL that contains the new ACEs.
        if (SetEntriesInAcl(1, &ea, NULL, &acl) != ERROR_SUCCESS)
        {
-               AgentWriteDebugLog(2, _T("ExternalSubagentConnector: SetEntriesInAcl failed (%s)"), GetSystemErrorText(GetLastError(), errorText, 1024));
+               nxlog_debug(2, _T("ExternalSubagentConnector(%s): SetEntriesInAcl failed (%s)"), 
+         subagent->getName(), GetSystemErrorText(GetLastError(), errorText, 1024));
                goto cleanup;
        }
 
        sd = (PSECURITY_DESCRIPTOR)LocalAlloc(LPTR, SECURITY_DESCRIPTOR_MIN_LENGTH);
        if (sd == NULL)
        {
-               AgentWriteDebugLog(2, _T("ExternalSubagentConnector: LocalAlloc failed (%s)"), GetSystemErrorText(GetLastError(), errorText, 1024));
+               nxlog_debug(2, _T("ExternalSubagentConnector(%s): LocalAlloc failed (%s)"), 
+         subagent->getName(), GetSystemErrorText(GetLastError(), errorText, 1024));
                goto cleanup;
        }
 
        if (!InitializeSecurityDescriptor(sd, SECURITY_DESCRIPTOR_REVISION))
        {
-               AgentWriteDebugLog(2, _T("ExternalSubagentConnector: InitializeSecurityDescriptor failed (%s)"), GetSystemErrorText(GetLastError(), errorText, 1024));
+               nxlog_debug(2, _T("ExternalSubagentConnector(%s): InitializeSecurityDescriptor failed (%s)"), 
+         subagent->getName(), GetSystemErrorText(GetLastError(), errorText, 1024));
                goto cleanup;
        }
 
        // Add the ACL to the security descriptor. 
    if (!SetSecurityDescriptorDacl(sd, TRUE, acl, FALSE))
        {
-               AgentWriteDebugLog(2, _T("ExternalSubagentConnector: SetSecurityDescriptorDacl failed (%s)"), GetSystemErrorText(GetLastError(), errorText, 1024));
+               nxlog_debug(2, _T("ExternalSubagentConnector(%s): SetSecurityDescriptorDacl failed (%s)"), 
+         subagent->getName(), GetSystemErrorText(GetLastError(), errorText, 1024));
                goto cleanup;
        }
 
@@ -525,11 +532,12 @@ static THREAD_RESULT THREAD_CALL ExternalSubagentConnector(void *arg)
        HANDLE hPipe = CreateNamedPipe(pipeName, PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, 1, 8192, 8192, 0, &sa);
        if (hPipe == INVALID_HANDLE_VALUE)
        {
-               AgentWriteDebugLog(2, _T("ExternalSubagentConnector: CreateNamedPipe failed (%s)"), GetSystemErrorText(GetLastError(), errorText, 1024));
+               nxlog_debug(2, _T("ExternalSubagentConnector(%s): CreateNamedPipe failed (%s)"), 
+         subagent->getName(), GetSystemErrorText(GetLastError(), errorText, 1024));
                goto cleanup;
        }
 
-       AgentWriteDebugLog(2, _T("ExternalSubagent(%s): named pipe created, waiting for connection"), subagent->getName());
+       nxlog_debug(2, _T("ExternalSubagentConnector(%s): named pipe created, waiting for connection"), subagent->getName());
        int connectErrors = 0;
        while(!(g_dwFlags & AF_SHUTDOWN))
        {
@@ -542,7 +550,8 @@ static THREAD_RESULT THREAD_CALL ExternalSubagentConnector(void *arg)
                }
                else
                {
-                       AgentWriteDebugLog(2, _T("ExternalSubagentConnector: ConnectNamedPipe failed (%s)"), GetSystemErrorText(GetLastError(), errorText, 1024));
+                       nxlog_debug(2, _T("ExternalSubagentConnector(%s): ConnectNamedPipe failed (%s)"), 
+            subagent->getName(), GetSystemErrorText(GetLastError(), errorText, 1024));
                        connectErrors++;
                        if (connectErrors > 10)
                                break;  // Stop this connector if ConnectNamedPipe fails instantly
index cb88af5..b40bfa2 100644 (file)
@@ -1,6 +1,6 @@
 /*
 ** NetXMS multiplatform core agent
-** Copyright (C) 2003-2016 Victor Kirhenshtein
+** Copyright (C) 2003-2017 Victor Kirhenshtein
 **
 ** 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
@@ -54,6 +54,8 @@
 #include <pwd.h>
 #endif
 
+#define DEFAULT_CONFIG_SECTION   _T("CORE")
+
 /**
  * Externals
  */
@@ -119,9 +121,9 @@ extern const TCHAR *g_szMessages[];
  * Valid options for getopt()
  */
 #if defined(_WIN32)
-#define VALID_OPTIONS   "c:CdD:e:EfhHiIKM:n:N:P:r:RsSUvX:W:Z:"
+#define VALID_OPTIONS   "c:CdD:e:EfG:hHiIKM:n:N:P:r:RsSUvW:X:Z:"
 #else
-#define VALID_OPTIONS   "c:CdD:fg:hKM:p:P:r:u:vX:W:Z:"
+#define VALID_OPTIONS   "c:CdD:fg:G:hKM:p:P:r:u:vW:X:Z:"
 #endif
 
 /**
@@ -319,8 +321,9 @@ static TCHAR m_szHelpText[] =
 #endif
        _T("   -f         : Run in foreground\n")
 #if !defined(_WIN32)
-   _T("   -g <gid>   : Chhange group ID to <gid> after start\n")
+   _T("   -g <gid>   : Change group ID to <gid> after start\n")
 #endif
+   _T("   -G <name>  : Use alternate global section <name> in configuration file\n")
    _T("   -h         : Display help and exit\n")
 #ifdef _WIN32
    _T("   -H         : Hide agent's window when in standalone mode\n")
@@ -949,6 +952,16 @@ BOOL Initialize()
       free(m_pszExtSubagentList);
    }
 
+   // Additional external subagents implicitly defined by EXT:* config sections
+   ObjectArray<ConfigEntry> *entries = g_config->getSubEntries(_T("/"), _T("EXT:*"));
+   for(int i = 0; i < entries->size(); i++)
+   {
+      const TCHAR *name = entries->get(i)->getName() + 4;
+      if (!AddExternalSubagent(name))
+         nxlog_write(MSG_ADD_EXTERNAL_SUBAGENT_FAILED, EVENTLOG_WARNING_TYPE, "s", name);
+   }
+   delete entries;
+
    // Parse application agents list
        if (!(g_dwFlags & AF_SUBAGENT_LOADER) && (m_pszAppAgentList != NULL))
    {
@@ -1248,10 +1261,11 @@ static int CreateConfig(const char *pszServer, const char *pszLogFile, const cha
 /**
  * Init config
  */
-static void InitConfig()
+static void InitConfig(const TCHAR *configSection)
 {
        g_config = new Config();
        g_config->setTopLevelTag(_T("config"));
+   g_config->setAlias(_T("agent"), configSection);
 
    // Set default data directory on Windows
 #ifdef _WIN32
@@ -1366,6 +1380,7 @@ int main(int argc, char *argv[])
    BOOL bRestart = FALSE;
    UINT32 dwOldPID, dwMainPID;
        char *eptr;
+   TCHAR configSection[MAX_DB_STRING] = DEFAULT_CONFIG_SECTION;
 #ifdef _WIN32
    TCHAR szModuleName[MAX_PATH];
    HKEY hKey;
@@ -1436,6 +1451,14 @@ int main(int argc, char *argv[])
                                gid = GetGroupId(optarg);
                                break;
 #endif
+         case 'G':
+#ifdef UNICODE
+                               MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, optarg, -1, configSection, MAX_DB_STRING);
+                               configSection[MAX_DB_STRING - 1] = 0;
+#else
+            nx_strncpy(configSection, optarg, MAX_DB_STRING);
+#endif
+            break;
          case 'h':   // Display help and exit
             iAction = ACTION_HELP;
             break;
@@ -1670,7 +1693,7 @@ int main(int argc, char *argv[])
    if (bRestart)
       DoRestartActions(dwOldPID);
 
-   InitConfig();
+   InitConfig(configSection);
 
    // Do requested action
    switch(iAction)
@@ -1707,16 +1730,24 @@ int main(int argc, char *argv[])
             }
          }
 
-                       if (g_config->loadConfig(g_szConfigFile, _T("agent")))
+                       if (g_config->loadConfig(g_szConfigFile, DEFAULT_CONFIG_SECTION))
                        {
-                               const TCHAR *dir = g_config->getValue(_T("/agent/ConfigIncludeDir"));
+                               const TCHAR *dir = g_config->getValue(_T("/%agent/ConfigIncludeDir"));
+_tprintf(_T(">>>> %s\n"), dir);
                                if (dir != NULL)
                                        nx_strncpy(g_szConfigIncludeDir, dir, MAX_PATH);
-                               g_config->loadConfigDirectory(g_szConfigIncludeDir, _T("agent"));
+                               g_config->loadConfigDirectory(g_szConfigIncludeDir, DEFAULT_CONFIG_SECTION);
+
+                          g_config->loadConfigDirectory(g_szConfigPolicyDir, DEFAULT_CONFIG_SECTION);
 
-                          g_config->loadConfigDirectory(g_szConfigPolicyDir, _T("agent"));
+            // Check if master section starts with EXT:
+            // If yes, switch to external subagent mode
+            if (!_tcsnicmp(configSection, _T("EXT:"), 4))
+            {
+               nx_strncpy(g_masterAgent, &configSection[4], MAX_PATH);
+            }
 
-                               if (g_config->parseTemplate(_T("agent"), m_cfgTemplate))
+                               if (g_config->parseTemplate(configSection, m_cfgTemplate))
                                {
                DecryptPassword(_T("netxms"), g_szSharedSecret, g_szSharedSecret, MAX_SECRET_LENGTH);
 
@@ -1795,7 +1826,7 @@ int main(int argc, char *argv[])
 #ifndef _WIN32
                                           if (gid == 0)
                                           {
-                                             const TCHAR *v = g_config->getValue(_T("/agent/GroupId"));
+                                             const TCHAR *v = g_config->getValue(_T("/%agent/GroupId"));
                                              if (v != NULL)
                                              {
 #ifdef UNICODE
@@ -1810,7 +1841,7 @@ int main(int argc, char *argv[])
                                           }
                   if (uid == 0)
                   {
-                     const TCHAR *v = g_config->getValue(_T("/agent/UserId"));
+                     const TCHAR *v = g_config->getValue(_T("/%agent/UserId"));
                      if (v != NULL)
                      {
 #ifdef UNICODE
@@ -1884,13 +1915,13 @@ int main(int argc, char *argv[])
          break;
       case ACTION_CHECK_CONFIG:
          {
-            bool validConfig = g_config->loadConfig(g_szConfigFile, _T("agent"), false);
+            bool validConfig = g_config->loadConfig(g_szConfigFile, DEFAULT_CONFIG_SECTION, false);
             if (validConfig)
             {
-               const TCHAR *dir = g_config->getValue(_T("/agent/ConfigIncludeDir"));
+                                  const TCHAR *dir = g_config->getValue(_T("/%agent/ConfigIncludeDir"));
                if (dir != NULL)
                {
-                  validConfig = g_config->loadConfigDirectory(dir, _T("agent"), false);
+                  validConfig = g_config->loadConfigDirectory(dir, DEFAULT_CONFIG_SECTION, false);
                   if (!validConfig)
                   {
                      ConsolePrintf(_T("Error reading additional configuration files from \"%s\"\n"), dir);
@@ -1900,7 +1931,7 @@ int main(int argc, char *argv[])
 
             if (validConfig)
             {
-               validConfig = g_config->loadConfigDirectory(g_szConfigPolicyDir, _T("agent"));
+               validConfig = g_config->loadConfigDirectory(g_szConfigPolicyDir, DEFAULT_CONFIG_SECTION);
                if (!validConfig)
                {
                   ConsolePrintf(_T("Error reading additional configuration files from \"%s\"\n"), g_szConfigPolicyDir);
@@ -1910,7 +1941,7 @@ int main(int argc, char *argv[])
             if (validConfig)
             {
                g_config->print(stdout);
-               validConfig = g_config->parseTemplate(_T("agent"), m_cfgTemplate);
+               validConfig = g_config->parseTemplate(configSection, m_cfgTemplate);
             }
 
             if (!validConfig)
index af00c16..678c2db 100644 (file)
@@ -130,7 +130,7 @@ static THREAD_RESULT THREAD_CALL PushConnector(void *arg)
        ea.grfAccessPermissions = (FILE_GENERIC_READ | FILE_GENERIC_WRITE) & ~FILE_CREATE_PIPE_INSTANCE;
        ea.grfAccessMode = SET_ACCESS;
        ea.grfInheritance = NO_INHERITANCE;
-       const TCHAR *user = g_config->getValue(_T("/agent/PushUser"), _T("*"));
+       const TCHAR *user = g_config->getValue(_T("/%agent/PushUser"), _T("*"));
        if ((user[0] == 0) || !_tcscmp(user, _T("*")))
        {
                ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
index 519ec22..f214b8a 100644 (file)
@@ -72,7 +72,7 @@ static THREAD_RESULT THREAD_CALL StorageDiscoveryConnector(void *arg)
        ea.grfAccessPermissions = (FILE_GENERIC_READ | FILE_GENERIC_WRITE) & ~FILE_CREATE_PIPE_INSTANCE;
        ea.grfAccessMode = SET_ACCESS;
        ea.grfInheritance = NO_INHERITANCE;
-       const TCHAR *user = g_config->getValue(_T("/agent/StorageDiscoveryUser"), _T("*"));
+       const TCHAR *user = g_config->getValue(_T("/%agent/StorageDiscoveryUser"), _T("*"));
        if ((user[0] == 0) || !_tcscmp(user, _T("*")))
        {
                ea.Trustee.TrusteeForm = TRUSTEE_IS_SID;
index 14b3e8a..8c827e2 100644 (file)
@@ -126,7 +126,7 @@ static TCHAR *ExpandValue(const TCHAR *src)
 /**
  * Constructor for config entry
  */
-ConfigEntry::ConfigEntry(const TCHAR *name, ConfigEntry *parent, const TCHAR *file, int line, int id)
+ConfigEntry::ConfigEntry(const TCHAR *name, ConfigEntry *parent, const Config *owner, const TCHAR *file, int line, int id)
 {
    m_name = _tcsdup(CHECK_NULL(name));
    m_first = NULL;
@@ -140,6 +140,7 @@ ConfigEntry::ConfigEntry(const TCHAR *name, ConfigEntry *parent, const TCHAR *fi
    m_file = _tcsdup(CHECK_NULL(file));
    m_line = line;
    m_id = id;
+   m_owner = owner;
 }
 
 /**
@@ -176,10 +177,20 @@ void ConfigEntry::setName(const TCHAR *name)
  */
 ConfigEntry* ConfigEntry::findEntry(const TCHAR *name)
 {
-   ConfigEntry *e;
-
-   for(e = m_first; e != NULL; e = e->getNext())
-      if (!_tcsicmp(e->getName(), name))
+   const TCHAR *realName;
+   if (name[0] == _T('%'))
+   {
+      const TCHAR *alias = m_owner->getAlias(&name[1]);
+      if (alias == NULL)
+         return NULL;
+      realName = alias;
+   }
+   else
+   {
+      realName = name;
+   }
+   for(ConfigEntry *e = m_first; e != NULL; e = e->getNext())
+      if (!_tcsicmp(e->getName(), realName))
          return e;
    return NULL;
 }
@@ -189,13 +200,22 @@ ConfigEntry* ConfigEntry::findEntry(const TCHAR *name)
  */
 ConfigEntry* ConfigEntry::createEntry(const TCHAR *name)
 {
-   ConfigEntry *e;
+   const TCHAR *realName;
+   if (name[0] == _T('%'))
+   {
+      const TCHAR *alias = m_owner->getAlias(&name[1]);
+      realName = (alias != NULL) ? alias : &name[1];
+   }
+   else
+   {
+      realName = name;
+   }
 
-   for(e = m_first; e != NULL; e = e->getNext())
-      if (!_tcsicmp(e->getName(), name))
+   for(ConfigEntry *e = m_first; e != NULL; e = e->getNext())
+      if (!_tcsicmp(e->getName(), realName))
          return e;
 
-   return new ConfigEntry(name, this, _T("<memory>"), 0, 0);
+   return new ConfigEntry(realName, this, m_owner, _T("<memory>"), 0, 0);
 }
 
 /**
@@ -667,7 +687,7 @@ void ConfigEntry::createXml(String &xml, int level)
  */
 Config::Config()
 {
-   m_root = new ConfigEntry(_T("[root]"), NULL, NULL, 0, 0);
+   m_root = new ConfigEntry(_T("[root]"), NULL, this, NULL, 0, 0);
    m_errorCount = 0;
    m_mutex = MutexCreate();
 }
@@ -949,16 +969,16 @@ ObjectArray<ConfigEntry> *Config::getOrderedSubEntries(const TCHAR *path, const
  */
 ConfigEntry *Config::getEntry(const TCHAR *path)
 {
-   const TCHAR *curr, *end;
-   TCHAR name[256];
-   ConfigEntry *entry = m_root;
-
    if ((path == NULL) || (*path != _T('/')))
       return NULL;
 
    if (!_tcscmp(path, _T("/")))
       return m_root;
 
+   TCHAR name[256];
+   const TCHAR *curr, *end;
+   ConfigEntry *entry = m_root;
+
    curr = path + 1;
    while(entry != NULL)
    {
@@ -1008,14 +1028,14 @@ ConfigEntry *Config::createEntry(const TCHAR *path)
          entry = parent->findEntry(name);
          curr = end + 1;
          if (entry == NULL)
-            entry = new ConfigEntry(name, parent, _T("<memory>"), 0, 0);
+            entry = new ConfigEntry(name, parent, this, _T("<memory>"), 0, 0);
          parent = entry;
       }
       else
       {
          entry = parent->findEntry(curr);
          if (entry == NULL)
-            entry = new ConfigEntry(curr, parent, _T("<memory>"), 0, 0);
+            entry = new ConfigEntry(curr, parent, this, _T("<memory>"), 0, 0);
       }
    }
    while(end != NULL);
@@ -1162,7 +1182,7 @@ bool Config::loadIniConfig(const TCHAR *file, const TCHAR *defaultIniSection, bo
    currentSection = m_root->findEntry(defaultIniSection);
    if (currentSection == NULL)
    {
-      currentSection = new ConfigEntry(defaultIniSection, m_root, file, 0, 0);
+      currentSection = new ConfigEntry(defaultIniSection, m_root, this, file, 0, 0);
    }
 
    while(!feof(cfg))
@@ -1202,7 +1222,7 @@ bool Config::loadIniConfig(const TCHAR *file, const TCHAR *defaultIniSection, bo
          currentSection = m_root->findEntry(&buffer[1]);
          if (currentSection == NULL)
          {
-            currentSection = new ConfigEntry(&buffer[1], m_root, file, sourceLine, 0);
+            currentSection = new ConfigEntry(&buffer[1], m_root, this, file, sourceLine, 0);
          }
       }
       else
@@ -1223,7 +1243,7 @@ bool Config::loadIniConfig(const TCHAR *file, const TCHAR *defaultIniSection, bo
          ConfigEntry *entry = currentSection->findEntry(buffer);
          if (entry == NULL)
          {
-            entry = new ConfigEntry(buffer, currentSection, file, sourceLine, 0);
+            entry = new ConfigEntry(buffer, currentSection, this, file, sourceLine, 0);
          }
          entry->addValuePreallocated(ExpandValue(ptr));
       }
@@ -1309,7 +1329,7 @@ static void StartElement(void *userData, const char *name, const char **attrs)
          ps->stack[ps->level] = merge ? ps->stack[ps->level - 1]->findEntry(entryName) : NULL;
          if (ps->stack[ps->level] == NULL)
          {
-            ConfigEntry *e = new ConfigEntry(entryName, ps->stack[ps->level - 1], ps->file, XML_GetCurrentLineNumber(ps->parser), (int)id);
+            ConfigEntry *e = new ConfigEntry(entryName, ps->stack[ps->level - 1], ps->config, ps->file, XML_GetCurrentLineNumber(ps->parser), (int)id);
             ps->stack[ps->level] = e;
             // add all attributes to the entry
             for(int i = 0; attrs[i] != NULL; i += 2)
index 9a1dc3f..42b294d 100644 (file)
@@ -1472,7 +1472,7 @@ int LIBNETXMS_EXPORTABLE NumCharsA(const char *pszStr, char ch)
 /**
  * Match string against regexp (UNICODE version)
  */
-BOOL LIBNETXMS_EXPORTABLE RegexpMatchW(const WCHAR *str, const WCHAR *expr, bool matchCase)
+bool LIBNETXMS_EXPORTABLE RegexpMatchW(const WCHAR *str, const WCHAR *expr, bool matchCase)
 {
    regex_t preg;
    bool result = false;
@@ -1490,7 +1490,7 @@ BOOL LIBNETXMS_EXPORTABLE RegexpMatchW(const WCHAR *str, const WCHAR *expr, bool
 /**
  * Match string against regexp (multibyte version)
  */
-BOOL LIBNETXMS_EXPORTABLE RegexpMatchA(const char *str, const char *expr, bool matchCase)
+bool LIBNETXMS_EXPORTABLE RegexpMatchA(const char *str, const char *expr, bool matchCase)
 {
    regex_t preg;
    bool result = false;