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.

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