- Added component locks
authorVictor Kirhenshtein <victor@netxms.org>
Wed, 10 Mar 2004 22:00:36 +0000 (22:00 +0000)
committerVictor Kirhenshtein <victor@netxms.org>
Wed, 10 Mar 2004 22:00:36 +0000 (22:00 +0000)
- Added event processing policy

13 files changed:
.gitattributes
src/server/core/NmsCore.dsp
src/server/core/epp.cpp [new file with mode: 0644]
src/server/core/events.cpp
src/server/core/evproc.cpp
src/server/core/locks.cpp [new file with mode: 0644]
src/server/core/log.cpp
src/server/core/main.cpp
src/server/core/messages.mc
src/server/core/nms_core.h
src/server/core/nms_events.h
src/server/core/tools.cpp
src/server/core/users.cpp

index 43f8d09..dc70c3b 100644 (file)
@@ -88,10 +88,12 @@ src/server/core/debug.cpp -text
 src/server/core/discovery.cpp -text
 src/server/core/dload.cpp -text
 src/server/core/entirenet.cpp -text
+src/server/core/epp.cpp -text
 src/server/core/events.cpp -text
 src/server/core/evproc.cpp -text
 src/server/core/hk.cpp -text
 src/server/core/interface.cpp -text
+src/server/core/locks.cpp -text
 src/server/core/log.cpp -text
 src/server/core/main.cpp -text
 src/server/core/messages.mc -text
index a11a9b4..19eadf1 100644 (file)
@@ -139,6 +139,10 @@ SOURCE=.\entirenet.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\epp.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\events.cpp
 # End Source File
 # Begin Source File
@@ -155,6 +159,10 @@ SOURCE=.\interface.cpp
 # End Source File
 # Begin Source File
 
+SOURCE=.\locks.cpp
+# End Source File
+# Begin Source File
+
 SOURCE=.\log.cpp
 # End Source File
 # Begin Source File
