You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
716 lines
20 KiB
716 lines
20 KiB
//+------------------------------------------------------------
|
|
//
|
|
// Copyright (C) 1999, Microsoft Corporation
|
|
//
|
|
// File: cnfgmgr.h
|
|
//
|
|
// Contents: Declaration of classes related to the handling on
|
|
// different LDAP host configurations.
|
|
// This includes LDAP failover and load balancing.
|
|
//
|
|
// Classes:
|
|
// CLdapCfgMgr
|
|
// CLdapCfg
|
|
// CLdapHost
|
|
// CCfgConnectionCache
|
|
// CCfgConnection
|
|
//
|
|
// Functions:
|
|
//
|
|
// History:
|
|
// jstamerj 1999/06/15 14:49:52: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
#ifndef __CNFGMGR_H__
|
|
#define __CNFGMGR_H__
|
|
|
|
|
|
#include <windows.h>
|
|
#include "asyncctx.h"
|
|
#include <baseobj.h>
|
|
#include <ntdsapi.h>
|
|
#include <dsgetdc.h>
|
|
#include <lmcons.h>
|
|
#include <lmapibuf.h>
|
|
#include <baseobj.h>
|
|
#include "asyncctx.h"
|
|
|
|
class CLdapCfg;
|
|
class CLdapServerCfg;
|
|
class CCfgConectionCache;
|
|
class CCfgConnection;
|
|
|
|
#define CONN_RETRY_TIME (5*60) // 5 Minutes
|
|
typedef DWORD CONN_PRIORITY;
|
|
|
|
enum CONN_STATE {
|
|
CONN_STATE_INITIAL,
|
|
CONN_STATE_CONNECTED,
|
|
CONN_STATE_DOWN,
|
|
CONN_STATE_RETRY,
|
|
};
|
|
|
|
typedef struct _tagLdapServerConfig {
|
|
DWORD dwPort;
|
|
CONN_PRIORITY pri;
|
|
LDAP_BIND_TYPE bt;
|
|
CHAR szHost[CAT_MAX_DOMAIN];
|
|
CHAR szNamingContext[CAT_MAX_DOMAIN];
|
|
CHAR szAccount[CAT_MAX_LOGIN];
|
|
CHAR szPassword[CAT_MAX_PASSWORD];
|
|
} LDAPSERVERCONFIG, *PLDAPSERVERCONFIG;
|
|
|
|
typedef DWORD LDAPSERVERCOST, *PLDAPSERVERCOST;
|
|
|
|
//
|
|
// Connection costs:
|
|
//
|
|
// The smallest unit of cost is the number of pending searches.
|
|
// The next factor of cost is the connection state.
|
|
// States:
|
|
// Connected = + COST_CONNECTED
|
|
// Initially state (unconnected) = + COST_INITIAL
|
|
// Connection down = + COST_RETRY
|
|
// Connection recently went down = + COST_DOWN
|
|
//
|
|
// A configurable priority is always added to the cost.
|
|
//
|
|
#define DEFAULT_COST_CONNECTED_LOCAL 0
|
|
#define DEFAULT_COST_CONNECTED_REMOTE 2
|
|
#define DEFAULT_COST_INITIAL_LOCAL 4
|
|
#define DEFAULT_COST_INITIAL_REMOTE 8
|
|
#define DEFAULT_COST_RETRY_LOCAL 6
|
|
#define DEFAULT_COST_RETRY_REMOTE 10
|
|
#define COST_DOWN_LOCAL 0x80000000
|
|
#define COST_DOWN_REMOTE 0x80000000
|
|
#define COST_TOO_HIGH_TO_CONNECT 0x80000000
|
|
|
|
//
|
|
// Registry key and value names for initializing GC cost values from the registry
|
|
//
|
|
#define GC_COST_PARAMETERS_KEY "System\\CurrentControlSet\\Services\\SMTPSVC\\Parameters"
|
|
#define GC_COST_CONNECTED_LOCAL_VALUE "GCCostConnectedLocal"
|
|
#define GC_COST_CONNECTED_REMOTE_VALUE "GCCostConnectedRemote"
|
|
#define GC_COST_INITIAL_LOCAL_VALUE "GCCostInitialLocal"
|
|
#define GC_COST_INITIAL_REMOTE_VALUE "GCCostInitialRemote"
|
|
#define GC_COST_RETRY_LOCAL_VALUE "GCCostRetryLocal"
|
|
#define GC_COST_RETRY_REMOTE_VALUE "GCCostRetryRemote"
|
|
|
|
//
|
|
// The maximum number of threads that will try to connect to a
|
|
// connection in CONN_STATE_RETRY:
|
|
//
|
|
#define MAX_CONNECT_THREADS 1
|
|
|
|
//
|
|
// Requerying of available GC control:
|
|
// The code will rebuild the list of available GCs at a hard coded
|
|
// time interval. The code will also requery for available GCs after
|
|
// a hard coded number of connection failures and a minimum time interval.
|
|
//
|
|
#define DEFAULT_REBUILD_GC_LIST_MAX_INTERVAL (60*60) // 1 hour
|
|
#define DEFAULT_REBUILD_GC_LIST_MAX_FAILURES (100) // 100 connection failures
|
|
#define DEFAULT_REBUILD_GC_LIST_MIN_INTERVAL (60*5) // 5 minutes
|
|
|
|
//
|
|
// Registry key and value names for initializing values from the registry
|
|
//
|
|
#define REBUILD_GC_LIST_PARAMETERS_KEY "System\\CurrentControlSet\\Services\\SMTPSVC\\Parameters"
|
|
#define REBUILD_GC_LIST_MAX_INTERVAL_VALUE "RebuildGCListMaxInterval"
|
|
#define REBUILD_GC_LIST_MAX_FAILURES_VALUE "RebuildGCListMaxFailures"
|
|
#define REBUILD_GC_LIST_MIN_INTERVAL_VALUE "RebuildGCListMinInterval"
|
|
|
|
//
|
|
// An LDAP connection cache object that creates CCfgConnection objects
|
|
//
|
|
class CCfgConnectionCache :
|
|
public CBatchLdapConnectionCache
|
|
{
|
|
public:
|
|
CCfgConnectionCache(
|
|
ISMTPServerEx *pISMTPServerEx) :
|
|
CBatchLdapConnectionCache(pISMTPServerEx)
|
|
{
|
|
}
|
|
HRESULT GetConnection(
|
|
CCfgConnection **ppConn,
|
|
PLDAPSERVERCONFIG pServerConfig,
|
|
CLdapServerCfg *pCLdapServerConfig);
|
|
|
|
CCachedLdapConnection *CreateCachedLdapConnection(
|
|
LPSTR szHost,
|
|
DWORD dwPort,
|
|
LPSTR szNamingContext,
|
|
LPSTR szAccount,
|
|
LPSTR szPassword,
|
|
LDAP_BIND_TYPE bt,
|
|
PVOID pCreateContext);
|
|
|
|
private:
|
|
#define SIGNATURE_CCFGCONNECTIONCACHE (DWORD)'CCCC'
|
|
#define SIGNATURE_CCFGCONNECTIONCACHE_INVALID (DWORD)'CCCX'
|
|
DWORD m_dwSignature;
|
|
};
|
|
|
|
//
|
|
// CLdapCfgMgr is a wrapper around CLdapCfg. It contains thread save
|
|
// code to build a new CLdapCfg object with a new list of available
|
|
// LDAP servers
|
|
//
|
|
CatDebugClass(CLdapCfgMgr),
|
|
public CBaseObject
|
|
{
|
|
public:
|
|
CLdapCfgMgr(
|
|
ISMTPServerEx *pISMTPServerEx,
|
|
BOOL fAutomaticConfigUpdate,
|
|
ICategorizerParameters *pICatParams,
|
|
LDAP_BIND_TYPE bt = BIND_TYPE_NONE,
|
|
LPSTR pszAccount = NULL,
|
|
LPSTR pszPassword = NULL,
|
|
LPSTR pszNamingContext = NULL);
|
|
|
|
//
|
|
// Reads parameters from the registry, setting member variables
|
|
// when configuration data is available
|
|
//
|
|
VOID InitializeFromRegistry();
|
|
|
|
//
|
|
// Build a list of all available GCs and initialize
|
|
// This function may be called multiple times (necessary if the
|
|
// available GCs change)
|
|
//
|
|
HRESULT HrInit(
|
|
BOOL fRediscoverGCs = FALSE);
|
|
|
|
//
|
|
// Initialize using a specified list of avialable LDAP servers
|
|
// THis function may be called more than once
|
|
//
|
|
HRESULT HrInit(
|
|
DWORD dwcServers,
|
|
PLDAPSERVERCONFIG prgServerConfig);
|
|
|
|
//
|
|
// Get a connection
|
|
//
|
|
HRESULT HrGetConnection(
|
|
CCfgConnection **ppConn);
|
|
|
|
//
|
|
// Called very often to update the GC configuration if warranted.
|
|
//
|
|
HRESULT HrUpdateConfigurationIfNecessary();
|
|
|
|
//
|
|
// Wrapper to cancel all searches on all connections
|
|
//
|
|
VOID CancelAllConnectionSearches(
|
|
ISMTPServer *pIServer)
|
|
{
|
|
m_LdapConnectionCache.CancelAllConnectionSearches(
|
|
pIServer);
|
|
}
|
|
|
|
ISMTPServerEx * GetISMTPServerEx()
|
|
{
|
|
return m_pISMTPServerEx;
|
|
}
|
|
|
|
private:
|
|
~CLdapCfgMgr();
|
|
|
|
HRESULT HrGetGCServers(
|
|
IN ICategorizerLdapConfig *pICatLdapConfigInterface,
|
|
IN LDAP_BIND_TYPE bt,
|
|
IN LPSTR pszAccount,
|
|
IN LPSTR pszPassword,
|
|
IN LPSTR pszNamingContext,
|
|
OUT DWORD *pdwcServerConfig,
|
|
OUT PLDAPSERVERCONFIG *pprgServerConfig);
|
|
|
|
HRESULT HrBuildGCServerArray(
|
|
IN LDAP_BIND_TYPE bt,
|
|
IN LPSTR pszAccount,
|
|
IN LPSTR pszPassword,
|
|
IN LPSTR pszNamingContext,
|
|
IN BOOL fRediscoverGCs,
|
|
OUT DWORD *pdwcServerConfig,
|
|
OUT PLDAPSERVERCONFIG *pprgServerConfig);
|
|
|
|
HRESULT HrBuildArrayFromDCInfo(
|
|
IN LDAP_BIND_TYPE bt,
|
|
IN LPSTR pszAccount,
|
|
IN LPSTR pszPassword,
|
|
IN LPSTR pszNamingContext,
|
|
IN DWORD dwcDSDCInfo,
|
|
IN PDS_DOMAIN_CONTROLLER_INFO_2 prgDSDCInfo,
|
|
OUT DWORD *pdwcServerConfig,
|
|
OUT PLDAPSERVERCONFIG *pprgServerConfig);
|
|
|
|
BOOL fReadyForUpdate();
|
|
|
|
LPSTR SzConnectNameFromDomainControllerInfo(
|
|
PDS_DOMAIN_CONTROLLER_INFO_2 pDCInfo)
|
|
{
|
|
if(pDCInfo->DnsHostName)
|
|
return pDCInfo->DnsHostName;
|
|
else if(pDCInfo->NetbiosName)
|
|
return pDCInfo->NetbiosName;
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
VOID LogCnfgInit();
|
|
VOID LogCnfgEntry(PLDAPSERVERCONFIG pConfig);
|
|
|
|
private:
|
|
#define SIGNATURE_CLDAPCFGMGR (DWORD)'MCLC'
|
|
#define SIGNATURE_CLDAPCFGMGR_INVALID (DWORD)'MCLX'
|
|
DWORD m_dwSignature;
|
|
BOOL m_fAutomaticConfigUpdate;
|
|
DWORD m_dwUpdateInProgress;
|
|
ULARGE_INTEGER m_ulLastUpdateTime;
|
|
CExShareLock m_sharelock;
|
|
CLdapCfg *m_pCLdapCfg;
|
|
DWORD m_dwRebuildGCListMaxInterval;
|
|
DWORD m_dwRebuildGCListMaxFailures;
|
|
DWORD m_dwRebuildGCListMinInterval;
|
|
|
|
//
|
|
// Default configuration to use with automatic host selection
|
|
//
|
|
LDAP_BIND_TYPE m_bt;
|
|
CHAR m_szNamingContext[CAT_MAX_DOMAIN];
|
|
CHAR m_szAccount[CAT_MAX_LOGIN];
|
|
CHAR m_szPassword[CAT_MAX_PASSWORD];
|
|
|
|
ICategorizerParameters *m_pICatParams;
|
|
ISMTPServerEx *m_pISMTPServerEx;
|
|
|
|
CCfgConnectionCache m_LdapConnectionCache;
|
|
};
|
|
|
|
//
|
|
// CLdapCfg contains the configuration of a group of LDAP servers at
|
|
// one point in time. The group of LDAP servers may not be changed
|
|
// (without creating a new CLdapCfg object)
|
|
//
|
|
CatDebugClass(CLdapCfg),
|
|
public CBaseObject
|
|
{
|
|
public:
|
|
CLdapCfg(
|
|
ISMTPServerEx *pISMTPServerEx);
|
|
|
|
void * operator new(size_t size, DWORD dwcServers);
|
|
//
|
|
// HrInit should only be called once per object
|
|
//
|
|
HRESULT HrInit(
|
|
DWORD dwcServers,
|
|
PLDAPSERVERCONFIG prgServerConfig,
|
|
CLdapCfg *pCLdapCfgOld);
|
|
|
|
//
|
|
// Get a connection
|
|
//
|
|
HRESULT HrGetConnection(
|
|
CCfgConnection **ppConn,
|
|
CCfgConnectionCache *pLdapConnectionCache);
|
|
|
|
DWORD DwNumConnectionFailures()
|
|
{
|
|
return m_dwcConnectionFailures;
|
|
}
|
|
DWORD DwNumServers()
|
|
{
|
|
return m_dwcServers;
|
|
}
|
|
ISMTPServerEx * GetISMTPServerEx()
|
|
{
|
|
return m_pISMTPServerEx;
|
|
}
|
|
|
|
private:
|
|
~CLdapCfg();
|
|
|
|
VOID ShuffleArray();
|
|
|
|
private:
|
|
#define SIGNATURE_CLDAPCFG (DWORD)'fCLC'
|
|
#define SIGNATURE_CLDAPCFG_INVALID (DWORD)'fCLX'
|
|
|
|
DWORD m_dwSignature;
|
|
DWORD m_dwInc;
|
|
CExShareLock m_sharelock; // Protects m_prgpCLdapServerCfg
|
|
DWORD m_dwcServers;
|
|
DWORD m_dwcConnectionFailures;
|
|
CLdapServerCfg **m_prgpCLdapServerCfg;
|
|
ISMTPServerEx *m_pISMTPServerEx;
|
|
};
|
|
|
|
//
|
|
// CLdapServerCfg maintains information on the state of one LDAP
|
|
// server/port
|
|
//
|
|
CatDebugClass(CLdapServerCfg)
|
|
{
|
|
public:
|
|
static VOID GlobalInit()
|
|
{
|
|
InitializeListHead(&m_listhead);
|
|
InitializeFromRegistry();
|
|
}
|
|
|
|
static VOID InitializeFromRegistry();
|
|
|
|
static HRESULT GetServerCfg(
|
|
IN ISMTPServerEx *pISMTPServerEx,
|
|
IN PLDAPSERVERCONFIG pServerConfig,
|
|
OUT CLdapServerCfg **ppCLdapServerCfg);
|
|
|
|
LONG AddRef()
|
|
{
|
|
return InterlockedIncrement(&m_lRefCount);
|
|
}
|
|
LONG Release()
|
|
{
|
|
LONG lRet;
|
|
lRet = InterlockedDecrement(&m_lRefCount);
|
|
if(lRet == 0) {
|
|
//
|
|
// Remove object from global list and destroy
|
|
//
|
|
m_listlock.ExclusiveLock();
|
|
|
|
if(m_lRefCount > 0) {
|
|
//
|
|
// Somebody grabbed this object out of the global list
|
|
// and AddRef'd it. Abort deletion.
|
|
//
|
|
} else {
|
|
|
|
RemoveEntryList(&m_le);
|
|
delete this;
|
|
}
|
|
m_listlock.ExclusiveUnlock();
|
|
}
|
|
return lRet;
|
|
}
|
|
|
|
//
|
|
// Get a connection
|
|
//
|
|
HRESULT HrGetConnection(
|
|
ISMTPServerEx *pISMTPServerEx,
|
|
CCfgConnection **ppConn,
|
|
CCfgConnectionCache *pLdapConnectionCache);
|
|
|
|
VOID Cost(
|
|
IN ISMTPServerEx *pISMTPServerEx,
|
|
OUT PLDAPSERVERCOST pCost);
|
|
|
|
VOID IncrementPendingSearches()
|
|
{
|
|
DWORD dwcSearches;
|
|
CatFunctEnterEx((LPARAM)this, "CLdapServerCfg::IncrementPendingSearches");
|
|
dwcSearches = (LONG) InterlockedIncrement((PLONG)&m_dwcPendingSearches);
|
|
DebugTrace((LPARAM)this, "%ld pending searches on connection [%s:%d]",
|
|
dwcSearches, m_ServerConfig.szHost, m_ServerConfig.dwPort);
|
|
CatFunctLeaveEx((LPARAM)this);
|
|
}
|
|
VOID DecrementPendingSearches()
|
|
{
|
|
DWORD dwcSearches;
|
|
CatFunctEnterEx((LPARAM)this, "CLdapServerCfg::IncrementPendingSearches");
|
|
dwcSearches = (DWORD) InterlockedDecrement((PLONG)&m_dwcPendingSearches);
|
|
DebugTrace((LPARAM)this, "%ld pending searches on connection [%s:%d]",
|
|
dwcSearches, m_ServerConfig.szHost, m_ServerConfig.dwPort);
|
|
CatFunctLeaveEx((LPARAM)this);
|
|
}
|
|
|
|
VOID UpdateConnectionState(
|
|
ISMTPServerEx *pISMTPServerEx,
|
|
ULARGE_INTEGER *pft,
|
|
CONN_STATE connstate);
|
|
|
|
VOID IncrementFailedCount()
|
|
{
|
|
InterlockedIncrement((PLONG) &m_dwcFailedConnectAttempts);
|
|
}
|
|
VOID ResetFailedCount()
|
|
{
|
|
InterlockedExchange((PLONG) &m_dwcFailedConnectAttempts, 0);
|
|
}
|
|
CONN_STATE CurrentState()
|
|
{
|
|
return m_connstate;
|
|
}
|
|
ULARGE_INTEGER GetCurrentTime()
|
|
{
|
|
ULARGE_INTEGER FileTime;
|
|
|
|
_ASSERT(sizeof(ULARGE_INTEGER) == sizeof(FILETIME));
|
|
GetSystemTimeAsFileTime((LPFILETIME)&FileTime);
|
|
return FileTime;
|
|
}
|
|
private:
|
|
CLdapServerCfg();
|
|
~CLdapServerCfg();
|
|
|
|
HRESULT HrInit(
|
|
PLDAPSERVERCONFIG pServerConfig);
|
|
|
|
BOOL fReadyForRetry()
|
|
{
|
|
// 100 nanoseconds * 10^7 == 1 second
|
|
return ((GetCurrentTime().QuadPart - m_ftLastStateUpdate.QuadPart) >=
|
|
((LONGLONG)CONN_RETRY_TIME * 10000000));
|
|
}
|
|
|
|
BOOL fMatch(
|
|
PLDAPSERVERCONFIG pServerConfig);
|
|
|
|
VOID LogStateChangeEvent(
|
|
IN ISMTPServerEx *pISMTPServerEx,
|
|
IN CONN_STATE connstate,
|
|
IN LPSTR pszHost,
|
|
IN DWORD dwPort);
|
|
|
|
static CLdapServerCfg *FindServerCfg(
|
|
PLDAPSERVERCONFIG pServerConfig);
|
|
|
|
static BOOL fIsLocalComputer(
|
|
PLDAPSERVERCONFIG pServerConfig);
|
|
|
|
private:
|
|
#define SIGNATURE_CLDAPSERVERCFG (DWORD)'CSLC'
|
|
#define SIGNATURE_CLDAPSERVERCFG_INVALID (DWORD)'CSLX'
|
|
|
|
static DWORD m_dwCostConnectedLocal;
|
|
static DWORD m_dwCostConnectedRemote;
|
|
static DWORD m_dwCostInitialLocal;
|
|
static DWORD m_dwCostInitialRemote;
|
|
static DWORD m_dwCostRetryLocal;
|
|
static DWORD m_dwCostRetryRemote;
|
|
|
|
DWORD m_dwSignature;
|
|
LONG m_lRefCount;
|
|
LDAPSERVERCONFIG m_ServerConfig;
|
|
CExShareLock m_sharelock;
|
|
CONN_STATE m_connstate;
|
|
ULARGE_INTEGER m_ftLastStateUpdate;
|
|
DWORD m_dwcPendingSearches;
|
|
DWORD m_dwcCurrentConnectAttempts;
|
|
DWORD m_dwcFailedConnectAttempts;
|
|
|
|
//
|
|
// Member variables to keep/protect a list of CLdapServer objects
|
|
//
|
|
static CExShareLock m_listlock;
|
|
static LIST_ENTRY m_listhead;
|
|
LIST_ENTRY m_le;
|
|
|
|
BOOL m_fLocalServer;
|
|
};
|
|
|
|
//
|
|
// An LDAP connection that notifies CLdapServerCfg about state changes
|
|
//
|
|
class CCfgConnection :
|
|
public CBatchLdapConnection
|
|
{
|
|
#define SIGNATURE_CCFGCONNECTION (DWORD)'oCCC'
|
|
#define SIGNATURE_CCFGCONNECTION_INVALID (DWORD)'oCCX'
|
|
public:
|
|
CCfgConnection(
|
|
LPSTR szHost,
|
|
DWORD dwPort,
|
|
LPSTR szNamingContext,
|
|
LPSTR szAccount,
|
|
LPSTR szPassword,
|
|
LDAP_BIND_TYPE bt,
|
|
CLdapConnectionCache *pCache,
|
|
CLdapServerCfg *pCLdapServerCfg) :
|
|
CBatchLdapConnection(
|
|
szHost,
|
|
dwPort,
|
|
szNamingContext,
|
|
szAccount,
|
|
szPassword,
|
|
bt,
|
|
pCache)
|
|
{
|
|
m_dwSignature = SIGNATURE_CCFGCONNECTION;
|
|
m_pCLdapServerCfg = pCLdapServerCfg;
|
|
pCLdapServerCfg->AddRef();
|
|
|
|
m_connstate = CONN_STATE_INITIAL;
|
|
}
|
|
|
|
~CCfgConnection()
|
|
{
|
|
_ASSERT(m_pCLdapServerCfg);
|
|
m_pCLdapServerCfg->Release();
|
|
|
|
_ASSERT(m_dwSignature == SIGNATURE_CCFGCONNECTION);
|
|
m_dwSignature = SIGNATURE_CCFGCONNECTION_INVALID;
|
|
}
|
|
|
|
virtual HRESULT Connect();
|
|
|
|
virtual HRESULT AsyncSearch( // Asynchronously look up
|
|
LPCWSTR szBaseDN, // objects matching specified
|
|
int nScope, // criteria in the DS. The
|
|
LPCWSTR szFilter, // results are passed to
|
|
LPCWSTR szAttributes[], // fnCompletion when they
|
|
DWORD dwPageSize, // Optinal page size
|
|
LPLDAPCOMPLETION fnCompletion, // become available.
|
|
LPVOID ctxCompletion);
|
|
|
|
private:
|
|
virtual VOID CallCompletion(
|
|
PPENDING_REQUEST preq,
|
|
PLDAPMessage pres,
|
|
HRESULT hrStatus,
|
|
BOOL fFinalCompletion);
|
|
|
|
VOID NotifyServerDown();
|
|
|
|
private:
|
|
DWORD m_dwSignature;
|
|
CLdapServerCfg *m_pCLdapServerCfg;
|
|
CExShareLock m_sharelock;
|
|
CONN_STATE m_connstate;
|
|
};
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CLdapCfgMgr::HrUpdateConfigurationIfNecessary
|
|
//
|
|
// Synopsis: Check to see if the CLdapCfg should be updated.
|
|
// If it should be, do the update.
|
|
//
|
|
// Arguments: NONE
|
|
//
|
|
// Returns:
|
|
// S_OK: Success
|
|
// error from HrInit
|
|
//
|
|
// History:
|
|
// jstamerj 1999/06/29 20:51:23: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
inline HRESULT CLdapCfgMgr::HrUpdateConfigurationIfNecessary()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
DWORD dw;
|
|
BOOL fUpdate;
|
|
|
|
if(m_fAutomaticConfigUpdate == FALSE)
|
|
//
|
|
// Update is disabled
|
|
return S_OK;
|
|
|
|
//
|
|
// See if some other thread is already updating the configuration
|
|
// (try to enter the lock)
|
|
//
|
|
dw = InterlockedExchange((PLONG)&m_dwUpdateInProgress, TRUE);
|
|
|
|
if(dw == FALSE) {
|
|
//
|
|
// No other thread is updating
|
|
//
|
|
fUpdate = fReadyForUpdate();
|
|
|
|
if(fUpdate) {
|
|
//
|
|
// Call HrInit to generate a new CLdapCfg
|
|
//
|
|
hr = HrInit(TRUE);
|
|
if(SUCCEEDED(hr)) {
|
|
//
|
|
// Set the last update time
|
|
//
|
|
GetSystemTimeAsFileTime((LPFILETIME)&m_ulLastUpdateTime);
|
|
}
|
|
}
|
|
//
|
|
// Release the lock
|
|
//
|
|
InterlockedExchange((PLONG)&m_dwUpdateInProgress, FALSE);
|
|
}
|
|
return hr;
|
|
} // CLdapCfgMgr::HrUpdateConfigurationIfNecessary
|
|
|
|
|
|
//+------------------------------------------------------------
|
|
//
|
|
// Function: CLdapCfgMgr::fReadyForUpdate
|
|
//
|
|
// Synopsis: Calculates wether or not this object is due for an
|
|
// automatic cfg update
|
|
//
|
|
// Arguments: NONE
|
|
//
|
|
// Returns:
|
|
// TRUE: Yes, it is time for an update
|
|
// FALSE: No, an update is not required at this time
|
|
//
|
|
// History:
|
|
// jstamerj 1999/06/30 12:08:35: Created.
|
|
//
|
|
//-------------------------------------------------------------
|
|
inline BOOL CLdapCfgMgr::fReadyForUpdate()
|
|
{
|
|
DWORD dwNumConnectionFailures;
|
|
ULARGE_INTEGER ulCurrentTime;
|
|
|
|
//
|
|
// We need an update when:
|
|
// 1) A periodic time interval has ellapsed
|
|
// 100 ns * 10^7 == 1 second
|
|
//
|
|
GetSystemTimeAsFileTime((LPFILETIME)&ulCurrentTime);
|
|
|
|
if((ulCurrentTime.QuadPart - m_ulLastUpdateTime.QuadPart) >=
|
|
(ULONGLONG) Int32x32To64((LONG)m_dwRebuildGCListMaxInterval, 10000000))
|
|
|
|
return TRUE;
|
|
|
|
//
|
|
// We also need an update when:
|
|
// 2) We have received more than a set number of connection
|
|
// failures on the current configuration and at least a minimum
|
|
// time interval has passed
|
|
//
|
|
// Check for the mimimum time interval
|
|
//
|
|
if( (ulCurrentTime.QuadPart - m_ulLastUpdateTime.QuadPart) >=
|
|
(ULONGLONG) Int32x32To64((LONG)m_dwRebuildGCListMinInterval, 10000000)) {
|
|
//
|
|
// Get the number of connection failures
|
|
//
|
|
m_sharelock.ShareLock();
|
|
|
|
if(m_pCLdapCfg) {
|
|
dwNumConnectionFailures = m_pCLdapCfg->DwNumConnectionFailures();
|
|
} else {
|
|
dwNumConnectionFailures = 0;
|
|
_ASSERT(0 && "HrInit was not called or failed");
|
|
}
|
|
|
|
m_sharelock.ShareUnlock();
|
|
|
|
if(dwNumConnectionFailures >= m_dwRebuildGCListMaxFailures)
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
} // CLdapCfgMgr::fReadyForUpdate
|
|
|
|
#endif //__CNFGMGR_H__
|