Source code of Windows XP (NT5)
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.

1713 lines
50 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1999.
  5. //
  6. // File: scopetbl.cxx
  7. //
  8. // Contents: Persistent scope table
  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 "cicat.hxx"
  25. #include "update.hxx"
  26. #include "notifmgr.hxx"
  27. #include "scanmgr.hxx"
  28. #include "scopetbl.hxx"
  29. //
  30. // Local constants
  31. //
  32. WCHAR const wcVirtualShadow = L'3'; // 3 --> Virtual, Indexed
  33. WCHAR const wcsVirtualShadow[] = L",,3"; // ,,3 --> No UNC alias, Virtual, Indexed
  34. //+---------------------------------------------------------------------------
  35. //
  36. // Method: DeleteIfShadow, private
  37. //
  38. // Synopsis: Deletes shadow scope registry entry
  39. //
  40. // Arguments: [pwcsScope] -- Scope to delete
  41. // [hkey] -- Registry key to catalog
  42. //
  43. // History: 15-May-97 KyleP Created
  44. //
  45. // Notes: Only deletes exact matches (as stored by system)
  46. //
  47. //----------------------------------------------------------------------------
  48. void DeleteIfShadow( WCHAR const * pwcsScope, HKEY hkey )
  49. {
  50. //
  51. // See if this is a shadow entry (flags == 2)
  52. //
  53. WCHAR wcsData[MAX_PATH];
  54. DWORD dwType;
  55. DWORD dwSize = sizeof(wcsData);
  56. DWORD dwError = RegQueryValueEx( hkey, // Key handle
  57. pwcsScope, // Name
  58. 0, // Reserved
  59. &dwType, // Datatype
  60. (BYTE *)wcsData, // Data returned here
  61. &dwSize ); // Size of data
  62. if ( ERROR_SUCCESS == dwError &&
  63. REG_SZ == dwType &&
  64. dwSize >= 8 && // 8 --> ,,#<null>
  65. wcVirtualShadow == wcsData[dwSize/sizeof(WCHAR) - 2] )
  66. {
  67. dwError = RegDeleteValue( hkey, pwcsScope );
  68. if ( ERROR_SUCCESS != dwError ) {
  69. ciDebugOut(( DEB_ERROR, "Error %d deleting %ws\n", dwError, pwcsScope ));
  70. }
  71. }
  72. }
  73. //+---------------------------------------------------------------------------
  74. //
  75. // Method: AddShadow, private
  76. //
  77. // Synopsis: Adds shadow scope registry entry
  78. //
  79. // Arguments: [pwcsScope] -- Scope to add
  80. // [hkey] -- Registry key to catalog
  81. //
  82. // History: 15-May-97 KyleP Created
  83. //
  84. //----------------------------------------------------------------------------
  85. void AddShadow( WCHAR const * pwcsScope, HKEY hkey )
  86. {
  87. //
  88. // Build string: NAME: ,,3
  89. //
  90. DWORD dwError = RegSetValueEx( hkey, // Key
  91. pwcsScope, // Value name
  92. 0, // Reserved
  93. REG_SZ, // Type
  94. (BYTE *)wcsVirtualShadow, // Data
  95. sizeof(wcsVirtualShadow) ); // Size (in bytes)
  96. if ( ERROR_SUCCESS != dwError ) {
  97. ciDebugOut(( DEB_ERROR, "Error %d writing %ws\n", dwError, pwcsScope ));
  98. }
  99. }
  100. //+---------------------------------------------------------------------------
  101. //
  102. // Method: RefreshIfShadow, private
  103. //
  104. // Synopsis: Refresh shadow scope registry entry (if blank)
  105. //
  106. // Arguments: [pwcsScope] -- Scope to refresh
  107. // [hkey] -- Registry key to catalog
  108. //
  109. // History: 11-Oct-97 KyleP Created
  110. //
  111. // Notes: Only refresh blank (missing) entries
  112. //
  113. //----------------------------------------------------------------------------
  114. void RefreshIfShadow( WCHAR const * pwcsScope, HKEY hkey )
  115. {
  116. //
  117. // See if this is a missing entry
  118. //
  119. WCHAR wcsData[MAX_PATH];
  120. DWORD dwType;
  121. DWORD dwSize = sizeof(wcsData);
  122. DWORD dwError = RegQueryValueEx( hkey, // Key handle
  123. pwcsScope, // Name
  124. 0, // Reserved
  125. &dwType, // Datatype
  126. (BYTE *)wcsData, // Data returned here
  127. &dwSize ); // Size of data
  128. //
  129. // It is, so we should re-add it.
  130. //
  131. if ( ERROR_FILE_NOT_FOUND == dwError )
  132. AddShadow( pwcsScope, hkey );
  133. }
  134. //+---------------------------------------------------------------------------
  135. //
  136. // Member: CCiScopeTable::~CCiScopeTable
  137. //
  138. // Synopsis: ~dtor of the persistent scope table.
  139. //
  140. // History: 1-21-96 srikants Created
  141. //
  142. // Notes:
  143. //
  144. //----------------------------------------------------------------------------
  145. CCiScopeTable::~CCiScopeTable()
  146. {
  147. delete _pTable;
  148. }
  149. void CCiScopeTable::_FatalCorruption()
  150. {
  151. PStorage & storage = _cicat.GetStorage();
  152. Win4Assert( !"Corrupt scope table" );
  153. storage.ReportCorruptComponent( L"ScopeTable1" );
  154. THROW( CException( CI_CORRUPT_CATALOG ) );
  155. }
  156. //+---------------------------------------------------------------------------
  157. //
  158. // Member: CCiScopeTable::Empty
  159. //
  160. // Synopsis: Empties out the in-memory contents of the scope table for
  161. // a later re-init.
  162. //
  163. // History: 3-21-96 srikants Created
  164. //
  165. //----------------------------------------------------------------------------
  166. void CCiScopeTable::Empty()
  167. {
  168. delete _pTable; _pTable = 0;
  169. }
  170. //+---------------------------------------------------------------------------
  171. //
  172. // Member: CCiScopeTable::FastInit
  173. //
  174. // Synopsis: Quickly initializes the scope table.
  175. //
  176. // History: 3-21-96 srikants Created
  177. //
  178. //----------------------------------------------------------------------------
  179. void CCiScopeTable::FastInit()
  180. {
  181. CiStorage * pStorage = (CiStorage *) &_cicat.GetStorage();
  182. Win4Assert( 0 != pStorage );
  183. _pTable = pStorage->QueryScopeList(0);
  184. CRcovStorageHdr & storageHdr = _pTable->GetHeader();
  185. //
  186. // read the last scan time.
  187. //
  188. storageHdr.GetUserHdr( storageHdr.GetPrimary(), _usrHdr );
  189. if ( !_hdr.IsInitialized() )
  190. _hdr.Initialize();
  191. if ( _hdr.IsFullScanNeeded() )
  192. _state = eFullScanNeeded;
  193. } //FastInit
  194. //+---------------------------------------------------------------------------
  195. //
  196. // Class: CNullAdvise
  197. //
  198. // Purpose: Null implementation of ICiCAdviseStatus, for use in opening
  199. // a CiStorage when advise isn't needed.
  200. //
  201. // History: 4-6-99 dlee Created
  202. //
  203. //----------------------------------------------------------------------------
  204. class CNullAdvise : public ICiCAdviseStatus
  205. {
  206. public:
  207. STDMETHOD(QueryInterface)( REFIID riid, LPVOID *ppiuk ) { return E_NOINTERFACE; }
  208. STDMETHOD_(ULONG, AddRef) () { return 1; }
  209. STDMETHOD_(ULONG, Release)() { return 0; }
  210. STDMETHOD(SetPerfCounterValue)( CI_PERF_COUNTER_NAME name,
  211. long value ) { return S_OK; }
  212. STDMETHOD(IncrementPerfCounterValue)( CI_PERF_COUNTER_NAME name ) { return S_OK; }
  213. STDMETHOD(DecrementPerfCounterValue)( CI_PERF_COUNTER_NAME name ) { return S_OK; }
  214. STDMETHOD(GetPerfCounterValue)( CI_PERF_COUNTER_NAME name,
  215. long * pValue ) { return S_OK; }
  216. STDMETHOD(NotifyEvent)( WORD fType,
  217. DWORD eventId,
  218. ULONG nParams,
  219. const PROPVARIANT *aParams,
  220. ULONG cbData = 0,
  221. void* data = 0) { return S_OK; }
  222. STDMETHOD(NotifyStatus)( CI_NOTIFY_STATUS_VALUE status,
  223. ULONG nParams,
  224. const PROPVARIANT *aParams ) { return S_OK; }
  225. };
  226. //+---------------------------------------------------------------------------
  227. //
  228. // Function: GetDriveLetterOfAnyScope
  229. //
  230. // Synopsis: Returns the drive letter of the first scope in the catalog or
  231. // 0 on error
  232. //
  233. // History: 4-6-99 dlee Created
  234. //
  235. //----------------------------------------------------------------------------
  236. WCHAR GetDriveLetterOfAnyScope( WCHAR const * pwcCatalog )
  237. {
  238. TRY
  239. {
  240. CNullAdvise adviseStatus;
  241. CiStorage store( pwcCatalog,
  242. adviseStatus,
  243. 0,
  244. FSCI_VERSION_STAMP,
  245. TRUE );
  246. XPtr<PRcovStorageObj> xTable( store.QueryScopeList( 0 ) );
  247. CRcovStorageHdr & hdr = xTable->GetHeader();
  248. ULONG cPaths = hdr.GetCount( hdr.GetPrimary() );
  249. if ( 0 == cPaths )
  250. return 0;
  251. // read the last scan start time for the scope
  252. CRcovStrmReadTrans xact( xTable.GetReference() );
  253. xact.Seek(0);
  254. LONGLONG llSig;
  255. ULONG cbRead = xact.Read( &llSig, sizeof(llSig) );
  256. if ( cbRead != sizeof(llSig) )
  257. return 0;
  258. if ( eSigCiScopeTable != llSig )
  259. return 0;
  260. //
  261. // Get Volume ID
  262. //
  263. VOLUMEID volumeId;
  264. cbRead = xact.Read( &volumeId, sizeof(VOLUMEID) );
  265. if ( cbRead != sizeof(VOLUMEID) )
  266. return 0;
  267. //
  268. // And Volume Creation Time
  269. //
  270. ULONGLONG VolumeCreationTime = 0;
  271. cbRead = xact.Read( &VolumeCreationTime, sizeof(VolumeCreationTime) );
  272. if ( cbRead != sizeof(VolumeCreationTime) )
  273. return 0;
  274. //
  275. // And Volume Serial Number
  276. //
  277. ULONG VolumeSerialNumber = 0;
  278. cbRead = xact.Read( &VolumeSerialNumber, sizeof(VolumeSerialNumber) );
  279. if ( cbRead != sizeof(VolumeSerialNumber) )
  280. return 0;
  281. //
  282. // Filesystem-Specific stuff.
  283. //
  284. if ( CI_VOLID_USN_NOT_ENABLED == volumeId )
  285. {
  286. //
  287. // Read filetime for non-usn volumes
  288. //
  289. FILETIME ft;
  290. cbRead = xact.Read( &ft, sizeof(FILETIME) );
  291. if ( cbRead != sizeof(FILETIME) )
  292. return 0;
  293. }
  294. else
  295. {
  296. //
  297. // Read usn for usn volumes
  298. //
  299. USN usn;
  300. cbRead = xact.Read( &usn, sizeof(USN) );
  301. if ( cbRead != sizeof(USN) )
  302. return 0;
  303. //
  304. // And Journal ID
  305. //
  306. ULONGLONG JournalId = 0;
  307. cbRead = xact.Read( &JournalId, sizeof(JournalId) );
  308. if ( cbRead != sizeof(JournalId) )
  309. return 0;
  310. }
  311. ULONG cchPath;
  312. cbRead = xact.Read( &cchPath, sizeof(ULONG) );
  313. if ( cbRead != sizeof(ULONG) )
  314. return 0;
  315. if ( 0 == cchPath || cchPath > MAX_PATH )
  316. return 0;
  317. WCHAR wcsPath[MAX_PATH+1];
  318. cbRead = xact.Read( wcsPath, cchPath*sizeof(WCHAR) );
  319. if ( cchPath*sizeof(WCHAR) != cbRead )
  320. return 0;
  321. return wcsPath[0];
  322. }
  323. CATCH( CException, e )
  324. {
  325. // ignore failure -- just fall out returning 0
  326. }
  327. END_CATCH;
  328. return 0;
  329. } //GetDriveOfFirstScope
  330. //+---------------------------------------------------------------------------
  331. //
  332. // Member: CCiScopeTable::_DeSerialize
  333. //
  334. // Synopsis: Reads the scopes from the persistent scope table and adds
  335. // them to the stack.
  336. //
  337. // Arguments: [stk] - (out) - Will have all the paths from the table.
  338. //
  339. // History: 30-Jan-96 srikants Created
  340. // 07-May-97 SitaramR Usns
  341. // 11-Mar-98 KyleP USN Journal ID
  342. //
  343. //----------------------------------------------------------------------------
  344. void CCiScopeTable::_DeSerialize( CScopeInfoStack & stk )
  345. {
  346. Win4Assert( 0 != _pTable );
  347. if ( 0 == _pTable )
  348. _FatalCorruption();
  349. CImpersonateSystem impersonate;
  350. CLock lock(_mutex);
  351. CRcovStorageHdr & hdr = _pTable->GetHeader();
  352. //
  353. // read the last scan time.
  354. //
  355. ULONG nPaths = hdr.GetCount( hdr.GetPrimary() );
  356. ciDebugOut(( DEB_ITRACE, "CCiScopeTable::_DeSerialize nPaths: %d\n", nPaths ));
  357. if ( nPaths == 0 )
  358. return;
  359. // We have to iterate over the paths and add them to our list
  360. //
  361. WCHAR wcsPath[MAX_PATH+1];
  362. CRcovStrmReadTrans xact( *_pTable );
  363. xact.Seek(0);
  364. XPtr<CScopeInfo> xScopeInfo;
  365. for ( ULONG i = 0; i < nPaths; i++ )
  366. {
  367. VOLUMEID volumeId;
  368. FILETIME ft;
  369. USN usn;
  370. ULONGLONG JournalId = 0;
  371. ULONGLONG VolumeCreationTime = 0;
  372. ULONG VolumeSerialNumber = 0;
  373. LONGLONG llSig;
  374. // read the last scan start time for the scope
  375. ULONG cbRead;
  376. cbRead = xact.Read( &llSig, sizeof(llSig) );
  377. if ( cbRead != sizeof(llSig) )
  378. {
  379. ciDebugOut(( DEB_ERROR,
  380. "CCiScopeTable::_DeSerialize - Read %d bytes instead of %d \n",
  381. cbRead, sizeof(llSig) ));
  382. _FatalCorruption();
  383. }
  384. if ( eSigCiScopeTable != llSig )
  385. {
  386. ciDebugOut(( DEB_ERROR,
  387. "CCiScopeTable::_DeSerialize - Signature mismatch 0x%X:0x%X\n",
  388. lltoLowPart( llSig ), lltoHighPart( llSig ) ));
  389. _FatalCorruption();
  390. }
  391. //
  392. // Get Volume ID
  393. //
  394. cbRead = xact.Read( &volumeId, sizeof(VOLUMEID) );
  395. if ( cbRead != sizeof(VOLUMEID) )
  396. {
  397. ciDebugOut(( DEB_ERROR,
  398. "CCiScopeTable::_DeSerialize - Read %d bytes instead of %d \n",
  399. cbRead,
  400. sizeof(VOLUMEID) ));
  401. _FatalCorruption();
  402. }
  403. //
  404. // And Volume Creation Time
  405. //
  406. cbRead = xact.Read( &VolumeCreationTime, sizeof(VolumeCreationTime) );
  407. if ( cbRead != sizeof(VolumeCreationTime) )
  408. {
  409. ciDebugOut(( DEB_ERROR,
  410. "CCiScopeTable::_DeSerialize - Read %d bytes instead of %d \n",
  411. cbRead,
  412. sizeof(VolumeCreationTime) ));
  413. _FatalCorruption();
  414. }
  415. //
  416. // And Volume Serial Number
  417. //
  418. cbRead = xact.Read( &VolumeSerialNumber, sizeof(VolumeSerialNumber) );
  419. if ( cbRead != sizeof(VolumeSerialNumber) )
  420. {
  421. ciDebugOut(( DEB_ERROR,
  422. "CCiScopeTable::_DeSerialize - Read %d bytes instead of %d \n",
  423. cbRead,
  424. sizeof(VolumeSerialNumber) ));
  425. _FatalCorruption();
  426. }
  427. //
  428. // Filesystem-Specific stuff.
  429. //
  430. if ( CI_VOLID_USN_NOT_ENABLED == volumeId )
  431. {
  432. //
  433. // Read filetime for non-usn volumes
  434. //
  435. cbRead = xact.Read( &ft, sizeof(FILETIME) );
  436. if ( cbRead != sizeof(FILETIME) )
  437. {
  438. ciDebugOut(( DEB_ERROR,
  439. "CCiScopeTable::_DeSerialize - Read %d bytes instead of %d \n",
  440. cbRead, sizeof(FILETIME) ));
  441. _FatalCorruption();
  442. }
  443. }
  444. else
  445. {
  446. //
  447. // Read usn for usn volumes
  448. //
  449. cbRead = xact.Read( &usn, sizeof(USN) );
  450. if ( cbRead != sizeof(USN) )
  451. {
  452. ciDebugOut(( DEB_ERROR,
  453. "CCiScopeTable::_DeSerialize - Read %d bytes instead of %d \n",
  454. cbRead,
  455. sizeof(USN) ));
  456. _FatalCorruption();
  457. }
  458. //
  459. // And Journal ID
  460. //
  461. cbRead = xact.Read( &JournalId, sizeof(JournalId) );
  462. if ( cbRead != sizeof(JournalId) )
  463. {
  464. ciDebugOut(( DEB_ERROR,
  465. "CCiScopeTable::_DeSerialize - Read %d bytes instead of %d \n",
  466. cbRead,
  467. sizeof(JournalId) ));
  468. _FatalCorruption();
  469. }
  470. }
  471. ULONG cchPath;
  472. cbRead = xact.Read( &cchPath, sizeof(ULONG) );
  473. if ( cbRead != sizeof(ULONG) )
  474. {
  475. ciDebugOut(( DEB_ERROR,
  476. "CCiScopeTable::_DeSerialize - Read %d bytes instead of %d \n",
  477. cbRead, sizeof(ULONG) ));
  478. _FatalCorruption();
  479. }
  480. if ( 0 == cchPath || cchPath > MAX_PATH )
  481. {
  482. ciDebugOut(( DEB_ERROR,
  483. "CCiScopeTable::_DeSerialize - Illegal path length %d\n", cchPath ));
  484. _FatalCorruption();
  485. }
  486. cbRead = xact.Read( wcsPath, cchPath*sizeof(WCHAR) );
  487. if ( cchPath*sizeof(WCHAR) != cbRead )
  488. {
  489. ciDebugOut(( DEB_ERROR,
  490. "CCiScopeTable::_DeSerialize - Requested %d bytes. Read %d bytes\n",
  491. cchPath*sizeof(WCHAR), cbRead ));
  492. _FatalCorruption();
  493. }
  494. cchPath--; // includes the length of the terminating 0
  495. if ( 0 != wcsPath[cchPath] || L'\\' != wcsPath[cchPath-1] )
  496. {
  497. ciDebugOut(( DEB_ERROR,
  498. "CCiScopeTable::_DeSerialize - Illegaly formed path %ws \n", wcsPath ));
  499. _FatalCorruption();
  500. }
  501. if ( CI_VOLID_USN_NOT_ENABLED == volumeId )
  502. xScopeInfo.Set( new CScopeInfo( wcsPath,
  503. VolumeCreationTime,
  504. VolumeSerialNumber,
  505. ft ) );
  506. else
  507. xScopeInfo.Set( new CScopeInfo( wcsPath,
  508. VolumeCreationTime,
  509. VolumeSerialNumber,
  510. volumeId,
  511. usn,
  512. JournalId,
  513. (0 == usn) ) );
  514. stk.Push( xScopeInfo.GetPointer() ); // Push can throw
  515. xScopeInfo.Acquire();
  516. }
  517. } //_DeSerialize
  518. //+---------------------------------------------------------------------------
  519. //
  520. // Member: CCiScopeTable::_Serialize
  521. //
  522. // Synopsis: Writes the given stack of scopes to the persistent table.
  523. //
  524. // Arguments: [stk] - Stack of scopes to write.
  525. //
  526. // History: 1-30-96 srikants Created
  527. // 28-Jul-1996 AlanW Allow for invalid scopes, e.g., when
  528. // one is removed in middle of stack
  529. // 05-May-1997 SitaramR Usns
  530. //
  531. //----------------------------------------------------------------------------
  532. void CCiScopeTable::_Serialize( CScopeInfoStack const & stk )
  533. {
  534. if ( 0 == _pTable )
  535. {
  536. _FatalCorruption();
  537. }
  538. CLock lock(_mutex);
  539. CRcovStorageHdr & hdr = _pTable->GetHeader();
  540. CRcovStrmWriteTrans xact( *_pTable );
  541. xact.Empty();
  542. ULONG nPaths = 0;
  543. FILETIME ft;
  544. RtlZeroMemory( &ft, sizeof(ft) );
  545. LONGLONG llSig = eSigCiScopeTable; // Signature for corruption detection
  546. for ( unsigned i = 0; i < stk.Count(); i++ )
  547. {
  548. CScopeInfo & scopeInfo = *stk.Get(i);
  549. if ( !scopeInfo.IsValid() )
  550. continue;
  551. WCHAR const * pwszScope = scopeInfo.GetPath();
  552. ULONG cchPath = wcslen( pwszScope ) + 1;
  553. Win4Assert( cchPath <= MAX_PATH );
  554. #if CIDBG == 1
  555. if ( wcschr( pwszScope, L'~' ) )
  556. {
  557. // Possible shortnames in scope path. We must only use long names.
  558. CLowerFunnyPath lowerFunnyPath( pwszScope );
  559. if ( lowerFunnyPath.IsShortPath( ) )
  560. {
  561. ciDebugOut(( DEB_WARN,
  562. "CCiScopeTable::_Seiralize: possible shortname path %ws\n",
  563. lowerFunnyPath.GetActualPath() ));
  564. }
  565. }
  566. #endif // CIDBG == 1
  567. xact.Append( &llSig, sizeof(llSig) );
  568. VOLUMEID volumeId = scopeInfo.VolumeId();
  569. xact.Append( &volumeId, sizeof(VOLUMEID) );
  570. ULONGLONG const & VolumeCreationTime = scopeInfo.VolumeCreationTime();
  571. xact.Append( &VolumeCreationTime, sizeof(VolumeCreationTime) );
  572. ULONG VolumeSerialNumber = scopeInfo.VolumeSerialNumber();
  573. xact.Append( &VolumeSerialNumber, sizeof(VolumeSerialNumber) );
  574. if ( scopeInfo.VolumeId() == CI_VOLID_USN_NOT_ENABLED )
  575. {
  576. //
  577. // Write filetime for non-usn volumes
  578. //
  579. ft = scopeInfo.GetLastScanTime();
  580. xact.Append( &ft, sizeof(ft) );
  581. }
  582. else
  583. {
  584. //
  585. // Write usn for usn volumes
  586. //
  587. USN usn = scopeInfo.Usn();
  588. xact.Append( &usn, sizeof(USN) );
  589. ULONGLONG JournalId = scopeInfo.JournalId();
  590. xact.Append( &JournalId, sizeof(JournalId) );
  591. }
  592. xact.Append( &cchPath, sizeof(cchPath) );
  593. xact.Append( pwszScope, cchPath*sizeof(WCHAR) );
  594. nPaths++;
  595. }
  596. ciDebugOut(( DEB_ITRACE, "_Serialize, nPaths %d\n", nPaths ));
  597. hdr.SetCount ( hdr.GetBackup(), nPaths );
  598. hdr.SetUserHdr( hdr.GetBackup(), _usrHdr );
  599. xact.Commit();
  600. }
  601. //+---------------------------------------------------------------------------
  602. //
  603. // Member: CCiScopeTable::_LokScheduleScans
  604. //
  605. // Synopsis: Schedules all the scopes for either full or incremental
  606. // scan depending upon the header information.
  607. //
  608. // History: 4-15-96 srikants Moved out of StartUp
  609. // 7-May-97 SitaramR Usns
  610. //
  611. //----------------------------------------------------------------------------
  612. void CCiScopeTable::_LokScheduleScans( PARTITIONID partId,
  613. BOOL & fSerializeNotifyList )
  614. {
  615. ciDebugOut(( DEB_ITRACE, "in CCiScopeTable::_LokScheduleScans\n" ));
  616. fSerializeNotifyList = FALSE;
  617. {
  618. //
  619. // Read the persistent scope list
  620. //
  621. CRcovStorageHdr & storageHdr = _pTable->GetHeader();
  622. //
  623. // read the last scan time.
  624. //
  625. storageHdr.GetUserHdr( storageHdr.GetPrimary(), _usrHdr );
  626. if ( !_hdr.IsInitialized() )
  627. _hdr.Initialize();
  628. CScopeInfoStack stk;
  629. _DeSerialize( stk );
  630. ciDebugOut(( DEB_ITRACE, "scope stack count: %d\n", stk.Count() ));
  631. if ( 0 == stk.Count() )
  632. return;
  633. //
  634. // Enable batch processing in the scan manager. This will result in
  635. // all the scopes being processed at once and avoid the scan of
  636. // the property store once per scope.
  637. //
  638. XBatchScan xBatchScans( _scanMgr );
  639. XBatchUsnProcessing xBatchUsns( _usnMgr );
  640. for ( ULONG i = 0; i < stk.Count(); i++ )
  641. {
  642. CScopeInfo & scopeInfo = *stk.Get(i);
  643. if ( !scopeInfo.IsValid() )
  644. continue;
  645. ciDebugOut(( DEB_ITRACE, "Adding path %ws to CI\n",
  646. scopeInfo.GetPath() ));
  647. BOOL fSubScopesRemoved;
  648. //
  649. // Check if there has been a volume format change, e.g.
  650. // from a non-usn-enabled volume to an usn-enabled
  651. // volume.
  652. //
  653. BOOL fUsnEnabledNow = _cicat.VolumeSupportsUsns( scopeInfo.GetPath()[0] );
  654. BOOL fUsnEnabledPrev = scopeInfo.VolumeId() != CI_VOLID_USN_NOT_ENABLED;
  655. if ( fUsnEnabledNow != fUsnEnabledPrev )
  656. {
  657. //
  658. // Volume format has changed, so reset scopeInfo to simulate a fresh
  659. // scan using the appropriate method for new format.
  660. //
  661. ciDebugOut(( DEB_WARN,
  662. "Switching monitoring method for path %ws, due to format change\n",
  663. scopeInfo.GetPath() ));
  664. if ( fUsnEnabledNow )
  665. {
  666. VOLUMEID volId = _cicat.MapPathToVolumeId( scopeInfo.GetPath() );
  667. scopeInfo.ResetForUsns( volId );
  668. }
  669. else
  670. scopeInfo.ResetForScans();
  671. }
  672. //
  673. // Check if a USN-enabled volume has been opened in NT4.
  674. //
  675. if ( fUsnEnabledNow )
  676. {
  677. ULONGLONG jidNow = _cicat.GetJournalId( scopeInfo.GetPath() );
  678. ULONGLONG jidPrev = scopeInfo.JournalId();
  679. if ( jidNow != jidPrev )
  680. {
  681. ciDebugOut(( DEB_WARN,
  682. "Scanning USN-enabled volume %ws due to downlevel (NT4) open.\n",
  683. scopeInfo.GetPath() ));
  684. scopeInfo.ResetForUsns( scopeInfo.VolumeId(), fUsnEnabledPrev ? scopeInfo.Usn() : 0 );
  685. }
  686. }
  687. //
  688. // Check to see if the volume has been reformatted.
  689. //
  690. BOOL fReformatted = (_cicat.GetVolumeCreationTime( scopeInfo.GetPath() ) != scopeInfo.VolumeCreationTime()) ||
  691. (_cicat.GetVolumeSerialNumber( scopeInfo.GetPath() ) != scopeInfo.VolumeSerialNumber());
  692. if ( fReformatted || IsFullScanNeeded() )
  693. {
  694. ciDebugOut(( DEB_WARN, "Scanning newly formatted/trashed volume %ws\n", scopeInfo.GetPath() ));
  695. if ( CI_VOLID_USN_NOT_ENABLED == scopeInfo.VolumeId() )
  696. scopeInfo.ResetForScans();
  697. else
  698. {
  699. scopeInfo.SetScanNeeded( TRUE ); // Full scan
  700. scopeInfo.ResetForUsns( scopeInfo.VolumeId() ); // From USN = 0
  701. }
  702. }
  703. ciDebugOut(( DEB_ITRACE, "_LokScheduleScans, '%ws'\n",
  704. scopeInfo.GetPath() ));
  705. _notifyMgr.AddPath( scopeInfo, fSubScopesRemoved );
  706. if ( CI_VOLID_USN_NOT_ENABLED == scopeInfo.VolumeId() )
  707. {
  708. ULONG updFlag;
  709. if ( fReformatted || fUsnEnabledNow != fUsnEnabledPrev )
  710. {
  711. //
  712. // Do a full scan if there has been a format change
  713. //
  714. updFlag = UPD_FULL;
  715. }
  716. else
  717. {
  718. //
  719. // Use scan info from persistent header of scopetable
  720. //
  721. if ( IsFullScanNeeded() )
  722. updFlag = UPD_FULL;
  723. else
  724. updFlag = UPD_INCREM;
  725. }
  726. _scanMgr.ScanScope( scopeInfo.GetPath(),
  727. partId,
  728. updFlag, // Full or increm update
  729. TRUE, // do deletions,
  730. TRUE // delayed scanning
  731. );
  732. }
  733. else
  734. {
  735. Win4Assert( (0 == scopeInfo.Usn() && scopeInfo.FUsnTreeScan()) ||
  736. 0 != scopeInfo.Usn() );
  737. if ( scopeInfo.FUsnTreeScan() )
  738. {
  739. //
  740. // An usn of 0 indicates that a scan and subsequent
  741. // CheckPointChangesFlushed for this volume id has not
  742. // completed successfully, and hence a scan is needed
  743. //
  744. ciDebugOut(( DEB_ITRACE, "_LokScheduleScans, AddScope\n" ));
  745. _usnMgr.AddScope( scopeInfo.GetPath(),
  746. scopeInfo.VolumeId(),
  747. TRUE, // Do deletions
  748. scopeInfo.Usn(), // Starting USN
  749. scopeInfo.IsFullScan() ); // TRUE --> delete everything first
  750. }
  751. else
  752. {
  753. //
  754. // Start monitoring for usn notifications. This is the main
  755. // performance advantage of usns when compared with the
  756. // _scanMgr.ScanScope above --- no scan is needed.
  757. //
  758. ciDebugOut(( DEB_ITRACE, "_LokScheduleScans, MonitorScope\n" ));
  759. _usnMgr.MonitorScope( scopeInfo.GetPath(),
  760. scopeInfo.VolumeId(),
  761. scopeInfo.Usn() );
  762. }
  763. }
  764. if ( fSubScopesRemoved )
  765. fSerializeNotifyList = TRUE;
  766. }
  767. }
  768. }
  769. //+---------------------------------------------------------------------------
  770. //
  771. // Member: CCiScopeTable::StartUp
  772. //
  773. // Synopsis: Starts up the contentIndex scope scanning and notification
  774. // mechanism for all the scopes that are registered with the
  775. // content index.
  776. //
  777. // Arguments: [notifyMgr] - The notification manager.
  778. // [scanMgr] - The scan manager.
  779. // [partId] - PartitionId.
  780. //
  781. // History: 1-21-96 srikants Created
  782. //
  783. // Notes: MUST BE UNDER CICAT LOCK
  784. //
  785. //----------------------------------------------------------------------------
  786. void CCiScopeTable::StartUp( CClientDocStore & docStore ,
  787. PARTITIONID partId )
  788. {
  789. Win4Assert( 0 != _pTable );
  790. if ( _fInitialized )
  791. return;
  792. // ============================ ScopeTable lock ===================
  793. CLock lock(_mutex);
  794. //
  795. // If there was no full scan needed when it was shutdown last,
  796. // set up for an incremental scan.
  797. //
  798. if ( eNoScan == _state )
  799. RecordIncrScanNeeded( TRUE ); // fStartup is TRUE
  800. ScheduleScansIfNeeded( docStore );
  801. _fInitialized = TRUE;
  802. // ============================ ScopeTable lock ===================
  803. }
  804. //+---------------------------------------------------------------------------
  805. //
  806. // Member: CCiScopeTable::AddScope
  807. //
  808. // Synopsis: Registers a scope persistently with CI for scanning and
  809. // notification.
  810. //
  811. // Arguments: [volumeId] -- Volume id
  812. // [pwcsScope] -- The scope to be registered.
  813. // [pwcsCatScope] -- If non-zero, name of catalog key under
  814. // which a shadow registry entry should be
  815. // created.
  816. //
  817. // History: 1-21-96 srikants Created
  818. //
  819. //----------------------------------------------------------------------------
  820. void CCiScopeTable::AddScope( VOLUMEID volumeId,
  821. WCHAR const * pwszScope,
  822. WCHAR const * pwszCatScope )
  823. {
  824. ULONG ccPath = wcslen( pwszScope );
  825. Win4Assert( ccPath < MAX_PATH );
  826. Win4Assert( L'\\' == pwszScope[ccPath-1] );
  827. #if CIDBG == 1
  828. if ( wcschr( pwszScope, L'~' ) )
  829. {
  830. // Possible shortnames in scope path. We must only use long names.
  831. CLowerFunnyPath lowerFunnyPath( pwszScope );
  832. if ( lowerFunnyPath.IsShortPath( ) )
  833. {
  834. ciDebugOut(( DEB_WARN,
  835. "CCiScopeTable::AddScope: possible shortname path %ws\n",
  836. lowerFunnyPath.GetActualPath() ));
  837. }
  838. }
  839. #endif // CIDBG == 1
  840. Win4Assert( 0 != _pTable );
  841. if ( 0 == _pTable )
  842. {
  843. _FatalCorruption();
  844. }
  845. CLock lock(_mutex);
  846. CRcovStorageHdr & hdr = _pTable->GetHeader();
  847. CRcovStrmAppendTrans xact( *_pTable );
  848. ULONG nPaths = hdr.GetCount( hdr.GetPrimary() );
  849. ccPath++; // increment to include the trailing 0
  850. LONGLONG llSig = eSigCiScopeTable; // Signature for corruption detection.
  851. xact.Append( &llSig, sizeof(llSig) );
  852. xact.Append( &volumeId, sizeof(VOLUMEID) );
  853. ULONGLONG VolumeCreationTime = _cicat.GetVolumeCreationTime(pwszScope);
  854. xact.Append( &VolumeCreationTime, sizeof(VolumeCreationTime) );
  855. ULONG VolumeSerialNumber = _cicat.GetVolumeSerialNumber(pwszScope);
  856. xact.Append( &VolumeSerialNumber, sizeof(VolumeSerialNumber) );
  857. if ( volumeId == CI_VOLID_USN_NOT_ENABLED )
  858. {
  859. FILETIME ft;
  860. RtlZeroMemory( &ft, sizeof(ft) );
  861. xact.Append( &ft, sizeof(ft) );
  862. }
  863. else
  864. {
  865. USN usn = 0;
  866. xact.Append( &usn, sizeof(USN) );
  867. ULONGLONG JournalId = _cicat.GetJournalId( pwszScope );
  868. xact.Append( &JournalId, sizeof(JournalId) );
  869. }
  870. xact.Append( &ccPath, sizeof(ccPath) );
  871. xact.Append( pwszScope, ccPath*sizeof(WCHAR) );
  872. nPaths++;
  873. hdr.SetCount( hdr.GetBackup(), nPaths );
  874. xact.Commit();
  875. if ( 0 != pwszCatScope )
  876. {
  877. //
  878. // Build string: NAME: ,,3 --> Virtual, Indexed
  879. //
  880. WCHAR wcsScope[] = L",,3";
  881. HKEY hkey;
  882. DWORD dwError = RegOpenKey( HKEY_LOCAL_MACHINE, pwszCatScope, &hkey );
  883. if ( ERROR_SUCCESS != dwError )
  884. {
  885. ciDebugOut(( DEB_ERROR, "Error %d opening %ws\n", dwError, pwszCatScope ));
  886. }
  887. else
  888. {
  889. AddShadow( pwszScope, hkey );
  890. RegCloseKey( hkey );
  891. }
  892. }
  893. }
  894. //+---------------------------------------------------------------------------
  895. //
  896. // Member: CCiScopeTable::_Serialize
  897. //
  898. // Synopsis: Serializes the scopes in the notification manager.
  899. //
  900. // History: 1-25-96 srikants Created
  901. //
  902. //----------------------------------------------------------------------------
  903. void CCiScopeTable::_Serialize()
  904. {
  905. if ( 0 == _pTable )
  906. {
  907. _FatalCorruption();
  908. }
  909. CScopeInfoStack stk;
  910. // ====================== NOTIFY MGR LOCK =========================
  911. {
  912. for ( CCiNotifyIter iter( _notifyMgr );
  913. !iter.AtEnd() && 0 != iter.Get();
  914. iter.Advance() )
  915. {
  916. WCHAR const * pwszScope = iter.Get();
  917. ULONG ccPath = wcslen( pwszScope );
  918. ccPath++; // increment to include trailing 0
  919. FILETIME ft;
  920. iter.GetLastScanTime( ft );
  921. XPtr<CScopeInfo> xScopeInfo;
  922. if ( iter.IsDownlevelVolume() )
  923. xScopeInfo.Set( new CScopeInfo( pwszScope,
  924. iter.VolumeCreationTime(),
  925. iter.VolumeSerialNumber(),
  926. ft ) );
  927. else
  928. xScopeInfo.Set( new CScopeInfo( pwszScope,
  929. iter.VolumeCreationTime(),
  930. iter.VolumeSerialNumber(),
  931. iter.VolumeId(),
  932. iter.Usn(),
  933. iter.JournalId(),
  934. iter.FUsnTreeScan() ) );
  935. stk.Push( xScopeInfo.GetPointer() ); // Push can throw
  936. xScopeInfo.Acquire();
  937. }
  938. }
  939. // ====================== NOTIFY MGR LOCK =========================
  940. //
  941. // If the notification manager is shutting down, it probably gave
  942. // us an incomplete list of scopes
  943. //
  944. if ( _notifyMgr.IsRunning() )
  945. _Serialize( stk );
  946. else
  947. ciDebugOut(( DEB_WARN, "Not serializing scopes; notifymgr is shutdown\n" ));
  948. } //_Serialize
  949. //+---------------------------------------------------------------------------
  950. //
  951. // Member: CCiScopeTable::_UpdateHeader
  952. //
  953. // Synopsis: Updates the on-disk header information based on the in-memory
  954. // version.
  955. //
  956. // History: 4-15-96 srikants Moved into a separate function
  957. //
  958. //----------------------------------------------------------------------------
  959. void CCiScopeTable::_UpdateHeader()
  960. {
  961. Win4Assert( sizeof(CCiScopeUsrHdr) <= sizeof(CRcovUserHdr) );
  962. if ( 0 == _pTable )
  963. {
  964. _FatalCorruption();
  965. }
  966. CRcovStorageHdr & storageHdr = _pTable->GetHeader();
  967. CRcovStrmAppendTrans xact( *_pTable );
  968. if ( !_hdr.IsInitialized() )
  969. _hdr.Initialize();
  970. storageHdr.SetUserHdr( storageHdr.GetBackup(), _usrHdr );
  971. xact.Commit();
  972. }
  973. //+---------------------------------------------------------------------------
  974. //
  975. // Member: CCiScopeTable::ProcessChangesFlush
  976. //
  977. // Synopsis: Flushes the scope table, which will
  978. // write the latest flush time and usn flush info to disk.
  979. //
  980. // History: 1-26-96 srikants Created
  981. //
  982. //----------------------------------------------------------------------------
  983. void CCiScopeTable::ProcessChangesFlush( )
  984. {
  985. _Serialize();
  986. }
  987. //+---------------------------------------------------------------------------
  988. //
  989. // Member: CCiScopeTable::RemoveScope
  990. //
  991. // Synopsis: Removes the specified scope from the persistent table.
  992. //
  993. // Arguments: [pwcsScope] -- Scope to be removed.
  994. // [pwcsCatScope] -- If non-zero, name of catalog key under
  995. // which a shadow registry entry should be
  996. // created.
  997. //
  998. // History: 1-30-96 srikants Created
  999. //
  1000. //----------------------------------------------------------------------------
  1001. void CCiScopeTable::RemoveScope( WCHAR const * pwcsScope,
  1002. WCHAR const * pwcsCatScope )
  1003. {
  1004. CScopeInfoStack scopes;
  1005. _DeSerialize( scopes );
  1006. for ( unsigned i = 0; i < scopes.Count(); i++ )
  1007. {
  1008. CScopeInfo & scopeInfo = *scopes.Get(i);
  1009. if ( !scopeInfo.IsValid() )
  1010. continue;
  1011. if ( AreIdenticalPaths(pwcsScope, scopeInfo.GetPath()) )
  1012. scopeInfo.Invalidate();
  1013. }
  1014. _Serialize( scopes );
  1015. //
  1016. // Delete any remnant in registry.
  1017. //
  1018. HKEY hkey;
  1019. DWORD dwError = RegOpenKey( HKEY_LOCAL_MACHINE, pwcsCatScope, &hkey );
  1020. if ( ERROR_SUCCESS != dwError )
  1021. {
  1022. ciDebugOut(( DEB_ERROR, "Error %d opening %ws\n", dwError, pwcsCatScope ));
  1023. }
  1024. else
  1025. {
  1026. DeleteIfShadow( pwcsScope, hkey );
  1027. RegCloseKey( hkey );
  1028. }
  1029. }
  1030. //+---------------------------------------------------------------------------
  1031. //
  1032. // Member: CCiScopeTable::RemoveSubScopes
  1033. //
  1034. // Synopsis: Removes only the sub-scopes of the given scope. The scope
  1035. // itself is NOT removed.
  1036. //
  1037. // Arguments: [pwcsScope] -- Sub-scopes of the scope to be removed.
  1038. // [pwcsCatScope] -- If non-zero, name of catalog key under
  1039. // which a shadow registry entry should be
  1040. // created.
  1041. //
  1042. // History: 1-30-96 srikants Created
  1043. //
  1044. //----------------------------------------------------------------------------
  1045. void CCiScopeTable::RemoveSubScopes( WCHAR const * pwcsScope,
  1046. WCHAR const * pwcsCatScope )
  1047. {
  1048. //
  1049. // Open key for reg deletes.
  1050. //
  1051. HKEY hkey = 0;
  1052. DWORD dwError = RegOpenKey( HKEY_LOCAL_MACHINE, pwcsCatScope, &hkey );
  1053. if ( ERROR_SUCCESS != dwError ) {
  1054. ciDebugOut(( DEB_ERROR, "Error %d opening %ws\n", dwError, pwcsCatScope ));
  1055. }
  1056. SRegKey xKey( hkey );
  1057. //
  1058. // Search for sub-scopes
  1059. //
  1060. CScopeInfoStack scopes;
  1061. _DeSerialize( scopes );
  1062. CScopeMatch match( pwcsScope, wcslen(pwcsScope) );
  1063. for ( unsigned i = 0;
  1064. i < scopes.Count();
  1065. i++ )
  1066. {
  1067. CScopeInfo & scopeInfo = *scopes.Get(i);
  1068. if ( !scopeInfo.IsValid() )
  1069. continue;
  1070. if ( match.IsInScope( scopeInfo.GetPath(), wcslen(scopeInfo.GetPath()) ) &&
  1071. !AreIdenticalPaths( scopeInfo.GetPath(), pwcsScope ) )
  1072. {
  1073. scopeInfo.Invalidate();
  1074. //
  1075. // Delete any remnant in registry.
  1076. //
  1077. if ( 0 != hkey )
  1078. DeleteIfShadow( scopeInfo.GetPath(), hkey );
  1079. }
  1080. }
  1081. _Serialize( scopes );
  1082. }
  1083. //+---------------------------------------------------------------------------
  1084. //
  1085. // Member: CCiScopeTable::RefreshShadow, public
  1086. //
  1087. // Synopsis: Re-adds missing shadow (virtual) scopes to registry.
  1088. //
  1089. // Arguments: [pwcsPScope] -- Physical scope to re-add (if doesn't exist)
  1090. // [pwcsCatScope] -- Name of catalog key under which a shadow
  1091. // registry entry should be created.
  1092. //
  1093. // History: 12-10-1997 KyleP Created
  1094. //
  1095. //----------------------------------------------------------------------------
  1096. void CCiScopeTable::RefreshShadow( WCHAR const * pwcsPScope, WCHAR const * pwcsCatScope )
  1097. {
  1098. //
  1099. // Open key for reg refresh.
  1100. //
  1101. HKEY hkey = 0;
  1102. DWORD dwError = RegOpenKey( HKEY_LOCAL_MACHINE, pwcsCatScope, &hkey );
  1103. if ( ERROR_SUCCESS != dwError ) {
  1104. ciDebugOut(( DEB_ERROR, "Error %d opening %ws\n", dwError, pwcsCatScope ));
  1105. }
  1106. SRegKey xKey( hkey );
  1107. //
  1108. // Try the refresh
  1109. //
  1110. if ( 0 != hkey )
  1111. RefreshIfShadow( pwcsPScope, hkey );
  1112. }
  1113. //+---------------------------------------------------------------------------
  1114. //
  1115. // Member: CCiScopeTable::ProcessDiskFull
  1116. //
  1117. // Synopsis: Processes disk full condition.
  1118. //
  1119. // Arguments: [scanMgr] -
  1120. // [cci] -
  1121. // [partId] -
  1122. //
  1123. // History: 4-17-96 srikants Created
  1124. //
  1125. // Notes:
  1126. //
  1127. //----------------------------------------------------------------------------
  1128. void CCiScopeTable::ProcessDiskFull( CClientDocStore & docStore,
  1129. PARTITIONID partId )
  1130. {
  1131. CLock lock(_mutex);
  1132. if ( !_fInitialized )
  1133. return;
  1134. RecordIncrScanNeeded( FALSE ); // fStartup is FALSE
  1135. }
  1136. //+---------------------------------------------------------------------------
  1137. //
  1138. // Member: CCiScopeTable::ClearDiskFull
  1139. //
  1140. // Synopsis: Processes the clearing of the disk full situation. If there
  1141. // was in incremental scan scheduled, it will be processed.
  1142. //
  1143. // Arguments: [partId] - PartitionId.
  1144. //
  1145. // History: 4-21-96 srikants Created
  1146. //
  1147. // Notes:
  1148. //
  1149. //----------------------------------------------------------------------------
  1150. void CCiScopeTable::ClearDiskFull( CClientDocStore &docStore )
  1151. {
  1152. if ( !_fInitialized )
  1153. return;
  1154. ScheduleScansIfNeeded( docStore );
  1155. }
  1156. //+---------------------------------------------------------------------------
  1157. //
  1158. // Member: CCiScopeTable::MarkCiDataCorrupt, public
  1159. //
  1160. // Synopsis: Persistently marks catalog as corrupt.
  1161. //
  1162. // History: 06-May-1998 KyleP Added header
  1163. //
  1164. //----------------------------------------------------------------------------
  1165. void CCiScopeTable::MarkCiDataCorrupt()
  1166. {
  1167. //
  1168. // Abort any in-progress scans and usn updates
  1169. //
  1170. _scanMgr.DisableScan();
  1171. _usnMgr.DisableUpdates();
  1172. //
  1173. // And persistently mark the corruption.
  1174. //
  1175. _hdr.SetCiDataCorrupt();
  1176. _UpdateHeader();
  1177. }
  1178. //+---------------------------------------------------------------------------
  1179. //
  1180. // Member: CCiScopeTable::RecordFullScanNeeded
  1181. //
  1182. // Synopsis: Records that a full scan is needed in memory and persistently.
  1183. //
  1184. // History: 1-27-97 srikants Created
  1185. //
  1186. //----------------------------------------------------------------------------
  1187. void CCiScopeTable::RecordFullScanNeeded()
  1188. {
  1189. // =============================================================
  1190. //
  1191. // Note that we call into scan manager from here which will need that
  1192. // to acquire the lock but scan manager never calls into the scope
  1193. // table with the lock held. So, we are okay.
  1194. //
  1195. CLock lock(_mutex);
  1196. //
  1197. // Abort any in-progress scans and usn updates
  1198. //
  1199. _scanMgr.DisableScan();
  1200. _usnMgr.DisableUpdates();
  1201. //
  1202. // Mark that we need a full scan.
  1203. //
  1204. _state = eFullScanNeeded;
  1205. _hdr.SetFullScanNeeded();
  1206. _UpdateHeader();
  1207. // =============================================================
  1208. }
  1209. //+---------------------------------------------------------------------------
  1210. //
  1211. // Member: CCiScopeTable::RecordIncrScanNeeded
  1212. //
  1213. // Synopsis: If there is no full scan, it records that an incremental
  1214. // scan is needed.
  1215. //
  1216. // Arguments: [fStartup] -- Is it startup time ?
  1217. //
  1218. // History: 1-27-97 srikants Created
  1219. //
  1220. //----------------------------------------------------------------------------
  1221. void CCiScopeTable::RecordIncrScanNeeded( BOOL fStartup )
  1222. {
  1223. //
  1224. // Note that we call into scan manager from here which will need that
  1225. // to acquire the lock but scan manager never calls into the scope
  1226. // table with the lock held. So, we are okay.
  1227. //
  1228. // =============================================================
  1229. CLock lock(_mutex);
  1230. //
  1231. // Abort any in-progress scans and usn updates
  1232. //
  1233. _scanMgr.DisableScan();
  1234. if ( !fStartup )
  1235. {
  1236. //
  1237. // An incremental scan needs to be persistently written at startup,
  1238. // but there is no need to disable updates at startup
  1239. //
  1240. _usnMgr.DisableUpdates();
  1241. }
  1242. //
  1243. // If there is full scan needed or a full scan is going on,
  1244. // we have to do a full scan later. Otherwise, record an
  1245. // incremental scan.
  1246. //
  1247. if ( eFullScanNeeded == _state || eDoingFullScan == _state )
  1248. {
  1249. _state = eFullScanNeeded;
  1250. }
  1251. else
  1252. {
  1253. _state = eIncrScanNeeded;
  1254. }
  1255. // =============================================================
  1256. //
  1257. // We don't have to update the persistent state about incremental
  1258. // scans because we always do an incremental scan on startup.
  1259. //
  1260. }
  1261. //+---------------------------------------------------------------------------
  1262. //
  1263. // Member: CCiScopeTable::RecordScansComplete
  1264. //
  1265. // Synopsis: Records that any in-progress scan has been completed.
  1266. //
  1267. // History: 1-27-97 srikants Created
  1268. //
  1269. //----------------------------------------------------------------------------
  1270. void CCiScopeTable::RecordScansComplete()
  1271. {
  1272. // =============================================================
  1273. CLock lock(_mutex);
  1274. if ( eDoingIncrScan == _state || eDoingFullScan == _state )
  1275. {
  1276. _hdr.ClearFullScanNeeded();
  1277. _UpdateHeader();
  1278. _state = eNoScan;
  1279. }
  1280. }
  1281. //+---------------------------------------------------------------------------
  1282. //
  1283. // Member: CCiScopeTable::ScheduleScansIfNeeded
  1284. //
  1285. // Synopsis: If there is a pending scan and the disk is not full, it
  1286. // schedules the appropriate scan.
  1287. //
  1288. // Arguments: [docStore] - DocStore to use for checking disk space
  1289. // situation.
  1290. //
  1291. // History: 1-27-97 srikants Created
  1292. //
  1293. //----------------------------------------------------------------------------
  1294. void CCiScopeTable::ScheduleScansIfNeeded( CClientDocStore & docStore )
  1295. {
  1296. Win4Assert( _state >= eNoScan && _state <= eDoingIncrScan );
  1297. ciDebugOut(( DEB_ITRACE, "schedulescansifneeded, _state: %#x\n", _state ));
  1298. BOOL fSerializeNotifyList = TRUE;
  1299. // =============================================================
  1300. {
  1301. //
  1302. // Note that we call into scan manager from here which will need that
  1303. // to acquire the lock but scan manager never calls into the scope
  1304. // table with the lock held. So, we are okay.
  1305. //
  1306. CLock lock(_mutex);
  1307. if ( eDoingFullScan == _state ||
  1308. eDoingIncrScan == _state ||
  1309. eNoScan == _state )
  1310. {
  1311. //
  1312. // There is nothing to do.
  1313. //
  1314. return;
  1315. }
  1316. BOOL fLowOnDisk = docStore.VerifyIfLowOnDiskSpace();
  1317. if ( !fLowOnDisk )
  1318. {
  1319. _scanMgr.EnableScan();
  1320. _usnMgr.EnableUpdates();
  1321. _LokScheduleScans( 1, fSerializeNotifyList );
  1322. if ( _state == eFullScanNeeded )
  1323. {
  1324. _state = eDoingFullScan;
  1325. ciDebugOut(( DEB_WARN, "CCiScopeTable - Scheduled a full content scan\n" ));
  1326. }
  1327. else
  1328. {
  1329. _state = eDoingIncrScan;
  1330. ciDebugOut(( DEB_WARN, "CCiScopeTable - Scheduled an incremental content scan\n" ));
  1331. }
  1332. }
  1333. }
  1334. // =============================================================
  1335. if ( fSerializeNotifyList )
  1336. _Serialize();
  1337. }
  1338. //+---------------------------------------------------------------------------
  1339. //
  1340. // Member: CCiScopeTable::Enumerate, public
  1341. //
  1342. // Synopsis: Enumerates entries in the scope table
  1343. //
  1344. // Arguments: [pwcScope] - Buffer into which scope is written
  1345. // [partId] - bookmark for enumeration, 0 to rewind
  1346. //
  1347. // History: 10/17/96 dlee Created
  1348. //
  1349. //----------------------------------------------------------------------------
  1350. BOOL CCiScopeTable::Enumerate(
  1351. WCHAR * pwcScope,
  1352. unsigned cwc,
  1353. unsigned & iBmk )
  1354. {
  1355. CScopeInfoStack scopes;
  1356. _DeSerialize( scopes );
  1357. do
  1358. {
  1359. if ( iBmk >= scopes.Count() )
  1360. return FALSE;
  1361. CScopeInfo & scopeInfo = *scopes.Get( iBmk );
  1362. iBmk++;
  1363. if ( scopeInfo.IsValid() )
  1364. {
  1365. if ( cwc < ( wcslen( scopeInfo.GetPath() ) + 1 ) )
  1366. THROW( CException( STATUS_INVALID_PARAMETER ) );
  1367. wcscpy( pwcScope, scopeInfo.GetPath() );
  1368. return TRUE;
  1369. }
  1370. } while ( TRUE );
  1371. return FALSE;
  1372. } //Enumerate
  1373. //+----------------------------------------------------------------------------
  1374. //
  1375. // Member: CCiScopeTable::ClearCiDataCorrupt, public
  1376. //
  1377. // Synopsis: Clears corrupted data if the catalog is not read-only
  1378. //
  1379. // History: 02/20/98 kitmanh Moved from scopetbl.hxx
  1380. //
  1381. //-----------------------------------------------------------------------------
  1382. void CCiScopeTable::ClearCiDataCorrupt()
  1383. {
  1384. if (!_cicat.IsReadOnly())
  1385. {
  1386. _hdr.ClearCiDataCorrupt();
  1387. _UpdateHeader();
  1388. }
  1389. }
  1390. //+----------------------------------------------------------------------------
  1391. //
  1392. // Member: CCiScopeTable::Dump, public
  1393. //
  1394. // Synopsis: dumps scope table
  1395. //
  1396. // History: 3-1-98 mohamedn created
  1397. //
  1398. //-----------------------------------------------------------------------------
  1399. #if CIDBG==1
  1400. void CCiScopeTable::Dump()
  1401. {
  1402. CScopeInfoStack scopes;
  1403. _DeSerialize( scopes );
  1404. ciDebugOut(( DEB_ERROR, "========= Start ScopesTable =============\n" ));
  1405. for ( unsigned i = 0; i < scopes.Count(); i++ )
  1406. {
  1407. ciDebugOut((DEB_ERROR,"scopetable: %ws\n", (scopes.Get(i))->GetPath() ));
  1408. }
  1409. ciDebugOut(( DEB_ERROR, "========= End ScopesTable =============\n" ));
  1410. }
  1411. #endif