diff --git a/src/server/core/epp.cpp b/src/server/core/epp.cpp
new file mode 100644 (file)
index 0000000..bd3e4e0
--- /dev/null
@@ -0,0 +1,176 @@
+/* 
+** NetXMS - Network Management System
+** Copyright (C) 2003, 2004 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
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+** $module: epp.cpp
+**
+**/
+
+#include "nms_core.h"
+
+
+//
+// Event policy rule constructor
+//
+
+EPRule::EPRule(DWORD dwId, char *szComment, DWORD dwFlags)
+{
+   m_dwId = dwId;
+   m_dwFlags = dwFlags;
+   m_dwNumSources = 0;
+   m_pSourceList = NULL;
+   m_dwNumEvents = 0;
+   m_pdwEventList = NULL;
+   m_dwNumActions = 0;
+   m_pdwActionList = NULL;
+   m_pszComment = strdup(szComment);
+}
+
+
+//
+// Event policy rule destructor
+//
+
+EPRule::~EPRule()
+{
+   safe_free(m_pSourceList);
+   safe_free(m_pdwEventList);
+   safe_free(m_pdwActionList);
+   safe_free(m_pszComment);
+}
+
+
+//
+// Load rule from database
+//
+
+BOOL EPRule::LoadFromDB(void)
+{
+   DB_RESULT hResult;
+   char szQuery[256];
+   BOOL bSuccess = TRUE;
+   DWORD i;
+   
+   // Load rule's sources
+   sprintf(szQuery, "SELECT source_type,object_id FROM PolicySourceList WHERE rule_id=%ld", m_dwId);
+   hResult = DBSelect(g_hCoreDB, szQuery);
+   if (hResult != NULL)
+   {
+      m_dwNumSources = DBGetNumRows(hResult);
+      m_pSourceList = (EVENT_SOURCE *)malloc(sizeof(EVENT_SOURCE) * m_dwNumSources);
+      for(i = 0; i < m_dwNumSources; i++)
+      {
+         m_pSourceList[i].iType = DBGetFieldLong(hResult, i, 0);
+         m_pSourceList[i].dwObjectId = DBGetFieldULong(hResult, i, 1);
+      }
+      DBFreeResult(hResult);
+   }
+   else
+   {
+      bSuccess = FALSE;
+   }
+
+   // Load rule's events
+   sprintf(szQuery, "SELECT event_id FROM PolicyEventList WHERE rule_id=%ld", m_dwId);
+   hResult = DBSelect(g_hCoreDB, szQuery);
+   if (hResult != NULL)
+   {
+      m_dwNumEvents = DBGetNumRows(hResult);
+      m_pdwEventList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumEvents);
+      for(i = 0; i < m_dwNumEvents; i++)
+         m_pdwEventList[i] = DBGetFieldULong(hResult, i, 0);
+      DBFreeResult(hResult);
+   }
+   else
+   {
+      bSuccess = FALSE;
+   }
+
+   // Load rule's sources
+   sprintf(szQuery, "SELECT action_id FROM PolicyActionList WHERE rule_id=%ld", m_dwId);
+   hResult = DBSelect(g_hCoreDB, szQuery);
+   if (hResult != NULL)
+   {
+      m_dwNumActions = DBGetNumRows(hResult);
+      m_pdwActionList = (DWORD *)malloc(sizeof(DWORD) * m_dwNumActions);
+      for(i = 0; i < m_dwNumActions; i++)
+         m_pdwActionList[i] = DBGetFieldULong(hResult, i, 0);
+      DBFreeResult(hResult);
+   }
+   else
+   {
+      bSuccess = FALSE;
+   }
+
+   return bSuccess;
+}
+
+
+//
+// Event processing policy constructor
+//
+
+EventPolicy::EventPolicy()
+{
+   m_dwNumRules = 0;
+   m_ppRuleList = NULL;
+}
+
+
+//
+// Event processing policy destructor
+//
+
+EventPolicy::~EventPolicy()
+{
+   DWORD i;
+
+   for(i = 0; i < m_dwNumRules; i++)
+      safe_free(m_ppRuleList[i]);
+   safe_free(m_ppRuleList);
+}
+
+
+//
+// Load event processing policy from database
+//
+
+BOOL EventPolicy::LoadFromDB(void)
+{
+   DB_RESULT hResult;
+   BOOL bSuccess = FALSE;
+
+   hResult = DBSelect(g_hCoreDB, "SELECT id,flags,comments FROM EventPolicy ORDER BY id");
+   if (hResult != NULL)
+   {
+      DWORD i;
+
+      bSuccess = TRUE;
+      m_dwNumRules = DBGetNumRows(hResult);
+      m_ppRuleList = (EPRule **)malloc(sizeof(EPRule *) * m_dwNumRules);
+      for(i = 0; i < m_dwNumRules; i++)
+      {
+         m_ppRuleList[i] = new EPRule(DBGetFieldULong(hResult, i, 0), 
+                                      DBGetField(hResult, i, 2),
+                                      DBGetFieldULong(hResult, i, 1));
+         bSuccess = bSuccess && m_ppRuleList[i]->LoadFromDB();
+      }
+      DBFreeResult(hResult);
+   }
+
+   return bSuccess;
+}
index a066185..3296a36 100644 (file)
@@ -29,6 +29,7 @@
 //
 
 Queue *g_pEventQueue = NULL;
+EventPolicy *g_pEventPolicy = NULL;
 
 
 //
