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.

1823 lines
55 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2002.
  5. //
  6. // File: notifmgr.cxx
  7. //
  8. // Contents: Registry and file system change notifications
  9. //
  10. // History: 14-Jul-97 SitaramR Created from dlnotify.cxx
  11. //
  12. // Notes : For lock hierarchy and order of acquiring locks, please see
  13. // cicat.cxx
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.cxx>
  17. #pragma hdrstop
  18. #include <ciregkey.hxx>
  19. #include <cistore.hxx>
  20. #include <rcstxact.hxx>
  21. #include <imprsnat.hxx>
  22. #include <eventlog.hxx>
  23. #include <docstore.hxx>
  24. #include <svcutil.hxx>
  25. #include "cicat.hxx"
  26. #include "update.hxx"
  27. #include "notifmgr.hxx"
  28. #include "scanmgr.hxx"
  29. #include "scopetbl.hxx"
  30. BOOL AreIdenticalPaths( WCHAR const * pwcsPath1, WCHAR const * pwcsPath2 )
  31. {
  32. ULONG len1 = wcslen( pwcsPath1 );
  33. ULONG len2 = wcslen( pwcsPath2 );
  34. return len1 == len2 &&
  35. RtlEqualMemory( pwcsPath1, pwcsPath2, len1*sizeof(WCHAR) );
  36. }
  37. //+---------------------------------------------------------------------------
  38. //
  39. // Member: CCiNotify::CCiNotify
  40. //
  41. // Synopsis: Constructor of the single scope notification object CCiNotify.
  42. //
  43. // Arguments: [notifyMgr] -- Notification manager.
  44. // [wcsScope] -- Scope of the notification.
  45. // [cwcScope] -- Length in chars of [wcsScope]
  46. // [volumeId] -- Volume id
  47. // [ftlastScan] -- Last scan time
  48. // [usn] -- Usn
  49. // [fDeep] -- Set to TRUE if deep notifications are enabled.
  50. //
  51. // History: 1-17-96 srikants Created
  52. //
  53. //----------------------------------------------------------------------------
  54. CCiNotify::CCiNotify( CCiNotifyMgr & notifyMgr,
  55. WCHAR const * wcsScope,
  56. unsigned cwcScope,
  57. VOLUMEID volumeId,
  58. ULONGLONG const & VolumeCreationTime,
  59. ULONG VolumeSerialNumber,
  60. FILETIME const & ftLastScan,
  61. USN usn,
  62. ULONGLONG const & JournalId,
  63. BOOL fUsnTreeScan,
  64. BOOL fDeep )
  65. : CGenericNotify( & notifyMgr.GetCatalog(), wcsScope, cwcScope, fDeep, TRUE ),
  66. _sigCiNotify(sigCiNotify),
  67. _notifyMgr(notifyMgr),
  68. _volumeId(volumeId),
  69. _VolumeCreationTime( VolumeCreationTime ),
  70. _VolumeSerialNumber( VolumeSerialNumber ),
  71. _fUsnTreeScan(fUsnTreeScan)
  72. {
  73. if ( volumeId == CI_VOLID_USN_NOT_ENABLED )
  74. _ftLastScan = ftLastScan;
  75. else
  76. {
  77. _usn = usn;
  78. _JournalId = JournalId;
  79. }
  80. _notifyMgr.AddRef();
  81. XInterface<CCiNotifyMgr> xNotify( &notifyMgr );
  82. if ( volumeId == CI_VOLID_USN_NOT_ENABLED )
  83. {
  84. //
  85. // Enable file system notifications for non-usn volumes
  86. //
  87. EnableNotification();
  88. }
  89. xNotify.Acquire();
  90. } //CCiNotify
  91. //+---------------------------------------------------------------------------
  92. //
  93. // Member: CCiNotify::~CCiNotify
  94. //
  95. // Synopsis: Destructor
  96. //
  97. // History: 05-07-97 SitaramR Added Header
  98. //
  99. //----------------------------------------------------------------------------
  100. CCiNotify::~CCiNotify()
  101. {
  102. _notifyMgr.Release();
  103. }
  104. //+---------------------------------------------------------------------------
  105. //
  106. // Member: CCiNotify::Abort
  107. //
  108. // Synopsis: Marks that an abort is in progress. Also disables further
  109. // notifications for this scope.
  110. //
  111. // History: 1-17-96 srikants Created
  112. //
  113. //----------------------------------------------------------------------------
  114. void CCiNotify::Abort()
  115. {
  116. CLock lock(_notifyMgr.GetMutex());
  117. _fAbort = TRUE;
  118. if ( _volumeId == CI_VOLID_USN_NOT_ENABLED )
  119. {
  120. //
  121. // Notifications are enabled only for those volumes that
  122. // do not support usns.
  123. //
  124. DisableNotification();
  125. }
  126. else
  127. {
  128. //
  129. // Ctor of CGenericNotify does an AddRef, which is released by
  130. // the APC for non-usn volumes. For usn volumes do the Release here.
  131. //
  132. Release();
  133. }
  134. }
  135. //+---------------------------------------------------------------------------
  136. //
  137. // Member: CCiNotify::IsMatch
  138. //
  139. // Synopsis: Checks if the given path is within the scope of the notifi-
  140. // cations. If deep notifications are enabled, it is sufficient
  141. // for the notification scope to be a subset of the given path.
  142. // Otherwise, there must be an exact match.
  143. //
  144. // Arguments: [wcsPath] - Path to be tested.
  145. // [len] - Length of wcsPath.
  146. //
  147. // Returns: TRUE if there is a match. FALSE o/w
  148. //
  149. // History: 1-18-96 srikants Created
  150. //
  151. //----------------------------------------------------------------------------
  152. BOOL CCiNotify::IsMatch( WCHAR const * wcsPath, ULONG len ) const
  153. {
  154. CScopeMatch match( GetScope(), ScopeLength() );
  155. return match.IsInScope( wcsPath, len );
  156. }
  157. //+---------------------------------------------------------------------------
  158. //
  159. // Member: CCiNotifyMgr::QueryAsyncWorkItem
  160. //
  161. // Synopsis: Creates an async work item to process notifications.
  162. //
  163. // Arguments: [pbChanges] - Buffer of changes
  164. // [cbChanges] - Number of bytes in pbChanges
  165. // [pwcsRoot] - The directory root where the change happened.
  166. //
  167. // Returns: A pointer to an async work item
  168. //
  169. // History: 1-03-97 srikants Moved from hxx file to use the new
  170. // CWorkManager.
  171. //
  172. //----------------------------------------------------------------------------
  173. CCiAsyncProcessNotify * CCiNotifyMgr::QueryAsyncWorkItem(
  174. BYTE const * pbChanges,
  175. ULONG cbChanges,
  176. WCHAR const * pwcsRoot )
  177. {
  178. XArray<BYTE> xChanges( cbChanges );
  179. RtlCopyMemory( xChanges.GetPointer(), pbChanges, cbChanges );
  180. CWorkManager & workMan = _cicat.GetWorkMan();
  181. return new CCiAsyncProcessNotify( workMan,
  182. _cicat,
  183. _scanMgr,
  184. xChanges,
  185. pwcsRoot );
  186. }
  187. //+---------------------------------------------------------------------------
  188. //
  189. // Member: CCiNotify::DoIt()
  190. //
  191. // Synopsis: Called from APC.
  192. //
  193. // History: 1-17-96 srikants Created
  194. //
  195. //----------------------------------------------------------------------------
  196. void CCiNotify::DoIt()
  197. {
  198. BOOL fNotifyReEnabled = FALSE; // Indicates if the notification was reenabled
  199. // successfully
  200. NTSTATUS status = STATUS_SUCCESS;
  201. TRY
  202. {
  203. #if 0
  204. XPtr<CCiAsyncProcessNotify> xWorker;
  205. #endif // 0
  206. if ( _fAbort )
  207. ciDebugOut(( DEB_ITRACE, "CiNotification APC: ABORT (IGNORE) 0x%x\n", this ));
  208. else
  209. {
  210. if ( !BufferOverflow() )
  211. {
  212. ciDebugOut(( DEB_ITRACE, "CiNotification APC: CHANGES 0x%x\n", this ));
  213. #if 0
  214. xWorker.Set( _notifyMgr.QueryAsyncWorkItem( GetBuf(),
  215. BufLength(),
  216. GetScope()) );
  217. #else
  218. _notifyMgr.ProcessChanges( GetBuf(),
  219. GetScope() );
  220. #endif // 0
  221. }
  222. // ==================================================
  223. {
  224. //
  225. // Re-enable the notification for this scope.
  226. //
  227. CLock lock(_notifyMgr.GetMutex());
  228. StartNotification(&status);
  229. fNotifyReEnabled = SUCCEEDED(status);
  230. }
  231. // ==================================================
  232. if ( BufferOverflow() )
  233. _notifyMgr.SetupScan( GetScope() );
  234. }
  235. #if 0
  236. if ( 0 != xWorker.GetPointer() )
  237. {
  238. _notifyMgr.ProcessChanges( xWorker );
  239. }
  240. #endif // 0
  241. }
  242. CATCH(CException, e)
  243. {
  244. ciDebugOut(( DEB_ERROR, "CiNotification APC: CATCH 0x%x\n", e.GetErrorCode() ));
  245. status = e.GetErrorCode();
  246. }
  247. END_CATCH;
  248. if ( !_fAbort && !fNotifyReEnabled )
  249. {
  250. LogNotificationsFailed( status );
  251. CLock lock( _notifyMgr.GetMutex() );
  252. LokClearNotifyEnabled();
  253. }
  254. }
  255. //+---------------------------------------------------------------------------
  256. //
  257. // Member: CCiNotify::ClearNotifyEnabled
  258. //
  259. // Synopsis: Clears the flag to indicate that notifications are disabled
  260. // for this scope. This will permit periodic scanning of scopes
  261. // by the scan thread.
  262. //
  263. // History: 5-03-96 srikants Created
  264. //
  265. // Notes: The operation must be done under a lock.
  266. //
  267. //----------------------------------------------------------------------------
  268. void CCiNotify::ClearNotifyEnabled()
  269. {
  270. CLock lock( _notifyMgr.GetMutex() );
  271. LokClearNotifyEnabled();
  272. }
  273. //+---------------------------------------------------------------------------
  274. //
  275. // Member: CVRootNotify::CVRootNotify, public
  276. //
  277. // Synopsis: Constructor for object to watch IIS vroot changes
  278. //
  279. // Arguments: [cat] -- Catalog
  280. // [eType] -- Type of vroot
  281. // [Instance] -- Instance # of the vserver
  282. // [notifyMgr] -- Notify manager controller
  283. //
  284. // History: 2-20-96 KyleP Created
  285. //
  286. //----------------------------------------------------------------------------
  287. CVRootNotify::CVRootNotify(
  288. CiCat & cat,
  289. CiVRootTypeEnum eType,
  290. ULONG Instance,
  291. CCiNotifyMgr & notifyMgr )
  292. : _type( eType ),
  293. _cat( cat ),
  294. _notifyMgr( notifyMgr ),
  295. _mdMgr( FALSE, eType, Instance )
  296. {
  297. _mdMgr.EnableVPathNotify( this );
  298. }
  299. //+---------------------------------------------------------------------------
  300. //
  301. // Member: CRegistryScopesNotify::CRegistryScopesNotify
  302. //
  303. // Synopsis: Constructor for object to watch ci scopes
  304. //
  305. // Arguments: [cat] -- Catalog
  306. //
  307. // History: 10-16-96 dlee Created
  308. //
  309. //----------------------------------------------------------------------------
  310. CRegistryScopesNotify::CRegistryScopesNotify(
  311. CiCat & cat,
  312. CCiNotifyMgr & notifyMgr )
  313. : _cat( cat ),
  314. _notifyMgr( notifyMgr ),
  315. CRegNotify( cat.GetScopesKey() )
  316. {
  317. _notifyMgr.AddRef();
  318. }
  319. //+---------------------------------------------------------------------------
  320. //
  321. // Member: CCiRegistryNotify::CCiRegistryNotify
  322. //
  323. // Synopsis: Constructor for the CCiRegistryNotify.
  324. //
  325. // Arguments: [cat] -
  326. // [notifyMgr] -
  327. //
  328. // History: 12-12-96 srikants Created
  329. //
  330. //----------------------------------------------------------------------------
  331. CCiRegistryNotify::CCiRegistryNotify(
  332. CiCat & cat,
  333. CCiNotifyMgr & notifyMgr )
  334. : _cat( cat ),
  335. _notifyMgr( notifyMgr ),
  336. CRegNotify( wcsRegAdminTree )
  337. {
  338. _notifyMgr.AddRef();
  339. }
  340. //+---------------------------------------------------------------------------
  341. //
  342. // Member: CVRootNotify::DisableNotification, public
  343. //
  344. // Synopsis: Turns off notifications (if on )
  345. //
  346. // History: 2-13-97 dlee Created
  347. //
  348. //----------------------------------------------------------------------------
  349. void CVRootNotify::DisableNotification()
  350. {
  351. // Need TRY since RPC may access violate if iisadmin has gone down
  352. TRY
  353. {
  354. _mdMgr.DisableVPathNotify();
  355. }
  356. CATCH( CException, e )
  357. {
  358. ciDebugOut(( DEB_WARN,
  359. "CVRootNotify::DisableNotification caught exception 0x%x\n",
  360. e.GetErrorCode() ));
  361. }
  362. END_CATCH
  363. }
  364. //+---------------------------------------------------------------------------
  365. //
  366. // Member: CRegistryScopesNotify::~CRegistryScopesNotify
  367. //
  368. // Synopsis: Destructor.
  369. //
  370. // History: 10-16-96 dlee Created
  371. //
  372. //----------------------------------------------------------------------------
  373. CRegistryScopesNotify::~CRegistryScopesNotify()
  374. {
  375. _notifyMgr.Release();
  376. }
  377. //+---------------------------------------------------------------------------
  378. //
  379. // Member: CCiRegistryNotify::~CCiRegistryNotify
  380. //
  381. // Synopsis: Destructor
  382. //
  383. // History: 12-12-96 srikants Created
  384. //
  385. //----------------------------------------------------------------------------
  386. CCiRegistryNotify::~CCiRegistryNotify()
  387. {
  388. _notifyMgr.Release();
  389. }
  390. //+---------------------------------------------------------------------------
  391. //
  392. // Member: CVRootNotify::CallBack, public
  393. //
  394. // Synopsis: Callback from metabase connection point
  395. //
  396. // Arguments: [fCancel] -- If TRUE, iisadmin is going down, so cancel
  397. // notifications and poll for it to come back up.
  398. //
  399. // History: 2-20-96 KyleP Created
  400. // 2-13-97 dlee Updated for metabase
  401. //
  402. //----------------------------------------------------------------------------
  403. SCODE CVRootNotify::CallBack( BOOL fCancel )
  404. {
  405. if ( fCancel )
  406. {
  407. ciDebugOut(( DEB_WARN,
  408. "Scheduling worker for '%ws' shutdown...\n",
  409. GetVRootService( _type ) ));
  410. _notifyMgr.CancelIISVRootNotify( _type );
  411. // note: we may be deleted by now, don't access private data
  412. }
  413. else
  414. {
  415. ciDebugOut(( DEB_WARN,
  416. "Scheduling worker thread for VRoot registry change...\n" ));
  417. CWorkManager & workMan = _cat.GetWorkMan();
  418. XInterface<CIISVRootAsyncNotify> xNotify(
  419. new CIISVRootAsyncNotify( _cat, workMan ) );
  420. workMan.AddToWorkList( xNotify.GetPointer() );
  421. xNotify->AddToWorkQueue();
  422. }
  423. return S_OK;
  424. } //CallBack
  425. //+---------------------------------------------------------------------------
  426. //
  427. // Member: CRegistryScopesNotify::DoIt, public
  428. //
  429. // Synopsis: Callback from APC
  430. //
  431. // History: 10-16-96 dlee Created
  432. //
  433. //----------------------------------------------------------------------------
  434. void CRegistryScopesNotify::DoIt()
  435. {
  436. ciDebugOut(( DEB_WARN,
  437. "Scheduling worker thread for RegistryScopes registry change...\n" ));
  438. CWorkManager & workMan = _cat.GetWorkMan();
  439. CRegistryScopesAsyncNotify * pNotify = new CRegistryScopesAsyncNotify(_cat, workMan);
  440. workMan.AddToWorkList( pNotify );
  441. pNotify->AddToWorkQueue();
  442. pNotify->Release();
  443. }
  444. //+---------------------------------------------------------------------------
  445. //
  446. // Member: CCiRegistryNotify::DoIt
  447. //
  448. // Synopsis: Refreshes the registry parameters
  449. //
  450. // History: 12-12-96 srikants Created
  451. //
  452. //----------------------------------------------------------------------------
  453. void CCiRegistryNotify::DoIt()
  454. {
  455. //
  456. // We don't need a worker thread to do this because it is very
  457. // quick and simple.
  458. //
  459. _cat.RefreshRegistryParams();
  460. }
  461. //+---------------------------------------------------------------------------
  462. //
  463. // Member: CCiNotifyMgr::CCiNotifyMgr
  464. //
  465. // Synopsis: ctor of the CI notification manager.
  466. //
  467. // Arguments: [cicat] - Catalog
  468. // [scanMgr] - Scan thread manager
  469. //
  470. // History: 1-18-96 srikants Created
  471. //
  472. //----------------------------------------------------------------------------
  473. CCiNotifyMgr::CCiNotifyMgr( CiCat & cicat, CCiScanMgr & scanMgr )
  474. : _cicat(cicat),
  475. _scanMgr(scanMgr),
  476. _nUpdates(0),
  477. _fAbort(FALSE),
  478. _evtType(eNone),
  479. _pRegistryScopesNotify(0),
  480. _fIISAdminAlive( TRUE ),
  481. _fTrackW3Svc( FALSE ),
  482. _fTrackNNTPSvc( FALSE ),
  483. _fTrackIMAPSvc( FALSE ),
  484. _W3SvcInstance( 1 ),
  485. _NNTPSvcInstance( 1 ),
  486. _IMAPSvcInstance( 1 ),
  487. _pCiRegistryNotify(0),
  488. #pragma warning( disable : 4355 ) // this used in base initialization
  489. _thrNotify( NotifyThread, this, TRUE ) // create suspended
  490. #pragma warning( default : 4355 )
  491. {
  492. _evt.Reset();
  493. RtlZeroMemory( &_ftLastNetPathScan, sizeof(_ftLastNetPathScan) );
  494. _thrNotify.SetPriority( THREAD_PRIORITY_ABOVE_NORMAL );
  495. }
  496. //+---------------------------------------------------------------------------
  497. //
  498. // Member: CCiNotifyMgr::~CCiNotifyMgr
  499. //
  500. // Synopsis: dtor of the CI notification manager.
  501. //
  502. // History: 17 Dec 1997 AlanW Created
  503. //
  504. //----------------------------------------------------------------------------
  505. CCiNotifyMgr::~CCiNotifyMgr( )
  506. {
  507. // Be sure the thread will die...
  508. if (_thrNotify.IsRunning())
  509. _KillThread();
  510. }
  511. //+---------------------------------------------------------------------------
  512. //
  513. // Member: CCiNotifyMgr::TrackIISVRoots
  514. //
  515. // Synopsis: Registers for notification of VRoot registry changes
  516. //
  517. // Arguments: [fTrackW3Svc] -- TRUE if W3 should be tracked
  518. // [W3SvcInstance] -- W3 instance # to be tracked.
  519. // [fTrackNNTPSvc] -- TRUE if NNTP should be tracked
  520. // [NNTPSvcInstance] -- NNTP instance # to be tracked.
  521. // [fTrackIMAPSvc] -- TRUE if IMAP should be tracked
  522. // [IMAPSvcInstance] -- IMAP instance # to be tracked.
  523. //
  524. // History: 2-21-96 KyleP Created
  525. // 2-13-97 dlee converted to metabase
  526. //
  527. //----------------------------------------------------------------------------
  528. void CCiNotifyMgr::TrackIISVRoots(
  529. BOOL fTrackW3Svc,
  530. ULONG W3SvcInstance,
  531. BOOL fTrackNNTPSvc,
  532. ULONG NNTPSvcInstance,
  533. BOOL fTrackIMAPSvc,
  534. ULONG IMAPSvcInstance )
  535. {
  536. CLock lock(_mutex);
  537. Win4Assert( _xW3SvcVRootNotify.IsNull() );
  538. Win4Assert( _xNNTPSvcVRootNotify.IsNull() );
  539. Win4Assert( _xIMAPSvcVRootNotify.IsNull() );
  540. _fTrackW3Svc = fTrackW3Svc;
  541. _W3SvcInstance = W3SvcInstance;
  542. _fTrackNNTPSvc = fTrackNNTPSvc;
  543. _NNTPSvcInstance = NNTPSvcInstance;
  544. _fTrackIMAPSvc = fTrackIMAPSvc;
  545. _IMAPSvcInstance = IMAPSvcInstance;
  546. _evtType |= eWatchIISVRoots;
  547. _evt.Set();
  548. } //TrackIISVRoots
  549. //+---------------------------------------------------------------------------
  550. //
  551. // Member: CCiNotifyMgr::TrackScopesInRegistry
  552. //
  553. // Synopsis: Registers for notification of scope registry changes
  554. //
  555. // History: 10/17/96 dlee Created
  556. //
  557. //----------------------------------------------------------------------------
  558. void CCiNotifyMgr::TrackScopesInRegistry()
  559. {
  560. CLock lock(_mutex);
  561. Win4Assert( 0 == _pRegistryScopesNotify );
  562. _evtType |= eWatchRegistryScopes;
  563. _evt.Set();
  564. }
  565. //+---------------------------------------------------------------------------
  566. //
  567. // Member: CCiNotifyMgr::TrackCiRegistry
  568. //
  569. // Synopsis: Registers for notifications of CI registry changes.
  570. //
  571. // History: 12-12-96 srikants Created
  572. //
  573. //----------------------------------------------------------------------------
  574. void CCiNotifyMgr::TrackCiRegistry()
  575. {
  576. CLock lock(_mutex);
  577. Win4Assert( 0 == _pCiRegistryNotify );
  578. _evtType |= eWatchCiRegistry;
  579. _evt.Set();
  580. }
  581. //+---------------------------------------------------------------------------
  582. //
  583. // Member: CCiNotifyMgr::CancelIISVRootNotify
  584. //
  585. // Synopsis: Cancels notifications on iisadmin since it's going down
  586. //
  587. // History: 2-13-97 dlee Created
  588. //
  589. //----------------------------------------------------------------------------
  590. void CCiNotifyMgr::CancelIISVRootNotify( CiVRootTypeEnum eType )
  591. {
  592. // after this, we'll poll for the iisadmin svc to start again
  593. CLock lock( _mutex );
  594. if ( W3VRoot == eType )
  595. _evtType |= eUnWatchW3VRoots;
  596. else if ( NNTPVRoot == eType )
  597. _evtType |= eUnWatchNNTPVRoots;
  598. else if ( IMAPVRoot == eType )
  599. _evtType |= eUnWatchIMAPVRoots;
  600. else
  601. {
  602. Win4Assert( !"invalid IIS vroot notify type!" );
  603. }
  604. _evt.Set();
  605. } //CancelIISVRootNotify
  606. //+---------------------------------------------------------------------------
  607. //
  608. // Member: CCiNotifyMgr::LokUnWatchIISVServerNoThrow
  609. //
  610. // Synopsis: Turns off notifications on W3, NNTP, or IMAP
  611. //
  612. // History: 2-Sep-97 dlee created
  613. //
  614. //----------------------------------------------------------------------------
  615. void CCiNotifyMgr::LokUnWatchIISVServerNoThrow(
  616. CVRootNotify * pNotify )
  617. {
  618. ciDebugOut(( DEB_WARN, "LokUnWatchIISVServer\n" ));
  619. TRY
  620. {
  621. delete pNotify;
  622. }
  623. CATCH(CException, e)
  624. {
  625. _fIISAdminAlive = FALSE;
  626. ciDebugOut(( DEB_WARN,
  627. "caught exception while tearing down IIS tracking\n" ));
  628. }
  629. END_CATCH;
  630. } //LokUnWatchIISVServerNoThrow
  631. //+---------------------------------------------------------------------------
  632. //
  633. // Member: CCiNotifyMgr::LokWatchIISVServerNoThrow
  634. //
  635. // Synopsis: Registers for notification of IIS VRoot changes
  636. //
  637. // History: 2-21-96 KyleP Created
  638. // 2-13-97 dlee converted to metabase
  639. //
  640. //----------------------------------------------------------------------------
  641. void CCiNotifyMgr::LokWatchIISVServerNoThrow()
  642. {
  643. ciDebugOut(( DEB_WARN,
  644. "LokWatchIISVServer w3 %d:%d, nntp %d:%d, imap %d:%d\n",
  645. _fTrackW3Svc,
  646. _W3SvcInstance,
  647. _fTrackNNTPSvc,
  648. _NNTPSvcInstance,
  649. _fTrackIMAPSvc,
  650. _IMAPSvcInstance ));
  651. Win4Assert( _fTrackW3Svc || _fTrackNNTPSvc || _fTrackIMAPSvc );
  652. //
  653. // If iisadmin isn't running and it wasn't running before, don't
  654. // ping the metabase. Doing a CoCreateInstance() on the metabase
  655. // object when iisadmin is disabled results in a DCOM error in
  656. // the eventlog. Since we check every 5 minutes this can fill
  657. // the log.
  658. //
  659. if ( !_fIISAdminAlive )
  660. {
  661. if ( ! IsServiceRunning( L"iisadmin" ) )
  662. return;
  663. }
  664. // Assume iisadmin is alive and we can get notifications
  665. BOOL fWasAlive = _fIISAdminAlive;
  666. _fIISAdminAlive = TRUE;
  667. TRY
  668. {
  669. if ( _fTrackW3Svc && _xW3SvcVRootNotify.IsNull() )
  670. _xW3SvcVRootNotify.Set( new CVRootNotify( _cicat,
  671. W3VRoot,
  672. _W3SvcInstance,
  673. *this ) );
  674. if ( _fTrackNNTPSvc && _xNNTPSvcVRootNotify.IsNull() )
  675. _xNNTPSvcVRootNotify.Set( new CVRootNotify( _cicat,
  676. NNTPVRoot,
  677. _NNTPSvcInstance,
  678. *this ) );
  679. if ( _fTrackIMAPSvc && _xIMAPSvcVRootNotify.IsNull() )
  680. _xIMAPSvcVRootNotify.Set( new CVRootNotify( _cicat,
  681. IMAPVRoot,
  682. _IMAPSvcInstance,
  683. *this ) );
  684. }
  685. CATCH(CException, e)
  686. {
  687. _fIISAdminAlive = FALSE;
  688. ciDebugOut(( DEB_WARN,
  689. "caught exception while setting up iis tracking\n" ));
  690. }
  691. END_CATCH;
  692. // did we miss notifications but can catch up now?
  693. if ( !fWasAlive && _fIISAdminAlive )
  694. {
  695. TRY
  696. {
  697. ciDebugOut(( DEB_WARN, "Polling IIS: iisadmin woke up\n" ));
  698. CWorkManager & workMan = _cicat.GetWorkMan();
  699. XInterface<CIISVRootAsyncNotify> xNotify(
  700. new CIISVRootAsyncNotify( _cicat, workMan ) );
  701. workMan.AddToWorkList( xNotify.GetPointer() );
  702. xNotify->AddToWorkQueue();
  703. }
  704. CATCH(CException, e)
  705. {
  706. ciDebugOut(( DEB_WARN,
  707. "caught exception while setting up iis enumeration\n" ));
  708. // try again after the timeout
  709. _fIISAdminAlive = FALSE;
  710. }
  711. END_CATCH;
  712. }
  713. } //LokWatchIISVServerNoThrow
  714. //+---------------------------------------------------------------------------
  715. //
  716. // Member: CCiNotifyMgr::LokWatchRegistryScopesNoThrow
  717. //
  718. // Synopsis: Registers for notification of RegistryScopes registry changes
  719. //
  720. // History: 2-21-96 KyleP Created
  721. //
  722. // Notes: This must be done from thread waiting in alertable mode
  723. //
  724. //----------------------------------------------------------------------------
  725. void CCiNotifyMgr::LokWatchRegistryScopesNoThrow()
  726. {
  727. TRY
  728. {
  729. Win4Assert( 0 == _pRegistryScopesNotify );
  730. _pRegistryScopesNotify = new CRegistryScopesNotify( _cicat, *this );
  731. }
  732. CATCH( CException, e )
  733. {
  734. ciDebugOut(( DEB_WARN, "_LokWatchRegistryScopesNoThrow caught 0x%x\n",
  735. e.GetErrorCode() ));
  736. }
  737. END_CATCH
  738. } //LokWatchRegistryScopesNoThrow
  739. //+---------------------------------------------------------------------------
  740. //
  741. // Member: CCiNotifyMgr::LokWatchCiRegistryNoThrow
  742. //
  743. // Synopsis: Watches for changes in CI registry.
  744. //
  745. // History: 12-12-96 srikants Created
  746. //
  747. //----------------------------------------------------------------------------
  748. void CCiNotifyMgr::LokWatchCiRegistryNoThrow()
  749. {
  750. TRY
  751. {
  752. Win4Assert( 0 == _pCiRegistryNotify );
  753. _pCiRegistryNotify = new CCiRegistryNotify( _cicat, *this );
  754. }
  755. CATCH( CException, e )
  756. {
  757. ciDebugOut(( DEB_WARN, "_LokWatchCiRegistryNoThrow caught 0x%x\n",
  758. e.GetErrorCode() ));
  759. }
  760. END_CATCH
  761. } //LokWatchCiRegistryNoThrow
  762. //+---------------------------------------------------------------------------
  763. //
  764. // Member: CCiNotifyMgr::_KillThread
  765. //
  766. // Synopsis: Asks the notification thread to die and waits for its death.
  767. //
  768. // History: 1-18-96 srikants Created
  769. //
  770. //----------------------------------------------------------------------------
  771. void CCiNotifyMgr::_KillThread()
  772. {
  773. {
  774. CLock lock(_mutex);
  775. _evtType |= eKillThread;
  776. _evt.Set();
  777. }
  778. ciDebugOut(( DEB_ITRACE, "Waiting for death of notify thread\n" ));
  779. _thrNotify.WaitForDeath();
  780. }
  781. //+---------------------------------------------------------------------------
  782. //
  783. // Member: CCiNotifyMgr::Shutdown
  784. //
  785. // Synopsis: Shut down notification thread.
  786. //
  787. // History: 1-30-96 srikants Created
  788. //
  789. //----------------------------------------------------------------------------
  790. void CCiNotifyMgr::WaitForShutdown()
  791. {
  792. //
  793. // If we never started running, then just bail out.
  794. //
  795. if ( _thrNotify.IsRunning() )
  796. {
  797. //
  798. // must wait until all the APCs are aborted.
  799. //
  800. _refCount.Wait();
  801. //
  802. // Kill the notification thread.
  803. //
  804. _KillThread();
  805. }
  806. }
  807. //+---------------------------------------------------------------------------
  808. //
  809. // Member: CCiNotifyMgr::InitiateShutdown
  810. //
  811. // Synopsis: Turns off notifications
  812. //
  813. // History: 1-18-96 srikants Created
  814. //
  815. //----------------------------------------------------------------------------
  816. void CCiNotifyMgr::InitiateShutdown()
  817. {
  818. {
  819. CLock lock(_mutex);
  820. _fAbort = TRUE;
  821. }
  822. //
  823. // Abort registry notification (if any)
  824. //
  825. if ( !_xW3SvcVRootNotify.IsNull() )
  826. {
  827. _xW3SvcVRootNotify->DisableNotification();
  828. _xW3SvcVRootNotify.Free();
  829. }
  830. if ( !_xNNTPSvcVRootNotify.IsNull() )
  831. {
  832. _xNNTPSvcVRootNotify->DisableNotification();
  833. _xNNTPSvcVRootNotify.Free();
  834. }
  835. if ( !_xIMAPSvcVRootNotify.IsNull() )
  836. {
  837. _xIMAPSvcVRootNotify->DisableNotification();
  838. _xIMAPSvcVRootNotify.Free();
  839. }
  840. // these are refcounted and needn't be freed
  841. if ( 0 != _pRegistryScopesNotify )
  842. _pRegistryScopesNotify->DisableNotification();
  843. if ( 0 != _pCiRegistryNotify )
  844. _pCiRegistryNotify->DisableNotification();
  845. //
  846. // Abort all the notifications and the APCs queued for that.
  847. //
  848. {
  849. CLock lock(_mutex);
  850. for ( CCiNotify * pNotify = _list.Pop();
  851. 0 != pNotify;
  852. pNotify = _list.Pop() )
  853. {
  854. pNotify->Close();
  855. pNotify->Abort();
  856. }
  857. }
  858. }
  859. //+---------------------------------------------------------------------------
  860. //
  861. // Member: CCiNotifyMgr::_LokTellThreadToAddScope
  862. //
  863. // Synopsis: Sets the event type to add a scope for notifications and
  864. // wakes up the notification thread.
  865. //
  866. // History: 1-18-96 srikants Created
  867. //
  868. //----------------------------------------------------------------------------
  869. void CCiNotifyMgr::_LokTellThreadToAddScope()
  870. {
  871. if ( 0 == (eKillThread & _evtType) )
  872. {
  873. _evtType |= eAddScopes;
  874. _evt.Set();
  875. }
  876. }
  877. //+---------------------------------------------------------------------------
  878. //
  879. // Member: CCiNotifyMgr::AddPath
  880. //
  881. // Synopsis: Adds a scope for ci notifications. If the given scope (wcsScope)
  882. // is a superset of any existing scopes, they are removed from
  883. // the notification list.
  884. //
  885. // Arguments: [wcsScope] - Scope to be added.
  886. // [fSubscopesRemoved] - Set to TRUE if sub-scopes of wcsScope
  887. // were removed as a result of adding wcsScope.
  888. // [volumeId] - Volume id
  889. // [ftLastScan] - Last scan time
  890. // [usn] - Usn
  891. //
  892. // History: 1-17-96 srikants Created
  893. //
  894. //----------------------------------------------------------------------------
  895. void CCiNotifyMgr::AddPath( CScopeInfo const & scopeInfo, BOOL & fSubscopesRemoved )
  896. {
  897. fSubscopesRemoved = FALSE;
  898. //
  899. // Allocate storage for the string and terminate it with the
  900. // backslash character.
  901. //
  902. ULONG len = wcslen( scopeInfo.GetPath() );
  903. if ( L'\\' != scopeInfo.GetPath()[len-1] )
  904. len++;
  905. Win4Assert( len < MAX_PATH );
  906. XArray<WCHAR> xPath(len+1);
  907. WCHAR * pwcsPath = xPath.Get();
  908. wcscpy( pwcsPath, scopeInfo.GetPath() );
  909. pwcsPath[len-1] = L'\\';
  910. pwcsPath[len] = 0;
  911. CLock lock(_mutex);
  912. //
  913. // First see if notifications are already enabled on this path
  914. // in some other scope.
  915. //
  916. for ( CFwdCiNotifyIter iter1(_list); !_list.AtEnd(iter1); _list.Advance(iter1) )
  917. {
  918. if (iter1->IsMatch( pwcsPath, len ) )
  919. {
  920. Win4Assert( iter1->VolumeId() == scopeInfo.VolumeId() );
  921. //
  922. // there is an entry for this scope already. Just enable/start
  923. // the notification if not already done so.
  924. //
  925. if ( iter1->VolumeId() == CI_VOLID_USN_NOT_ENABLED )
  926. iter1->LokEnableIf();
  927. return;
  928. }
  929. }
  930. //
  931. // We have to create a new notification object for this scope.
  932. //
  933. XPtr<CScopeInfo> xScopeInfo;
  934. if ( CI_VOLID_USN_NOT_ENABLED == scopeInfo.VolumeId() )
  935. xScopeInfo.Set( new CScopeInfo( xPath,
  936. scopeInfo.VolumeCreationTime(),
  937. scopeInfo.VolumeSerialNumber(),
  938. scopeInfo.GetLastScanTime() ) );
  939. else
  940. xScopeInfo.Set( new CScopeInfo( xPath,
  941. scopeInfo.VolumeCreationTime(),
  942. scopeInfo.VolumeSerialNumber(),
  943. scopeInfo.VolumeId(),
  944. scopeInfo.Usn(),
  945. scopeInfo.JournalId(),
  946. scopeInfo.FUsnTreeScan() ) );
  947. _stkScopes.Push( xScopeInfo.GetPointer() );
  948. xScopeInfo.Acquire();
  949. //
  950. // If the new path is going to be a superset of the existing paths,
  951. // they must be removed.
  952. //
  953. CScopeMatch superScope( pwcsPath, len );
  954. for ( CFwdCiNotifyIter iter2(_list); !_list.AtEnd(iter2); )
  955. {
  956. CCiNotify * pNotify = iter2.GetEntry();
  957. _list.Advance(iter2);
  958. //
  959. // See if the current node is a subset of the new path.
  960. // If so, remove the current node from the list.
  961. //
  962. if ( superScope.IsInScope( pNotify->GetScope(), pNotify->ScopeLength()) )
  963. {
  964. fSubscopesRemoved = TRUE;
  965. pNotify->LokRemove();
  966. }
  967. }
  968. //
  969. // Wake up the notification thread to add this scope.
  970. //
  971. _LokTellThreadToAddScope();
  972. } //AddPath
  973. //+---------------------------------------------------------------------------
  974. //
  975. // Member: CCiNotifyMgr::GetLastScanTime
  976. //
  977. // Synopsis: Gets the time of the last successful scan for the given scope.
  978. //
  979. // Arguments: [wcsScope] - Scope to check. If there is no entry for the
  980. // given scope, the time of the last successful scan of the
  981. // super scope of wcsScope will be returned.
  982. // [ft] - The filetime of the last successful scan
  983. // encompassing the given scope.
  984. //
  985. // Returns: TRUE if found; FALSE o/w. In case FALSE is returned, ft will
  986. // be zero filled.
  987. //
  988. // History: 4-19-96 srikants Created
  989. //
  990. //----------------------------------------------------------------------------
  991. BOOL CCiNotifyMgr::GetLastScanTime( WCHAR const * wcsScope, FILETIME & ft )
  992. {
  993. RtlZeroMemory( &ft, sizeof(FILETIME) );
  994. Win4Assert( 0 != wcsScope );
  995. ULONG len = wcslen( wcsScope );
  996. Win4Assert( L'\\' == wcsScope[len-1] );
  997. CLock lock(_mutex);
  998. //
  999. // Look for a scope which encompasses the given scope.
  1000. //
  1001. for ( CFwdCiNotifyIter iter1(_list); !_list.AtEnd(iter1); _list.Advance(iter1) )
  1002. {
  1003. if (iter1->IsMatch( wcsScope, len ) )
  1004. {
  1005. ft = iter1->GetLastScanTime();
  1006. return TRUE;
  1007. }
  1008. }
  1009. return FALSE;
  1010. }
  1011. //+---------------------------------------------------------------------------
  1012. //
  1013. // Member: CCiNotifyMgr::UpdateLastScanTimes
  1014. //
  1015. // Synopsis: Updates the last scan time of all the paths that have
  1016. // notifications enabled to the time given.
  1017. //
  1018. // Arguments: [ft] - Last successful scan time (all updates until this time
  1019. // are known for all the scopes with notifications enabled).
  1020. // [usnFlushInfoList] - Usn info list
  1021. //
  1022. // History: 4-21-96 srikants Created
  1023. // 05-07-97 SitaramR Usns
  1024. //
  1025. //----------------------------------------------------------------------------
  1026. void CCiNotifyMgr::UpdateLastScanTimes( FILETIME const & ft,
  1027. CUsnFlushInfoList & usnFlushInfoList )
  1028. {
  1029. CLock lock(_mutex);
  1030. for ( CFwdCiNotifyIter iter1(_list); !_list.AtEnd(iter1); _list.Advance(iter1) )
  1031. {
  1032. if ( iter1->LokIsNotifyEnabled() && iter1->VolumeId() == CI_VOLID_USN_NOT_ENABLED )
  1033. {
  1034. if ( ft.dwLowDateTime != 0 || ft.dwHighDateTime != 0 )
  1035. iter1->SetLastScanTime( ft );
  1036. }
  1037. else if ( iter1->VolumeId() != CI_VOLID_USN_NOT_ENABLED
  1038. && !iter1->FUsnTreeScan() )
  1039. {
  1040. //
  1041. // If an usn tree traversal is going on, then we shouldn't move the usn
  1042. // watermark because if there is a crash now, then we should
  1043. // restart the usn tree traversal from usn 0.
  1044. //
  1045. USN usnCurrent = usnFlushInfoList.GetUsn( iter1->VolumeId() );
  1046. ciDebugOut(( DEB_ITRACE,
  1047. "CCiNotifyMgr::UpdateLastScanTimes drive %wc, old %#I64x, current %#I64x\n",
  1048. (WCHAR) iter1->VolumeId(),
  1049. iter1->Usn(),
  1050. usnCurrent ));
  1051. if ( usnCurrent != 0 && usnCurrent > iter1->Usn() )
  1052. {
  1053. //
  1054. // Win4Assert( usnCurrent >= iter1->Usn() );
  1055. //
  1056. // We cannot assert the above because after the initial usn tree
  1057. // scan is done, the maxUsn is written to iter1 (CiCat::SetUsnTreeComplete),
  1058. // and there can be usn notifications prior to usn tree scan, i.e. there can
  1059. // be usn's less than maxUsn.
  1060. //
  1061. iter1->SetUsn( usnCurrent );
  1062. }
  1063. }
  1064. }
  1065. } //UpdateLastScanTimes
  1066. //+---------------------------------------------------------------------------
  1067. //
  1068. // Member: CCiNotifyMgr::ForceNetPathScansIf
  1069. //
  1070. // Synopsis: Forces the scan of network paths with no notifications if
  1071. // the interval for such scans has expired.
  1072. //
  1073. // History: 4-21-96 srikants Created
  1074. //
  1075. // Notes: If the remote machine is running networking software without
  1076. // notifications, we have to periodically scan for changes. This
  1077. // method identifies such paths and schedules scans for them if
  1078. // the minimum interval has expired since the last such scan.
  1079. //
  1080. // THIS METHOD MUST BE CALLED ONLY FROM THE SCAN THREAD. IT IS
  1081. // CALLED WHEN THE SCAN THREAD HAS DETECTED THAT THERE ARE NO
  1082. // OUTSTANDING SCANS AND SO IS A GOOD TIME TO SCAN NET PATHS.
  1083. //
  1084. //----------------------------------------------------------------------------
  1085. void CCiNotifyMgr::ForceNetPathScansIf()
  1086. {
  1087. CLock lock(_mutex);
  1088. Win4Assert( sizeof(FILETIME) == sizeof(LONGLONG) );
  1089. LONGLONG ftZero;
  1090. RtlZeroMemory( &ftZero, sizeof(ftZero) );
  1091. LONGLONG ftNow;
  1092. GetSystemTimeAsFileTime( (FILETIME *) &ftNow );
  1093. if ( 0 == CompareFileTime( (FILETIME *) &_ftLastNetPathScan,
  1094. (FILETIME *) &ftZero ) )
  1095. {
  1096. //
  1097. // We havent't yet started tracking the interval. Just initialize
  1098. // the _ftLastNetPathScan to the current time.
  1099. //
  1100. _ftLastNetPathScan = ftNow;
  1101. return;
  1102. }
  1103. if ( ftNow < _ftLastNetPathScan )
  1104. {
  1105. ciDebugOut(( DEB_WARN, "Time has been set back\n" ));
  1106. _ftLastNetPathScan = ftNow;
  1107. return;
  1108. }
  1109. //
  1110. // See if the interval for force scans has exceeded.
  1111. //
  1112. //
  1113. // Compute the interval in 100 nanosecond interval
  1114. //
  1115. const LONGLONG llInterval =
  1116. _cicat.GetRegParams()->GetForcedNetPathScanInterval() * 60 * 1000 * 10000;
  1117. if ( ftNow - _ftLastNetPathScan >= llInterval )
  1118. {
  1119. ciDebugOut(( DEB_ITRACE, "Forcing scan of net paths with no notifcations\n" ));
  1120. _LokForceScanNetPaths();
  1121. //
  1122. // Reset the last scan time for network paths.
  1123. //
  1124. RtlZeroMemory( &_ftLastNetPathScan, sizeof(_ftLastNetPathScan) );
  1125. }
  1126. }
  1127. //+---------------------------------------------------------------------------
  1128. //
  1129. // Member: CCiNotifyMgr::_LokForceScanNetPaths
  1130. //
  1131. // Synopsis: Forces incremental scans of net paths with no notifications.
  1132. //
  1133. // History: 4-21-96 srikants Created
  1134. //
  1135. // Notes: This method must be called only in the context of the scan
  1136. // thread.
  1137. //
  1138. //----------------------------------------------------------------------------
  1139. void CCiNotifyMgr::_LokForceScanNetPaths()
  1140. {
  1141. for ( CFwdCiNotifyIter iter1(_list); !_list.AtEnd(iter1); _list.Advance(iter1) )
  1142. {
  1143. if ( !iter1->LokIsNotifyEnabled() && iter1->VolumeId() == CI_VOLID_USN_NOT_ENABLED )
  1144. {
  1145. //
  1146. // Usn paths have their notifications disabled, but they should not be scanned
  1147. //
  1148. ciDebugOut(( DEB_WARN,
  1149. "Forcing an incremental scan of path (%ws)\n",
  1150. iter1->GetScope() ));
  1151. _cicat.ReScanPath( iter1->GetScope(), FALSE );
  1152. }
  1153. }
  1154. } //_LokForceScanNetPaths
  1155. //+---------------------------------------------------------------------------
  1156. //
  1157. // Member: CCiNotifyMgr::_LokAddScopesNoThrow
  1158. //
  1159. // Synopsis: Takes scopes from the stack and enables notifications for
  1160. // those scopes.
  1161. //
  1162. // History: 1-18-96 srikants Created
  1163. //
  1164. //----------------------------------------------------------------------------
  1165. void CCiNotifyMgr::_LokAddScopesNoThrow()
  1166. {
  1167. TRY
  1168. {
  1169. for ( unsigned i = 0; i < _stkScopes.Count(); i++ )
  1170. {
  1171. CScopeInfo & scopeInfo = *_stkScopes.Get(i);
  1172. if ( !scopeInfo.IsValid() )
  1173. continue;
  1174. WCHAR const * pwcsPath = scopeInfo.GetPath();
  1175. CCiNotify * pNotify = new CCiNotify( *this,
  1176. pwcsPath,
  1177. wcslen(pwcsPath),
  1178. scopeInfo.VolumeId(),
  1179. scopeInfo.VolumeCreationTime(),
  1180. scopeInfo.VolumeSerialNumber(),
  1181. scopeInfo.GetLastScanTime(),
  1182. scopeInfo.Usn(),
  1183. scopeInfo.JournalId(),
  1184. scopeInfo.FUsnTreeScan() );
  1185. //
  1186. // Acquire the path as a sign that we shouldn't try to use it
  1187. // again to add another notification object.
  1188. //
  1189. delete [] scopeInfo.AcquirePath();
  1190. _list.Push( pNotify );
  1191. }
  1192. // empty the stack now
  1193. while ( _stkScopes.Count() > 0 )
  1194. {
  1195. _stkScopes.DeleteTop();
  1196. }
  1197. }
  1198. CATCH( CException, e )
  1199. {
  1200. ciDebugOut(( DEB_WARN, "_LokAddScopesNoThrow caught 0x%x\n",
  1201. e.GetErrorCode() ));
  1202. }
  1203. END_CATCH
  1204. } //_LokAddScopesNoThrow
  1205. //+---------------------------------------------------------------------------
  1206. //
  1207. // Member: CCiNotifyMgr::_DoNotifications
  1208. //
  1209. // Synopsis: The thread which is responsible for adding notification scopes
  1210. // and processing the notifications. The notification APC will
  1211. // execute in this thread's context.
  1212. //
  1213. // History: 1-18-96 srikants Created
  1214. //
  1215. //----------------------------------------------------------------------------
  1216. void CCiNotifyMgr::_DoNotifications()
  1217. {
  1218. while ( TRUE )
  1219. {
  1220. //
  1221. // Don't do any work until the system has booted
  1222. //
  1223. while ( GetTickCount() < _cicat.GetRegParams()->GetStartupDelay() )
  1224. {
  1225. Sleep( 200 );
  1226. if ( _fAbort )
  1227. break;
  1228. }
  1229. BOOL fWait = FALSE;
  1230. CVRootNotify * pW3Notify = 0;
  1231. CVRootNotify * pNNTPNotify = 0;
  1232. CVRootNotify * pIMAPNotify = 0;
  1233. // ++++++++++++++++ lock obtained +++++++++++++++++++
  1234. {
  1235. CLock lock(_mutex);
  1236. _evt.Reset();
  1237. Win4Assert( 0 == ( _evtType &
  1238. ~(eKillThread|eAddScopes|eWatchIISVRoots|
  1239. eWatchRegistryScopes|eWatchCiRegistry|eUnWatchW3VRoots|
  1240. eUnWatchNNTPVRoots|eUnWatchIMAPVRoots)) );
  1241. if ( eKillThread & _evtType )
  1242. return;
  1243. if ( _fAbort )
  1244. {
  1245. _evtType = eNone;
  1246. }
  1247. else
  1248. {
  1249. if ( eAddScopes & _evtType )
  1250. {
  1251. _LokAddScopesNoThrow();
  1252. _evtType &= ~eAddScopes;
  1253. }
  1254. if ( eWatchIISVRoots & _evtType )
  1255. {
  1256. LokWatchIISVServerNoThrow();
  1257. _evtType &= ~eWatchIISVRoots;
  1258. }
  1259. if ( eUnWatchW3VRoots & _evtType )
  1260. {
  1261. pW3Notify = _xW3SvcVRootNotify.Acquire();
  1262. _evtType &= ~eUnWatchW3VRoots;
  1263. }
  1264. if ( eUnWatchNNTPVRoots & _evtType )
  1265. {
  1266. pNNTPNotify = _xNNTPSvcVRootNotify.Acquire();
  1267. _evtType &= ~eUnWatchNNTPVRoots;
  1268. }
  1269. if ( eUnWatchIMAPVRoots & _evtType )
  1270. {
  1271. pIMAPNotify = _xIMAPSvcVRootNotify.Acquire();
  1272. _evtType &= ~eUnWatchIMAPVRoots;
  1273. }
  1274. if ( eWatchRegistryScopes & _evtType )
  1275. {
  1276. LokWatchRegistryScopesNoThrow();
  1277. _evtType &= ~eWatchRegistryScopes;
  1278. }
  1279. if ( eWatchCiRegistry & _evtType )
  1280. {
  1281. LokWatchCiRegistryNoThrow();
  1282. _evtType &= ~eWatchCiRegistry;
  1283. }
  1284. }
  1285. fWait = ( eNone == _evtType );
  1286. }
  1287. // ---------------- lock released --------------------
  1288. //
  1289. // Free these without holding the lock to avoid a deadlock
  1290. // with iisadmin.
  1291. //
  1292. if ( 0 != pW3Notify )
  1293. LokUnWatchIISVServerNoThrow( pW3Notify );
  1294. if ( 0 != pNNTPNotify )
  1295. LokUnWatchIISVServerNoThrow( pNNTPNotify );
  1296. if ( 0 != pIMAPNotify )
  1297. LokUnWatchIISVServerNoThrow( pIMAPNotify );
  1298. //
  1299. // If we're not watching, turn the flag off
  1300. //
  1301. if ( _xW3SvcVRootNotify.IsNull() &&
  1302. _xNNTPSvcVRootNotify.IsNull() &&
  1303. _xIMAPSvcVRootNotify.IsNull() )
  1304. _fIISAdminAlive = FALSE;
  1305. if ( fWait )
  1306. {
  1307. const DWORD dwFiveMinutes = 1000 * 60 * 5;
  1308. DWORD dwWait = ( ( !_fIISAdminAlive ) &&
  1309. ( _fTrackW3Svc || _fTrackNNTPSvc || _fTrackIMAPSvc ) ) ?
  1310. dwFiveMinutes : INFINITE;
  1311. // TRUE: important to get APCs
  1312. ULONG res = _evt.Wait( dwWait, TRUE );
  1313. if ( WAIT_TIMEOUT == res )
  1314. {
  1315. // try again to talk to the iisadmin svc
  1316. CLock lock( _mutex );
  1317. _evtType |= eWatchIISVRoots;
  1318. }
  1319. }
  1320. }
  1321. }
  1322. //+---------------------------------------------------------------------------
  1323. //
  1324. // Member: CCiNotifyMgr::NotifyThread
  1325. //
  1326. // Arguments: [self] -
  1327. //
  1328. // History: 1-18-96 srikants Created
  1329. //
  1330. //----------------------------------------------------------------------------
  1331. DWORD CCiNotifyMgr::NotifyThread( void * self )
  1332. {
  1333. SCODE sc = CoInitializeEx( 0, COINIT_MULTITHREADED );
  1334. ((CCiNotifyMgr *) self)->_DoNotifications();
  1335. CoUninitialize();
  1336. ciDebugOut(( DEB_ITRACE, "Terminating notify thread\n" ));
  1337. //
  1338. // This is only necessary if thread is terminated from DLL_PROCESS_DETACH.
  1339. //
  1340. //TerminateThread( ((CCiNotifyMgr *) self)->_thrNotify.GetHandle(), 0 );
  1341. return 0;
  1342. }
  1343. //+---------------------------------------------------------------------------
  1344. //
  1345. // Member: CCiNotifyMgr::ProcessChanges
  1346. //
  1347. // Synopsis: Processes the changes to files.
  1348. //
  1349. // Arguments: [changes] -
  1350. //
  1351. // History: 1-17-96 srikants Created
  1352. //
  1353. //----------------------------------------------------------------------------
  1354. void CCiNotifyMgr::ProcessChanges( XPtr<CCiAsyncProcessNotify> & xWorker )
  1355. {
  1356. CWorkManager & workMan = _cicat.GetWorkMan();
  1357. workMan.AddToWorkList( xWorker.GetPointer() );
  1358. CCiAsyncProcessNotify *pAsyncNotify = xWorker.Acquire();
  1359. #if 0
  1360. //
  1361. // NTRAID#DB-NTBUG9-83784-2000/07/31-dlee FAT notifications don't use APCs -- they are handled by the notification thread
  1362. // There is a problem with lockups in NT. Until we figure
  1363. // that out, don't use worker threads. Just process the notifications
  1364. // in-line in the notification thread.
  1365. //
  1366. pAsyncNotify->AddToWorkQueue();
  1367. #else
  1368. pAsyncNotify->DoIt( 0 );
  1369. #endif
  1370. pAsyncNotify->Release();
  1371. }
  1372. //+---------------------------------------------------------------------------
  1373. //
  1374. // Member: CCiNotifyMgr::ProcessChanges
  1375. //
  1376. // Synopsis:
  1377. //
  1378. // Arguments: [pbChanges] -
  1379. // [wcsScope] -
  1380. //
  1381. // Returns:
  1382. //
  1383. // Modifies:
  1384. //
  1385. // History: 3-07-96 srikants Created
  1386. //
  1387. //----------------------------------------------------------------------------
  1388. void CCiNotifyMgr::ProcessChanges( BYTE const * pbChanges,
  1389. WCHAR const * wcsScope )
  1390. {
  1391. CCiSyncProcessNotify notify(_cicat, _scanMgr, pbChanges, wcsScope, _fAbort );
  1392. notify.DoIt();
  1393. }
  1394. //+---------------------------------------------------------------------------
  1395. //
  1396. // Member: CCiNotifyMgr::SetupScan
  1397. //
  1398. // Synopsis: Schedules the given path for background scan in the scan
  1399. // thread.
  1400. //
  1401. // Arguments: [pwcsPath] - The path to be scanned.
  1402. //
  1403. // History: 1-19-96 srikants Created
  1404. //
  1405. // Notes: This method is invoked when the notification buffer overflowed
  1406. // and hence some updates are lost. A rescan is needed to figure
  1407. // out the changed documents.
  1408. //
  1409. //----------------------------------------------------------------------------
  1410. void CCiNotifyMgr::SetupScan( WCHAR const * pwcsPath )
  1411. {
  1412. _cicat.ReScanPath( pwcsPath, TRUE );
  1413. }
  1414. //+---------------------------------------------------------------------------
  1415. //
  1416. // Member: CCiNotifyMgr::IsInScope
  1417. //
  1418. // Synopsis: Tests if the given scope is already in the list of scopes
  1419. // being watched for notifications.
  1420. //
  1421. // Arguments: [pwcsPath] - Input path to check.
  1422. //
  1423. // Returns: TRUE if the path is already in a notification scope.
  1424. // FALSE o/w
  1425. //
  1426. // History: 1-21-96 srikants Created
  1427. //
  1428. //----------------------------------------------------------------------------
  1429. BOOL CCiNotifyMgr::IsInScope( WCHAR const * pwcsPath )
  1430. {
  1431. Win4Assert( 0 != pwcsPath );
  1432. ULONG len = wcslen( pwcsPath );
  1433. CLock lock(_mutex);
  1434. //
  1435. // First check if it is in the list of paths to be added.
  1436. //
  1437. for ( unsigned i = 0;
  1438. i < _stkScopes.Count();
  1439. i++ )
  1440. {
  1441. if ( !_stkScopes.Get(i)->IsValid() )
  1442. continue;
  1443. WCHAR const * pwcsTmp = _stkScopes.Get(i)->GetPath();
  1444. CScopeMatch match( pwcsTmp, wcslen( pwcsTmp ) );
  1445. if ( match.IsInScope( pwcsPath, len ) )
  1446. return TRUE;
  1447. }
  1448. // next check in the list of notifications
  1449. for ( CFwdCiNotifyIter iter(_list); !_list.AtEnd(iter); _list.Advance(iter) )
  1450. {
  1451. if ( iter->IsMatch( pwcsPath, len ) )
  1452. return TRUE;
  1453. }
  1454. return FALSE;
  1455. } //IsInScope
  1456. //+---------------------------------------------------------------------------
  1457. //
  1458. // Member: CCiNotifyMgr::RemoveScope
  1459. //
  1460. // Synopsis: If there is an exact match for the given scope, it will be
  1461. // removed from the notification list.
  1462. //
  1463. // Arguments: [pwcsPath] - The scope to be removed.
  1464. //
  1465. // Returns: TRUE if the scope was found.
  1466. // FALSE if it was not found.
  1467. //
  1468. // History: 1-25-96 srikants Created
  1469. //
  1470. //----------------------------------------------------------------------------
  1471. BOOL CCiNotifyMgr::RemoveScope( WCHAR const * pwcsPath )
  1472. {
  1473. Win4Assert( 0 != pwcsPath );
  1474. ULONG len = wcslen( pwcsPath );
  1475. CLock lock(_mutex);
  1476. BOOL fFound = FALSE;
  1477. //
  1478. // First see if there is a match in the list of paths still
  1479. // to be added.
  1480. //
  1481. for ( unsigned i = 0; i < _stkScopes.Count(); i++ )
  1482. {
  1483. CScopeInfo & scopeInfo = *_stkScopes.Get(i);
  1484. if ( !scopeInfo.IsValid() )
  1485. continue;
  1486. if ( AreIdenticalPaths( pwcsPath, scopeInfo.GetPath() ) )
  1487. {
  1488. scopeInfo.Invalidate();
  1489. fFound = TRUE;
  1490. }
  1491. }
  1492. //
  1493. // Next remove from the list of notifications.
  1494. //
  1495. for ( CFwdCiNotifyIter iter(_list); !_list.AtEnd(iter); )
  1496. {
  1497. CCiNotify * pNotify = iter.GetEntry();
  1498. _list.Advance(iter);
  1499. if ( AreIdenticalPaths(pwcsPath, pNotify->GetScope()) )
  1500. {
  1501. ciDebugOut(( DEB_ITRACE,
  1502. "Removing path (%ws) from notification list\n",
  1503. pNotify->GetScope() ));
  1504. pNotify->LokRemove();
  1505. return TRUE;
  1506. }
  1507. }
  1508. return FALSE;
  1509. }
  1510. //+---------------------------------------------------------------------------
  1511. //
  1512. // Member: CCiNotifyIter::SetTreeScanComplete, public
  1513. //
  1514. // Synopsis: Mark a scope as scanned. Used to update volume version info.
  1515. //
  1516. // History: 13-Apr-1998 KyleP Created
  1517. //
  1518. //----------------------------------------------------------------------------
  1519. void CCiNotifyIter::SetTreeScanComplete()
  1520. {
  1521. Win4Assert( !AtEnd() );
  1522. ULONGLONG const & VolumeCreationTime = _notifyMgr._cicat.GetVolumeCreationTime( Get() );
  1523. ULONG VolumeSerialNumber = _notifyMgr._cicat.GetVolumeSerialNumber( Get() );
  1524. if ( _iNotAdded < _stack.Count() )
  1525. _stack.Get(_iNotAdded)->SetVolumeInfo( VolumeCreationTime, VolumeSerialNumber );
  1526. else
  1527. _iter->SetVolumeInfo( VolumeCreationTime, VolumeSerialNumber );
  1528. }
  1529. //+---------------------------------------------------------------------------
  1530. //
  1531. // Member: CCiNotifyIter::SetUsnTreeScanComplete, public
  1532. //
  1533. // Synopsis: Same as SetTreeScanComplete, but also updates USN info.
  1534. //
  1535. // Arguments: [usnMax] -- New high-water mark.
  1536. //
  1537. // History: 13-Apr-1998 KyleP Created
  1538. //
  1539. //----------------------------------------------------------------------------
  1540. void CCiNotifyIter::SetUsnTreeScanComplete( USN usnMax )
  1541. {
  1542. Win4Assert( !AtEnd() );
  1543. ULONGLONG const & JournalId = _notifyMgr._cicat.GetJournalId( Get() );
  1544. ULONGLONG const & VolumeCreationTime = _notifyMgr._cicat.GetVolumeCreationTime( Get() );
  1545. ULONG VolumeSerialNumber = _notifyMgr._cicat.GetVolumeSerialNumber( Get() );
  1546. if ( _iNotAdded < _stack.Count() )
  1547. {
  1548. _stack.Get(_iNotAdded)->SetUsnTreeScanComplete( usnMax );
  1549. _stack.Get(_iNotAdded)->SetVolumeInfo( VolumeCreationTime, VolumeSerialNumber );
  1550. _stack.Get(_iNotAdded)->SetJournalId( JournalId );
  1551. }
  1552. else
  1553. {
  1554. _iter->SetUsnTreeScanComplete( usnMax );
  1555. _iter->SetVolumeInfo( VolumeCreationTime, VolumeSerialNumber );
  1556. _iter->SetJournalId( JournalId );
  1557. }
  1558. }