change log updated
[public/netxms.git] / include / nms_util.h
index 1a51b9a..6896ff1 100644 (file)
 #define LIBNETXMS_EXPORTABLE
 #endif
 
-
 #include <nms_common.h>
+#include <nxatomic.h>
 #include <nms_cscp.h>
 #include <nms_threads.h>
 #include <time.h>
+#include <jansson.h>
+
+// JSON_EMBED was added in jansson 2.10 - ignore it for older version
+#ifndef JSON_EMBED
+#define JSON_EMBED 0
+#endif
+
+#if HAVE_POLL_H
+#include <poll.h>
+#endif
 
 #if HAVE_BYTESWAP_H
 #include <byteswap.h>
@@ -82,7 +92,7 @@ inline UINT32 bswap_32(UINT32 val)
 {
    UINT32 result;
    BYTE *sptr = (BYTE *)&val;
-   BYTE *dptr = (BYTE *)&result + 7;
+   BYTE *dptr = (BYTE *)&result + 3;
    for(int i = 0; i < 4; i++, sptr++, dptr--)
       *dptr = *sptr;
    return result;
@@ -111,9 +121,32 @@ inline double bswap_double(double val)
    return result;
 }
 
+#else
+
+#if !(HAVE_DECL_BSWAP_16)
+UINT16 LIBNETXMS_EXPORTABLE __bswap_16(UINT16 val);
+#define bswap_16 __bswap_16
+#endif
+
+#if !(HAVE_DECL_BSWAP_32)
+UINT32 LIBNETXMS_EXPORTABLE __bswap_32(UINT32 val);
+#define bswap_32 __bswap_32
+#endif
+
+#if !(HAVE_DECL_BSWAP_64)
+UINT64 LIBNETXMS_EXPORTABLE __bswap_64(UINT64 val);
+#define bswap_64 __bswap_64
+#endif
+
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 void LIBNETXMS_EXPORTABLE bswap_array_16(UINT16 *v, int len);
 void LIBNETXMS_EXPORTABLE bswap_array_32(UINT32 *v, int len);
-
+#ifdef __cplusplus
+}
 #endif
 
 
@@ -386,6 +419,7 @@ char LIBNETXMS_EXPORTABLE *MBStringFromUCS4String(const UCS4CHAR *src);
 
 /******* end of UNICODE related conversion and helper functions *******/
 
+
 /**
  * Class for serial communications
  */
@@ -454,6 +488,66 @@ public:
 };
 
 /**
+ * Class that can store any object with connected to it mutex
+ */
+template <class T> class ObjectLock
+{
+private:
+   Mutex m_mutex;
+   T *m_object;
+
+public:
+   ObjectLock() { m_object = NULL; }
+   ObjectLock(T *object) { m_object = object; }
+   ObjectLock(const ObjectLock<T> &src) { m_object = src.m_object; m_mutex = src.m_mutex; }
+
+   void lock() { m_mutex.lock(); }
+   void unlock() { m_mutex.unlock(); }
+
+   T *get() { return m_object; }
+   void set(T *object) { m_object = object; }
+
+   operator T*() { return m_object; }
+   ObjectLock<T>& operator =(const ObjectLock<T> &src)
+   {
+      m_object = src.m_object;
+      m_mutex = src.m_mutex;
+      return *this;
+   }
+};
+
+/**
+ * Pair class (stores pair of items)
+ */
+template <typename T1, typename T2> class Pair
+{
+private:
+   T1 value1;
+   T2 value2;
+
+public:
+   Pair() { }
+   Pair(const T1& v1, const T2& v2)
+   {
+      value1 = v1;
+      value2 = v2;
+   }
+   Pair(const Pair<T1, T2>& src)
+   {
+      value1 = src.value1;
+      value2 = src.value2;
+   }
+
+   Pair<T1, T2>& operator=(const Pair<T1, T2> &src)
+   {
+      return Pair<T1, T2>(src.value1, src.value2);
+   }
+
+   const T1& first() const { return value1; }
+   const T2& second() const { return value2; }
+};
+
+/**
  * Dynamic string class
  */
 class LIBNETXMS_EXPORTABLE String
@@ -478,12 +572,17 @@ public:
    size_t getAllocationStep() { return m_allocationStep; }
    void setAllocationStep(size_t step) { m_allocationStep = step; }
 
-   const String& operator =(const TCHAR *str);
-       const String& operator =(const String &src);
-   const String&  operator +=(const TCHAR *str);
-   const String&  operator +=(const String &str);
+   String& operator =(const TCHAR *str);
+       String& operator =(const String &src);
+   String& operator +=(const TCHAR *str);
+   String& operator +=(const String &str);
+   String operator +(const String &right) const;
+   String operator +(const TCHAR *right) const;
    operator const TCHAR*() const { return CHECK_NULL_EX(m_buffer); }
 
+   bool operator ==(const String &s) const { return equals(s); }
+   bool operator !=(const String &s) const { return !equals(s); }
+
        char *getUTF8String();
 
    void append(const TCHAR *str) { if (str != NULL) append(str, _tcslen(str)); }
@@ -507,15 +606,28 @@ public:
        size_t length() const { return m_length; }
        bool isEmpty() const { return m_length == 0; }
 
+       bool equals(const String& s) const;
+       bool equals(const TCHAR *s) const;
+   bool startsWith(const String& s) const;
+   bool startsWith(const TCHAR *s) const;
+   bool endsWith(const String& s) const;
+   bool endsWith(const TCHAR *s) const;
+
        wchar_t charAt(size_t pos) const { return (pos < m_length) ? m_buffer[pos] : 0; }
 
-       TCHAR *substring(int nStart, int nLen, TCHAR *pszBuffer = NULL);
-       int find(const TCHAR *str, int nStart = 0);
+   String substring(size_t start, ssize_t len) const;
+       TCHAR *substring(size_t start, ssize_t len, TCHAR *buffer) const;
+       String left(size_t len) const { return substring(0, static_cast<ssize_t>(len)); }
+   String right(size_t len) const { return substring((m_length > len) ? m_length - len : 0, static_cast<ssize_t>(len)); }
+
+   StringList *split(const TCHAR *separator) const;
+
+       int find(const TCHAR *str, size_t start = 0) const;
 
    void escapeCharacter(int ch, int esc);
    void replace(const TCHAR *pszSrc, const TCHAR *pszDst);
        void trim();