@@ -268,31 +269,41 @@ BOOL InitEventSubsystem(void)
 {
    DB_RESULT hResult;
    DWORD i;
+   BOOL bSuccess = FALSE;
 
    // Create event queue
    g_pEventQueue = new Queue;
 
    // Load events from database
    hResult = DBSelect(g_hCoreDB, "SELECT id,severity,flags,message,description FROM events ORDER BY id");
-   if (hResult == 0)
+   if (hResult != NULL)
    {
-      WriteLog(MSG_EVENT_LOAD_ERROR, EVENTLOG_ERROR_TYPE, NULL);
-      return FALSE;
-   }
+      m_dwNumTemplates = DBGetNumRows(hResult);
+      m_pEventTemplates = (EVENT_TEMPLATE *)malloc(sizeof(EVENT_TEMPLATE) * m_dwNumTemplates);
+      for(i = 0; i < m_dwNumTemplates; i++)
+      {
+         m_pEventTemplates[i].dwId = DBGetFieldULong(hResult, i, 0);
+         m_pEventTemplates[i].dwSeverity = DBGetFieldLong(hResult, i, 1);
+         m_pEventTemplates[i].dwFlags = DBGetFieldLong(hResult, i, 2);
+         m_pEventTemplates[i].szMessageTemplate = strdup(DBGetField(hResult, i, 3));
+         m_pEventTemplates[i].szDescription = strdup(DBGetField(hResult, i, 4));
+      }
+
+      DBFreeResult(hResult);
 
-   m_dwNumTemplates = DBGetNumRows(hResult);
-   m_pEventTemplates = (EVENT_TEMPLATE *)malloc(sizeof(EVENT_TEMPLATE) * m_dwNumTemplates);
-   for(i = 0; i < m_dwNumTemplates; i++)
+      // Create and initialize event processing policy
+      g_pEventPolicy = new EventPolicy;
+      if (g_pEventPolicy->LoadFromDB())
+         bSuccess = TRUE;
+      else
+         WriteLog(MSG_EPP_LOAD_FAILED, EVENTLOG_ERROR_TYPE, NULL);
+   }
+   else
    {
-      m_pEventTemplates[i].dwId = DBGetFieldULong(hResult, i, 0);
-      m_pEventTemplates[i].dwSeverity = DBGetFieldLong(hResult, i, 1);
-      m_pEventTemplates[i].dwFlags = DBGetFieldLong(hResult, i, 2);
-      m_pEventTemplates[i].szMessageTemplate = strdup(DBGetField(hResult, i, 3));
-      m_pEventTemplates[i].szDescription = strdup(DBGetField(hResult, i, 4));
+      WriteLog(MSG_EVENT_LOAD_ERROR, EVENTLOG_ERROR_TYPE, NULL);
    }
 
-   DBFreeResult(hResult);
-   return TRUE;
+   return bSuccess;
 }
 
 
