Leaked source code of windows server 2003
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

  1. //+------------------------------------------------------------
  2. //
  3. // Copyright (C) 1999, Microsoft Corporation
  4. //
  5. // File: cnfgmgr.h
  6. //
  7. // Contents: Declaration of classes related to the handling on
  8. // different LDAP host configurations.
  9. // This includes LDAP failover and load balancing.
  10. //
  11. // Classes:
  12. // CLdapCfgMgr
  13. // CLdapCfg
  14. // CLdapHost
  15. // CCfgConnectionCache
  16. // CCfgConnection
  17. //
  18. // Functions:
  19. //
  20. // History:
  21. // jstamerj 1999/06/15 14:49:52: Created.
  22. //
  23. //-------------------------------------------------------------
  24. #ifndef __CNFGMGR_H__
  25. #define __CNFGMGR_H__
  26. #include <windows.h>
  27. #include "asyncctx.h"
  28. #include <baseobj.h>
  29. #include <ntdsapi.h>
  30. #include <dsgetdc.h>
  31. #include <lmcons.h>
  32. #include <lmapibuf.h>
  33. #include <baseobj.h>
  34. #include "asyncctx.h"
  35. class CLdapCfg;
  36. class CLdapServerCfg;
  37. class CCfgConectionCache;
  38. class CCfgConnection;
  39. #define CONN_RETRY_TIME (5*60) // 5 Minutes
  40. typedef DWORD CONN_PRIORITY;
  41. enum CONN_STATE {
  42. CONN_STATE_INITIAL,
  43. CONN_STATE_CONNECTED,
  44. CONN_STATE_DOWN,
  45. CONN_STATE_RETRY,
  46. };
  47. typedef struct _tagLdapServerConfig {
  48. DWORD dwPort;
  49. CONN_PRIORITY pri;
  50. LDAP_BIND_TYPE bt;
  51. CHAR szHost[CAT_MAX_DOMAIN];
  52. CHAR szNamingContext[CAT_MAX_DOMAIN];
  53. CHAR szAccount[CAT_MAX_LOGIN];
  54. CHAR szPassword[CAT_MAX_PASSWORD];
  55. } LDAPSERVERCONFIG, *PLDAPSERVERCONFIG;
  56. typedef DWORD LDAPSERVERCOST, *PLDAPSERVERCOST;
  57. //
  58. // Connection costs:
  59. //
  60. // The smallest unit of cost is the number of pending searches.
  61. // The next factor of cost is the connection state.
  62. // States:
  63. // Connected = + COST_CONNECTED
  64. // Initially state (unconnected) = + COST_INITIAL
  65. // Connection down = + COST_RETRY
  66. // Connection recently went down = + COST_DOWN
  67. //
  68. // A configurable priority is always added to the cost.
  69. //
  70. #define DEFAULT_COST_CONNECTED_LOCAL 0
  71. #define DEFAULT_COST_CONNECTED_REMOTE 2
  72. #define DEFAULT_COST_INITIAL_LOCAL 4
  73. #define DEFAULT_COST_INITIAL_REMOTE 8
  74. #define DEFAULT_COST_RETRY_LOCAL 6
  75. #define DEFAULT_COST_RETRY_REMOTE 10
  76. #define COST_DOWN_LOCAL 0x80000000
  77. #define COST_DOWN_REMOTE 0x80000000
  78. #define COST_TOO_HIGH_TO_CONNECT 0x80000000
  79. //
  80. // Registry key and value names for initializing GC cost values from the registry
  81. //
  82. #define GC_COST_PARAMETERS_KEY "System\\CurrentControlSet\\Services\\SMTPSVC\\Parameters"
  83. #define GC_COST_CONNECTED_LOCAL_VALUE "GCCostConnectedLocal"
  84. #define GC_COST_CONNECTED_REMOTE_VALUE "GCCostConnectedRemote"
  85. #define GC_COST_INITIAL_LOCAL_VALUE "GCCostInitialLocal"
  86. #define GC_COST_INITIAL_REMOTE_VALUE "GCCostInitialRemote"
  87. #define GC_COST_RETRY_LOCAL_VALUE "GCCostRetryLocal"
  88. #define GC_COST_RETRY_REMOTE_VALUE "GCCostRetryRemote"
  89. //
  90. // The maximum number of threads that will try to connect to a
  91. // connection in CONN_STATE_RETRY:
  92. //
  93. #define MAX_CONNECT_THREADS 1
  94. //
  95. // Requerying of available GC control:
  96. // The code will rebuild the list of available GCs at a hard coded
  97. // time interval. The code will also requery for available GCs after
  98. // a hard coded number of connection failures and a minimum time interval.
  99. //
  100. #define DEFAULT_REBUILD_GC_LIST_MAX_INTERVAL (60*60) // 1 hour
  101. #define DEFAULT_REBUILD_GC_LIST_MAX_FAILURES (100) // 100 connection failures
  102. #define DEFAULT_REBUILD_GC_LIST_MIN_INTERVAL (60*5) // 5 minutes
  103. //
  104. // Registry key and value names for initializing values from the registry
  105. //
  106. #define REBUILD_GC_LIST_PARAMETERS_KEY "System\\CurrentControlSet\\Services\\SMTPSVC\\Parameters"
  107. #define REBUILD_GC_LIST_MAX_INTERVAL_VALUE "RebuildGCListMaxInterval"
  108. #define REBUILD_GC_LIST_MAX_FAILURES_VALUE "RebuildGCListMaxFailures"
  109. #define REBUILD_GC_LIST_MIN_INTERVAL_VALUE "RebuildGCListMinInterval"
  110. //
  111. // An LDAP connection cache object that creates CCfgConnection objects
  112. //
  113. class CCfgConnectionCache :
  114. public CBatchLdapConnectionCache
  115. {
  116. public:
  117. CCfgConnectionCache(
  118. ISMTPServerEx *pISMTPServerEx) :
  119. CBatchLdapConnectionCache(pISMTPServerEx)
  120. {
  121. }
  122. HRESULT GetConnection(
  123. CCfgConnection **ppConn,
  124. PLDAPSERVERCONFIG pServerConfig,
  125. CLdapServerCfg *pCLdapServerConfig);
  126. CCachedLdapConnection *CreateCachedLdapConnection(
  127. LPSTR szHost,
  128. DWORD dwPort,
  129. LPSTR szNamingContext,
  130. LPSTR szAccount,
  131. LPSTR szPassword,
  132. LDAP_BIND_TYPE bt,
  133. PVOID pCreateContext);
  134. private:
  135. #define SIGNATURE_CCFGCONNECTIONCACHE (DWORD)'CCCC'
  136. #define SIGNATURE_CCFGCONNECTIONCACHE_INVALID (DWORD)'CCCX'
  137. DWORD m_dwSignature;
  138. };
  139. //
  140. // CLdapCfgMgr is a wrapper around CLdapCfg. It contains thread save
  141. // code to build a new CLdapCfg object with a new list of available
  142. // LDAP servers
  143. //
  144. CatDebugClass(CLdapCfgMgr),
  145. public CBaseObject
  146. {
  147. public:
  148. CLdapCfgMgr(
  149. ISMTPServerEx *pISMTPServerEx,
  150. BOOL fAutomaticConfigUpdate,
  151. ICategorizerParameters *pICatParams,
  152. LDAP_BIND_TYPE bt = BIND_TYPE_NONE,
  153. LPSTR pszAccount = NULL,
  154. LPSTR pszPassword = NULL,
  155. LPSTR pszNamingContext = NULL);
  156. //
  157. // Reads parameters from the registry, setting member variables
  158. // when configuration data is available
  159. //
  160. VOID InitializeFromRegistry();
  161. //
  162. // Build a list of all available GCs and initialize
  163. // This function may be called multiple times (necessary if the
  164. // available GCs change)
  165. //
  166. HRESULT HrInit(
  167. BOOL fRediscoverGCs = FALSE);
  168. //
  169. // Initialize using a specified list of avialable LDAP servers
  170. // THis function may be called more than once
  171. //
  172. HRESULT HrInit(
  173. DWORD dwcServers,
  174. PLDAPSERVERCONFIG prgServerConfig);
  175. //
  176. // Get a connection
  177. //
  178. HRESULT HrGetConnection(
  179. CCfgConnection **ppConn);
  180. //
  181. // Called very often to update the GC configuration if warranted.
  182. //
  183. HRESULT HrUpdateConfigurationIfNecessary();
  184. //
  185. // Wrapper to cancel all searches on all connections
  186. //
  187. VOID CancelAllConnectionSearches(
  188. ISMTPServer *pIServer)
  189. {
  190. m_LdapConnectionCache.CancelAllConnectionSearches(
  191. pIServer);
  192. }
  193. ISMTPServerEx * GetISMTPServerEx()
  194. {
  195. return m_pISMTPServerEx;
  196. }
  197. private:
  198. ~CLdapCfgMgr();
  199. HRESULT HrGetGCServers(
  200. IN ICategorizerLdapConfig *pICatLdapConfigInterface,
  201. IN LDAP_BIND_TYPE bt,
  202. IN LPSTR pszAccount,
  203. IN LPSTR pszPassword,
  204. IN LPSTR pszNamingContext,
  205. OUT DWORD *pdwcServerConfig,
  206. OUT PLDAPSERVERCONFIG *pprgServerConfig);
  207. HRESULT HrBuildGCServerArray(
  208. IN LDAP_BIND_TYPE bt,
  209. IN LPSTR pszAccount,
  210. IN LPSTR pszPassword,
  211. IN LPSTR pszNamingContext,
  212. IN BOOL fRediscoverGCs,
  213. OUT DWORD *pdwcServerConfig,
  214. OUT PLDAPSERVERCONFIG *pprgServerConfig);
  215. HRESULT HrBuildArrayFromDCInfo(
  216. IN LDAP_BIND_TYPE bt,
  217. IN LPSTR pszAccount,
  218. IN LPSTR pszPassword,
  219. IN LPSTR pszNamingContext,
  220. IN DWORD dwcDSDCInfo,
  221. IN PDS_DOMAIN_CONTROLLER_INFO_2 prgDSDCInfo,
  222. OUT DWORD *pdwcServerConfig,
  223. OUT PLDAPSERVERCONFIG *pprgServerConfig);
  224. BOOL fReadyForUpdate();
  225. LPSTR SzConnectNameFromDomainControllerInfo(
  226. PDS_DOMAIN_CONTROLLER_INFO_2 pDCInfo)
  227. {
  228. if(pDCInfo->DnsHostName)
  229. return pDCInfo->DnsHostName;
  230. else if(pDCInfo->NetbiosName)
  231. return pDCInfo->NetbiosName;
  232. else
  233. return NULL;
  234. }
  235. VOID LogCnfgInit();
  236. VOID LogCnfgEntry(PLDAPSERVERCONFIG pConfig);
  237. private:
  238. #define SIGNATURE_CLDAPCFGMGR (DWORD)'MCLC'
  239. #define SIGNATURE_CLDAPCFGMGR_INVALID (DWORD)'MCLX'
  240. DWORD m_dwSignature;
  241. BOOL m_fAutomaticConfigUpdate;
  242. DWORD m_dwUpdateInProgress;
  243. ULARGE_INTEGER m_ulLastUpdateTime;
  244. CExShareLock m_sharelock;
  245. CLdapCfg *m_pCLdapCfg;
  246. DWORD m_dwRebuildGCListMaxInterval;
  247. DWORD m_dwRebuildGCListMaxFailures;
  248. DWORD m_dwRebuildGCListMinInterval;
  249. //
  250. // Default configuration to use with automatic host selection
  251. //
  252. LDAP_BIND_TYPE m_bt;
  253. CHAR m_szNamingContext[CAT_MAX_DOMAIN];
  254. CHAR m_szAccount[CAT_MAX_LOGIN];
  255. CHAR m_szPassword[CAT_MAX_PASSWORD];
  256. ICategorizerParameters *m_pICatParams;
  257. ISMTPServerEx *m_pISMTPServerEx;
  258. CCfgConnectionCache m_LdapConnectionCache;
  259. };
  260. //
  261. // CLdapCfg contains the configuration of a group of LDAP servers at
  262. // one point in time. The group of LDAP servers may not be changed
  263. // (without creating a new CLdapCfg object)
  264. //
  265. CatDebugClass(CLdapCfg),
  266. public CBaseObject
  267. {
  268. public:
  269. CLdapCfg(
  270. ISMTPServerEx *pISMTPServerEx);
  271. void * operator new(size_t size, DWORD dwcServers);
  272. //
  273. // HrInit should only be called once per object
  274. //
  275. HRESULT HrInit(
  276. DWORD dwcServers,
  277. PLDAPSERVERCONFIG prgServerConfig,
  278. CLdapCfg *pCLdapCfgOld);
  279. //
  280. // Get a connection
  281. //
  282. HRESULT HrGetConnection(
  283. CCfgConnection **ppConn,
  284. CCfgConnectionCache *pLdapConnectionCache);
  285. DWORD DwNumConnectionFailures()
  286. {
  287. return m_dwcConnectionFailures;
  288. }
  289. DWORD DwNumServers()
  290. {
  291. return m_dwcServers;
  292. }
  293. ISMTPServerEx * GetISMTPServerEx()
  294. {
  295. return m_pISMTPServerEx;
  296. }
  297. private:
  298. ~CLdapCfg();
  299. VOID ShuffleArray();
  300. private:
  301. #define SIGNATURE_CLDAPCFG (DWORD)'fCLC'
  302. #define SIGNATURE_CLDAPCFG_INVALID (DWORD)'fCLX'
  303. DWORD m_dwSignature;
  304. DWORD m_dwInc;
  305. CExShareLock m_sharelock; // Protects m_prgpCLdapServerCfg
  306. DWORD m_dwcServers;
  307. DWORD m_dwcConnectionFailures;
  308. CLdapServerCfg **m_prgpCLdapServerCfg;
  309. ISMTPServerEx *m_pISMTPServerEx;
  310. };
  311. //
  312. // CLdapServerCfg maintains information on the state of one LDAP
  313. // server/port
  314. //
  315. CatDebugClass(CLdapServerCfg)
  316. {
  317. public:
  318. static VOID GlobalInit()
  319. {
  320. InitializeListHead(&m_listhead);
  321. InitializeFromRegistry();
  322. }
  323. static VOID InitializeFromRegistry();
  324. static HRESULT GetServerCfg(
  325. IN ISMTPServerEx *pISMTPServerEx,
  326. IN PLDAPSERVERCONFIG pServerConfig,
  327. OUT CLdapServerCfg **ppCLdapServerCfg);
  328. LONG AddRef()
  329. {
  330. return InterlockedIncrement(&m_lRefCount);
  331. }
  332. LONG Release()
  333. {
  334. LONG lRet;
  335. lRet = InterlockedDecrement(&m_lRefCount);
  336. if(lRet == 0) {
  337. //
  338. // Remove object from global list and destroy
  339. //
  340. m_listlock.ExclusiveLock();
  341. if(m_lRefCount > 0) {
  342. //
  343. // Somebody grabbed this object out of the global list
  344. // and AddRef'd it. Abort deletion.
  345. //
  346. } else {
  347. RemoveEntryList(&m_le);
  348. delete this;
  349. }
  350. m_listlock.ExclusiveUnlock();
  351. }
  352. return lRet;
  353. }
  354. //
  355. // Get a connection
  356. //
  357. HRESULT HrGetConnection(
  358. ISMTPServerEx *pISMTPServerEx,
  359. CCfgConnection **ppConn,
  360. CCfgConnectionCache *pLdapConnectionCache);
  361. VOID Cost(
  362. IN ISMTPServerEx *pISMTPServerEx,
  363. OUT PLDAPSERVERCOST pCost);
  364. VOID IncrementPendingSearches()
  365. {
  366. DWORD dwcSearches;
  367. CatFunctEnterEx((LPARAM)this, "CLdapServerCfg::IncrementPendingSearches");
  368. dwcSearches = (LONG) InterlockedIncrement((PLONG)&m_dwcPendingSearches);
  369. DebugTrace((LPARAM)this, "%ld pending searches on connection [%s:%d]",
  370. dwcSearches, m_ServerConfig.szHost, m_ServerConfig.dwPort);
  371. CatFunctLeaveEx((LPARAM)this);
  372. }
  373. VOID DecrementPendingSearches()
  374. {
  375. DWORD dwcSearches;
  376. CatFunctEnterEx((LPARAM)this, "CLdapServerCfg::IncrementPendingSearches");
  377. dwcSearches = (DWORD) InterlockedDecrement((PLONG)&m_dwcPendingSearches);
  378. DebugTrace((LPARAM)this, "%ld pending searches on connection [%s:%d]",
  379. dwcSearches, m_ServerConfig.szHost, m_ServerConfig.dwPort);
  380. CatFunctLeaveEx((LPARAM)this);
  381. }
  382. VOID UpdateConnectionState(
  383. ISMTPServerEx *pISMTPServerEx,
  384. ULARGE_INTEGER *pft,
  385. CONN_STATE connstate);
  386. VOID IncrementFailedCount()
  387. {
  388. InterlockedIncrement((PLONG) &m_dwcFailedConnectAttempts);
  389. }
  390. VOID ResetFailedCount()
  391. {
  392. InterlockedExchange((PLONG) &m_dwcFailedConnectAttempts, 0);
  393. }
  394. CONN_STATE CurrentState()
  395. {
  396. return m_connstate;
  397. }
  398. ULARGE_INTEGER GetCurrentTime()
  399. {
  400. ULARGE_INTEGER FileTime;
  401. _ASSERT(sizeof(ULARGE_INTEGER) == sizeof(FILETIME));
  402. GetSystemTimeAsFileTime((LPFILETIME)&FileTime);
  403. return FileTime;
  404. }
  405. private:
  406. CLdapServerCfg();
  407. ~CLdapServerCfg();
  408. HRESULT HrInit(
  409. PLDAPSERVERCONFIG pServerConfig);
  410. BOOL fReadyForRetry()
  411. {
  412. // 100 nanoseconds * 10^7 == 1 second
  413. return ((GetCurrentTime().QuadPart - m_ftLastStateUpdate.QuadPart) >=
  414. ((LONGLONG)CONN_RETRY_TIME * 10000000));
  415. }
  416. BOOL fMatch(
  417. PLDAPSERVERCONFIG pServerConfig);
  418. VOID LogStateChangeEvent(
  419. IN ISMTPServerEx *pISMTPServerEx,
  420. IN CONN_STATE connstate,
  421. IN LPSTR pszHost,
  422. IN DWORD dwPort);
  423. static CLdapServerCfg *FindServerCfg(
  424. PLDAPSERVERCONFIG pServerConfig);
  425. static BOOL fIsLocalComputer(
  426. PLDAPSERVERCONFIG pServerConfig);
  427. private:
  428. #define SIGNATURE_CLDAPSERVERCFG (DWORD)'CSLC'
  429. #define SIGNATURE_CLDAPSERVERCFG_INVALID (DWORD)'CSLX'
  430. static DWORD m_dwCostConnectedLocal;
  431. static DWORD m_dwCostConnectedRemote;
  432. static DWORD m_dwCostInitialLocal;
  433. static DWORD m_dwCostInitialRemote;
  434. static DWORD m_dwCostRetryLocal;
  435. static DWORD m_dwCostRetryRemote;
  436. DWORD m_dwSignature;
  437. LONG m_lRefCount;
  438. LDAPSERVERCONFIG m_ServerConfig;
  439. CExShareLock m_sharelock;
  440. CONN_STATE m_connstate;
  441. ULARGE_INTEGER m_ftLastStateUpdate;
  442. DWORD m_dwcPendingSearches;
  443. DWORD m_dwcCurrentConnectAttempts;
  444. DWORD m_dwcFailedConnectAttempts;
  445. //
  446. // Member variables to keep/protect a list of CLdapServer objects
  447. //
  448. static CExShareLock m_listlock;
  449. static LIST_ENTRY m_listhead;
  450. LIST_ENTRY m_le;
  451. BOOL m_fLocalServer;
  452. };
  453. //
  454. // An LDAP connection that notifies CLdapServerCfg about state changes
  455. //
  456. class CCfgConnection :
  457. public CBatchLdapConnection
  458. {
  459. #define SIGNATURE_CCFGCONNECTION (DWORD)'oCCC'
  460. #define SIGNATURE_CCFGCONNECTION_INVALID (DWORD)'oCCX'
  461. public:
  462. CCfgConnection(
  463. LPSTR szHost,
  464. DWORD dwPort,
  465. LPSTR szNamingContext,
  466. LPSTR szAccount,
  467. LPSTR szPassword,
  468. LDAP_BIND_TYPE bt,
  469. CLdapConnectionCache *pCache,
  470. CLdapServerCfg *pCLdapServerCfg) :
  471. CBatchLdapConnection(
  472. szHost,
  473. dwPort,
  474. szNamingContext,
  475. szAccount,
  476. szPassword,
  477. bt,
  478. pCache)
  479. {
  480. m_dwSignature = SIGNATURE_CCFGCONNECTION;
  481. m_pCLdapServerCfg = pCLdapServerCfg;
  482. pCLdapServerCfg->AddRef();
  483. m_connstate = CONN_STATE_INITIAL;
  484. }
  485. ~CCfgConnection()
  486. {
  487. _ASSERT(m_pCLdapServerCfg);
  488. m_pCLdapServerCfg->Release();
  489. _ASSERT(m_dwSignature == SIGNATURE_CCFGCONNECTION);
  490. m_dwSignature = SIGNATURE_CCFGCONNECTION_INVALID;
  491. }
  492. virtual HRESULT Connect();
  493. virtual HRESULT AsyncSearch( // Asynchronously look up
  494. LPCWSTR szBaseDN, // objects matching specified
  495. int nScope, // criteria in the DS. The
  496. LPCWSTR szFilter, // results are passed to
  497. LPCWSTR szAttributes[], // fnCompletion when they
  498. DWORD dwPageSize, // Optinal page size
  499. LPLDAPCOMPLETION fnCompletion, // become available.
  500. LPVOID ctxCompletion);
  501. private:
  502. virtual VOID CallCompletion(
  503. PPENDING_REQUEST preq,
  504. PLDAPMessage pres,
  505. HRESULT hrStatus,
  506. BOOL fFinalCompletion);
  507. VOID NotifyServerDown();
  508. private:
  509. DWORD m_dwSignature;
  510. CLdapServerCfg *m_pCLdapServerCfg;
  511. CExShareLock m_sharelock;
  512. CONN_STATE m_connstate;
  513. };
  514. //+------------------------------------------------------------
  515. //
  516. // Function: CLdapCfgMgr::HrUpdateConfigurationIfNecessary
  517. //
  518. // Synopsis: Check to see if the CLdapCfg should be updated.
  519. // If it should be, do the update.
  520. //
  521. // Arguments: NONE
  522. //
  523. // Returns:
  524. // S_OK: Success
  525. // error from HrInit
  526. //
  527. // History:
  528. // jstamerj 1999/06/29 20:51:23: Created.
  529. //
  530. //-------------------------------------------------------------
  531. inline HRESULT CLdapCfgMgr::HrUpdateConfigurationIfNecessary()
  532. {
  533. HRESULT hr = S_OK;
  534. DWORD dw;
  535. BOOL fUpdate;
  536. if(m_fAutomaticConfigUpdate == FALSE)
  537. //
  538. // Update is disabled
  539. return S_OK;
  540. //
  541. // See if some other thread is already updating the configuration
  542. // (try to enter the lock)
  543. //
  544. dw = InterlockedExchange((PLONG)&m_dwUpdateInProgress, TRUE);
  545. if(dw == FALSE) {
  546. //
  547. // No other thread is updating
  548. //
  549. fUpdate = fReadyForUpdate();
  550. if(fUpdate) {
  551. //
  552. // Call HrInit to generate a new CLdapCfg
  553. //
  554. hr = HrInit(TRUE);
  555. if(SUCCEEDED(hr)) {
  556. //
  557. // Set the last update time
  558. //
  559. GetSystemTimeAsFileTime((LPFILETIME)&m_ulLastUpdateTime);
  560. }
  561. }
  562. //
  563. // Release the lock
  564. //
  565. InterlockedExchange((PLONG)&m_dwUpdateInProgress, FALSE);
  566. }
  567. return hr;
  568. } // CLdapCfgMgr::HrUpdateConfigurationIfNecessary
  569. //+------------------------------------------------------------
  570. //
  571. // Function: CLdapCfgMgr::fReadyForUpdate
  572. //
  573. // Synopsis: Calculates wether or not this object is due for an
  574. // automatic cfg update
  575. //
  576. // Arguments: NONE
  577. //
  578. // Returns:
  579. // TRUE: Yes, it is time for an update
  580. // FALSE: No, an update is not required at this time
  581. //
  582. // History:
  583. // jstamerj 1999/06/30 12:08:35: Created.
  584. //
  585. //-------------------------------------------------------------
  586. inline BOOL CLdapCfgMgr::fReadyForUpdate()
  587. {
  588. DWORD dwNumConnectionFailures;
  589. ULARGE_INTEGER ulCurrentTime;
  590. //
  591. // We need an update when:
  592. // 1) A periodic time interval has ellapsed
  593. // 100 ns * 10^7 == 1 second
  594. //
  595. GetSystemTimeAsFileTime((LPFILETIME)&ulCurrentTime);
  596. if((ulCurrentTime.QuadPart - m_ulLastUpdateTime.QuadPart) >=
  597. (ULONGLONG) Int32x32To64((LONG)m_dwRebuildGCListMaxInterval, 10000000))
  598. return TRUE;
  599. //
  600. // We also need an update when:
  601. // 2) We have received more than a set number of connection
  602. // failures on the current configuration and at least a minimum
  603. // time interval has passed
  604. //
  605. // Check for the mimimum time interval
  606. //
  607. if( (ulCurrentTime.QuadPart - m_ulLastUpdateTime.QuadPart) >=
  608. (ULONGLONG) Int32x32To64((LONG)m_dwRebuildGCListMinInterval, 10000000)) {
  609. //
  610. // Get the number of connection failures
  611. //
  612. m_sharelock.ShareLock();
  613. if(m_pCLdapCfg) {
  614. dwNumConnectionFailures = m_pCLdapCfg->DwNumConnectionFailures();
  615. } else {
  616. dwNumConnectionFailures = 0;
  617. _ASSERT(0 && "HrInit was not called or failed");
  618. }
  619. m_sharelock.ShareUnlock();
  620. if(dwNumConnectionFailures >= m_dwRebuildGCListMaxFailures)
  621. return TRUE;
  622. }
  623. return FALSE;
  624. } // CLdapCfgMgr::fReadyForUpdate
  625. #endif //__CNFGMGR_H__