-       void shrink(int chars = 1);
+       void shrink(size_t chars = 1);
 };
 
 /**
@@ -523,6 +635,11 @@ public:
  */
 class LIBNETXMS_EXPORTABLE AbstractIterator
 {
+   DISABLE_COPY_CTOR(AbstractIterator)
+
+protected:
+   AbstractIterator();
+
 public:
    virtual ~AbstractIterator();
 
@@ -536,6 +653,8 @@ public:
  */
 template <class T> class Iterator
 {
+   DISABLE_COPY_CTOR(Iterator)
+
 private:
    AbstractIterator *m_worker;
 
@@ -553,6 +672,8 @@ public:
  */
 class LIBNETXMS_EXPORTABLE Array
 {
+   DISABLE_COPY_CTOR(Array)
+
 private:
        int m_size;
        int m_allocated;
@@ -582,6 +703,7 @@ public:
    int indexOf(void *element) const;
        void set(int index, void *element);
        void replace(int index, void *element);
+   void insert(int index, void *element);
        void remove(int index) { internalRemove(index, true); }
    void remove(void *element) { internalRemove(indexOf(element), true); }
        void unlink(int index) { internalRemove(index, false); }
@@ -591,6 +713,7 @@ public:
    void *find(const void *key, int (*cb)(const void *, const void *)) const;
 
        int size() const { return m_size; }
+       bool isEmpty() const { return m_size == 0; }
 
        void setOwner(bool owner) { m_objectOwner = owner; }
        bool isOwner() const { return m_objectOwner; }
@@ -601,6 +724,8 @@ public:
  */
 class LIBNETXMS_EXPORTABLE ArrayIterator : public AbstractIterator
 {
+   DISABLE_COPY_CTOR(ArrayIterator)
+
 private:
    Array *m_array;
    int m_pos;
@@ -618,6 +743,8 @@ public:
  */
 template <class T> class ObjectArray : public Array
 {
+   DISABLE_COPY_CTOR(ObjectArray)
+
 private:
        static void destructor(void *object) { delete (T*)object; }
 
@@ -627,6 +754,44 @@ public:
 
        int add(T *object) { return Array::add((void *)object); }
        T *get(int index) const { return (T*)Array::get(index); }
+       T *first() const { return get(0); }
+       T *last() const { return get(size() - 1); }
+   int indexOf(T *object) const { return Array::indexOf((void *)object); }
+   bool contains(T *object) const { return indexOf(object) >= 0; }
+       void set(int index, T *object) { Array::set(index, (void *)object); }
+       void replace(int index, T *object) { Array::replace(index, (void *)object); }
+   void insert(int index, T *object) { Array::insert(index, (void *)object); }
+       void remove(int index) { Array::remove(index); }
+   void remove(T *object) { Array::remove((void *)object); }
+       void unlink(int index) { Array::unlink(index); }
+   void unlink(T *object) { Array::unlink((void *)object); }
+
+   void sort(int (*cb)(const T **, const T **)) { Array::sort((int (*)(const void *, const void *))cb); }
+   T *find(const T *key, int (*cb)(const T **, const T **)) const
+   {
+      T **result = (T **)Array::find(&key, (int (*)(const void *, const void *))cb);
+      return (result != NULL) ? *result : NULL;
+   }
+
+   Iterator<T> *iterator() { return new Iterator<T>(new ArrayIterator(this)); }
+};
+
+/**
+ * Template class for dynamic array which holds references to objects with inaccessible destructors
+ */
+template <class T> class ObjectRefArray : public Array
+{
+   DISABLE_COPY_CTOR(ObjectRefArray)
+
+private:
+       static void destructor(void *object) { }
+
+public:
+       ObjectRefArray(int initial = 0, int grow = 16) : Array(initial, grow, false) { m_objectDestructor = destructor; }
+       virtual ~ObjectRefArray() { }
+
+       int add(T *object) { return Array::add((void *)object); }
+       T *get(int index) const { return (T*)Array::get(index); }
    int indexOf(T *object) const { return Array::indexOf((void *)object); }
    bool contains(T *object) const { return indexOf(object) >= 0; }
        void set(int index, T *object) { Array::set(index, (void *)object); }
@@ -644,6 +809,8 @@ public:
  */
 template <class T> class IntegerArray : public Array
 {
+   DISABLE_COPY_CTOR(IntegerArray)
+
 private:
        static void destructor(void *element) { }
 
@@ -660,6 +827,8 @@ public:
    void replace(int index, T value) { Array::replace(index, m_storePointers ? CAST_TO_POINTER(value, void *) : &value); }
 
    T *getBuffer() const { return (T*)__getBuffer(); }
+
+   json_t *toJson() const { json_t *a = json_array(); for(int i = 0; i < size(); i++) json_array_append_new(a, json_integer(get(i))); return a; }
 };
 
 /**
@@ -667,6 +836,8 @@ public:
  */
 template <class T> class StructArray : public Array
 {
+   DISABLE_COPY_CTOR(StructArray)
+
 private:
        static void destructor(void *element) { }
 
@@ -715,9 +886,10 @@ protected:
    bool m_ignoreCase;
        void (*m_objectDestructor)(void *);
 
-       StringMapEntry *find(const TCHAR *key) const;
+       StringMapEntry *find(const TCHAR *key, int keyLen) const;
        void setObject(TCHAR *key, void *value, bool keyPreAlloc);
        void *getObject(const TCHAR *key) const;
+   void *getObject(const TCHAR *key, size_t len) const;
        void destroyObject(void *object) { if (object != NULL) m_objectDestructor(object); }
 
 public:
@@ -732,7 +904,8 @@ public:
    void filterElements(bool (*filter)(const TCHAR *, const void *, void *), void *userData);
 
        int size() const;
-   bool contains(const TCHAR *key) const { return find(key) != NULL; }
+   bool contains(const TCHAR *key) const { return (key != NULL) ? (find(key, (int)_tcslen(key) * sizeof(TCHAR)) != NULL) : false; }
+   bool contains(const TCHAR *key, size_t len) const { return (key != NULL) ? (find(key, (int)len * sizeof(TCHAR)) != NULL) : false; }
 
    EnumerationCallbackResult forEach(EnumerationCallbackResult (*cb)(const TCHAR *, const void *, void *), void *userData) const;
    const void *findElement(bool (*comparator)(const TCHAR *, const void *, void *), void *userData) const;
@@ -762,9 +935,10 @@ public:
        void setPreallocated(TCHAR *key, TCHAR *value) { setObject(key, value, true); }
        void set(const TCHAR *key, UINT32 value);
 
-   void addAll(StringMap *src);
+   void addAll(const StringMap *src);
 
        const TCHAR *get(const TCHAR *key) const { return (const TCHAR *)getObject(key); }
+   const TCHAR *get(const TCHAR *key, size_t len) const { return (const TCHAR *)getObject(key, len); }
    INT32 getInt32(const TCHAR *key, INT32 defaultValue) const;
        UINT32 getUInt32(const TCHAR *key, UINT32 defaultValue) const;
    INT64 getInt64(const TCHAR *key, INT64 defaultValue) const;
@@ -774,6 +948,8 @@ public:
 
    void fillMessage(NXCPMessage *msg, UINT32 sizeFieldId, UINT32 baseFieldId) const;
    void loadMessage(const NXCPMessage *msg, UINT32 sizeFieldId, UINT32 baseFieldId);
+
+   json_t *toJson() const;
 };
 
 /**
@@ -781,6 +957,8 @@ public:
  */
 template <class T> class StringObjectMap : public StringMapBase
 {
+   DISABLE_COPY_CTOR(StringObjectMap)
+
 private:
        static void destructor(void *object) { delete (T*)object; }
 
@@ -790,6 +968,7 @@ public:
        void set(const TCHAR *key, T *object) { setObject((TCHAR *)key, (void *)object, false); }
        void setPreallocated(TCHAR *key, T *object) { setObject((TCHAR *)key, (void *)object, true); }
        T *get(const TCHAR *key) const { return (T*)getObject(key); }
+   T *get(const TCHAR *key, size_t len) const { return (T*)getObject(key, len); }
 };
 
 /**
@@ -805,6 +984,7 @@ private:
 public:
        StringList();
        StringList(const StringList *src);
+   StringList(const StringList &src);
        StringList(const TCHAR *src, const TCHAR *separator);
        ~StringList();
 
@@ -823,18 +1003,25 @@ public:
 #else
        void addMBString(const char *value) { add(value); }
 #endif
+   void addAll(const StringList *src);
+   void merge(const StringList *src, bool matchCase);
+   void splitAndAdd(const TCHAR *src, const TCHAR *separator);
+   void remove(int index);
        void clear();
+
+   void sort(bool ascending = true, bool caseSensitive = false);
+
        int size() const { return m_count; }
+       bool isEmpty() const { return m_count == 0; }
        const TCHAR *get(int index) const { return ((index >=0) && (index < m_count)) ? m_values[index] : NULL; }
        int indexOf(const TCHAR *value) const;
+       bool contains(const TCHAR *value) const { return indexOf(value) != -1; }
        int indexOfIgnoreCase(const TCHAR *value) const;
-       void remove(int index);
-   void addAll(const StringList *src);
-   void merge(const StringList *src, bool matchCase);
+   bool containsIgnoreCase(const TCHAR *value) const { return indexOfIgnoreCase(value) != -1; }
    TCHAR *join(const TCHAR *separator);
-   void splitAndAdd(const TCHAR *src, const TCHAR *separator);
-   void sort(bool ascending = true, bool caseSensitive = false);
+
    void fillMessage(NXCPMessage *msg, UINT32 baseId, UINT32 countId);
+   json_t *toJson() const;
 };
 
 /**
@@ -857,6 +1044,8 @@ class StringSet;
  */
 class LIBNETXMS_EXPORTABLE StringSetIterator : public AbstractIterator
 {
+   DISABLE_COPY_CTOR(StringSetIterator)
+
 private:
    StringSet *m_stringSet;
    StringSetEntry *m_curr;
@@ -956,6 +1145,8 @@ public:
  */
 class LIBNETXMS_EXPORTABLE HashMapIterator : public AbstractIterator
 {
+   DISABLE_COPY_CTOR(HashMapIterator)
+
 private:
    HashMapBase *m_hashMap;
    HashMapEntry *m_curr;
@@ -1000,6 +1191,7 @@ public:
    RefCountHashMap(bool objectOwner = false) : HashMapBase(objectOwner, sizeof(K)) { m_objectDestructor = destructor; }
 
    V *get(const K& key) { V *v = (V*)_get(&key); if (v != NULL) v->incRefCount(); return v; }
+   V *peek(const K& key) { return (V*)_get(&key); }
    void set(const K& key, V *value) { if (value != NULL) value->incRefCount(); _set(&key, (void *)value); }
    void remove(const K& key) { _remove(&key); }
    bool contains(const K& key) { return _contains(&key); }
@@ -1008,10 +1200,38 @@ public:
 };
 
 /**
+ * Ring buffer
+ */
+class LIBNETXMS_EXPORTABLE RingBuffer
+{
+   DISABLE_COPY_CTOR(RingBuffer)
+
+private:
+   BYTE *m_data;
+   size_t m_size;
+   size_t m_allocated;
+   size_t m_allocationStep;
+   size_t m_readPos;
+   size_t m_writePos;
+
+public:
+   RingBuffer(size_t initial = 8192, size_t allocationStep = 8192);
+   ~RingBuffer();
+
+   void write(const BYTE *data, size_t dataSize);
+   size_t read(BYTE *buffer, size_t bufferSize);
+
+   size_t size() const { return m_size; }
+   bool isEmpty() const { return m_size == 0; }
+};
+
+/**
  * Byte stream
  */
 class LIBNETXMS_EXPORTABLE ByteStream
 {
+   DISABLE_COPY_CTOR(ByteStream)
+
 private:
    BYTE *m_data;
    size_t m_size;
@@ -1068,6 +1288,8 @@ public:
  */
 class LIBNETXMS_EXPORTABLE RefCountObject
 {
+   DISABLE_COPY_CTOR(RefCountObject)
+
 private:
        VolatileCounter m_refCount;
 
@@ -1099,6 +1321,8 @@ class NXCPMessage;
  */
 class LIBNETXMS_EXPORTABLE TableColumnDefinition
 {
+   DISABLE_COPY_CTOR(TableColumnDefinition)
+
 private:
    TCHAR *m_name;
    TCHAR *m_displayName;
@@ -1107,16 +1331,16 @@ private:
 
 public:
    TableColumnDefinition(const TCHAR *name, const TCHAR *displayName, INT32 dataType, bool isInstance);
-   TableColumnDefinition(NXCPMessage *msg, UINT32 baseId);
-   TableColumnDefinition(TableColumnDefinition *src);
+   TableColumnDefinition(const NXCPMessage *msg, UINT32 baseId);
+   TableColumnDefinition(const TableColumnDefinition *src);
    ~TableColumnDefinition();
 
-   void fillMessage(NXCPMessage *msg, UINT32 baseId);
+   void fillMessage(NXCPMessage *msg, UINT32 baseId) const;
 
-   const TCHAR *getName() { return m_name; }
-   const TCHAR *getDisplayName() { return m_displayName; }
-   INT32 getDataType() { return m_dataType; }
-   bool isInstanceColumn() { return m_instanceColumn; }
+   const TCHAR *getName() const { return m_name; }
+   const TCHAR *getDisplayName() const { return m_displayName; }
+   INT32 getDataType() const { return m_dataType; }
+   bool isInstanceColumn() const { return m_instanceColumn; }
 
    void setDataType(INT32 type) { m_dataType = type; }
    void setInstanceColumn(bool isInstance) { m_instanceColumn = isInstance; }
@@ -1128,6 +1352,8 @@ public:
  */
 class TableCell
 {
+   DISABLE_COPY_CTOR(TableCell)
+
 private:
    TCHAR *m_value;
    int m_status;
@@ -1143,14 +1369,14 @@ public:
    void set(const TCHAR *value, int status, UINT32 objectId) { safe_free(m_value); m_value = _tcsdup_ex(value); m_status = status; m_objectId = objectId; }
    void setPreallocated(TCHAR *value, int status, UINT32 objectId) { safe_free(m_value); m_value = value; m_status = status; m_objectId = objectId; }
 
-   const TCHAR *getValue() { return m_value; }
+   const TCHAR *getValue() const { return m_value; }
    void setValue(const TCHAR *value) { safe_free(m_value); m_value = _tcsdup_ex(value); }
    void setPreallocatedValue(TCHAR *value) { free(m_value); m_value = value; }
 
-   int getStatus() { return m_status; }
+   int getStatus() const { return m_status; }
    void setStatus(int status) { m_status = status; }
 
-   int getObjectId() { return m_objectId; }
+   int getObjectId() const { return m_objectId; }
    void setObjectId(UINT32 id) { m_objectId = id; }
 };
 
@@ -1159,9 +1385,12 @@ public:
  */
 class TableRow
 {
+   DISABLE_COPY_CTOR(TableRow)
+
 private:
    ObjectArray<TableCell> *m_cells;
    UINT32 m_objectId;
+   int m_baseRow;
 
 public:
    TableRow(int columnCount);
@@ -1179,13 +1408,16 @@ public:
 
    void setStatus(int index, int status) { TableCell *c = m_cells->get(index); if (c != NULL) c->setStatus(status); }
 
-   const TCHAR *getValue(int index) { TableCell *c = m_cells->get(index); return (c != NULL) ? c->getValue() : NULL; }
-   int getStatus(int index) { TableCell *c = m_cells->get(index); return (c != NULL) ? c->getStatus() : -1; }
+   const TCHAR *getValue(int index) const { const TableCell *c = m_cells->get(index); return (c != NULL) ? c->getValue() : NULL; }
+   int getStatus(int index) const { const TableCell *c = m_cells->get(index); return (c != NULL) ? c->getStatus() : -1; }
 
-   UINT32 getObjectId() { return m_objectId; }
+   UINT32 getObjectId() const { return m_objectId; }
    void setObjectId(UINT32 id) { m_objectId = id; }
 
-   UINT32 getCellObjectId(int index) { TableCell *c = m_cells->get(index); return (c != NULL) ? c->getObjectId() : 0; }
+   int getBaseRow() const { return m_baseRow; }
+   void setBaseRow(int baseRow) { m_baseRow = baseRow; }
+
+   UINT32 getCellObjectId(int index) const { const TableCell *c = m_cells->get(index); return (c != NULL) ? c->getObjectId() : 0; }
    void setCellObjectId(int index, UINT32 id) { TableCell *c = m_cells->get(index); if (c != NULL) c->setObjectId(id); }
 };
 
@@ -1194,6 +1426,8 @@ public:
  */
 class LIBNETXMS_EXPORTABLE Table : public RefCountObject
 {
+   DISABLE_COPY_CTOR(Table)
+
 private:
    ObjectArray<TableRow> *m_data;
    ObjectArray<TableColumnDefinition> *m_columns;
@@ -1217,22 +1451,24 @@ public:
    void addAll(Table *src);
    void copyRow(Table *src, int row);
 
-   int getNumRows() { return m_data->size(); }
-   int getNumColumns() { return m_columns->size(); }
-       const TCHAR *getTitle() { return CHECK_NULL_EX(m_title); }
-   int getSource() { return m_source; }
+   int getNumRows() const { return m_data->size(); }
+   int getNumColumns() const { return m_columns->size(); }
+       const TCHAR *getTitle() const { return CHECK_NULL_EX(m_title); }
+   int getSource() const { return m_source; }
 
    bool isExtendedFormat() { return m_extendedFormat; }
    void setExtendedFormat(bool ext) { m_extendedFormat = ext; }
 
-   const TCHAR *getColumnName(int col) { return ((col >= 0) && (col < m_columns->size())) ? m_columns->get(col)->getName() : NULL; }
-   INT32 getColumnDataType(int col) { return ((col >= 0) && (col < m_columns->size())) ? m_columns->get(col)->getDataType() : 0; }
-       int getColumnIndex(const TCHAR *name);
+   const TCHAR *getColumnName(int col) const { return ((col >= 0) && (col < m_columns->size())) ? m_columns->get(col)->getName() : NULL; }
+   INT32 getColumnDataType(int col) const { return ((col >= 0) && (col < m_columns->size())) ? m_columns->get(col)->getDataType() : 0; }
+   const TableColumnDefinition *getColumnDefinition(int col) const { return m_columns->get(col); }
+       int getColumnIndex(const TCHAR *name) const;
    ObjectArray<TableColumnDefinition> *getColumnDefinitions() { return m_columns; }
 
        void setTitle(const TCHAR *title) { safe_free(m_title); m_title = _tcsdup_ex(title); }
    void setSource(int source) { m_source = source; }
    int addColumn(const TCHAR *name, INT32 dataType = 0, const TCHAR *displayName = NULL, bool isInstance = false);
+   int addColumn(const TableColumnDefinition *d);
    void setColumnDataType(int col, INT32 dataType) { if ((col >= 0) && (col < m_columns->size())) m_columns->get(col)->setDataType(dataType); }
    int addRow();
 
@@ -1263,33 +1499,94 @@ public:
    void setStatusAt(int row, int col, int status);
    void setStatus(int col, int status) { setStatusAt(getNumRows() - 1, col, status); }
 
-   const TCHAR *getAsString(int nRow, int nCol);
-   INT32 getAsInt(int nRow, int nCol);
-   UINT32 getAsUInt(int nRow, int nCol);
-   INT64 getAsInt64(int nRow, int nCol);
-   UINT64 getAsUInt64(int nRow, int nCol);
-   double getAsDouble(int nRow, int nCol);
+   const TCHAR *getAsString(int nRow, int nCol, const TCHAR *defaultValue = NULL) const;
+   INT32 getAsInt(int nRow, int nCol) const;
+   UINT32 getAsUInt(int nRow, int nCol) const;
+   INT64 getAsInt64(int nRow, int nCol) const;
+   UINT64 getAsUInt64(int nRow, int nCol) const;
+   double getAsDouble(int nRow, int nCol) const;
 
-   int getStatus(int nRow, int nCol);
+   int getStatus(int nRow, int nCol) const;
 
    void buildInstanceString(int row, TCHAR *buffer, size_t bufLen);
    int findRowByInstance(const TCHAR *instance);
 
-   UINT32 getObjectId(int row) { TableRow *r = m_data->get(row); return (r != NULL) ? r->getObjectId() : 0; }
-   void setObjectId(int row, UINT32 id) { TableRow *r = m_data->get(row); if (r != NULL) r->setObjectId(id); }
+   UINT32 getObjectId(int row) const { const TableRow *r = m_data->get(row); return (r != NULL) ? r->getObjectId() : 0; }
+   void setObjectIdAt(int row, UINT32 id) { TableRow *r = m_data->get(row); if (r != NULL) r->setObjectId(id); }
+   void setObjectId(UINT32 id) { setObjectIdAt(getNumRows() - 1, id); }
 
    void setCellObjectIdAt(int row, int col, UINT32 objectId);
    void setCellObjectId(int col, UINT32 objectId) { setCellObjectIdAt(getNumRows() - 1, col, objectId); }
-   UINT32 getCellObjectId(int row, int col) { TableRow *r = m_data->get(row); return (r != NULL) ? r->getCellObjectId(col) : 0; }
+   UINT32 getCellObjectId(int row, int col) const { const TableRow *r = m_data->get(row); return (r != NULL) ? r->getCellObjectId(col) : 0; }
+
+   void setBaseRowAt(int row, int baseRow);
+   void setBaseRow(int baseRow) { setBaseRowAt(getNumRows() - 1, baseRow); }
+   int getBaseRow(int row) const { const TableRow *r = m_data->get(row); return (r != NULL) ? r->getBaseRow() : 0; }
 
    static Table *createFromXML(const char *xml);
-   TCHAR *createXML();
+   TCHAR *createXML() const;
 
    static Table *createFromPackedXML(const char *packedXml);
-   char *createPackedXML();
+   char *createPackedXML() const;
 };
 
 /**
+ * Create JSON string with null check
+ */
+inline json_t *json_string_a(const char *s)
+{
+   return (s != NULL) ? json_string(s) : json_null();
+}
+
+/**
+ * Create JSON string from wide character string
+ */
+inline json_t *json_string_w(const WCHAR *s)
+{
+   if (s == NULL)
+      return json_null();
+   char *us = UTF8StringFromWideString(s);
+   json_t *js = json_string(us);
+   free(us);
+   return js;
+}
+
+#ifdef UNICODE
+#define json_string_t json_string_w
+#else
+#define json_string_t json_string_a
+#endif
+
+/**
+ * Create JSON array from integer array
+ */
+template<typename T> json_t *json_integer_array(const T *values, size_t size)
+{
+   json_t *a = json_array();
+   for(size_t i = 0; i < size; i++)
+      json_array_append_new(a, json_integer(values[i]));
+   return a;
+}
+
+/**
+ * Serialize ObjectArray as JSON
+ */
+template<typename T> json_t *json_object_array(ObjectArray<T> *a)
+{
+   json_t *root = json_array();
+   if (a != NULL)
+   {
+      for(int i = 0; i < a->size(); i++)
+      {
+         T *e = a->get(i);
+         if (e != NULL)
+            json_array_append_new(root, e->toJson());
+      }
+   }
+   return root;
+}
+
+/**
  * sockaddr buffer
  */
 union SockAddrBuffer
@@ -1303,6 +1600,7 @@ union SockAddrBuffer
 /**
  * sockaddr length calculation
  */
+#undef SA_LEN
 #ifdef WITH_IPV6
 #define SA_LEN(sa) (((sa)->sa_family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6))
 #else
@@ -1334,6 +1632,47 @@ inline bool SocketAddressEquals(struct sockaddr *a1, struct sockaddr *a2)
    return false;
 }
 
+enum MacAddressNotation
+{
+   MAC_ADDR_FLAT_STRING = 0,
+   MAC_ADDR_COLON_SEPARATED = 1,
+   MAC_ADDR_BYTEPAIR_COLON_SEPARATED = 2,
+   MAC_ADDR_HYPHEN_SEPARATED = 3,
+   MAC_ADDR_DOT_SEPARATED = 4,
+   MAC_ADDR_BYTEPAIR_DOT_SEPARATED = 5
+};
+
+/**
+ * MAC address
+ */
+class LIBNETXMS_EXPORTABLE MacAddress
+{
+private:
+   BYTE m_value[16];
+   size_t m_length;
+
+   TCHAR *toStringInternal(TCHAR *buffer, const TCHAR separator, bool bytePair = false) const;
+   TCHAR *toStringInternal3(TCHAR *buffer, const TCHAR separator) const;
+
+public:
+   MacAddress() { m_length = 0; memset(m_value, 0, 16); }
+   MacAddress(const BYTE *value, size_t length) { m_length = MIN(length, 16); memcpy(m_value, value, m_length); }
+   MacAddress(const MacAddress& src) { memcpy(m_value, src.m_value, src.m_length); m_length = src.m_length; }
+
+   static MacAddress parse(const char *str);
+   static MacAddress parse(const WCHAR *str);
+
+   const BYTE *value() const { return m_value; }
+   size_t length() const { return m_length; }
+
+   bool isMulticast() const;
+   bool isBroadcast() const;
+   bool equals(const MacAddress &a) const;
+
+   TCHAR *toString(TCHAR *buffer, MacAddressNotation notation = MAC_ADDR_COLON_SEPARATED) const;
+   String toString(MacAddressNotation notation = MAC_ADDR_COLON_SEPARATED) const;
+};
+
 /**
  * IP address
  */
@@ -1387,6 +1726,8 @@ public:
    char *toStringA(char *buffer) const { return toString(buffer); }
 #endif
 
+   json_t *toJson() const;
+
    BYTE *buildHashKey(BYTE *key) const;
 
    TCHAR *getHostByAddr(TCHAR *buffer, size_t buflen) const;
@@ -1408,6 +1749,8 @@ public:
  */
 class LIBNETXMS_EXPORTABLE InetAddressList
 {
+   DISABLE_COPY_CTOR(InetAddressList)
+
 private:
    ObjectArray<InetAddress> *m_list;
 
@@ -1436,6 +1779,8 @@ public:
    const ObjectArray<InetAddress> *getList() const { return m_list; }
 
    void fillMessage(NXCPMessage *msg, UINT32 sizeFieldId, UINT32 baseFieldId) const;
+
+   json_t *toJson() const { return json_object_array(m_list); }
 };
 
 /**
@@ -1443,13 +1788,16 @@ public:
  */
 class LIBNETXMS_EXPORTABLE SocketConnection
 {
+   DISABLE_COPY_CTOR(SocketConnection)
+
 protected:
        SOCKET m_socket;
        char m_data[4096];
        int m_dataPos;
 
+   SocketConnection();
+
 public:
-       SocketConnection();
        virtual ~SocketConnection();
 
        bool connectTCP(const TCHAR *hostName, WORD port, UINT32 timeout);
@@ -1471,15 +1819,21 @@ public:
  */
 class LIBNETXMS_EXPORTABLE TelnetConnection : public SocketConnection
 {
+   DISABLE_COPY_CTOR(TelnetConnection)
+
 protected:
+   TelnetConnection() : SocketConnection() { }
+
        bool connectTCP(const TCHAR *hostName, WORD port, UINT32 timeout);
        bool connectTCP(const InetAddress& ip, WORD port, UINT32 timeout);
 
+   bool connect(const TCHAR *hostName, WORD port, UINT32 timeout);
+   bool connect(const InetAddress& ip, WORD port, UINT32 timeout);
+
 public:
        static TelnetConnection *createConnection(const TCHAR *hostName, WORD port, UINT32 timeout);
+   static TelnetConnection *createConnection(const InetAddress& ip, WORD port, UINT32 timeout);
 
-   bool connect(const TCHAR *hostName, WORD port, UINT32 timeout);
-       bool connect(const InetAddress& ip, WORD port, UINT32 timeout);
        virtual int read(char *pBuff, int nSize, UINT32 timeout = INFINITE);
        int readLine(char *buffer, int size, UINT32 timeout = INFINITE);
 };
@@ -1489,6 +1843,8 @@ public:
  */
 class LIBNETXMS_EXPORTABLE PostalAddress
 {
+   DISABLE_COPY_CTOR(PostalAddress)
+
 private:
    TCHAR *m_country;
    TCHAR *m_city;
@@ -1505,10 +1861,90 @@ public:
    const TCHAR *getStreetAddress() const { return CHECK_NULL_EX(m_streetAddress); }
    const TCHAR *getPostCode() const { return CHECK_NULL_EX(m_postcode); }
 
-   void setCountry(const TCHAR *country) { safe_free(m_country); m_country = _tcsdup_ex(country); }
-   void setCity(const TCHAR *city) { safe_free(m_city); m_city = _tcsdup_ex(city); }
-   void setStreetAddress(const TCHAR *streetAddress) { safe_free(m_streetAddress); m_streetAddress = _tcsdup_ex(streetAddress); }
-   void setPostCode(const TCHAR *postcode) { safe_free(m_postcode); m_postcode = _tcsdup_ex(postcode); }
+   json_t *toJson() const;
+
+   void setCountry(const TCHAR *country) { free(m_country); m_country = _tcsdup_ex(country); }
+   void setCity(const TCHAR *city) { free(m_city); m_city = _tcsdup_ex(city); }
+   void setStreetAddress(const TCHAR *streetAddress) { free(m_streetAddress); m_streetAddress = _tcsdup_ex(streetAddress); }
+   void setPostCode(const TCHAR *postcode) { free(m_postcode); m_postcode = _tcsdup_ex(postcode); }
+};
+
+/**
+ * Max number of polled sockets
+ */
+#define SOCKET_POLLER_MAX_SOCKETS    16
+
+/**
+ * Socket poller
+ */
+class LIBNETXMS_EXPORTABLE SocketPoller
+{
+   DISABLE_COPY_CTOR(SocketPoller)
+
+private:
+   bool m_write;
+   int m_count;
+#if HAVE_POLL
+   struct pollfd m_sockets[SOCKET_POLLER_MAX_SOCKETS];
+#else
+   fd_set m_sockets;
+#ifndef _WIN32
+   SOCKET m_maxfd;
+#endif
+#endif
+
+public:
+   SocketPoller(bool write = false);
+   ~SocketPoller();
+
+   bool add(SOCKET s);
+   int poll(UINT32 timeout);
+   bool isSet(SOCKET s);
+   void reset();
+};
+
+/**
+ * Abstract communication channel
+ */
+class LIBNETXMS_EXPORTABLE AbstractCommChannel : public RefCountObject
+{
+   DISABLE_COPY_CTOR(AbstractCommChannel)
+
+protected:
+   virtual ~AbstractCommChannel();
+
+public:
+   AbstractCommChannel();
+
+   virtual int send(const void *data, size_t size, MUTEX mutex = INVALID_MUTEX_HANDLE) = 0;
+   virtual int recv(void *buffer, size_t size, UINT32 timeout = INFINITE) = 0;
+   virtual int poll(UINT32 timeout, bool write = false) = 0;
+   virtual int shutdown() = 0;
+   virtual void close() = 0;
+};
+
+/**
+ * Socket communication channel
+ */
+class LIBNETXMS_EXPORTABLE SocketCommChannel : public AbstractCommChannel
+{
+   DISABLE_COPY_CTOR(SocketCommChannel)
+
+private:
+   SOCKET m_socket;
+   bool m_owner;
+
+protected:
+   virtual ~SocketCommChannel();
+
+public:
+   SocketCommChannel(SOCKET socket, bool owner = true);
+
+   virtual int send(const void *data, size_t size, MUTEX mutex = INVALID_MUTEX_HANDLE);
+   virtual int recv(void *buffer, size_t size, UINT32 timeout = INFINITE);
+   virtual int poll(UINT32 timeout, bool write = false);
+   virtual int shutdown();
+   virtual void close();
 };
 
 #endif   /* __cplusplus */
@@ -1550,20 +1986,22 @@ typedef struct __CODE_TO_TEXT
 
 #ifdef _WIN32
 
+#define DT_UNKNOWN   0
+#define DT_REG       1
+#define DT_DIR       2
+
 typedef struct dirent
 {
    long            d_ino;  /* inode number (not used by MS-DOS) */
+   unsigned char   d_type; /* file type */
    int             d_namlen;       /* Name length */
-   char            d_name[257];    /* file name */
+   char            d_name[MAX_PATH];    /* file name */
 } _DIRECT;
 
 typedef struct _dir_struc
 {
-   char           *start;  /* Starting position */
-   char           *curr;   /* Current position */
-   long            size;   /* Size of string table */
-   long            nfiles; /* number if filenames in table */
-   struct dirent   dirstr; /* Directory structure to return */
+   HANDLE handle;
+   struct dirent dirstr; /* Directory structure to return */
 } DIR;
 
 #ifdef UNICODE
@@ -1571,16 +2009,14 @@ typedef struct _dir_struc
 typedef struct dirent_w
 {
    long            d_ino;  /* inode number (not used by MS-DOS) */
+   unsigned char   d_type; /* file type */
    int             d_namlen;       /* Name length */
-   WCHAR           d_name[257];    /* file name */
+   WCHAR           d_name[MAX_PATH];    /* file name */
 } _DIRECTW;
 
 typedef struct _dir_struc_w
 {
-   WCHAR          *start;  /* Starting position */
-   WCHAR          *curr;   /* Current position */
-   long            size;   /* Size of string table */
-   long            nfiles; /* number if filenames in table */
+   HANDLE handle;
    struct dirent_w dirstr; /* Directory structure to return */
 } DIRW;
 
@@ -1601,6 +2037,9 @@ typedef struct _dir_struc_w
 typedef struct dirent_w
 {
    long            d_ino;  /* inode number */
+#if HAVE_DIRENT_D_TYPE
+   unsigned char   d_type; /* file type */
+#endif
    WCHAR           d_name[257];    /* file name */
 } _DIRECTW;
 
@@ -1613,38 +2052,19 @@ typedef struct _dir_struc_w
 #endif   /* _WIN32 */
 
 
+/***** For compatibility *****/
+#ifdef UNICODE
+#define nx_strncpy      wcslcpy
+#else
+#define nx_strncpy      strlcpy
+#endif
+
 //
 // Functions
 //
 
 #ifdef __cplusplus
 
-inline TCHAR *nx_strncpy(TCHAR *pszDest, const TCHAR *pszSrc, size_t nLen)
-{
-#if defined(_WIN32) && (_MSC_VER >= 1400)
-       _tcsncpy_s(pszDest, nLen, pszSrc, _TRUNCATE);
-#else
-   _tcsncpy(pszDest, pszSrc, nLen - 1);
-   pszDest[nLen - 1] = 0;
-#endif
-   return pszDest;
-}
-
-#ifdef UNICODE
-inline char *nx_strncpy_mb(char *pszDest, const char *pszSrc, size_t nLen)
-{
-#if defined(_WIN32) && (_MSC_VER >= 1400)
-       strncpy_s(pszDest, nLen, pszSrc, _TRUNCATE);
-#else
-   strncpy(pszDest, pszSrc, nLen - 1);
-   pszDest[nLen - 1] = 0;
-#endif
-   return pszDest;
-}
-#else
-#define nx_strncpy_mb nx_strncpy
-#endif
-
 int LIBNETXMS_EXPORTABLE ConnectEx(SOCKET s, struct sockaddr *addr, int len, UINT32 timeout);
 int LIBNETXMS_EXPORTABLE SendEx(SOCKET hSocket, const void *data, size_t len, int flags, MUTEX mutex);
 int LIBNETXMS_EXPORTABLE RecvEx(SOCKET hSocket, void *data, size_t len, int flags, UINT32 timeout);
@@ -1659,7 +2079,7 @@ extern "C"
 {
 #endif
 
-void LIBNETXMS_EXPORTABLE InitNetXMSProcess();
+void LIBNETXMS_EXPORTABLE InitNetXMSProcess(bool commandLineTool);
 
 #ifndef _WIN32
 #if defined(UNICODE_UCS2) || defined(UNICODE_UCS4)
@@ -1701,8 +2121,8 @@ TCHAR LIBNETXMS_EXPORTABLE *SockaddrToStr(struct sockaddr *addr, TCHAR *buffer);
 void LIBNETXMS_EXPORTABLE *nx_memdup(const void *data, size_t size);
 void LIBNETXMS_EXPORTABLE nx_memswap(void *block1, void *block2, size_t size);
 
-WCHAR LIBNETXMS_EXPORTABLE *BinToStrW(const BYTE *data, size_t size, WCHAR *pStr);
-char LIBNETXMS_EXPORTABLE *BinToStrA(const BYTE *data, size_t size, char *pStr);
+WCHAR LIBNETXMS_EXPORTABLE *BinToStrW(const void *data, size_t size, WCHAR *str);
+char LIBNETXMS_EXPORTABLE *BinToStrA(const void *data, size_t size, char *str);
 #ifdef UNICODE
 #define BinToStr BinToStrW
 #else
@@ -1751,8 +2171,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
@@ -1761,16 +2181,13 @@ BOOL LIBNETXMS_EXPORTABLE RegexpMatchW(const WCHAR *str, const WCHAR *expr, bool
 
 const TCHAR LIBNETXMS_EXPORTABLE *ExpandFileName(const TCHAR *name, TCHAR *buffer, size_t bufSize, bool allowShellCommand);
 BOOL LIBNETXMS_EXPORTABLE CreateFolder(const TCHAR *directory);
+bool LIBNETXMS_EXPORTABLE SetLastModificationTime(TCHAR *fileName, time_t lastModDate);
 TCHAR LIBNETXMS_EXPORTABLE *Trim(TCHAR *str);
 bool LIBNETXMS_EXPORTABLE MatchString(const TCHAR *pattern, const TCHAR *str, bool matchCase);
 TCHAR LIBNETXMS_EXPORTABLE **SplitString(const TCHAR *source, TCHAR sep, int *numStrings);
 int LIBNETXMS_EXPORTABLE GetLastMonthDay(struct tm *currTime);
-#ifdef __cplusplus
-bool LIBNETXMS_EXPORTABLE MatchScheduleElement(TCHAR *pszPattern, int nValue, int maxValue, struct tm *localTime, time_t currTime = 0);
-#else
 bool LIBNETXMS_EXPORTABLE MatchScheduleElement(TCHAR *pszPattern, int nValue, int maxValue, struct tm *localTime, time_t currTime);
-#endif
-
+bool LIBNETXMS_EXPORTABLE MatchSchedule(const TCHAR *schedule, struct tm *currTime, time_t now);
 
 #ifdef __cplusplus
 BOOL LIBNETXMS_EXPORTABLE IsValidObjectName(const TCHAR *pszName, BOOL bExtendedChars = FALSE);
@@ -1787,21 +2204,42 @@ BYTE LIBNETXMS_EXPORTABLE *LoadFileA(const char *pszFileName, UINT32 *pdwFileSiz
 #endif
 
 UINT32 LIBNETXMS_EXPORTABLE CalculateCRC32(const unsigned char *data, UINT32 size, UINT32 dwCRC);
-void LIBNETXMS_EXPORTABLE CalculateMD5Hash(const unsigned char *data, size_t nbytes, unsigned char *hash);
-void LIBNETXMS_EXPORTABLE MD5HashForPattern(const unsigned char *data, size_t patternSize, size_t fullSize, BYTE *hash);
-void LIBNETXMS_EXPORTABLE CalculateSHA1Hash(unsigned char *data, size_t nbytes, unsigned char *hash);
-void LIBNETXMS_EXPORTABLE SHA1HashForPattern(unsigned char *data, size_t patternSize, size_t fullSize, unsigned char *hash);
-void LIBNETXMS_EXPORTABLE CalculateSHA256Hash(const unsigned char *data, size_t len, unsigned char *hash);
+BOOL LIBNETXMS_EXPORTABLE CalculateFileCRC32(const TCHAR *pszFileName, UINT32 *pResult);
+
+typedef unsigned char MD5_STATE[128];
+
+void LIBNETXMS_EXPORTABLE CalculateMD5Hash(const BYTE *data, size_t nbytes, BYTE *hash);
+void LIBNETXMS_EXPORTABLE MD5HashForPattern(const BYTE *data, size_t patternSize, size_t fullSize, BYTE *hash);
 BOOL LIBNETXMS_EXPORTABLE CalculateFileMD5Hash(const TCHAR *pszFileName, BYTE *pHash);
+void LIBNETXMS_EXPORTABLE MD5Init(MD5_STATE *state);
+void LIBNETXMS_EXPORTABLE MD5Update(MD5_STATE *state, const BYTE *data, size_t size);
+void LIBNETXMS_EXPORTABLE MD5Finish(MD5_STATE *state, BYTE *hash);
+
+typedef unsigned char SHA1_STATE[128];
+
+void LIBNETXMS_EXPORTABLE CalculateSHA1Hash(const BYTE *data, size_t nbytes, BYTE *hash);
+void LIBNETXMS_EXPORTABLE SHA1HashForPattern(const BYTE *data, size_t patternSize, size_t fullSize, BYTE *hash);
 BOOL LIBNETXMS_EXPORTABLE CalculateFileSHA1Hash(const TCHAR *pszFileName, BYTE *pHash);
-BOOL LIBNETXMS_EXPORTABLE CalculateFileCRC32(const TCHAR *pszFileName, UINT32 *pResult);
+void LIBNETXMS_EXPORTABLE SHA1Init(SHA1_STATE *state);
+void LIBNETXMS_EXPORTABLE SHA1Update(SHA1_STATE *state, const BYTE *data, size_t size);
+void LIBNETXMS_EXPORTABLE SHA1Finish(SHA1_STATE *state, BYTE *hash);
+
+void LIBNETXMS_EXPORTABLE CalculateSHA256Hash(const BYTE *data, size_t len, BYTE *hash);
 
 void LIBNETXMS_EXPORTABLE GenerateRandomBytes(BYTE *buffer, size_t size);
 
+void LIBNETXMS_EXPORTABLE LogOpenSSLErrorStack(int level);
+
 void LIBNETXMS_EXPORTABLE ICEEncryptData(const BYTE *in, int inLen, BYTE *out, const BYTE *key);
 void LIBNETXMS_EXPORTABLE ICEDecryptData(const BYTE *in, int inLen, BYTE *out, const BYTE *key);
 
-bool LIBNETXMS_EXPORTABLE DecryptPassword(const TCHAR *login, const TCHAR *encryptedPasswd, TCHAR *decryptedPasswd, size_t bufferLenght);
+bool LIBNETXMS_EXPORTABLE DecryptPasswordW(const WCHAR *login, const WCHAR *encryptedPasswd, WCHAR *decryptedPasswd, size_t bufferLenght);
+bool LIBNETXMS_EXPORTABLE DecryptPasswordA(const char *login, const char *encryptedPasswd, char *decryptedPasswd, size_t bufferLenght);
+#ifdef UNICODE
+#define DecryptPassword DecryptPasswordW
+#else
+#define DecryptPassword DecryptPasswordA
+#endif
 
 int LIBNETXMS_EXPORTABLE NxDCIDataTypeFromText(const TCHAR *pszText);
 
@@ -1828,9 +2266,14 @@ long LIBNETXMS_EXPORTABLE ExtractNamedOptionValueAsIntA(const char *optString, c
 #endif
 
 #ifdef __cplusplus
-const TCHAR LIBNETXMS_EXPORTABLE *CodeToText(int iCode, CODE_TO_TEXT *pTranslator, const TCHAR *pszDefaultText = _T("Unknown"));
+const TCHAR LIBNETXMS_EXPORTABLE *CodeToText(int code, CODE_TO_TEXT *translator, const TCHAR *defaultText = _T("Unknown"));
+#else
+const TCHAR LIBNETXMS_EXPORTABLE *CodeToText(int code, CODE_TO_TEXT *translator, const TCHAR *defaultText);
+#endif
+#ifdef __cplusplus
+int LIBNETXMS_EXPORTABLE CodeFromText(const TCHAR *text, CODE_TO_TEXT *translator, int defaultCode = -1);
 #else
-const TCHAR LIBNETXMS_EXPORTABLE *CodeToText(int iCode, CODE_TO_TEXT *pTranslator, const TCHAR *pszDefaultText);
+int LIBNETXMS_EXPORTABLE CodeFromText(const TCHAR *text, CODE_TO_TEXT *translator, int defaultCode);
 #endif
 
 #ifdef _WIN32
@@ -1839,6 +2282,10 @@ BOOL LIBNETXMS_EXPORTABLE GetWindowsVersionString(TCHAR *versionString, int strS
 INT64 LIBNETXMS_EXPORTABLE GetProcessRSS();
 #endif
 
+TCHAR LIBNETXMS_EXPORTABLE *GetLastSocketErrorText(TCHAR *buffer, size_t size);
+
+TCHAR LIBNETXMS_EXPORTABLE *GetLocalHostName(TCHAR *buffer, size_t size, bool fqdn);
+
 #if !HAVE_DAEMON || !HAVE_DECL_DAEMON
 int LIBNETXMS_EXPORTABLE __daemon(int nochdir, int noclose);
 #define daemon __daemon
@@ -1856,6 +2303,7 @@ int LIBNETXMS_EXPORTABLE MultiByteToWideChar(int iCodePage, UINT32 dwFlags, cons
                                              int cchByteChar, WCHAR *pWideCharStr,
                                              int cchWideChar);
 
+#ifdef UNICODE
 int LIBNETXMS_EXPORTABLE nx_wprintf(const WCHAR *format, ...);
 int LIBNETXMS_EXPORTABLE nx_fwprintf(FILE *fp, const WCHAR *format, ...);
 int LIBNETXMS_EXPORTABLE nx_swprintf(WCHAR *buffer, size_t size, const WCHAR *format, ...);
@@ -1869,6 +2317,7 @@ int LIBNETXMS_EXPORTABLE nx_swscanf(const WCHAR *str, const WCHAR *format, ...);
 int LIBNETXMS_EXPORTABLE nx_vwscanf(const WCHAR *format, va_list args);
 int LIBNETXMS_EXPORTABLE nx_vfwscanf(FILE *fp, const WCHAR *format, va_list args);
 int LIBNETXMS_EXPORTABLE nx_vswscanf(const WCHAR *str, const WCHAR *format, va_list args);
+#endif
 
 #endif /* _WIN32 */
 
@@ -1903,6 +2352,9 @@ int wchdir(const WCHAR *_path);
 #if !HAVE_WMKDIR
 int wmkdir(const WCHAR *_path, int mode);
 #endif
+#if !HAVE_WUTIME
+int wutime(const WCHAR *_path, struct utimbuf *buf);
+#endif
 #if !HAVE_WRMDIR
 int wrmdir(const WCHAR *_path);
 #endif
@@ -1960,10 +2412,30 @@ INT64 LIBNETXMS_EXPORTABLE wcstoll(const WCHAR *nptr, WCHAR **endptr, int base);
 UINT64 LIBNETXMS_EXPORTABLE wcstoull(const WCHAR *nptr, WCHAR **endptr, int base);
 #endif
 
+#if !HAVE_STRLWR && !defined(_WIN32)
+char LIBNETXMS_EXPORTABLE *strlwr(char *str);
+#endif
+
 #if !HAVE_WCSLWR && !defined(_WIN32)
 WCHAR LIBNETXMS_EXPORTABLE *wcslwr(WCHAR *str);
 #endif
 
+#if !HAVE_STRLCPY
+size_t LIBNETXMS_EXPORTABLE strlcpy(char *dst, const char *src, size_t size);
+#endif
+
+#if !HAVE_WCSLCPY
+size_t LIBNETXMS_EXPORTABLE wcslcpy(WCHAR *dst, const WCHAR *src, size_t size);
+#endif
+
+#if !HAVE_STRLCAT
+size_t LIBNETXMS_EXPORTABLE strlcat(char *dst, const char *src, size_t size);
+#endif
+
+#if !HAVE_WCSLCAT
+size_t LIBNETXMS_EXPORTABLE wcslcat(WCHAR *dst, const WCHAR *src, size_t size);
+#endif
+
 #if !HAVE_WCSCASECMP && !defined(_WIN32)
 int LIBNETXMS_EXPORTABLE wcscasecmp(const wchar_t *s1, const wchar_t *s2);
 #endif
@@ -2002,9 +2474,9 @@ WCHAR LIBNETXMS_EXPORTABLE *_itow(int value, WCHAR *str, int base);
 
 #ifdef _WIN32
 #ifdef UNICODE
-DIRW LIBNETXMS_EXPORTABLE *wopendir(const WCHAR *filename);
-struct dirent_w LIBNETXMS_EXPORTABLE *wreaddir(DIRW *dirp);
-int LIBNETXMS_EXPORTABLE wclosedir(DIRW *dirp);
+DIRW LIBNETXMS_EXPORTABLE *wopendir(const WCHAR *path);
+struct dirent_w LIBNETXMS_EXPORTABLE *wreaddir(DIRW *p);
+int LIBNETXMS_EXPORTABLE wclosedir(DIRW *p);
 
 #define _topendir wopendir
 #define _treaddir wreaddir
@@ -2015,9 +2487,9 @@ int LIBNETXMS_EXPORTABLE wclosedir(DIRW *dirp);
 #define _tclosedir closedir
 #endif
 
-DIR LIBNETXMS_EXPORTABLE *opendir(const char *filename);
-struct dirent LIBNETXMS_EXPORTABLE *readdir(DIR *dirp);
-int LIBNETXMS_EXPORTABLE closedir(DIR *dirp);
+DIR LIBNETXMS_EXPORTABLE *opendir(const char *path);
+struct dirent LIBNETXMS_EXPORTABLE *readdir(DIR *p);
+int LIBNETXMS_EXPORTABLE closedir(DIR *p);
 
 #else  /* not _WIN32 */
 
@@ -2037,17 +2509,47 @@ int LIBNETXMS_EXPORTABLE alphasort(const struct dirent **a, const struct dirent
 TCHAR LIBNETXMS_EXPORTABLE *safe_fgetts(TCHAR *buffer, int len, FILE *f);
 
 bool LIBNETXMS_EXPORTABLE nxlog_open(const TCHAR *logName, UINT32 flags, const TCHAR *msgModule,
-                                     unsigned int msgCount, const TCHAR **messages, DWORD debugMsg);
-void LIBNETXMS_EXPORTABLE nxlog_close(void);
+                                     unsigned int msgCount, const TCHAR **messages,
+                                     DWORD debugMsg, DWORD debugMsgTag, DWORD genericMsg);
+void LIBNETXMS_EXPORTABLE nxlog_close();
 void LIBNETXMS_EXPORTABLE nxlog_write(DWORD msg, WORD wType, const char *format, ...);
+void LIBNETXMS_EXPORTABLE nxlog_write_generic(WORD type, const TCHAR *format, ...);
 void LIBNETXMS_EXPORTABLE nxlog_debug(int level, const TCHAR *format, ...);
 void LIBNETXMS_EXPORTABLE nxlog_debug2(int level, const TCHAR *format, va_list args);
+void LIBNETXMS_EXPORTABLE nxlog_debug_tag(const TCHAR *tag, int level, const TCHAR *format, ...);
+void LIBNETXMS_EXPORTABLE nxlog_debug_tag2(const TCHAR *tag, int level, const TCHAR *format, va_list args);
+void LIBNETXMS_EXPORTABLE nxlog_debug_tag_object(const TCHAR *tag, UINT32 objectId, int level, const TCHAR *format, ...);
+void LIBNETXMS_EXPORTABLE nxlog_debug_tag_object2(const TCHAR *tag, UINT32 objectId, int level, const TCHAR *format, va_list args);
 bool LIBNETXMS_EXPORTABLE nxlog_set_rotation_policy(int rotationMode, UINT64 maxLogSize, int historySize, const TCHAR *dailySuffix);
 bool LIBNETXMS_EXPORTABLE nxlog_rotate();
 void LIBNETXMS_EXPORTABLE nxlog_set_debug_level(int level);
+void LIBNETXMS_EXPORTABLE nxlog_set_debug_level_tag(const TCHAR *tags, int level);
 int LIBNETXMS_EXPORTABLE nxlog_get_debug_level();
+int LIBNETXMS_EXPORTABLE nxlog_get_debug_level_tag(const TCHAR *tag);
+int LIBNETXMS_EXPORTABLE nxlog_get_debug_level_tag_object(const TCHAR *tag, UINT32 objectId);
 
-typedef void (*NxLogDebugWriter)(const TCHAR *);
+#ifdef __cplusplus
+
+/**
+ * Debug tag information
+ */
+struct DebugTagInfo
+{
+   TCHAR tag[64];
+   int level;
+
+   DebugTagInfo(const TCHAR *_tag, int _level)
+   {
+      _tcslcpy(tag, _tag, 64);
+      level = _level;
+   }
+};
+
+ObjectArray<DebugTagInfo> LIBNETXMS_EXPORTABLE *nxlog_get_all_debug_tags();
+
+#endif   /* __cplusplus */
+
+typedef void (*NxLogDebugWriter)(const TCHAR *, const TCHAR *);
 void LIBNETXMS_EXPORTABLE nxlog_set_debug_writer(NxLogDebugWriter writer);
 
 typedef void (*NxLogConsoleWriter)(const TCHAR *, ...);
@@ -2060,6 +2562,8 @@ void LIBNETXMS_EXPORTABLE WriteToTerminalEx(const TCHAR *format, ...)
 #endif
 ;
 
+bool LIBNETXMS_EXPORTABLE ReadPassword(const TCHAR *prompt, TCHAR *buffer, size_t bufferSize);
+
 #ifdef _WIN32
 int LIBNETXMS_EXPORTABLE mkstemp(char *tmpl);
 int LIBNETXMS_EXPORTABLE wmkstemp(WCHAR *tmpl);
@@ -2070,11 +2574,6 @@ int LIBNETXMS_EXPORTABLE wmkstemp(WCHAR *tmpl);
 #endif
 #endif
 
-#ifndef _WIN32
-int strcat_s(char *dst, size_t dstSize, const char *src);
-int wcscat_s(WCHAR *dst, size_t dstSize, const WCHAR *src);
-#endif
-
 #if !HAVE_STRPTIME
 char LIBNETXMS_EXPORTABLE *strptime(const char *buf, const char *fmt, struct tm *_tm);
 #endif
@@ -2137,9 +2636,15 @@ String LIBNETXMS_EXPORTABLE EscapeStringForAgent(const TCHAR *s);
 StringList LIBNETXMS_EXPORTABLE *ParseCommandLine(const TCHAR *cmdline);
 
 #if !defined(_WIN32) && !defined(_NETWARE) && defined(NMS_THREADS_H_INCLUDED)
+void LIBNETXMS_EXPORTABLE BlockAllSignals(bool processWide, bool allowInterrupt);
 void LIBNETXMS_EXPORTABLE StartMainLoop(ThreadFunction pfSignalHandler, ThreadFunction pfMain);
 #endif
 
+String LIBNETXMS_EXPORTABLE GenerateLineDiff(const String& left, const String& right);
+
+bool LIBNETXMS_EXPORTABLE DeflateFile(const TCHAR *inputFile, const TCHAR *outputFile = NULL);
+int LIBNETXMS_EXPORTABLE DeflateFileStream(FILE *source, FILE *dest, bool gzipFormat);
+
 #endif
 
 #endif   /* _nms_util_h_ */