index 845c1f5..d404cc6 100644 (file)
@@ -45,6 +45,8 @@ void EventProcessor(void *arg)
    while(!ShutdownInProgress())
    {
       pEvent = (Event *)g_pEventQueue->GetOrBlock();
+      if (pEvent == INVALID_POINTER_VALUE)
+         break;   // Shutdown indicator
 
       // Write event to log if required
       if (pEvent->Flags() & EF_LOG)
diff --git a/src/server/core/locks.cpp b/src/server/core/locks.cpp
new file mode 100644 (file)
index 0000000..3e5097a
--- /dev/null
@@ -0,0 +1,91 @@
+/* 
+** NetXMS - Network Management System
+** Copyright (C) 2003, 2004 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
+** the Free Software Foundation; either version 2 of the License, or
+** (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+** GNU General Public License for more details.
+**
+** You should have received a copy of the GNU General Public License
+** along with this program; if not, write to the Free Software
+** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+**
+** $module: locks.cpp
+**
+**/
+
+#include "nms_core.h"
+
+
+//
+// Lock entire database and clear all other locks
+// Will return FALSE if someone already locked database
+//
+
+BOOL InitLocks(DWORD *pdwIpAddr, char *pszInfo)
+{
+   DB_RESULT hResult;
+   BOOL bSuccess = FALSE;
+   DWORD dwStatus;
+
+   *pdwIpAddr = UNLOCKED;
+   pszInfo[0] = 0;
+
+   hResult = DBSelect(g_hCoreDB, "SELECT lock_status,owner_info FROM locks WHERE component_id=0");
+   if (hResult != NULL)
+   {
+      if (DBGetNumRows(hResult) > 0)
+      {
+         dwStatus = DBGetFieldULong(hResult, 0, 0);
+         if (dwStatus != UNLOCKED)
+         {
+            // Database is locked by someone else, fetch owner info
+            *pdwIpAddr = dwStatus;
+            strcpy(pszInfo, DBGetField(hResult, 0, 1));
+         }
+         else
+         {
+            char szQuery[1024], szSysInfo[512];
+
+            // Lock database
+            GetSysInfoStr(szSysInfo);
+            sprintf(szQuery, "UPDATE locks SET lock_status=%ld,owner_info='%s' WHERE component_id=0",
+                    GetLocalIpAddr(), szSysInfo);
+            DBQuery(g_hCoreDB, szQuery);
+            bSuccess = TRUE;
+         }
+      }
+      DBFreeResult(hResult);
+   }
+
+   // Clear all locks if we was successfully locked the database
+   if (bSuccess)
+      DBQuery(g_hCoreDB, "UPDATE locks SET lock_status=-1,owner_info='' WHERE COMPONENT_id<>0");
+
+   return bSuccess;
+}
+
+
+//
+// Lock component
+//
+
+BOOL LockComponent(DWORD dwId, DWORD dwLockBy, char *pszOwnerInfo)
+{
+   return FALSE;
+}
+
+
+//
+// Unlock component
+//
+
+void UnlockComponent(DWORD dwId)
+{
+}
index 9616292..3bc8f71 100644 (file)
@@ -124,6 +124,7 @@ static void WriteLogToFile(char *szMessage)
 //             d - Decimal integer
 //             x - Hex integer
 //             e - System error code (will appear in log as textual description)
+//             a - IP address in network byte order
 //
 
 void WriteLog(DWORD msg, WORD wType, char *format, ...)
@@ -154,6 +155,10 @@ void WriteLog(DWORD msg, WORD wType, char *format, ...)
                strings[numStrings] = (char *)malloc(16);
                sprintf(strings[numStrings], "0x%08X", va_arg(args, DWORD));
                break;
+            case 'a':
+               strings[numStrings] = (char *)malloc(20);
+               IpToStr(va_arg(args, DWORD), strings[numStrings]);
+               break;
             case 'e':
                error = va_arg(args, DWORD);
 #ifdef _WIN32
index 560832d..0249877 100644 (file)
@@ -108,6 +108,8 @@ static void LoadGlobalConfig()
 BOOL Initialize(void)
 {
    int i, iNumThreads;
+   DWORD dwAddr;
+   char szInfo[256];
 
    InitLog();
 
@@ -136,6 +138,16 @@ BOOL Initialize(void)
       return FALSE;
    }
 
+   // Initialize locks
+   if (!InitLocks(&dwAddr, szInfo))
+   {
+      if (dwAddr == UNLOCKED)    // Some SQL problems
+         WriteLog(MSG_INIT_LOCKS_FAILED, EVENTLOG_ERROR_TYPE, NULL);
+      else     // Database already locked by another server instance
+         WriteLog(MSG_DB_LOCKED, EVENTLOG_ERROR_TYPE, "as", dwAddr, szInfo);
+      return FALSE;
+   }
+
    // Load global configuration parameters
    LoadGlobalConfig();
 
@@ -153,15 +165,15 @@ BOOL Initialize(void)
       return FALSE;
    }
 
-   // Initialize event handling subsystem
-   if (!InitEventSubsystem())
-      return FALSE;
-
    // Initialize objects infrastructure and load objects from database
    ObjectsInit();
    if (!LoadObjects())
       return FALSE;
 
+   // Initialize event handling subsystem
+   if (!InitEventSubsystem())
+      return FALSE;
+
    // Initialize data collection subsystem
    if (!InitDataCollector())
       return FALSE;
@@ -220,18 +232,26 @@ void Shutdown(void)
    EnumerateClientSessions(NotifyClient, NULL);
 
    WriteLog(MSG_SERVER_STOPPED, EVENTLOG_INFORMATION_TYPE, NULL);
+   g_dwFlags |= AF_SHUTDOWN;     // Set shutdown flag
 #ifdef _WIN32
    SetEvent(m_hEventShutdown);
 #else    /* _WIN32 */
    pthread_cond_broadcast(&m_hCondShutdown);
 #endif
-   g_dwFlags |= AF_SHUTDOWN;     // Set shutdown flag
+
+   g_pEventQueue->Put(INVALID_POINTER_VALUE);   // Stop event processor
    ThreadSleep(5);     // Give other threads a chance to terminate in a safe way
    SaveObjects();
    StopDBWriter();
