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.

1053 lines
33 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: CatArray.cxx
  7. //
  8. // Contents: Catalog array, for user mode content index
  9. //
  10. // History: 22-Dec-92 KyleP Split from vquery.cxx
  11. // 11-Oct-96 dlee added catalog name support
  12. //
  13. //--------------------------------------------------------------------------
  14. #include <pch.cxx>
  15. #pragma hdrstop
  16. #include <catarray.hxx>
  17. #include <ciregkey.hxx>
  18. #include <regacc.hxx>
  19. #include <docstore.hxx>
  20. #include <imprsnat.hxx>
  21. #include <eventlog.hxx>
  22. #include <cievtmsg.h>
  23. #include "cicat.hxx"
  24. #include <dbgproxy.hxx>
  25. #include <query.hxx>
  26. #include <srequest.hxx>
  27. #include <removcat.hxx>
  28. CCatArray Catalogs;
  29. //+---------------------------------------------------------------------------
  30. //
  31. // Member: COldCatState::COldCatState, public
  32. //
  33. // Synopsis: Constructor
  34. //
  35. // Arguments: [dwOldState] -- old state of the catalog
  36. // [wcsCatName] -- name of the catalog
  37. // [wcVol] -- volume letter
  38. //
  39. // History: 15-Jul-98 KitmanH Created
  40. //
  41. //----------------------------------------------------------------------------
  42. COldCatState::COldCatState( DWORD dwOldState, WCHAR const * wcsCatName, WCHAR wcVol )
  43. : _dwOldState(dwOldState),
  44. _cStopCount(1)
  45. {
  46. RtlZeroMemory( _aVol, sizeof _aVol );
  47. if ( 0 != wcVol )
  48. _aVol[toupper(wcVol) - L'A'] = 1;
  49. _xCatName.Init( wcslen( wcsCatName ) + 1 );
  50. RtlCopyMemory( _xCatName.Get(), wcsCatName, _xCatName.SizeOf() );
  51. }
  52. //+---------------------------------------------------------------------------
  53. //
  54. // Member: CCatArray::CCatArray, public
  55. //
  56. // Synopsis: Constructor for array to handle switching drives for catalogs
  57. //
  58. // History: 07-May-92 AmyA Lifted from vquery.cxx
  59. // 02-Jun-92 KyleP Added UNC support.
  60. // 12-Jun-92 KyleP Lifted from citest.cxx
  61. //
  62. //----------------------------------------------------------------------------
  63. CCatArray::CCatArray()
  64. : _aDocStores(0),
  65. _pDrvNotifArray(0),
  66. _fInit(FALSE),
  67. _mutex(FALSE)
  68. {
  69. }
  70. //+---------------------------------------------------------------------------
  71. //
  72. // Member: CCatArray::Init, public
  73. //
  74. // Synopsis: Initializer for catalogs array
  75. //
  76. // History: 20 May 99 AlanW Created
  77. //
  78. //----------------------------------------------------------------------------
  79. void CCatArray::Init()
  80. {
  81. _mutex.Init();
  82. _fInit = TRUE;
  83. }
  84. //+---------------------------------------------------------------------------
  85. //
  86. // Member: CCatArray::~CCatArray, public
  87. //
  88. // Synopsis: Destructor for array to handle switching drives for catalogs
  89. //
  90. // History: 07-May-92 AmyA Lifted from vquery.cxx
  91. // 02-Jun-92 KyleP Added UNC support.
  92. // 12-Jun-92 KyleP Lifted from citest.cxx
  93. //
  94. //----------------------------------------------------------------------------
  95. CCatArray::~CCatArray()
  96. {
  97. if (_fInit)
  98. {
  99. CLock lockx( _mutex );
  100. _pDrvNotifArray = 0;
  101. ClearStopArray();
  102. Flush();
  103. }
  104. } //~CCatArray
  105. //+-------------------------------------------------------------------------
  106. //
  107. // Member: CCatArray::Flush, public
  108. //
  109. // Synopsis: Close all open catalogs
  110. //
  111. // History: 03-Sep-93 KyleP Created
  112. //
  113. // Notes: This is a dangerous operation. It should only be called
  114. // when no-one is accessing any indexes.
  115. //
  116. //--------------------------------------------------------------------------
  117. void CCatArray::Flush()
  118. {
  119. if (! _fInit)
  120. return;
  121. CLock lock( _mutex );
  122. TRY
  123. {
  124. // Close all the open docstores
  125. for ( unsigned i = 0; i < _aDocStores.Count(); i++ )
  126. {
  127. Win4Assert( 0 != _aDocStores[i] );
  128. _aDocStores[i]->Shutdown();
  129. }
  130. // Delete registry entries for auto-mounted catalogs
  131. if ( 0 != _pDrvNotifArray )
  132. {
  133. BOOL aDrives[ RTL_MAX_DRIVE_LETTERS ];
  134. RtlZeroMemory( aDrives, sizeof aDrives );
  135. _pDrvNotifArray->GetAutoMountDrives( aDrives );
  136. for ( WCHAR x = 0; x < RTL_MAX_DRIVE_LETTERS; x++ )
  137. {
  138. if ( aDrives[x] )
  139. {
  140. CRemovableCatalog cat( L'A' + x );
  141. cat.Destroy();
  142. }
  143. }
  144. }
  145. }
  146. CATCH( CException, e )
  147. {
  148. Win4Assert( !"unexpected exception when shutting down a docstore" );
  149. }
  150. END_CATCH
  151. _aDocStores.Free();
  152. } //Flush
  153. //+-------------------------------------------------------------------------
  154. //
  155. // Member: CCatArray::FlushOne, public
  156. //
  157. // Synopsis: Close one catalog
  158. //
  159. // Arguments: [pDocStore] -- Pointer to the docstore to be flushed
  160. //
  161. // History: 27-Apr-98 KitmanH Created
  162. //
  163. // Notes: This is a dangerous operation. It should only be called
  164. // when no-one is accessing any indexes. If this wasn't
  165. // downlevel scaffolding we'd have to perform some serious
  166. // serialization and refcounting here.
  167. //
  168. //--------------------------------------------------------------------------
  169. void CCatArray::FlushOne( ICiCDocStore * pDocStore )
  170. {
  171. CLock lock( _mutex );
  172. for ( unsigned i = 0; i < _aDocStores.Count(); i++ )
  173. {
  174. Win4Assert( 0 != _aDocStores[i] );
  175. if ( _aDocStores[i] == pDocStore)
  176. {
  177. _aDocStores[i]->Shutdown();
  178. CClientDocStore * p = _aDocStores.AcquireAndShrink(i);
  179. p->Release();
  180. return;
  181. }
  182. }
  183. } //FlushOne
  184. //+---------------------------------------------------------------------------
  185. //
  186. // Member: CCatArray::GetDocStore, public
  187. //
  188. // Synopsis: Returns a PCatalog by either using an existing catalog or
  189. // creating a new one. Returns 0 if a catalog couldn't be
  190. // found or created.
  191. //
  192. // Arguments: [pwcPathOrName] -- Root of the catalog or friendly name
  193. //
  194. // History: 07-May-92 AmyA Lifted from vquery.cxx
  195. // 22-May-92 AmyA Added TRY/CATCH
  196. // 02-Jun-92 KyleP Added UNC support.
  197. // 12-Jun-92 KyleP Lifted from citest.cxx
  198. // 29-Sep-94 KyleP Added ofs proxy support
  199. // 1-16-97 srikants Changed to return DocStore.
  200. //
  201. //----------------------------------------------------------------------------
  202. CClientDocStore * CCatArray::GetDocStore(
  203. WCHAR const * pwcPathOrName,
  204. BOOL fMustExist )
  205. {
  206. BOOL fPath = wcschr( pwcPathOrName, L':' ) ||
  207. wcschr( pwcPathOrName, L'\\' );
  208. return GetNamedDocStore( pwcPathOrName, fPath ? 0 : pwcPathOrName,
  209. FALSE, // read-only
  210. fMustExist );
  211. } //GetDocStore
  212. //+---------------------------------------------------------------------------
  213. //
  214. // Function: CatalogPathToName
  215. //
  216. // Synopsis: Enumerates catalogs looking for a named catalog whose
  217. // location matches the given path.
  218. //
  219. // Arguments: [pwcPath] -- Path to look for
  220. // [pwcName] -- Returns the catalog name
  221. //
  222. // Returns: S_OK if a match was found, S_FALSE otherwise.
  223. //
  224. // History: 22-Jun-98 dlee created
  225. //
  226. //----------------------------------------------------------------------------
  227. SCODE CatalogPathToName(
  228. WCHAR const * pwcPath,
  229. WCHAR * pwcName )
  230. {
  231. BOOL fFound = FALSE;
  232. HKEY hKey;
  233. if ( ERROR_SUCCESS == RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  234. wcsRegCatalogsSubKey,
  235. 0,
  236. KEY_QUERY_VALUE |
  237. KEY_ENUMERATE_SUB_KEYS,
  238. &hKey ) )
  239. {
  240. SRegKey xKey( hKey );
  241. DWORD iSubKey = 0;
  242. do
  243. {
  244. FILETIME ft;
  245. WCHAR awcName[MAX_PATH];
  246. DWORD cwcName = sizeof awcName / sizeof WCHAR;
  247. LONG err = RegEnumKeyEx( hKey,
  248. iSubKey,
  249. awcName,
  250. &cwcName,
  251. 0, 0, 0, &ft );
  252. // either error or end of enumeration
  253. if ( ERROR_SUCCESS != err )
  254. break;
  255. iSubKey++;
  256. HKEY hCatName;
  257. if ( ERROR_SUCCESS == RegOpenKeyEx( hKey,
  258. awcName,
  259. 0,
  260. KEY_QUERY_VALUE,
  261. &hCatName ) )
  262. {
  263. SRegKey xCatNameKey( hCatName );
  264. // Check if the catalog is inactive and can be ignored
  265. WCHAR awcKey[MAX_PATH];
  266. wcscpy( awcKey, wcsRegJustCatalogsSubKey );
  267. wcscat( awcKey, L"\\" );
  268. wcscat( awcKey, awcName );
  269. CRegAccess reg( RTL_REGISTRY_CONTROL, awcKey );
  270. BOOL fInactive = reg.Read( wcsCatalogInactive,
  271. CI_CATALOG_INACTIVE_DEFAULT );
  272. if ( !fInactive )
  273. {
  274. WCHAR awcPath[MAX_PATH];
  275. DWORD cbPath = sizeof awcPath;
  276. if ( ERROR_SUCCESS == RegQueryValueEx( hCatName,
  277. wcsCatalogLocation,
  278. 0,
  279. 0,
  280. (BYTE *)awcPath,
  281. &cbPath ) )
  282. {
  283. int cwc = wcslen( awcPath ) - 1;
  284. if ( ( cwc >= 0 ) && ( L'\\' == awcPath[ cwc ] ) )
  285. awcPath[ cwc ] = 0;
  286. if ( !_wcsicmp( awcPath, pwcPath ) )
  287. {
  288. fFound = TRUE;
  289. wcscpy( pwcName, awcName );
  290. break;
  291. }
  292. }
  293. }
  294. }
  295. } while ( TRUE );
  296. }
  297. return fFound ? S_OK : S_FALSE;
  298. } //CatalogPathToName
  299. //+---------------------------------------------------------------------------
  300. //
  301. // Member: CCatArray::GetNamedDocStore, public
  302. //
  303. // Synopsis: Returns a PCatalog by either using an existing catalog or
  304. // creating a new one. Returns 0 if a catalog couldn't be
  305. // found or created.
  306. //
  307. // Arguments: [pwcPath] -- Root of the catalog
  308. // [pwcName] -- 0 or name of the catalog (optional param)
  309. // [fMustExist] -- If TRUE, the catalog must exist unless
  310. // it is the null catalog. If FALSE, the
  311. // catalog can be opened.
  312. //
  313. // History: 12-Oct-96 dlee created
  314. // 1-16-97 srikants Changed to return DocStore.
  315. // 16-Feb-2000 KLam Make sure path is good before using it
  316. //
  317. //----------------------------------------------------------------------------
  318. CClientDocStore * CCatArray::GetNamedDocStore(
  319. WCHAR const * pwcPath,
  320. WCHAR const * pwcName,
  321. BOOL fOpenForReadOnly,
  322. BOOL fMustExist )
  323. {
  324. WCHAR awcPath[ MAX_PATH ];
  325. Win4Assert ( 0 != pwcPath );
  326. unsigned len = wcslen( pwcPath );
  327. RtlCopyMemory( awcPath, pwcPath, ( len + 1 ) * sizeof WCHAR );
  328. // Get rid of trailing slash.
  329. Win4Assert ( len > 0 && len < MAX_PATH );
  330. if ( len > 0 && awcPath[ len - 1 ] == '\\' )
  331. awcPath[ len - 1 ] = 0;
  332. // make a complete path including \catalog.wci
  333. WCHAR awcCompletePath[ MAX_PATH ];
  334. wcscpy( awcCompletePath, awcPath );
  335. wcscat( awcCompletePath, CAT_DIR );
  336. BOOL fNullCatalog = !wcscmp( pwcPath, CINULLCATALOG );
  337. CLock lock( _mutex );
  338. // Look for previous use of catalog path or name.
  339. for ( unsigned i = 0; i < _aDocStores.Count(); i++ )
  340. {
  341. Win4Assert( 0 != _aDocStores[i] );
  342. const WCHAR *pwcCatName = _aDocStores[i]->GetName();
  343. CiCat * pCat = _aDocStores[i]->GetCiCat();
  344. const WCHAR *pwcCatPath = ( 0 == pCat ) ? 0 : pCat->GetCatDir();
  345. ciDebugOut(( DEB_ITRACE, "pwcPath: '%ws'\n", pwcPath ));
  346. ciDebugOut(( DEB_ITRACE, "pwcName: '%ws'\n", pwcName ));
  347. ciDebugOut(( DEB_ITRACE, "pwcCatName: '%ws'\n", pwcCatName ));
  348. ciDebugOut(( DEB_ITRACE, "pwcCatPath: '%ws'\n", pwcCatPath ));
  349. ciDebugOut(( DEB_ITRACE, "awcPath: '%ws'\n", awcPath ));
  350. ciDebugOut(( DEB_ITRACE, "awcCompletePath: '%ws'\n", awcCompletePath ));
  351. if ( ( fNullCatalog && ( 0 == pwcCatName ) ) ||
  352. ( ( 0 != pwcCatPath ) &&
  353. ( 0 == _wcsicmp( awcCompletePath, pwcCatPath ) ) ) ||
  354. ( ( ( 0 != pwcCatName ) &&
  355. ( 0 != pwcName ) &&
  356. ( 0 == _wcsicmp( pwcName, pwcCatName ) ) ) ) )
  357. return _aDocStores[i];
  358. }
  359. //
  360. // We will let the special case of NullCatalog percolate through
  361. // so we can create it only if the registry entry IsCatalogActive
  362. // says we should activate it.
  363. //
  364. if ( fMustExist && !fNullCatalog)
  365. return 0;
  366. // Try to fault the catalog in by name or path
  367. WCHAR awcName[ MAX_PATH ];
  368. if ( !fMustExist )
  369. {
  370. // Can we fault-in a named catalog?
  371. if ( L':' != awcPath[1] )
  372. {
  373. HKEY hCatName;
  374. WCHAR awcCat[ MAX_PATH ];
  375. wcscpy( awcCat, wcsRegCatalogsSubKey );
  376. wcscat( awcCat, L"\\" );
  377. wcscat( awcCat, pwcName );
  378. ciDebugOut(( DEB_ITRACE, "attempting to fault-in %ws\n", awcCat ));
  379. if ( ERROR_SUCCESS != RegOpenKeyEx( HKEY_LOCAL_MACHINE,
  380. awcCat,
  381. 0,
  382. KEY_QUERY_VALUE,
  383. &hCatName ) )
  384. return 0;
  385. SRegKey xCatName( hCatName );
  386. DWORD cbPath = sizeof awcPath;
  387. if ( ERROR_SUCCESS != RegQueryValueEx( hCatName,
  388. wcsCatalogLocation,
  389. 0,
  390. 0,
  391. (BYTE *)awcPath,
  392. &cbPath ) )
  393. return 0;
  394. // Trim trailing backslash
  395. int cwc = wcslen( awcPath ) - 1;
  396. if ( ( cwc >= 0 ) && ( L'\\' == awcPath[ cwc ] ) )
  397. awcPath[ cwc ] = 0;
  398. }
  399. else if ( ( 0 == pwcName ) || ( L':' == pwcName[1] ) )
  400. {
  401. // no name, just a path in both fields -- inverse lookup
  402. if ( S_FALSE == CatalogPathToName( awcPath, awcName ) )
  403. return 0;
  404. pwcName = awcName;
  405. }
  406. }
  407. // Catalog name instead of a path? If so, fail the lookup since
  408. // catalogs can only be really opened by path.
  409. if ( L':' != awcPath[1] )
  410. return 0;
  411. TRY
  412. {
  413. BOOL fInactive = FALSE;
  414. // We want the null catalog's registry entry to be looked up using
  415. // friendly name.
  416. WCHAR const *pwcCatName = fNullCatalog ? pwcPath : pwcName;
  417. // Check if the catalog is marked as inactive. Don't do this
  418. // in the constructor of CiCat -- it would be after a few
  419. // threads are created and lots of activity has started.
  420. if ( 0 != pwcCatName )
  421. {
  422. WCHAR awcKey[MAX_PATH];
  423. wcscpy( awcKey, wcsRegJustCatalogsSubKey );
  424. wcscat( awcKey, L"\\" );
  425. wcscat( awcKey, pwcCatName );
  426. CRegAccess reg( RTL_REGISTRY_CONTROL, awcKey );
  427. fInactive = reg.Read( wcsCatalogInactive,
  428. CI_CATALOG_INACTIVE_DEFAULT );
  429. }
  430. if ( !fInactive )
  431. {
  432. CImpersonateSystem impersonate;
  433. // Have we reached the maximum # of docstores?
  434. if ( _aDocStores.Count() >= GetMaxCatalogs() )
  435. {
  436. ciDebugOut(( DEB_WARN, "can't open %ws, out of catalogs!\n", pwcName ));
  437. TRY
  438. {
  439. CEventLog eventLog( 0, wcsCiEventSource );
  440. CEventItem item( EVENTLOG_WARNING_TYPE,
  441. CI_SERVICE_CATEGORY,
  442. MSG_CI_TOO_MANY_CATALOGS,
  443. 1 );
  444. item.AddArg( awcPath );
  445. eventLog.ReportEvent( item );
  446. }
  447. CATCH( CException, e )
  448. {
  449. // if we can't log the event, ignore
  450. }
  451. END_CATCH
  452. return 0; //Expensive, but who cares?
  453. }
  454. XPtr<CClientDocStore> xDocStore;
  455. if (fNullCatalog)
  456. xDocStore.Set( new CClientDocStore() );
  457. else
  458. xDocStore.Set( new CClientDocStore( awcPath,
  459. fOpenForReadOnly,
  460. *_pDrvNotifArray,
  461. pwcName ) );
  462. _aDocStores.Add( xDocStore.GetPointer(), _aDocStores.Count() );
  463. xDocStore.Acquire();
  464. }
  465. }
  466. CATCH( CException, e )
  467. {
  468. // ignore catalogs that can't be opened
  469. }
  470. END_CATCH
  471. if ( i < _aDocStores.Count() )
  472. return _aDocStores[i];
  473. else
  474. return 0;
  475. } //GetNamedDocStore
  476. //+---------------------------------------------------------------------------
  477. //
  478. // Member: CCatArray::GetOne, public
  479. //
  480. // Synopsis: Returns a PCatalog by either using an existing catalog or
  481. // creating a new one. Returns 0 if a catalog couldn't be
  482. // found or created.
  483. //
  484. // Arguments: [pwcPathOrName] -- Root of the catalog or friendly name
  485. //
  486. // History: 07-May-92 AmyA Lifted from vquery.cxx
  487. // 22-May-92 AmyA Added TRY/CATCH
  488. // 02-Jun-92 KyleP Added UNC support.
  489. // 12-Jun-92 KyleP Lifted from citest.cxx
  490. // 29-Sep-94 KyleP Added ofs proxy support
  491. //
  492. //----------------------------------------------------------------------------
  493. PCatalog * CCatArray::GetOne ( WCHAR const * pwcPathOrName )
  494. {
  495. CClientDocStore * pDocStore = GetDocStore( pwcPathOrName );
  496. return pDocStore ? pDocStore->GetCiCat() : 0;
  497. } //GetOne
  498. //+---------------------------------------------------------------------------
  499. //
  500. // Member: CCatArray::GetNamedOne, public
  501. //
  502. // Synopsis: Returns a PCatalog by either using an existing catalog or
  503. // creating a new one. Returns 0 if a catalog couldn't be
  504. // found or created.
  505. //
  506. // Arguments: [pwcPath] -- Root of the catalog
  507. // [pwcName] -- 0 or name of the catalog (optional param)
  508. //
  509. // History: 12-Oct-96 dlee created
  510. //
  511. //----------------------------------------------------------------------------
  512. PCatalog * CCatArray::GetNamedOne(
  513. WCHAR const * pwcPath,
  514. WCHAR const * pwcName,
  515. BOOL fOpenForReadOnly,
  516. BOOL fNoQuery )
  517. {
  518. CClientDocStore * pDocStore = GetNamedDocStore( pwcPath, pwcName, fOpenForReadOnly );
  519. if ( pDocStore )
  520. {
  521. if ( fNoQuery )
  522. pDocStore->SetNoQuery();
  523. else
  524. pDocStore->UnSetNoQuery();
  525. }
  526. return pDocStore ? pDocStore->GetCiCat() : 0;
  527. } //GetNamedOne
  528. //+-------------------------------------------------------------------------
  529. //
  530. // Member: AddStoppedCat, public
  531. //
  532. // Synopsis: Add an item of COldCatState into the _aStopCatalogs array
  533. //
  534. // Arguments: [dwOldState] -- Old state of a docstore
  535. // [wcsCatName] -- Catalog name of the docstore
  536. // [wcVol] -- Letter of the volume on which the catalog resides
  537. //
  538. // History: 07-July-98 KitmanH Created
  539. // 10-July-98 KitmanH Don't add an item with same CatName
  540. // more than once
  541. // 23-July-98 KitmanH Add volume letter on which the catalog
  542. // resides
  543. //
  544. //--------------------------------------------------------------------------
  545. void CCatArray::AddStoppedCat( DWORD dwOldState,
  546. WCHAR const * wcsCatName,
  547. WCHAR wcVol )
  548. {
  549. XPtrST<COldCatState> xOldState( new COldCatState( dwOldState,
  550. wcsCatName,
  551. wcVol) );
  552. CLock lockx( _mutex );
  553. _aStoppedCatalogs.Add( xOldState.GetPointer(), _aStoppedCatalogs.Count() );
  554. xOldState.Acquire();
  555. } //AddStoppedCat
  556. //+-------------------------------------------------------------------------
  557. //
  558. // Member: CCatArray::LokFindCat, private
  559. //
  560. // Synopsis: returns the index of the catalog in the _aStoppedcatalogs
  561. // Array
  562. //
  563. // Arguments: [wcsCatName] -- name of the catalog
  564. //
  565. // History: 23-July-98 KitmanH Created
  566. //
  567. //--------------------------------------------------------------------------
  568. DWORD CCatArray::FindCat( WCHAR const * wcsCatName )
  569. {
  570. Win4Assert( _mutex.IsHeld() );
  571. for ( unsigned i = 0; i < _aStoppedCatalogs.Count(); i++ )
  572. {
  573. COldCatState * pOldState = _aStoppedCatalogs.Get(i);
  574. if ( !(_wcsicmp( pOldState->GetCatName(), wcsCatName ) ) )
  575. return i;
  576. }
  577. return -1;
  578. } //FindCat
  579. //+-------------------------------------------------------------------------
  580. //
  581. // Member: CCatArray::GetOldState, public
  582. //
  583. // Synopsis: returns the old state of a catalog before the volume was locked
  584. //
  585. // Arguments: [wcsCatName] -- catalog name
  586. //
  587. // Returns: old state of a catalog
  588. //
  589. // History: 07-July-98 KitmanH Created
  590. //
  591. //--------------------------------------------------------------------------
  592. DWORD CCatArray::GetOldState( WCHAR const * wcsCatName )
  593. {
  594. CLock lockx( _mutex );
  595. DWORD i = FindCat(wcsCatName);
  596. if ( -1 != i )
  597. return (_aStoppedCatalogs.Get(i)->GetOldState() );
  598. else
  599. return -1;
  600. } //GetOldState
  601. //+-------------------------------------------------------------------------
  602. //
  603. // Member: CCatArray::RmFromStopArray, public
  604. //
  605. // Synopsis: remove the catalog from the stop array
  606. //
  607. // Arguments: [wcsCatName] -- name of the catalog
  608. //
  609. // History: 05-May-98 KitmanH Created
  610. //
  611. //--------------------------------------------------------------------------
  612. void CCatArray::RmFromStopArray( WCHAR const * wcsCatName )
  613. {
  614. CLock lockx( _mutex );
  615. DWORD i = FindCat( wcsCatName );
  616. if ( -1 != i )
  617. {
  618. delete _aStoppedCatalogs.Get(i);
  619. _aStoppedCatalogs.Remove(i);
  620. ciDebugOut(( DEB_ITRACE, "Catalog %ws is deleted from Array\n",
  621. wcsCatName ));
  622. }
  623. } //RmFromStopArray
  624. //+-------------------------------------------------------------------------
  625. //
  626. // Member: CCatArray::IsCatStopped, public
  627. //
  628. // Synopsis: check if the catalog has been stopped
  629. //
  630. // Arguments: [wcsCatName] -- name of the catalog
  631. //
  632. // History: 05-May-98 KitmanH Created
  633. //
  634. //--------------------------------------------------------------------------
  635. BOOL CCatArray::IsCatStopped( WCHAR const * wcsCatName )
  636. {
  637. CLock lockx( _mutex );
  638. DWORD i = FindCat( wcsCatName );
  639. if ( -1 != i )
  640. {
  641. ciDebugOut(( DEB_ITRACE, "Catalog %ws is Stopped\n", wcsCatName ));
  642. return TRUE;
  643. }
  644. else
  645. return FALSE;
  646. } //IsCatStopped
  647. //+-------------------------------------------------------------------------
  648. //
  649. // Member: ClearStopArray, public
  650. //
  651. // Synopsis: clear the contents in the _aStoppedCatalogs array
  652. //
  653. // History: 05-May-98 KitmanH Created
  654. // 08-July-98 KitmanH ReWrited
  655. //
  656. // Note: _aStoppedCatalogs now stores the old state with the cat name
  657. //
  658. //--------------------------------------------------------------------------
  659. void CCatArray::ClearStopArray()
  660. {
  661. CLock lockx( _mutex );
  662. for ( unsigned i = 0; i < _aStoppedCatalogs.Count(); i++ )
  663. {
  664. ciDebugOut(( DEB_ITRACE, "ClearStopArray: i is %d\n", i ));
  665. COldCatState * pOldState = _aStoppedCatalogs.Get(i);
  666. delete pOldState;
  667. }
  668. _aStoppedCatalogs.Clear();
  669. } //ClearStopArray
  670. //+-------------------------------------------------------------------------
  671. //
  672. // Member: CCatArray::IncStopCount, public
  673. //
  674. // Synopsis: Increment the _cStopCount and set the appropriate element
  675. // in the volume array
  676. //
  677. // Arguments: [wcsCatName] -- name of the catalog
  678. // [wcVol] -- volume letter
  679. //
  680. // History: 24-Aug-98 KitmanH Created
  681. //
  682. //--------------------------------------------------------------------------
  683. BOOL CCatArray::IncStopCount( WCHAR const * wcsCatName, WCHAR wcVol )
  684. {
  685. ciDebugOut(( DEB_ITRACE, "IncStopCount %wc\n", wcVol ));
  686. CLock lockx( _mutex );
  687. DWORD i = FindCat( wcsCatName );
  688. if ( -1 != i )
  689. {
  690. COldCatState * pOldState = _aStoppedCatalogs.Get(i);
  691. pOldState->IncStopCountAndSetVol( wcVol );
  692. return TRUE;
  693. }
  694. else
  695. return FALSE;
  696. } //IncStop
  697. //+-------------------------------------------------------------------------
  698. //
  699. // Funtion: DriveHasCatalog
  700. //
  701. // Synopsis: Checks if there is a catalog.wci directory on the root
  702. // of the volume.
  703. //
  704. // Arguments: [wc] -- the volume to check
  705. //
  706. // History: 16-Apr-99 dlee Created
  707. //
  708. //--------------------------------------------------------------------------
  709. BOOL DriveHasCatalog( WCHAR wc )
  710. {
  711. BOOL fCat = FALSE;
  712. WCHAR wszVolumePath[] = L"\\\\.\\a:";
  713. wszVolumePath[4] = wc;
  714. HANDLE hVolume = CreateFile( wszVolumePath,
  715. GENERIC_READ,
  716. FILE_SHARE_READ | FILE_SHARE_WRITE,
  717. NULL,
  718. OPEN_EXISTING,
  719. 0,
  720. NULL );
  721. if ( hVolume != INVALID_HANDLE_VALUE )
  722. {
  723. SWin32Handle xHandleVolume( hVolume );
  724. //
  725. // Is there media in the drive? This check avoids possible hard-error
  726. // popups prompting for media.
  727. //
  728. ULONG ulSequence;
  729. DWORD cb = sizeof(ULONG);
  730. BOOL fOk = DeviceIoControl( hVolume,
  731. IOCTL_STORAGE_CHECK_VERIFY,
  732. 0,
  733. 0,
  734. &ulSequence,
  735. sizeof(ulSequence),
  736. &cb,
  737. 0 );
  738. if ( fOk )
  739. {
  740. WCHAR awcCatDir[ MAX_PATH ];
  741. wcscpy( awcCatDir, L"c:\\" );
  742. wcscat( awcCatDir, CAT_DIR ); // catalog.wci
  743. awcCatDir[0] = wc;
  744. WIN32_FILE_ATTRIBUTE_DATA fData;
  745. if ( GetFileAttributesEx( awcCatDir, GetFileExInfoStandard, &fData ) )
  746. {
  747. // Is the catalog path a file or a directory?
  748. fCat = ( 0 != ( fData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) );
  749. }
  750. }
  751. }
  752. ciDebugOut(( DEB_ITRACE, "catalog on drive %wc? %s\n", wc, fCat ? "yes" : "no" ));
  753. return fCat;
  754. } //DriveHasCatalog
  755. //+---------------------------------------------------------------------------
  756. //
  757. // Member: CCatArray::TryToStartCatalogOnRemovableVol
  758. //
  759. // Synopsis: Attempts to open a catalog on the root of the volume.
  760. //
  761. // Arguments: [wcVol] -- Volume letter
  762. // [pRequestQ] -- Pointer to the RequestQueue
  763. //
  764. // History: 16-Apr-99 dlee Created
  765. //
  766. //----------------------------------------------------------------------------
  767. void CCatArray::TryToStartCatalogOnRemovableVol(
  768. WCHAR wcVol,
  769. CRequestQueue * pRequestQ )
  770. {
  771. Win4Assert( IsRemovableDrive( wcVol ) );
  772. if ( DriveHasCatalog( wcVol ) )
  773. {
  774. ciDebugOut(( DEB_ITRACE, "opening temporary catalog\n" ));
  775. // Make the registry entries
  776. CRemovableCatalog cat( wcVol );
  777. cat.Create();
  778. WCHAR awcName[MAX_PATH];
  779. cat.MakeCatalogName( awcName );
  780. CClientDocStore *p = GetDocStore( awcName, FALSE );
  781. }
  782. } //TryToStartCatalogOnRemovableVol
  783. //+---------------------------------------------------------------------------
  784. //
  785. // Member: CCatArray::StartCatalogsOnVol
  786. //
  787. // Synopsis: Restore all catalogs on the volume specified to its previous
  788. // state before the volume was locked.
  789. //
  790. // Arguments: [wcVol] -- Volume letter
  791. // [pRequestQ] -- Pointer to the RequestQueue
  792. //
  793. // History: 09-03-98 kitmanh Created
  794. //
  795. //----------------------------------------------------------------------------
  796. void CCatArray::StartCatalogsOnVol( WCHAR wcVol, CRequestQueue * pRequestQ )
  797. {
  798. ciDebugOut(( DEB_ITRACE, "StartCatalogsOnVol %wc\n", wcVol ));
  799. CLock lock( _mutex );
  800. SCWorkItem newItem;
  801. RtlZeroMemory( &newItem, sizeof newItem );
  802. BOOL fOpenedCatalogs = FALSE;
  803. for ( unsigned i = 0 ; i < _aStoppedCatalogs.Count(); i++ )
  804. {
  805. COldCatState * pOldCatState = _aStoppedCatalogs.Get(i);
  806. if ( pOldCatState->IsVolSet( wcVol ) )
  807. {
  808. if ( 1 == pOldCatState->GetStopCount() )
  809. {
  810. ciDebugOut(( DEB_ITRACE, "Catalog %ws : pOldCatState->GetStopCount() is == 1\n",
  811. pOldCatState->GetCatName() ));
  812. WCHAR const * awcName = pOldCatState->GetCatName();
  813. DWORD dwOldState = pOldCatState->GetOldState();
  814. if ( -1 != dwOldState )
  815. {
  816. ciDebugOut(( DEB_ITRACE, "dwOldState for %ws is %d\n", awcName, dwOldState ));
  817. fOpenedCatalogs = TRUE;
  818. if ( !( (CICAT_READONLY & dwOldState) ||
  819. (CICAT_STOPPED & dwOldState) ) )
  820. {
  821. if ( 0 != (CICAT_NO_QUERY & dwOldState) )
  822. {
  823. newItem.type = eNoQuery;
  824. newItem.fNoQueryRW = TRUE;
  825. }
  826. else if ( 0 != (CICAT_WRITABLE & dwOldState) )
  827. {
  828. newItem.type = eCatW;
  829. }
  830. else
  831. {
  832. Win4Assert( !"Undefined CICAT state" );
  833. }
  834. newItem.pDocStore = 0;
  835. pRequestQ->AddSCItem( &newItem, awcName );
  836. }
  837. else if ( 0 != (CICAT_READONLY & dwOldState) ) //readonly
  838. {
  839. newItem.type = eCatRO;
  840. newItem.pDocStore = 0;
  841. pRequestQ->AddSCItem( &newItem, awcName );
  842. }
  843. }
  844. }
  845. else
  846. {
  847. ciDebugOut(( DEB_ITRACE, "Catalog %ws: pOldCatState->GetStopCount() is %d\n",
  848. pOldCatState->GetCatName(), pOldCatState->GetStopCount() ));
  849. Win4Assert( 1 < pOldCatState->GetStopCount() );
  850. // Decreament stopcount
  851. pOldCatState->UnSetVol( wcVol );
  852. pOldCatState->DecStopCount();
  853. }
  854. }
  855. }
  856. //
  857. // If we didn't open any catalogs on the volume and it's a removable
  858. // volume with a catalog.wci directory in the root, make a temporary
  859. // entry in the registry and open the catalog read-only. Close the
  860. // catalog and remove the registry entries when the volume is ejected.
  861. //
  862. if ( !fOpenedCatalogs )
  863. {
  864. if ( IsRemovableDrive( wcVol ) && DriveHasCatalog( wcVol ) )
  865. {
  866. ciDebugOut(( DEB_ITRACE, "trying to opening temporary catalog\n" ));
  867. // Make the registry entries
  868. CRemovableCatalog cat( wcVol );
  869. cat.Create();
  870. // Tell the request queue to open the catalog
  871. newItem.type = eCatRO;
  872. newItem.pDocStore = 0;
  873. newItem.fNoQueryRW = FALSE;
  874. WCHAR awcName[MAX_PATH];
  875. cat.MakeCatalogName( awcName );
  876. newItem.StoppedCat = awcName;
  877. pRequestQ->AddSCItem( &newItem, awcName );
  878. }
  879. else
  880. {
  881. //
  882. // File a null work item so the request queue won't close
  883. // connections to all query clients.
  884. //
  885. newItem.type = eNoCatWork;
  886. pRequestQ->AddSCItem( &newItem, L"" );
  887. }
  888. }
  889. } //StartCatalogsOnVol