+
+   // Remove database lock
+   DBQuery(g_hCoreDB, "UPDATE locks SET lock_status=-1,owner_info='' WHERE component_id=0");
+
+   // Disconnect from database and unload driver
    if (g_hCoreDB != 0)
       DBDisconnect(g_hCoreDB);
    DBUnloadDriver();
+
    CloseLog();
 }
 
index a79337d..97f4d38 100644 (file)
@@ -254,4 +254,22 @@ Language=English
 Invalid password hash for user %1: password reset to default
 .
 
+MessageId=
+SymbolicName=MSG_EPP_LOAD_FAILED
+Language=English
+Error loading event processing policy from database
+.
+
+MessageId=
+SymbolicName=MSG_INIT_LOCKS_FAILED
+Language=English
+Error initializing component locks table
+.
+
+MessageId=
+SymbolicName=MSG_DB_LOCKED
+Language=English
+Database is already locked by another NetXMS server instance (IP address: %1, machine info: %2)
+.
+
 ;#endif
index 43f4275..eca5aa9 100644 (file)
@@ -79,6 +79,8 @@
 #define MAX_DB_NAME        32
 #define MAX_LINE_SIZE      4096
 
+#define UNLOCKED           0xFFFFFFFF
+
 
 //
 // Application flags
 #define INFO_CAT_OBJECT       2
 
 
+//
+// Component identifiers used for locking
+//
+
+#define CID_NETXMS_INSTANCE   0
+#define CID_EPP               1
+#define CID_USER_MGMT         2
+
+
 //
 // Event handling subsystem definitions
 //
@@ -250,6 +261,10 @@ void InitLog(void);
 void CloseLog(void);
 void WriteLog(DWORD msg, WORD wType, char *format, ...);
 
+BOOL InitLocks(DWORD *pdwIpAddr, char *pszInfo);
+BOOL LockComponent(DWORD dwId, DWORD dwLockBy, char *pszOwnerInfo);
+void UnlockComponent(DWORD dwId);
+
 BOOL ParseCommandLine(int argc, char *argv[]);
 BOOL LoadConfig(void);
 
@@ -318,6 +333,9 @@ void EnumerateClientSessions(void (*pHandler)(ClientSession *, void *), void *pA
 void BinToStr(BYTE *pData, DWORD dwSize, char *pStr);
 DWORD StrToBin(char *pStr, BYTE *pData, DWORD dwSize);
 
+void GetSysInfoStr(char *pszBuffer);
+DWORD GetLocalIpAddr(void);
+
 #ifdef _WIN32
 
 void InitService(void);
index d28e8ec..1c559fb 100644 (file)
@@ -115,6 +115,71 @@ public:
 };
 
 
+//
+// Event policy rule flags
+//
+
+#define RF_STOP_PROCESSING    0x01
+#define RF_NEGATED_SOURCE     0x02
+#define RF_NEGATED_EVENTS     0x04
+
+
+//
+// Event source structure
+//
+
+typedef struct
+{
+   int iType;
+   DWORD dwObjectId;
+} EVENT_SOURCE;
+
+
+//
+// Event policy rule
+//
+
+class EPRule
+{
+private:
+   DWORD m_dwId;
+   DWORD m_dwFlags;
+   DWORD m_dwNumSources;
+   EVENT_SOURCE *m_pSourceList;
+   DWORD m_dwNumEvents;
+   DWORD *m_pdwEventList;
+   DWORD m_dwNumActions;
+   DWORD *m_pdwActionList;
+   char *m_pszComment;
+
+public:
+   EPRule(DWORD dwId, char *szComment, DWORD dwFlags);
+   ~EPRule();
+
+   DWORD Id(void) { return m_dwId; }
+
+   BOOL LoadFromDB(void);
+};
+
+
+//
+// Event policy
+//
+
+class EventPolicy
+{
+private:
+   DWORD m_dwNumRules;
+   EPRule **m_ppRuleList;
+
+public:
+   EventPolicy();
+   ~EventPolicy();
+
+   BOOL LoadFromDB(void);
+};
+
+
 //
 // Functions
 //
@@ -128,5 +193,6 @@ BOOL PostEvent(DWORD dwEventId, DWORD dwSourceId, char *szFormat, ...);
 //
 
 extern Queue *g_pEventQueue;
+extern EventPolicy *g_pEventPolicy;
 
 #endif   /* _nms_events_h_ */
index f374e33..c395066 100644 (file)
@@ -334,3 +334,70 @@ DWORD StrToBin(char *pStr, BYTE *pData, DWORD dwSize)
    }
    return i;
 }
+
+
+//
+// Get system information string
+//
+
+void GetSysInfoStr(char *pszBuffer)
+{
+#ifdef _WIN32
+   DWORD dwSize;
+   char computerName[MAX_COMPUTERNAME_LENGTH + 1], osVersion[256];
+   SYSTEM_INFO sysInfo;
+   OSVERSIONINFO versionInfo;
+
+   dwSize = MAX_COMPUTERNAME_LENGTH + 1;
+   GetComputerName(computerName, &dwSize);
+
+   versionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+   GetVersionEx(&versionInfo);
+   GetSystemInfo(&sysInfo);
+
+   switch(versionInfo.dwPlatformId)
+   {
+      case VER_PLATFORM_WIN32_WINDOWS:
+         sprintf(osVersion,"Windows %s-%s",versionInfo.dwMinorVersion == 0 ? "95" :
+            (versionInfo.dwMinorVersion == 10 ? "98" :
+               (versionInfo.dwMinorVersion == 90 ? "Me" : "Unknown")),versionInfo.szCSDVersion);
+         break;
+      case VER_PLATFORM_WIN32_NT:
+         if (versionInfo.dwMajorVersion != 5)
+            sprintf(osVersion,"Windows NT %d.%d %s",versionInfo.dwMajorVersion,
+                    versionInfo.dwMinorVersion,versionInfo.szCSDVersion);
+         else      // Windows 2000, Windows XP or Windows Server 2003
+            sprintf(osVersion,"Windows %s%s%s",versionInfo.dwMinorVersion == 0 ? "2000" : 
+                    (versionInfo.dwMinorVersion == 1 ? "XP" : "Server 2003"),
+                       versionInfo.szCSDVersion[0] == 0 ? "" : " ", versionInfo.szCSDVersion);
+         break;
+      default:
+         strcpy(osVersion,"Windows [Unknown Version]");
+         break;
+   }
+
+   sprintf(pszBuffer, "%s %s Build %d", computerName, osVersion, versionInfo.dwBuildNumber);
+#else
+   /* TODO: add UNIX code here */
+#endif
+}
+
+
+//
+// Get IP address for local machine
+//
+
+DWORD GetLocalIpAddr(void)
+{
+   INTERFACE_LIST *pIfList;
+   DWORD dwAddr = 0;
+
+   pIfList = GetLocalInterfaceList();
+   if (pIfList != NULL)
+   {
+      if (pIfList->iNumEntries > 0)
+         dwAddr = pIfList->pInterfaces[0].dwIpAddr;
+      DestroyInterfaceList(pIfList);
+   }
+   return dwAddr;
+}
index 0134797..5392a19 100644 (file)
@@ -66,10 +66,6 @@ BOOL LoadUsers(void)
    {
       m_pUserList[i].dwId = DBGetFieldULong(hResult, i, 0);
       strncpy(m_pUserList[i].szName, DBGetField(hResult, i, 1), MAX_USER_NAME);
-printf("%s %d %d\n",DBGetField(hResult, i, 2),StrToBin(DBGetField(hResult, i, 2), m_pUserList[i].szPassword, SHA_DIGEST_LENGTH),SHA_DIGEST_LENGTH);
-char buf[256];
-BinToStr(m_pUserList[i].szPassword,SHA_DIGEST_LENGTH,buf);
-printf("recover: %s\n",buf);
       if (StrToBin(DBGetField(hResult, i, 2), m_pUserList[i].szPassword, SHA_DIGEST_LENGTH) != SHA_DIGEST_LENGTH)
       {
          WriteLog(MSG_INVALID_SHA1_HASH, EVENTLOG_WARNING_TYPE, "s", m_pUserList[i].szName);