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.

2262 lines
71 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1993 - 1998.
  5. //
  6. // File: cistore.cxx
  7. //
  8. // Contents: CI physical storage
  9. //
  10. // Classes: CiStorage
  11. //
  12. // History: 07-Jul-93 BartoszM Separated from physidx.cxx
  13. // 20-Nov-98 KLam Moved IsVolumeWriteProtected to CDriveInfo
  14. //
  15. //----------------------------------------------------------------------------
  16. #include <pch.cxx>
  17. #pragma hdrstop
  18. #include <mmstrm.hxx>
  19. #include <cidir.hxx>
  20. #include <cistore.hxx>
  21. #include <idxtab.hxx>
  22. #include <circstob.hxx>
  23. #include <fullpath.hxx>
  24. #include <enumstr.hxx>
  25. #include <pathpars.hxx>
  26. #include <propbkp.hxx>
  27. #include <ntopen.hxx>
  28. #define CAT_TESTLOG_HDR L"\\CiTstLog.000"
  29. #define CAT_TESTLOG_CP1 L"\\CiTstLog.001"
  30. #define CAT_TESTLOG_CP2 L"\\CiTstLog.002"
  31. #define CAT_IDXTABLE_HDR L"\\INDEX.000"
  32. #define CAT_IDXTABLE_CP1 L"\\INDEX.001"
  33. #define CAT_IDXTABLE_CP2 L"\\INDEX.002"
  34. #define MMLOG_PREFIX L"\\CiML"
  35. #define PROPSTORE_PREFIX L"\\CiPS"
  36. #define PROPSTORE1_PREFIX L"\\CiP1"
  37. #define PROPSTORE2_PREFIX L"\\CiP2"
  38. #define PRI_CHANGELOG_PREFIX L"\\CiCL"
  39. #define SEC_CHANGELOG_PREFIX L"\\CiSL"
  40. #define FRESHLOG_PREFIX L"\\CiFL"
  41. #define PIDTABLE_PREFIX L"\\CiPT"
  42. #define SCOPELIST_PREFIX L"\\CiSP"
  43. #define SECSTORE_PREFIX L"\\CiST"
  44. #define VSCOPELIST_PREFIX L"\\CiVP"
  45. // constant definitions moved here from cicat.cxx
  46. const WCHAR CAT_FILEID_MAP_FILE[] = L"\\cicat.fid"; // File id map table
  47. const WCHAR CAT_HASH_FILE[] = L"\\cicat.hsh"; // Strings table
  48. //+-------------------------------------------------------------------------
  49. //--------------------------------------------------------------------------
  50. SStorage::SStorage(PStorage * pObj ) : _pObj(pObj)
  51. {
  52. }
  53. //+-------------------------------------------------------------------------
  54. //--------------------------------------------------------------------------
  55. SStorage::~SStorage()
  56. {
  57. delete _pObj;
  58. }
  59. //+-------------------------------------------------------------------------
  60. //--------------------------------------------------------------------------
  61. PStorageObject::PStorageObject()
  62. {
  63. }
  64. //+-------------------------------------------------------------------------
  65. //--------------------------------------------------------------------------
  66. inline CiStorageObject& CI_OBJ ( PStorageObject& obj )
  67. {
  68. return( (CiStorageObject&)obj );
  69. }
  70. //+-------------------------------------------------------------------------
  71. //--------------------------------------------------------------------------
  72. CiStorageObject::CiStorageObject(WORKID objectId)
  73. : _objectId(objectId)
  74. {
  75. }
  76. //+-------------------------------------------------------------------------
  77. //--------------------------------------------------------------------------
  78. CiStorageObject::~CiStorageObject()
  79. {
  80. }
  81. //+-------------------------------------------------------------------------
  82. //--------------------------------------------------------------------------
  83. SStorageObject::SStorageObject ( PStorageObject* pObj )
  84. : _pObj(pObj)
  85. {
  86. }
  87. //+-------------------------------------------------------------------------
  88. //--------------------------------------------------------------------------
  89. SStorageObject::~SStorageObject()
  90. {
  91. delete _pObj;
  92. }
  93. //+-------------------------------------------------------------------------
  94. //
  95. // Function: DoesVolumeSupportShrinkFromFront
  96. //
  97. // Synopsis: Checks if the volume supports SFF, like NTFS5
  98. //
  99. // Arguments: [pwcPath] -- Path to physical storage.
  100. //
  101. // Returns: TRUE if the file system supports sparse files
  102. // FALSE otherwise
  103. //
  104. // History: 5-Nov-97 dlee Created
  105. //
  106. //--------------------------------------------------------------------------
  107. BOOL DoesVolumeSupportShrinkFromFront( WCHAR const * pwcPath )
  108. {
  109. SHandle xDir( CiNtOpen( pwcPath,
  110. FILE_READ_DATA | SYNCHRONIZE,
  111. FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
  112. FILE_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT ) );
  113. BYTE aInfo[ sizeof FILE_FS_ATTRIBUTE_INFORMATION +
  114. MAX_PATH * sizeof WCHAR ];
  115. FILE_FS_ATTRIBUTE_INFORMATION *pAttributeInfo = (FILE_FS_ATTRIBUTE_INFORMATION *) aInfo;
  116. IO_STATUS_BLOCK IoStatus;
  117. NTSTATUS Status = NtQueryVolumeInformationFile( xDir.Get(),
  118. &IoStatus,
  119. pAttributeInfo,
  120. sizeof aInfo,
  121. FileFsAttributeInformation );
  122. if ( FAILED( Status ) )
  123. {
  124. ciDebugOut(( DEB_WARN, "can't get volume info %#x on '%ws'\n",
  125. Status, pwcPath ));
  126. THROW( CException( Status ) );
  127. }
  128. return 0 != ( FILE_SUPPORTS_SPARSE_FILES &
  129. pAttributeInfo->FileSystemAttributes );
  130. } //DoesVolumeSupportShrinkFromFront
  131. //+-------------------------------------------------------------------------
  132. //
  133. // Member: IsDirectoryWritable
  134. //
  135. // Synopsis: Checks if the directory is writable by trying to open
  136. // file "cicat.hsh" for write
  137. //
  138. // Arguments: [pwcPath] -- Path to physical storage.
  139. //
  140. // Returns: TRUE if the directory is writable
  141. // FALSE otherwise
  142. //
  143. // History: 17-Mar-98 KitmanH Created
  144. // 10-Jun-98 KitmanH Changed to only retrive file
  145. // attributes
  146. //
  147. // Note: Assume writable, if the file does not exist, caller needs
  148. // to check if the volume is writable
  149. //
  150. //--------------------------------------------------------------------------
  151. BOOL IsDirectoryWritable( WCHAR const * pwcPath )
  152. {
  153. WCHAR wcsPath [ MAX_PATH ];
  154. wcscpy(wcsPath, pwcPath );
  155. wcscat(wcsPath, CAT_HASH_FILE );
  156. ciDebugOut(( DEB_ITRACE, "wcsPath == %ws\n", wcsPath ));
  157. DWORD dwFileAttribute = GetFileAttributes( wcsPath );
  158. if ( 0xFFFFFFFF != dwFileAttribute)
  159. {
  160. Win4Assert( !(FILE_ATTRIBUTE_DIRECTORY & dwFileAttribute) );
  161. ciDebugOut(( DEB_ITRACE, "dwFileAttribute is %#x\n", dwFileAttribute ));
  162. if ( dwFileAttribute & FILE_ATTRIBUTE_READONLY )
  163. return FALSE;
  164. else
  165. return TRUE;
  166. }
  167. else
  168. return TRUE;
  169. } //IsDirectoryWritable
  170. //+-------------------------------------------------------------------------
  171. //
  172. // Member: CiStorage::CiStorage, public
  173. //
  174. // Effects: Saves path to physical storage.
  175. //
  176. // Arguments: [wcsPath] -- Path to physical storage.
  177. // [adviseStatus] -- advise status object
  178. // [cMegToLeaveOnDisk] -- number of megabytes to leave on disk
  179. // [ulVer] -- version [default: CURRENT_VERSION_STAMP]
  180. // [fReadOnly] -- is storage read-only [default: FALSE]
  181. //
  182. // History: 07-Mar-92 KyleP Created
  183. // 16-Feb-98 KitmanH Added fReadOnly argument
  184. // 20-Mar-98 KitmanH _fReadOnly is determined by both
  185. // IsDirectoryWritable() and
  186. // IsVolumeWriteProtected()
  187. // 27-Oct-98 KLam Added disk space to leave
  188. // 20-Nov-98 KLam Initialize _driveInfo
  189. //
  190. // Note: _fIsReadOnly value is set according whether the registry
  191. // value "IsReadOnly" is set OR the volume is WriteProtected
  192. // OR the directory is not writable
  193. //--------------------------------------------------------------------------
  194. CiStorage::CiStorage( WCHAR const * wcsPath,
  195. ICiCAdviseStatus & adviseStatus,
  196. ULONG cMegToLeaveOnDisk,
  197. ULONG ulVer,
  198. BOOL fReadOnly )
  199. :_widFreshLog( widInvalid ),
  200. _adviseStatus( adviseStatus ),
  201. _fCorruptionReported(FALSE),
  202. _ulVer( ulVer ),
  203. _fSupportsShrinkFromFront( FALSE ),
  204. _fIsReadOnly( fReadOnly ),
  205. _fFavorReadAhead( FALSE ), // optimize for queries, not merges
  206. _cMegToLeaveOnDisk ( cMegToLeaveOnDisk ),
  207. _driveInfo ( wcsPath, cMegToLeaveOnDisk )
  208. {
  209. // The constructor is extended to take a version parameter
  210. // to set the FSCI versioning apart from framework CI versioning.
  211. // When the content framework version changes, all framework clients should reindex.
  212. // However, if only the FSCI version changes, only FSCI should reindex.
  213. // The default value for the property store is the content index version.
  214. //
  215. // ulVer defaults to the framework's version stamp, so when FSCI alone changes,
  216. // others don't have to change (unless they are using a feature of FSCI.)
  217. CIndexId iid( itFreshLog, partidFresh2 );
  218. _widFreshLog = iid;
  219. //
  220. // Squirrel away the path.
  221. //
  222. _xPath.Set( new WCHAR [ wcslen( wcsPath ) + 1 ] );
  223. wcscpy( _xPath.GetPointer(), wcsPath );
  224. ciDebugOut(( DEB_ITRACE, "Content index physical storage: %ws\n", wcsPath ));
  225. // Is the volume writable?
  226. BOOL fAbsolutelyUnWritable = ( _driveInfo.IsWriteProtected() ) || !( IsDirectoryWritable( wcsPath ) );
  227. ciDebugOut(( DEB_ITRACE, "CiStorage::CiStorage.. fAbsolutelyUnWritable == %d\n", fAbsolutelyUnWritable ));
  228. _fIsReadOnly = fReadOnly || fAbsolutelyUnWritable;
  229. //
  230. // Determine whether this volume supports shrink from front (ntfs5)
  231. //
  232. _fSupportsShrinkFromFront = DoesVolumeSupportShrinkFromFront( wcsPath );
  233. ciDebugOut(( DEB_ITRACE, "supports SFF: %d\n", _fSupportsShrinkFromFront ));
  234. } //CiStorage
  235. //+-------------------------------------------------------------------------
  236. //
  237. // Member: CiStorage::~CiStorage, public
  238. //
  239. // Synopsis: Destroys physical storage.
  240. //
  241. // Effects: Has *no* effect on open indexes.
  242. //
  243. // History: 07-Mar-92 KyleP Created
  244. //
  245. //--------------------------------------------------------------------------
  246. CiStorage::~CiStorage()
  247. {
  248. }
  249. const WCHAR CiStorage::_aHexDigit[] = L"0123456789ABCDEF";
  250. //+-------------------------------------------------------------------------
  251. //
  252. // Member: CiStorage::MakePath, private
  253. //
  254. // Synopsis: Creates an index, dir, hash or prop path.
  255. //
  256. // Arguments: [type] -- Index, dir, etc.
  257. // [iid] -- Index ID.
  258. // [wcsIndex] -- Output path
  259. //
  260. // History: 07-Mar-92 KyleP Created
  261. // 28-Dec-95 KyleP Collapsed four routines into one
  262. //
  263. //--------------------------------------------------------------------------
  264. void CiStorage::MakePath( CiStorage::EPathType type, WORKID iid, WCHAR * wcsIndex )
  265. {
  266. //
  267. // Construct a path for the new index.
  268. //
  269. wcscpy( wcsIndex, _xPath.GetPointer() );
  270. int len = wcslen( wcsIndex );
  271. wcsIndex[len++] = L'\\';
  272. for ( int i = 7; i >= 0; i-- )
  273. {
  274. wcsIndex[len++] = _aHexDigit[ (iid >> (4 * i)) & 0xF ];
  275. }
  276. wcsIndex[len] = 0;
  277. Win4Assert( len < MAX_PATH );
  278. switch ( type )
  279. {
  280. case CiStorage::eIndexPath:
  281. wcscat( wcsIndex, L".ci" );
  282. break;
  283. case CiStorage::eHashPath:
  284. wcscat( wcsIndex, L".hsh" );
  285. break;
  286. case CiStorage::ePrimaryPropPath:
  287. wcscat( wcsIndex, L".ps1" );
  288. break;
  289. case CiStorage::eSecondaryPropPath:
  290. wcscat( wcsIndex, L".ps2" );
  291. break;
  292. case CiStorage::eDirPath:
  293. wcscat( wcsIndex, L".dir" );
  294. break;
  295. }
  296. ciDebugOut(( DEB_ITRACE, "Physical index name: %ws\n", wcsIndex ));
  297. }
  298. PStorageObject* CiStorage::QueryObject( WORKID objectId )
  299. {
  300. return new CiStorageObject(objectId);
  301. }
  302. //+---------------------------------------------------------------------------
  303. //
  304. // Function: QueryIdxTableObject
  305. //
  306. // Synopsis: Returns an "Index Table" as a "Recoverable Storage Object"
  307. //
  308. // Returns: Pointer to a recoverable storage object allocated from the
  309. // heap. It is the responsibiity of the caller to destroy the
  310. // object.
  311. //
  312. // History: 2-25-94 srikants Created
  313. // 27-Oct-98 KLam Pass cMegToLeaveOnDisk to CiRcovStorageObj
  314. //
  315. //----------------------------------------------------------------------------
  316. PRcovStorageObj * CiStorage::QueryIdxTableObject()
  317. {
  318. WCHAR wcsHdr[MAX_PATH];
  319. WCHAR wcsCopy1[MAX_PATH];
  320. WCHAR wcsCopy2[MAX_PATH];
  321. MakeLogPath( CAT_IDXTABLE_HDR, wcsHdr );
  322. MakeLogPath( CAT_IDXTABLE_CP1, wcsCopy1 );
  323. MakeLogPath( CAT_IDXTABLE_CP2, wcsCopy2 );
  324. return new CiRcovStorageObj( *this,
  325. wcsHdr,
  326. wcsCopy1,
  327. wcsCopy2,
  328. _cMegToLeaveOnDisk,
  329. _fIsReadOnly);
  330. }
  331. //+-------------------------------------------------------------------------
  332. //--------------------------------------------------------------------------
  333. PIndexTable* CiStorage::QueryIndexTable ( CTransaction& xact )
  334. {
  335. return new CIndexTable ( *this, xact );
  336. }
  337. //+-------------------------------------------------------------------------
  338. //--------------------------------------------------------------------------
  339. PMmStream* CiStorage::QueryNewIndexStream( PStorageObject& obj,
  340. BOOL isSparse )
  341. {
  342. WCHAR wcsIndex [ MAX_PATH ];
  343. MakePath( eIndexPath, CI_OBJ(obj).ObjectId(), wcsIndex );
  344. XPtr<PMmStream> xStream;
  345. //
  346. // If it's a master index and the storage supports sparse streams, make
  347. // the stream sparse.
  348. //
  349. BOOL fSparse = ( isSparse && _fSupportsShrinkFromFront );
  350. ciDebugOut(( DEB_ITRACE, "opening new %s stream '%ws'\n",
  351. isSparse ? "master" : "shadow",
  352. wcsIndex ));
  353. if ( fSparse )
  354. {
  355. CLockingMmStream * pLockingMmStream = new CLockingMmStream( _cMegToLeaveOnDisk );
  356. xStream.Set( pLockingMmStream );
  357. pLockingMmStream->Open( wcsIndex,
  358. GENERIC_READ | GENERIC_WRITE,
  359. FILE_SHARE_READ|FILE_SHARE_WRITE,
  360. CREATE_NEW, // File cannot already exist.
  361. FILE_ATTRIBUTE_NORMAL,
  362. TRUE ); // sparse file
  363. }
  364. else
  365. {
  366. CMmStream * pMmStream = new CMmStream( _cMegToLeaveOnDisk, _fIsReadOnly );
  367. xStream.Set( pMmStream );
  368. pMmStream->Open( wcsIndex,
  369. GENERIC_READ | GENERIC_WRITE,
  370. FILE_SHARE_READ|FILE_SHARE_WRITE,
  371. CREATE_NEW, // File cannot already exist.
  372. FILE_ATTRIBUTE_NORMAL,
  373. FALSE ); // non-sparse file
  374. }
  375. return xStream.Acquire();
  376. }
  377. //+---------------------------------------------------------------------------
  378. //
  379. // Function: QueryExistingIndexStream
  380. //
  381. // Synopsis: Returns an "existing" index stream as a memory mapped
  382. // stream.
  383. //
  384. // Arguments: [obj] -- The storage object associated with the main
  385. // object containing the stream.
  386. // [mode] -- The open mode: read/write
  387. //
  388. // History: 4-20-94 srikants Added fWrite parameter.
  389. // 2-18-98 kitmanh Ignore fWrite for readOnly catalogs
  390. //
  391. // Notes: The fWrite parameter was used for supporting a restartable
  392. // master merge for which an existing index stream must be
  393. // opened for write access. Otherwise, all existing streams are
  394. // normally opened for read access only.
  395. //
  396. //----------------------------------------------------------------------------
  397. PMmStream* CiStorage::QueryExistingIndexStream ( PStorageObject& obj,
  398. PStorage::EOpenMode mode )
  399. {
  400. WCHAR wcsIndex [ MAX_PATH ];
  401. MakePath( eIndexPath, CI_OBJ(obj).ObjectId(), wcsIndex );
  402. BOOL fWrite = _fIsReadOnly ? FALSE : (PStorage::eOpenForWrite == mode);
  403. DWORD dwAccess = fWrite ? (GENERIC_READ | GENERIC_WRITE) : (GENERIC_READ);
  404. ciDebugOut(( DEB_ITRACE, "opening existing %s stream '%ws'\n",
  405. fWrite ? "write" : "read",
  406. wcsIndex ));
  407. XPtr<PMmStream> xStream;
  408. if ( fWrite )
  409. {
  410. CLockingMmStream * pLockingMmStream = new CLockingMmStream( _cMegToLeaveOnDisk );
  411. xStream.Set( pLockingMmStream );
  412. pLockingMmStream->Open( wcsIndex,
  413. dwAccess, // Access flags
  414. FILE_SHARE_READ | FILE_SHARE_WRITE,
  415. OPEN_EXISTING, // File must already exist.
  416. FILE_ATTRIBUTE_NORMAL,
  417. fWrite && _fSupportsShrinkFromFront ); // sparse
  418. }
  419. else
  420. {
  421. dwAccess = _fIsReadOnly ? GENERIC_READ : dwAccess;
  422. CMmStream * pMmStream = new CMmStream( _cMegToLeaveOnDisk, _fIsReadOnly );
  423. xStream.Set( pMmStream );
  424. pMmStream->Open( wcsIndex,
  425. dwAccess, // Access flags
  426. FILE_SHARE_READ | FILE_SHARE_WRITE,
  427. OPEN_EXISTING, // File must already exist.
  428. FILE_ATTRIBUTE_NORMAL,
  429. FALSE ); // sparse
  430. }
  431. return xStream.Acquire();
  432. }
  433. //+-------------------------------------------------------------------------
  434. //--------------------------------------------------------------------------
  435. PMmStream * CiStorage::DupExistingIndexStream( PStorageObject& obj,
  436. PMmStream & mmStream,
  437. EOpenMode mode )
  438. {
  439. return new CDupStream( (CLockingMmStream &) mmStream );
  440. }
  441. //+-------------------------------------------------------------------------
  442. //
  443. // Method: CiStorage::QueryNewHashStream
  444. //
  445. // Synopsis: Creates hash stream
  446. //
  447. // Arguments: [obj] -- Object holding stream
  448. //
  449. // Returns: Stream
  450. //
  451. // History: 17-Feb-1994 KyleP Created
  452. //
  453. //--------------------------------------------------------------------------
  454. PMmStream* CiStorage::QueryNewHashStream ( PStorageObject& obj )
  455. {
  456. WCHAR wcsIndex [ MAX_PATH ];
  457. MakePath( eHashPath, CI_OBJ(obj).ObjectId(), wcsIndex );
  458. XPtr<CMmStream> xStream( new CMmStream( _cMegToLeaveOnDisk, _fIsReadOnly ) );
  459. xStream->Open( wcsIndex,
  460. GENERIC_READ | GENERIC_WRITE, // Access flags
  461. 0, // Sharing flags
  462. CREATE_NEW, // File cannot already exist.
  463. FILE_ATTRIBUTE_NORMAL );
  464. return xStream.Acquire();
  465. }
  466. //+-------------------------------------------------------------------------
  467. //
  468. // Method: CiStorage::QueryExistingHashStream
  469. //
  470. // Synopsis: Opens existing hash stream
  471. //
  472. // Arguments: [obj] -- Object holding stream
  473. // [fWrite] -- Flag indicating if the stream must be opened
  474. // for write access; set to TRUE during a restarted
  475. // master merge.
  476. //
  477. // Returns: Stream
  478. //
  479. // History: 17-Feb-1994 KyleP Created
  480. //
  481. //--------------------------------------------------------------------------
  482. PMmStream* CiStorage::QueryExistingHashStream ( PStorageObject& obj,
  483. PStorage::EOpenMode mode )
  484. {
  485. WCHAR wcsIndex [ MAX_PATH ];
  486. MakePath( eHashPath, CI_OBJ(obj).ObjectId(), wcsIndex );
  487. XPtr<CMmStream> xStream( new CMmStream( _cMegToLeaveOnDisk, _fIsReadOnly ) );
  488. BOOL fWrite = PStorage::eOpenForWrite == mode;
  489. DWORD dwAccess = fWrite ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ;
  490. xStream->Open( wcsIndex,
  491. dwAccess, // Access flags
  492. FILE_SHARE_READ | FILE_SHARE_WRITE, // Sharing flags
  493. OPEN_EXISTING ); // File must already exist.
  494. return xStream.Acquire();
  495. }
  496. //+-------------------------------------------------------------------------
  497. //
  498. // Method: CiStorage::QueryNewPropStream
  499. //
  500. // Synopsis: Creates prop stream
  501. //
  502. // Arguments: [obj] -- Object holding stream
  503. //
  504. // Returns: Stream
  505. //
  506. // History: 17-Feb-1994 KyleP Created
  507. //
  508. //--------------------------------------------------------------------------
  509. PMmStream* CiStorage::QueryNewPropStream ( PStorageObject& obj, DWORD dwStoreLevel )
  510. {
  511. WCHAR wcsIndex [ MAX_PATH ];
  512. Win4Assert(PRIMARY_STORE == dwStoreLevel || SECONDARY_STORE == dwStoreLevel);
  513. MakePath( (PRIMARY_STORE == dwStoreLevel) ? ePrimaryPropPath : eSecondaryPropPath,
  514. CI_OBJ(obj).ObjectId(), wcsIndex );
  515. XPtr<CMmStream> xStream( new CMmStream( _cMegToLeaveOnDisk, _fIsReadOnly ) );
  516. xStream->Open ( wcsIndex,
  517. GENERIC_READ | GENERIC_WRITE, // Access flags
  518. FILE_SHARE_READ | FILE_SHARE_WRITE, // Sharing flags
  519. CREATE_NEW, // File cannot already exist.
  520. FILE_ATTRIBUTE_NORMAL );
  521. return xStream.Acquire();
  522. }
  523. //+-------------------------------------------------------------------------
  524. //
  525. // Method: CiStorage::QueryExistingPropStream
  526. //
  527. // Synopsis: Opens existing prop stream
  528. //
  529. // Arguments: [obj] -- Object holding stream
  530. // [fWrite] -- Flag indicating if the stream must be opened
  531. // for write access; set to TRUE during a restarted
  532. // master merge.
  533. //
  534. // Returns: Stream
  535. //
  536. // History: 17-Feb-1994 KyleP Created
  537. //
  538. //--------------------------------------------------------------------------
  539. PMmStream* CiStorage::QueryExistingPropStream ( PStorageObject& obj,
  540. PStorage::EOpenMode mode,
  541. DWORD dwStoreLevel )
  542. {
  543. WCHAR wcsIndex [ MAX_PATH ];
  544. Win4Assert(PRIMARY_STORE == dwStoreLevel || SECONDARY_STORE == dwStoreLevel);
  545. MakePath( (PRIMARY_STORE == dwStoreLevel) ? ePrimaryPropPath : eSecondaryPropPath,
  546. CI_OBJ(obj).ObjectId(), wcsIndex );
  547. XPtr<CMmStream> xStream( new CMmStream( _cMegToLeaveOnDisk, _fIsReadOnly ) );
  548. BOOL fWrite = PStorage::eOpenForWrite == mode;
  549. DWORD dwAccess = fWrite ? GENERIC_READ | GENERIC_WRITE : GENERIC_READ;
  550. xStream->Open ( wcsIndex,
  551. dwAccess, // Access flags
  552. FILE_SHARE_READ | FILE_SHARE_WRITE, // Sharing flags
  553. OPEN_EXISTING); // File must already exist.
  554. return xStream.Acquire();
  555. }
  556. //+-------------------------------------------------------------------------
  557. //
  558. // Method: CiStorage::QueryNewPSBkpStream, public
  559. //
  560. // Synopsis: Creates property store backup stream.
  561. //
  562. // Arguments: [obj] -- Object holding stream
  563. // [ulMaxPages] -- Max pages to backup
  564. //
  565. // Returns: Property store backup stream
  566. //
  567. // History: 30-May-97 KrishnaN Created
  568. // 29-Oct-98 KLam Pass _cMegToLeaveOnDisk to
  569. // CPropStoreBackupStream
  570. //
  571. // Notes: This method can be called either to create a backup file when a
  572. // catalog is being created for the first time or when a catalog is
  573. // being opened at CI startup. In the latter case it will be called
  574. // after the existing backup file is already used, if necessary. Once
  575. // the backup file is used, it can be run over.
  576. //
  577. //--------------------------------------------------------------------------
  578. CPropStoreBackupStream* CiStorage::QueryNewPSBkpStream( PStorageObject& obj,
  579. ULONG ulMaxPages,
  580. DWORD dwStoreLevel )
  581. {
  582. WCHAR wcsIndex [ MAX_PATH ];
  583. wcscpy(wcsIndex, _xPath.GetPointer() );
  584. Win4Assert(PRIMARY_STORE == dwStoreLevel || SECONDARY_STORE == dwStoreLevel);
  585. wcscat(wcsIndex, (PRIMARY_STORE == dwStoreLevel) ? PROP_BKP_FILE1 : PROP_BKP_FILE2);
  586. XPtr<CPropStoreBackupStream> xStream( new CPropStoreBackupStream( _cMegToLeaveOnDisk ) );
  587. xStream->OpenForBackup ( wcsIndex,
  588. FILE_SHARE_READ | FILE_SHARE_WRITE, // Sharing flags
  589. CREATE_ALWAYS, // File may already exist, but we'll run over it.
  590. ulMaxPages);
  591. Win4Assert(xStream.GetPointer());
  592. return xStream.Acquire();
  593. }
  594. //+-------------------------------------------------------------------------
  595. //
  596. // Method: CiStorage::OpenExistingPSBkpStreamForRecovery, public
  597. //
  598. // Synopsis: Opens existing property store backup stream for recovery.
  599. //
  600. // Arguments: [obj] -- Object holding stream
  601. //
  602. // Returns: Property store backup stream
  603. //
  604. // History: 30-May-97 KrishnaN Created
  605. // 29-Oct-98 KLam Pass _cMegToLeaveOnDisk to
  606. // CPropStoreBackupStream
  607. //
  608. //--------------------------------------------------------------------------
  609. CPropStoreBackupStream* CiStorage::OpenExistingPSBkpStreamForRecovery(PStorageObject& obj,
  610. DWORD dwStoreLevel)
  611. {
  612. WCHAR wcsIndex [ MAX_PATH ];
  613. wcscpy( wcsIndex, _xPath.GetPointer() );
  614. Win4Assert(PRIMARY_STORE == dwStoreLevel || SECONDARY_STORE == dwStoreLevel);
  615. wcscat(wcsIndex, (PRIMARY_STORE == dwStoreLevel) ? PROP_BKP_FILE1 : PROP_BKP_FILE2);
  616. XPtr<CPropStoreBackupStream> xStream( new CPropStoreBackupStream( _cMegToLeaveOnDisk ) );
  617. xStream->OpenForRecovery( wcsIndex, FILE_SHARE_READ); // Sharing flags
  618. Win4Assert(xStream.GetPointer());
  619. return xStream.Acquire();
  620. }
  621. //+-------------------------------------------------------------------------
  622. //--------------------------------------------------------------------------
  623. PDirectory* CiStorage::QueryNewDirectory( PStorageObject& obj )
  624. {
  625. return new CiDirectory( *this,
  626. CI_OBJ(obj).ObjectId(),
  627. PStorage::eCreate );
  628. }
  629. //+---------------------------------------------------------------------------
  630. //
  631. // Function: QueryExistingDirectory
  632. //
  633. // Synopsis: Returns an existing directory stream for an index.
  634. //
  635. // Arguments: [obj] -- Storage object.
  636. // [fWrite] -- Flag indicating if the stream must be opened
  637. // for write access or for read access.
  638. //
  639. // History: 4-20-94 srikants Added fWrite parameter
  640. //
  641. // Notes: fWrite parameter was added to support restartable master
  642. // merge.
  643. //
  644. //----------------------------------------------------------------------------
  645. PDirectory* CiStorage::QueryExistingDirectory( PStorageObject& obj,
  646. PStorage::EOpenMode mode )
  647. {
  648. return new CiDirectory ( *this, CI_OBJ(obj).ObjectId(), mode );
  649. }
  650. //+-------------------------------------------------------------------------
  651. //--------------------------------------------------------------------------
  652. PMmStream* CiStorage::QueryNewDirStream ( WORKID iid )
  653. {
  654. WCHAR wcsDir [ MAX_PATH ];
  655. MakePath( eDirPath, iid, wcsDir );
  656. XPtr<CMmStream> xStream( new CMmStream( _cMegToLeaveOnDisk, _fIsReadOnly ) );
  657. xStream->Open ( wcsDir,
  658. GENERIC_READ | GENERIC_WRITE, // Access flags
  659. FILE_SHARE_READ, // Sharing flags
  660. CREATE_NEW, // File cannot already exist.
  661. FILE_ATTRIBUTE_NORMAL );
  662. return xStream.Acquire();
  663. }
  664. //+-------------------------------------------------------------------------
  665. //--------------------------------------------------------------------------
  666. PMmStream* CiStorage::QueryExistingDirStream ( WORKID iid, BOOL fWrite )
  667. {
  668. WCHAR wcsDir [ MAX_PATH ];
  669. MakePath( eDirPath, iid, wcsDir );
  670. XPtr<CMmStream> xStream( new CMmStream( _cMegToLeaveOnDisk, _fIsReadOnly ) );
  671. if ( _fIsReadOnly )
  672. fWrite = FALSE;
  673. DWORD dwAccess = fWrite ? (GENERIC_READ | GENERIC_WRITE) : GENERIC_READ;
  674. xStream->Open( wcsDir,
  675. dwAccess, // Access flags
  676. FILE_SHARE_READ | FILE_SHARE_WRITE, // Sharing flags
  677. OPEN_EXISTING ); // File must already exist.
  678. return xStream.Acquire();
  679. }
  680. //+-------------------------------------------------------------------------
  681. //--------------------------------------------------------------------------
  682. BOOL CiStorage::RemoveObject( WORKID iid )
  683. {
  684. WCHAR wcsIndex [ MAX_PATH ];
  685. //
  686. // Delete index
  687. //
  688. MakePath( eIndexPath, iid, wcsIndex );
  689. BOOL fSuccess = DeleteFile( wcsIndex );
  690. //
  691. // and directory
  692. //
  693. MakePath( eDirPath, iid, wcsIndex );
  694. fSuccess = fSuccess && DeleteFile( wcsIndex );
  695. //
  696. // and maybe hash
  697. //
  698. MakePath( eHashPath, iid, wcsIndex );
  699. if ( !DeleteFile( wcsIndex ) )
  700. fSuccess = fSuccess && (GetLastError() == ERROR_FILE_NOT_FOUND);
  701. //
  702. // and maybe prop
  703. //
  704. MakePath( ePrimaryPropPath, iid, wcsIndex );
  705. if ( !DeleteFile( wcsIndex ) )
  706. fSuccess = fSuccess && (GetLastError() == ERROR_FILE_NOT_FOUND);
  707. MakePath( eSecondaryPropPath, iid, wcsIndex );
  708. if ( !DeleteFile( wcsIndex ) )
  709. fSuccess = fSuccess && (GetLastError() == ERROR_FILE_NOT_FOUND);
  710. return fSuccess;
  711. }
  712. //+-------------------------------------------------------------------------
  713. //
  714. // Member: CiStorage::MakeLogPath, private
  715. //
  716. // Synopsis: Create a fully qualified path for which to store the
  717. // persistent log.
  718. //
  719. // Arguments: [wcsName] -- name of logfile to append to path
  720. // [wcsPath] -- (out) resulting fully qualified name
  721. //
  722. // Notes: It is assumed that wcsPath is large enough to hold the
  723. // name + path
  724. //
  725. // History: 18-Nov-93 DwightKr Created
  726. //
  727. //--------------------------------------------------------------------------
  728. void CiStorage::MakeLogPath(WCHAR * wcsName, WCHAR * wcsPath)
  729. {
  730. wcscpy(wcsPath, _xPath.GetPointer());
  731. wcscat(wcsPath, wcsName);
  732. Win4Assert( wcslen(wcsPath) < MAX_PATH );
  733. }
  734. //+-------------------------------------------------------------------------
  735. //
  736. // Member: CiStorage::QueryFreshLog, public
  737. //
  738. // Synopsis: Builds a new persistent freshlog, using the specified name
  739. //
  740. // Arguments: [wcsName] -- name to use for new stream
  741. //
  742. // Returns: a new CPersStream * object
  743. //
  744. // History: 19-Nov-93 DwightKr Created
  745. // 27-Oct-98 KLam Pass _cMegToLeaveOnDisk to CiRcovStorageObj
  746. //
  747. //--------------------------------------------------------------------------
  748. PRcovStorageObj * CiStorage::QueryFreshLog(WORKID wid)
  749. {
  750. WCHAR wcsHdr[MAX_PATH];
  751. WCHAR wcsCopy1[MAX_PATH];
  752. WCHAR wcsCopy2[MAX_PATH];
  753. FormRcovObjNames( wid, FRESHLOG_PREFIX, wcsHdr, wcsCopy1, wcsCopy2 );
  754. return new CiRcovStorageObj( *this,
  755. wcsHdr,
  756. wcsCopy1,
  757. wcsCopy2,
  758. _cMegToLeaveOnDisk,
  759. _fIsReadOnly);
  760. }
  761. //+---------------------------------------------------------------------------
  762. //----------------------------------------------------------------------------
  763. BOOL CiStorage::RemoveFreshLog(WORKID wid)
  764. {
  765. WCHAR wcsHdr[MAX_PATH];
  766. WCHAR wcsCopy1[MAX_PATH];
  767. WCHAR wcsCopy2[MAX_PATH];
  768. FormRcovObjNames( wid, FRESHLOG_PREFIX, wcsHdr, wcsCopy1, wcsCopy2 );
  769. DeleteFile( wcsHdr );
  770. DeleteFile( wcsCopy1 );
  771. DeleteFile( wcsCopy2 );
  772. return(TRUE);
  773. }
  774. //+---------------------------------------------------------------------------
  775. //
  776. // Function: QueryChangeLog
  777. //
  778. // Synopsis: Creates a recoverable storage object for testing.
  779. //
  780. // History: 2-08-94 DwightKr Created
  781. // 4-20-94 SrikantS Modified to use the common
  782. // FormRcovObjNames method.
  783. // 27-Oct-98 KLam Pass _cMegToLeaveOnDisk to CiRcovStorageObj
  784. //
  785. // Notes: For down level storage, the WID is really the partition ID.
  786. //
  787. //----------------------------------------------------------------------------
  788. PRcovStorageObj * CiStorage::QueryChangeLog( WORKID wid, EChangeLogType type )
  789. {
  790. WCHAR wcsHdr[MAX_PATH];
  791. WCHAR wcsCopy1[MAX_PATH];
  792. WCHAR wcsCopy2[MAX_PATH];
  793. if ( ePrimChangeLog == type )
  794. {
  795. FormRcovObjNames( wid, PRI_CHANGELOG_PREFIX, wcsHdr, wcsCopy1, wcsCopy2 );
  796. }
  797. else
  798. {
  799. FormRcovObjNames( wid, SEC_CHANGELOG_PREFIX, wcsHdr, wcsCopy1, wcsCopy2 );
  800. }
  801. return new CiRcovStorageObj( *this,
  802. wcsHdr,
  803. wcsCopy1,
  804. wcsCopy2,
  805. _cMegToLeaveOnDisk,
  806. _fIsReadOnly );
  807. }
  808. //+-------------------------------------------------------------------------
  809. //--------------------------------------------------------------------------
  810. PRcovStorageObj * CiStorage::QueryRecoverableLog(WORKID wid)
  811. {
  812. Win4Assert(!"QueryRecoverableLog() not supported in class CiStorage");
  813. PRcovStorageObj *a = 0;
  814. return a;
  815. }
  816. //+-------------------------------------------------------------------------
  817. //
  818. // Member: CiStorage::QueryPidLookupTable, public
  819. //
  820. // Synopsis: Builds a new persistent storage object for PID mapping.
  821. //
  822. // Arguments: [wid] -- WorkId of the object. For downlevel, only
  823. // the upper 4 bytes are used as the "partition id" that the
  824. // object belongs to. It is assumed that the upper 4 bytes of
  825. // the wid contain the partition id.
  826. //
  827. // Returns: a new CPersStream * object
  828. //
  829. // History: 05 Jan 1996 Alanw Created
  830. // 27 Oct 1998 KLam Pass _cMegToLeaveOnDisk to CiRcovStorageObj
  831. //
  832. //--------------------------------------------------------------------------
  833. PRcovStorageObj * CiStorage::QueryPidLookupTable(WORKID wid)
  834. {
  835. WCHAR wcsHdr[MAX_PATH];
  836. WCHAR wcsCopy1[MAX_PATH];
  837. WCHAR wcsCopy2[MAX_PATH];
  838. FormRcovObjNames( wid, PIDTABLE_PREFIX, wcsHdr, wcsCopy1, wcsCopy2 );
  839. return new CiRcovStorageObj( *this,
  840. wcsHdr,
  841. wcsCopy1,
  842. wcsCopy2,
  843. _cMegToLeaveOnDisk,
  844. _fIsReadOnly );
  845. }
  846. //+-------------------------------------------------------------------------
  847. //
  848. // Member: CiStorage::QuerySdidLookupTable, public
  849. //
  850. // Synopsis: Builds a new persistent storage object for SDID mapping.
  851. //
  852. // Arguments: [wid] -- WorkId of the object. For downlevel, only
  853. // the upper 4 bytes are used as the "partition id" that the
  854. // object belongs to. It is assumed that the upper 4 bytes of
  855. // the wid contain the partition id.
  856. //
  857. // Returns: a new CPersStream * object
  858. //
  859. // History: 29 Jan 1996 Alanw Created
  860. // 27 Oct 1998 KLam Pass _cMegToLeaveOnDisk to CiRcovStorageObj
  861. //
  862. //--------------------------------------------------------------------------
  863. PRcovStorageObj * CiStorage::QuerySdidLookupTable(WORKID wid)
  864. {
  865. WCHAR wcsHdr[MAX_PATH];
  866. WCHAR wcsCopy1[MAX_PATH];
  867. WCHAR wcsCopy2[MAX_PATH];
  868. FormRcovObjNames( wid, SECSTORE_PREFIX, wcsHdr, wcsCopy1, wcsCopy2 );
  869. return new CiRcovStorageObj( *this,
  870. wcsHdr,
  871. wcsCopy1,
  872. wcsCopy2,
  873. _cMegToLeaveOnDisk,
  874. _fIsReadOnly );
  875. }
  876. //+---------------------------------------------------------------------------
  877. //
  878. // Function: FormRcovObjNames
  879. //
  880. // Synopsis: Forms the down-level names for the three streams that make up
  881. // a recoverable object. This method can be used for creating
  882. // names for objects that exist on a "per partition" basis.
  883. //
  884. // Arguments: [wid] -- WorkId of the object. For downlevel, only
  885. // the upper 4 bytes are used as the "partition id" that the
  886. // object belongs to. It is assumed that the upper 4 bytes of
  887. // the wid contain the partition id.
  888. // [wcsPrefix] -- A 5 character prefix for the object name.
  889. // Must begin with a "\\". (That will leave 4 chars for name.)
  890. // [wcsHdr] -- On output will contain the file name for the
  891. // atomic header.
  892. // [wcsCopy1] -- On output will contain the name of the first
  893. // copy.
  894. // [wcsCopy2] -- On output, will contain the name of the
  895. // second copy.
  896. //
  897. // History: 4-20-94 srikants Created
  898. //
  899. // Notes:
  900. //
  901. //----------------------------------------------------------------------------
  902. void CiStorage::FormRcovObjNames( WORKID wid, WCHAR * wcsPrefix,
  903. WCHAR * wcsHdr, WCHAR * wcsCopy1,
  904. WCHAR * wcsCopy2 )
  905. {
  906. Win4Assert( wcslen(wcsPrefix) == 5 ); // extra char is for "\\"
  907. WCHAR wcsTemp[_MAX_FNAME+1];
  908. CIndexId iid(wid);
  909. Win4Assert( iid.PartId() <= 0x0000FFFF );
  910. swprintf(wcsTemp, L"%5s%4.4x.000", wcsPrefix, iid.PartId() );
  911. MakeLogPath( wcsTemp, wcsHdr );
  912. swprintf(wcsTemp, L"%5s%4.4x.001", wcsPrefix, iid.PartId() );
  913. MakeLogPath( wcsTemp, wcsCopy1 );
  914. swprintf(wcsTemp, L"%5s%4.4x.002", wcsPrefix, iid.PartId() );
  915. MakeLogPath( wcsTemp, wcsCopy2 );
  916. }
  917. //+---------------------------------------------------------------------------
  918. //
  919. // Function: QueryMMergeLog
  920. //
  921. // Synopsis: Returns a Master Merge Log object created on the heap.
  922. //
  923. // Arguments: [wid] -- WorkId of the master merge log. Only the upper
  924. // 4 bytes are used as the partition id.
  925. //
  926. // History: 4-20-94 srikants Created
  927. // 27-Oct-98 KLam Pass _cMegToLeaveOnDisk to CiRcovStorageObj
  928. //
  929. // Notes:
  930. //
  931. //----------------------------------------------------------------------------
  932. PRcovStorageObj * CiStorage::QueryMMergeLog( WORKID wid )
  933. {
  934. WCHAR wcsHdr[MAX_PATH];
  935. WCHAR wcsCopy1[MAX_PATH];
  936. WCHAR wcsCopy2[MAX_PATH];
  937. FormRcovObjNames( wid, MMLOG_PREFIX, wcsHdr, wcsCopy1, wcsCopy2 );
  938. return new CiRcovStorageObj( *this,
  939. wcsHdr,
  940. wcsCopy1,
  941. wcsCopy2,
  942. _cMegToLeaveOnDisk,
  943. _fIsReadOnly );
  944. }
  945. //+---------------------------------------------------------------------------
  946. //
  947. // Function: QueryPropStore
  948. //
  949. // Synopsis: Returns a property store table
  950. //
  951. // Arguments: [wid] -- WorkId of the property store table. Only the upper
  952. // 4 bytes are used as the partition id.
  953. //
  954. // History: 27-Dec-94 KyleP Created
  955. // 27-Oct-98 KLam Pass _cMegToLeaveOnDisk to CiRcovStorageObj
  956. //
  957. //----------------------------------------------------------------------------
  958. PRcovStorageObj * CiStorage::QueryPropStore( WORKID wid, DWORD dwStoreLevel )
  959. {
  960. WCHAR wcsHdr[MAX_PATH];
  961. WCHAR wcsCopy1[MAX_PATH];
  962. WCHAR wcsCopy2[MAX_PATH];
  963. Win4Assert(PRIMARY_STORE == dwStoreLevel || SECONDARY_STORE == dwStoreLevel);
  964. FormRcovObjNames( wid,
  965. (PRIMARY_STORE == dwStoreLevel) ? PROPSTORE1_PREFIX : PROPSTORE2_PREFIX,
  966. wcsHdr, wcsCopy1, wcsCopy2 );
  967. return new CiRcovStorageObj( *this,
  968. wcsHdr,
  969. wcsCopy1,
  970. wcsCopy2,
  971. _cMegToLeaveOnDisk,
  972. _fIsReadOnly );
  973. }
  974. //+---------------------------------------------------------------------------
  975. //
  976. // Member: CiStorage::RemovePropStore
  977. //
  978. // Synopsis: Removes the PropStore header files.
  979. //
  980. // Arguments: [wid] -- WorkId of the property store table. Only the upper
  981. // 4 bytes are used as the partition id.
  982. //
  983. // History: 3-26-97 srikants Created
  984. //
  985. //----------------------------------------------------------------------------
  986. void CiStorage::RemovePropStore( WORKID wid, DWORD dwStoreLevel )
  987. {
  988. WCHAR wcsHdr[MAX_PATH];
  989. WCHAR wcsCopy1[MAX_PATH];
  990. WCHAR wcsCopy2[MAX_PATH];
  991. Win4Assert(PRIMARY_STORE == dwStoreLevel || SECONDARY_STORE == dwStoreLevel);
  992. FormRcovObjNames( wid,
  993. (PRIMARY_STORE == dwStoreLevel) ? PROPSTORE1_PREFIX : PROPSTORE2_PREFIX,
  994. wcsHdr, wcsCopy1, wcsCopy2 );
  995. DeleteFile( wcsHdr );
  996. DeleteFile( wcsCopy1);
  997. DeleteFile( wcsCopy2 );
  998. }
  999. //+---------------------------------------------------------------------------
  1000. //
  1001. // Member: CiStorage::RemoveSecStore
  1002. //
  1003. // Synopsis: Removes the security store files.
  1004. //
  1005. // Arguments: [wid] -- Workid of the security store table.
  1006. //
  1007. // History: 7-14-97 srikants Created
  1008. //
  1009. //----------------------------------------------------------------------------
  1010. void CiStorage::RemoveSecStore( WORKID wid )
  1011. {
  1012. WCHAR wcsHdr[MAX_PATH];
  1013. WCHAR wcsCopy1[MAX_PATH];
  1014. WCHAR wcsCopy2[MAX_PATH];
  1015. FormRcovObjNames( wid, SECSTORE_PREFIX, wcsHdr, wcsCopy1, wcsCopy2 );
  1016. DeleteFile( wcsHdr );
  1017. DeleteFile( wcsCopy1);
  1018. DeleteFile( wcsCopy2 );
  1019. }
  1020. //+---------------------------------------------------------------------------
  1021. //
  1022. // Member: CiStorage::QueryScopeList
  1023. //
  1024. // Synopsis: Returns CI scopes list table
  1025. //
  1026. // Arguments: [wid] - Workid of the scopes list table.
  1027. //
  1028. // History: 1-19-96 srikants Created
  1029. // 27-Oct-98 KLam Pass _cMegToLeaveOnDisk to CiRcovStorageObj
  1030. //
  1031. // Notes:
  1032. //
  1033. //----------------------------------------------------------------------------
  1034. PRcovStorageObj * CiStorage::QueryScopeList( WORKID wid )
  1035. {
  1036. WCHAR wcsHdr[MAX_PATH];
  1037. WCHAR wcsCopy1[MAX_PATH];
  1038. WCHAR wcsCopy2[MAX_PATH];
  1039. FormRcovObjNames( wid, SCOPELIST_PREFIX, wcsHdr, wcsCopy1, wcsCopy2 );
  1040. return new CiRcovStorageObj( *this,
  1041. wcsHdr,
  1042. wcsCopy1,
  1043. wcsCopy2,
  1044. _cMegToLeaveOnDisk,
  1045. _fIsReadOnly );
  1046. }
  1047. //+---------------------------------------------------------------------------
  1048. //
  1049. // Member: CiStorage::QueryVirtualScopeList
  1050. //
  1051. // Synopsis: Returns CI virtual scopes list table
  1052. //
  1053. // Arguments: [wid] - Workid of the virtual scopes list table.
  1054. //
  1055. // History: 2-05-96 KyleP Created
  1056. // 27-Oct-98 KLam Pass _cMegToLeaveOnDisk to CiRcovStorageObj
  1057. //
  1058. //----------------------------------------------------------------------------
  1059. PRcovStorageObj * CiStorage::QueryVirtualScopeList( WORKID wid )
  1060. {
  1061. WCHAR wcsHdr[MAX_PATH];
  1062. WCHAR wcsCopy1[MAX_PATH];
  1063. WCHAR wcsCopy2[MAX_PATH];
  1064. FormRcovObjNames( wid, VSCOPELIST_PREFIX, wcsHdr, wcsCopy1, wcsCopy2 );
  1065. return new CiRcovStorageObj( *this,
  1066. wcsHdr,
  1067. wcsCopy1,
  1068. wcsCopy2,
  1069. _cMegToLeaveOnDisk,
  1070. _fIsReadOnly );
  1071. }
  1072. //+---------------------------------------------------------------------------
  1073. //
  1074. // Function: RemoveMMLog
  1075. //
  1076. // Synopsis: Deletes the specified master log object.
  1077. //
  1078. // Arguments: [wid] -- WorkId of the master merge log. Only the upper
  1079. // 4 bytes are used as the partition id.
  1080. //
  1081. // History: 4-20-94 srikants Created
  1082. //
  1083. //----------------------------------------------------------------------------
  1084. BOOL CiStorage::RemoveMMLog( WORKID wid )
  1085. {
  1086. WCHAR wcsHdr[MAX_PATH];
  1087. WCHAR wcsCopy1[MAX_PATH];
  1088. WCHAR wcsCopy2[MAX_PATH];
  1089. FormRcovObjNames( wid, MMLOG_PREFIX, wcsHdr, wcsCopy1, wcsCopy2 );
  1090. DeleteFile( wcsHdr );
  1091. DeleteFile( wcsCopy1 );
  1092. DeleteFile( wcsCopy2 );
  1093. return(TRUE);
  1094. }
  1095. //+---------------------------------------------------------------------------
  1096. //
  1097. // Function: QueryTestLog
  1098. //
  1099. // Synopsis: Creates a recoverable storage object for testing.
  1100. //
  1101. // History: 2-08-94 srikants Created
  1102. // 27-Oct-98 KLam Pass _cMegToLeaveOnDisk to CiRcovStorageObj
  1103. //
  1104. //----------------------------------------------------------------------------
  1105. PRcovStorageObj * CiStorage::QueryTestLog()
  1106. {
  1107. WCHAR wcsHdr[MAX_PATH];
  1108. WCHAR wcsCopy1[MAX_PATH];
  1109. WCHAR wcsCopy2[MAX_PATH];
  1110. MakeLogPath( CAT_TESTLOG_HDR, wcsHdr );
  1111. MakeLogPath( CAT_TESTLOG_CP1, wcsCopy1 );
  1112. MakeLogPath( CAT_TESTLOG_CP2, wcsCopy2 );
  1113. return new CiRcovStorageObj( *this,
  1114. wcsHdr,
  1115. wcsCopy1,
  1116. wcsCopy2,
  1117. _cMegToLeaveOnDisk,
  1118. _fIsReadOnly );
  1119. }
  1120. //+---------------------------------------------------------------------------
  1121. //
  1122. // Function: GetDiskSpace
  1123. //
  1124. // Synopsis: Returns the disk size & space remaining, in bytes
  1125. // Takes into consideration the space to leave on disk
  1126. //
  1127. // History: 31-Jul-94 DwightKr Created
  1128. // 27-Oct-98 KLam Compensates for DiskSpaceToLeave
  1129. // Forwards call to drive info
  1130. //
  1131. //----------------------------------------------------------------------------
  1132. void CiStorage::GetDiskSpace( __int64 & diskTotal,
  1133. __int64 & diskRemaining )
  1134. {
  1135. _driveInfo.GetDiskSpace ( diskTotal, diskRemaining );
  1136. }
  1137. //+---------------------------------------------------------------------------
  1138. //
  1139. // Member: CiStorage::ReportCorruptComponent, public
  1140. //
  1141. // Synopsis: Generates meaningful error message on storage corruption.
  1142. //
  1143. // Arguments: [pwszString] -- Error message
  1144. //
  1145. // History: 21-Jul-97 KyleP Move from header
  1146. //
  1147. //----------------------------------------------------------------------------
  1148. void CiStorage::ReportCorruptComponent( WCHAR const * pwszString )
  1149. {
  1150. if ( !_fCorruptionReported )
  1151. {
  1152. CFwCorruptionEvent event( GetVolumeName(), pwszString, _adviseStatus );
  1153. _fCorruptionReported = TRUE;
  1154. }
  1155. }
  1156. //+---------------------------------------------------------------------------
  1157. //
  1158. // Function: GetNewObjectIdForFreshLog
  1159. //
  1160. // Synopsis: Forms a new object id for the fresh log. It uses a pool of
  1161. // two ids and returns the one that is currently not in use.
  1162. //
  1163. // Returns: ObjectId for a new fresh log.
  1164. //
  1165. // History: 10-05-94 srikants Created
  1166. //
  1167. // Notes:
  1168. //
  1169. //----------------------------------------------------------------------------
  1170. WORKID CiStorage::GetNewObjectIdForFreshLog()
  1171. {
  1172. CIndexId iidCurr( _widFreshLog );
  1173. PARTITIONID partIdNew = partidFresh1 == iidCurr.PartId() ?
  1174. partidFresh2 : partidFresh1;
  1175. CIndexId iidNew( itFreshLog, partIdNew );
  1176. return( CreateObjectId( iidNew, PStorage::eRcovHdr ) );
  1177. }
  1178. //+---------------------------------------------------------------------------
  1179. //
  1180. // Function: SetSpecialItObjectId
  1181. //
  1182. // Synopsis: Sets the object id of the special index type.
  1183. //
  1184. // Arguments: [it] -- Index Type
  1185. // [wid] -- WorkId for this index type.
  1186. //
  1187. // History: 10-05-94 srikants Created
  1188. //
  1189. // Notes: As of now, only the itFreshLog is of interest to CiStorage.
  1190. //
  1191. //----------------------------------------------------------------------------
  1192. void CiStorage::SetSpecialItObjectId( IndexType it, WORKID wid )
  1193. {
  1194. switch ( it )
  1195. {
  1196. case itFreshLog:
  1197. #if CIDBG==1
  1198. CIndexId iid( wid );
  1199. Win4Assert( it == iid.PersId() );
  1200. Win4Assert( partidFresh1 == iid.PartId() ||
  1201. partidFresh2 == iid.PartId() );
  1202. #endif // CIDBG
  1203. _widFreshLog = wid;
  1204. break;
  1205. }
  1206. return;
  1207. }
  1208. //+---------------------------------------------------------------------------
  1209. //
  1210. // Function: GetSpecialItObjectId
  1211. //
  1212. // Synopsis: Returns the current object id of a special index type.
  1213. //
  1214. // Arguments: [it] -- Index Type
  1215. //
  1216. // History: 10-05-94 srikants Created
  1217. //
  1218. // Notes: As of now, only the itFreshLog is of interest.
  1219. //
  1220. //----------------------------------------------------------------------------
  1221. WORKID CiStorage::GetSpecialItObjectId( IndexType it ) const
  1222. {
  1223. switch ( it )
  1224. {
  1225. case itFreshLog:
  1226. return(_widFreshLog);
  1227. default:
  1228. return(0);
  1229. }
  1230. }
  1231. //+---------------------------------------------------------------------------
  1232. //
  1233. // Function: DeleteObject, public
  1234. //
  1235. // Synopsis: Deletes the file specified
  1236. //
  1237. // Arguments: [objectId] -- Object to delete
  1238. //
  1239. // History: Nov-16-94 DwightKr Added this header
  1240. //
  1241. //----------------------------------------------------------------------------
  1242. void CiStorage::DeleteObject( WORKID objectId )
  1243. {
  1244. RemoveObject( objectId );
  1245. }
  1246. //+---------------------------------------------------------------------------
  1247. //
  1248. // Function: EmptyIndexList, public
  1249. //
  1250. // Synopsis: Empties the index list
  1251. //
  1252. // History: Nov-16-94 DwightKr Created
  1253. //
  1254. //----------------------------------------------------------------------------
  1255. void CiStorage::EmptyIndexList()
  1256. {
  1257. WCHAR wcsHdr[MAX_PATH];
  1258. WCHAR wcsCopy1[MAX_PATH];
  1259. WCHAR wcsCopy2[MAX_PATH];
  1260. MakeLogPath( CAT_IDXTABLE_HDR, wcsHdr );
  1261. MakeLogPath( CAT_IDXTABLE_CP1, wcsCopy1 );
  1262. MakeLogPath( CAT_IDXTABLE_CP2, wcsCopy2 );
  1263. HANDLE hFile = CreateFile( wcsHdr, GENERIC_WRITE, 0,
  1264. NULL, TRUNCATE_EXISTING,
  1265. FILE_ATTRIBUTE_NORMAL,
  1266. NULL );
  1267. if ( INVALID_HANDLE_VALUE != hFile )
  1268. CloseHandle( hFile );
  1269. hFile = CreateFile( wcsCopy1, GENERIC_WRITE, 0,
  1270. NULL, TRUNCATE_EXISTING,
  1271. FILE_ATTRIBUTE_NORMAL,
  1272. NULL );
  1273. if ( INVALID_HANDLE_VALUE != hFile )
  1274. CloseHandle( hFile );
  1275. hFile = CreateFile( wcsCopy2, GENERIC_WRITE, 0,
  1276. NULL, TRUNCATE_EXISTING,
  1277. FILE_ATTRIBUTE_NORMAL,
  1278. NULL );
  1279. if ( INVALID_HANDLE_VALUE != hFile )
  1280. CloseHandle( hFile );
  1281. }
  1282. //+---------------------------------------------------------------------------
  1283. //
  1284. // Member: CiStorage::ListPropStoreFileNames, public
  1285. //
  1286. // Synopsis: Lists property store related files in the ci directory.
  1287. //
  1288. // Arguments: [enumStr] - String enumerator to which to add filenames to.
  1289. // [wid] - WORKID of the property store.
  1290. //
  1291. // History: 11-Apr-97 KrishnaN Created
  1292. // 30-May-97 KrishnaN Enumerate the backup file
  1293. // 24-Oct-97 KyleP Backup file is ephemeral and thus not
  1294. // part of the list.
  1295. //
  1296. //----------------------------------------------------------------------------
  1297. void CiStorage::ListPropStoreFileNames( CEnumString & enumStr, WORKID wid,
  1298. DWORD dwStoreLevel )
  1299. {
  1300. WCHAR wcsHdr[MAX_PATH];
  1301. WCHAR wcsCopy1[MAX_PATH];
  1302. WCHAR wcsCopy2[MAX_PATH];
  1303. //
  1304. // Get the recoverable storage object files
  1305. //
  1306. Win4Assert(PRIMARY_STORE == dwStoreLevel || SECONDARY_STORE == dwStoreLevel);
  1307. FormRcovObjNames( wid,
  1308. (PRIMARY_STORE == dwStoreLevel) ? PROPSTORE1_PREFIX:PROPSTORE2_PREFIX,
  1309. wcsHdr, wcsCopy1, wcsCopy2 );
  1310. enumStr.Append(wcsHdr);
  1311. enumStr.Append(wcsCopy1);
  1312. enumStr.Append(wcsCopy2);
  1313. //
  1314. // Get the property store and prop store backup file names
  1315. //
  1316. // Reuse wcsCopy1
  1317. PStorageObject *pObj = QueryObject(wid);
  1318. XPtr<PStorageObject> xObj(pObj);
  1319. MakePath( (PRIMARY_STORE == dwStoreLevel) ? ePrimaryPropPath:eSecondaryPropPath,
  1320. CI_OBJ(*pObj).ObjectId(), wcsCopy1);
  1321. enumStr.Append(wcsCopy1);
  1322. }
  1323. //+---------------------------------------------------------------------------
  1324. //
  1325. // Member: CiStorage::ListSecStoreFileNames
  1326. //
  1327. // Synopsis: Lists the names of the files that constitute the recoverable
  1328. // stoage object for the security store.
  1329. //
  1330. // Arguments: [enumStr] -- Output object to append the names of the
  1331. // security store.
  1332. // [wid] -- Workid
  1333. //
  1334. // History: 7-14-97 srikants Created
  1335. //
  1336. //----------------------------------------------------------------------------
  1337. void CiStorage::ListSecStoreFileNames( CEnumString & enumStr, WORKID wid )
  1338. {
  1339. WCHAR wcsHdr[MAX_PATH];
  1340. WCHAR wcsCopy1[MAX_PATH];
  1341. WCHAR wcsCopy2[MAX_PATH];
  1342. //
  1343. // Get the recoverable storage object files
  1344. //
  1345. FormRcovObjNames( wid, SECSTORE_PREFIX, wcsHdr, wcsCopy1, wcsCopy2 );
  1346. enumStr.Append(wcsHdr);
  1347. enumStr.Append(wcsCopy1);
  1348. enumStr.Append(wcsCopy2);
  1349. }
  1350. //+---------------------------------------------------------------------------
  1351. //
  1352. // Member: CiStorage::DeleteFilesInCiDir
  1353. //
  1354. // Synopsis: Deletes files in the ci directory which match the given
  1355. // pattern.
  1356. //
  1357. // Arguments: [pwszPattern] - Pattern of files to search.
  1358. //
  1359. // History: 1-31-97 srikants Created
  1360. //
  1361. //----------------------------------------------------------------------------
  1362. void CiStorage::DeleteFilesInCiDir( WCHAR const * pwszPattern )
  1363. {
  1364. CFullPath fullPath( _xPath.GetPointer() );
  1365. WCHAR wszFullPattern[MAX_PATH];
  1366. swprintf( wszFullPattern, L"%s%s", fullPath.GetBuf(), pwszPattern );
  1367. WIN32_FIND_DATA fileData;
  1368. HANDLE hFile = FindFirstFile( wszFullPattern, &fileData );
  1369. if ( INVALID_HANDLE_VALUE == hFile )
  1370. {
  1371. ciDebugOut(( DEB_ITRACE, "Did not find files for (%ws)\n",
  1372. wszFullPattern ));
  1373. return;
  1374. }
  1375. do
  1376. {
  1377. if ( !(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
  1378. {
  1379. fullPath.MakePath( fileData.cFileName );
  1380. BOOL fSuccess = DeleteFile( fullPath.GetBuf() );
  1381. if ( !fSuccess )
  1382. {
  1383. DWORD dwError = GetLastError();
  1384. ciDebugOut(( DEB_ITRACE,
  1385. "Failed to delete file (%ws) due to error (%d)\n",
  1386. fullPath.GetBuf(), dwError ));
  1387. }
  1388. else
  1389. {
  1390. ciDebugOut(( DEB_ITRACE,
  1391. "Deleted file (%ws)\n", fullPath.GetBuf() ));
  1392. }
  1393. }
  1394. else
  1395. {
  1396. ciDebugOut(( DEB_ITRACE,
  1397. "Not deleting directory (%ws) \n", fullPath.GetBuf() ));
  1398. }
  1399. }
  1400. while ( FindNextFile( hFile, &fileData ) );
  1401. FindClose( hFile );
  1402. }
  1403. //+---------------------------------------------------------------------------
  1404. //
  1405. // Member: CiStorage::DeleteAllFiles
  1406. //
  1407. // Synopsis: Deletes all the files in the Ci directory.
  1408. //
  1409. // History: 3-21-97 srikants Created
  1410. //
  1411. //----------------------------------------------------------------------------
  1412. void CiStorage::DeleteAllFiles()
  1413. {
  1414. WCHAR wszPattern[32];
  1415. swprintf( wszPattern, L"*.*" );
  1416. DeleteFilesInCiDir( wszPattern );
  1417. }
  1418. //+---------------------------------------------------------------------------
  1419. //
  1420. // Member: CiStorage::DeleteAllCiFiles
  1421. //
  1422. // Synopsis: Deletes files that belong to the CI engine.
  1423. //
  1424. // History: 1-31-97 srikants Created
  1425. //
  1426. //----------------------------------------------------------------------------
  1427. void CiStorage::DeleteAllCiFiles()
  1428. {
  1429. //
  1430. // Delete the following types of files.
  1431. //
  1432. WCHAR wszPattern[32];
  1433. swprintf( wszPattern, L"*.ci" );
  1434. DeleteFilesInCiDir( wszPattern );
  1435. swprintf( wszPattern, L"*.dir" );
  1436. DeleteFilesInCiDir( wszPattern );
  1437. swprintf( wszPattern, L"%s*", MMLOG_PREFIX );
  1438. DeleteFilesInCiDir( wszPattern );
  1439. swprintf( wszPattern, L"%s*", PRI_CHANGELOG_PREFIX );
  1440. DeleteFilesInCiDir( wszPattern );
  1441. swprintf( wszPattern, L"%s*", SEC_CHANGELOG_PREFIX );
  1442. DeleteFilesInCiDir( wszPattern );
  1443. swprintf( wszPattern, L"%s*", FRESHLOG_PREFIX );
  1444. DeleteFilesInCiDir( wszPattern );
  1445. swprintf( wszPattern, L"INDEX.*" );
  1446. DeleteFilesInCiDir( wszPattern );
  1447. }
  1448. //+---------------------------------------------------------------------------
  1449. //
  1450. // Member: CiStorage::DeleteAllPersistentIndexes
  1451. //
  1452. // Synopsis: Deletes all the persistent indexes in the ci directory.
  1453. //
  1454. // History: 3-25-97 srikants Created
  1455. //
  1456. //----------------------------------------------------------------------------
  1457. void CiStorage::DeleteAllPersIndexes()
  1458. {
  1459. //
  1460. // Delete the following types of files.
  1461. //
  1462. WCHAR wszPattern[32];
  1463. swprintf( wszPattern, L"*.ci" );
  1464. DeleteFilesInCiDir( wszPattern );
  1465. swprintf( wszPattern, L"*.dir" );
  1466. DeleteFilesInCiDir( wszPattern );
  1467. }
  1468. //+---------------------------------------------------------------------------
  1469. //
  1470. // Member: CiStorage::DeleteUnUsedPersIndexes
  1471. //
  1472. // Synopsis: Deletes any .ci and .dir files that are not referenced in
  1473. // the given iid list.
  1474. //
  1475. // Arguments: [iidStk] - List of in-use iids.
  1476. //
  1477. // History: 3-25-97 srikants Created
  1478. //
  1479. //----------------------------------------------------------------------------
  1480. void CiStorage::DeleteUnUsedPersIndexes( BOOL fIsCi,
  1481. CIndexIdList const & iidsInUse )
  1482. {
  1483. WCHAR wszPattern[32];
  1484. if ( fIsCi )
  1485. swprintf( wszPattern, L"*.ci" );
  1486. else
  1487. swprintf( wszPattern, L"*.dir" );
  1488. CFullPath fullPath( _xPath.GetPointer() );
  1489. WCHAR wszFullPattern[MAX_PATH];
  1490. swprintf( wszFullPattern, L"%s%s", fullPath.GetBuf(), wszPattern );
  1491. WIN32_FIND_DATA fileData;
  1492. HANDLE hFile = FindFirstFile( wszFullPattern, &fileData );
  1493. if ( INVALID_HANDLE_VALUE == hFile )
  1494. {
  1495. ciDebugOut(( DEB_ITRACE, "Did not find files for (%ws)\n",
  1496. wszFullPattern ));
  1497. return;
  1498. }
  1499. do
  1500. {
  1501. if ( !(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
  1502. {
  1503. if ( !IsInUse( fileData.cFileName, iidsInUse ) )
  1504. {
  1505. fullPath.MakePath( fileData.cFileName );
  1506. ciDebugOut(( DEB_ITRACE, "Deleting UnUsed Index (%ws) \n",
  1507. fullPath.GetBuf() ));
  1508. BOOL fSuccess = DeleteFile( fullPath.GetBuf() );
  1509. if ( !fSuccess )
  1510. {
  1511. DWORD dwError = GetLastError();
  1512. ciDebugOut(( DEB_ITRACE,
  1513. "Failed to delete file (%ws) due to error (%d)\n",
  1514. fullPath.GetBuf(), dwError ));
  1515. }
  1516. else
  1517. {
  1518. ciDebugOut(( DEB_ITRACE,
  1519. "Deleted file (%ws)\n", fullPath.GetBuf() ));
  1520. }
  1521. }
  1522. }
  1523. else
  1524. {
  1525. ciDebugOut(( DEB_ITRACE,
  1526. "Not deleting directory (%ws) \n", fullPath.GetBuf() ));
  1527. }
  1528. }
  1529. while ( FindNextFile( hFile, &fileData ) );
  1530. FindClose( hFile );
  1531. }
  1532. //+---------------------------------------------------------------------------
  1533. //
  1534. // Member: CiStorage::IsInUse
  1535. //
  1536. // Synopsis: Tests if the given file is in use.
  1537. //
  1538. // Arguments: [pwszFile] -
  1539. // [iidStk] -
  1540. //
  1541. // Returns: TRUE if it is in use. FALSE o/w
  1542. //
  1543. // History: 3-25-97 srikants Created
  1544. //
  1545. //----------------------------------------------------------------------------
  1546. BOOL CiStorage::IsInUse( WCHAR const * pwszFile,
  1547. CIndexIdList const & iidsInUse ) const
  1548. {
  1549. //
  1550. // Determine the iid and see if it is in the list.
  1551. //
  1552. WCHAR * pwszEnd;
  1553. INDEXID iid = (INDEXID) wcstol( pwszFile, &pwszEnd, 16 );
  1554. for ( ULONG i = 0; i < iidsInUse.Count(); i++ )
  1555. {
  1556. if ( iid == iidsInUse.Get(i) )
  1557. return TRUE;
  1558. }
  1559. return FALSE;
  1560. }
  1561. //+---------------------------------------------------------------------------
  1562. //
  1563. // Member: CiStorage::DeleteUnUsedPersIndexes
  1564. //
  1565. // Synopsis: Deletes the persistent .ci and .dir files that are not
  1566. // in the list of in-use iids.
  1567. //
  1568. // Arguments: [iidStk] - The list of in-use iids.
  1569. //
  1570. // History: 3-25-97 srikants Created
  1571. //
  1572. //----------------------------------------------------------------------------
  1573. void CiStorage::DeleteUnUsedPersIndexes( CIndexIdList const & iidsInUse )
  1574. {
  1575. DeleteUnUsedPersIndexes( TRUE, iidsInUse ); // delete the unused .ci files
  1576. DeleteUnUsedPersIndexes( FALSE, iidsInUse ); // delete the unused .dir files
  1577. }
  1578. //+---------------------------------------------------------------------------
  1579. //
  1580. // Member: CiStorage::DeleteAllFsCiFiles
  1581. //
  1582. // Synopsis: Deletes all the files belonging to the FileSystem CI client.
  1583. //
  1584. // History: 2-10-97 srikants Created
  1585. //
  1586. //----------------------------------------------------------------------------
  1587. void CiStorage::DeleteAllFsCiFiles()
  1588. {
  1589. //
  1590. // Delete the following types of files.
  1591. //
  1592. WCHAR wszPattern[32];
  1593. swprintf( wszPattern, L"cicat.hsh" );
  1594. DeleteFilesInCiDir( wszPattern );
  1595. swprintf( wszPattern, L"cicat.fid" );
  1596. DeleteFilesInCiDir( wszPattern );
  1597. swprintf( wszPattern, L"deletion.log" );
  1598. DeleteFilesInCiDir( wszPattern );
  1599. swprintf( wszPattern, PROP_BKP_FILE);
  1600. DeleteFilesInCiDir( wszPattern );
  1601. swprintf( wszPattern, PROP_BKP_FILE1);
  1602. DeleteFilesInCiDir( wszPattern );
  1603. swprintf( wszPattern, PROP_BKP_FILE2);
  1604. DeleteFilesInCiDir( wszPattern );
  1605. swprintf( wszPattern, L"*.prp" );
  1606. DeleteFilesInCiDir( wszPattern );
  1607. swprintf( wszPattern, L"*.ps1" );
  1608. DeleteFilesInCiDir( wszPattern );
  1609. swprintf( wszPattern, L"*.ps2" );
  1610. DeleteFilesInCiDir( wszPattern );
  1611. swprintf( wszPattern, L"%s*", PIDTABLE_PREFIX );
  1612. DeleteFilesInCiDir( wszPattern );
  1613. swprintf( wszPattern, L"%s*", SCOPELIST_PREFIX );
  1614. DeleteFilesInCiDir( wszPattern );
  1615. swprintf( wszPattern, L"%s*", SECSTORE_PREFIX );
  1616. DeleteFilesInCiDir( wszPattern );
  1617. swprintf( wszPattern, L"%s*", PROPSTORE_PREFIX );
  1618. DeleteFilesInCiDir( wszPattern );
  1619. swprintf( wszPattern, L"%s*", PROPSTORE1_PREFIX );
  1620. DeleteFilesInCiDir( wszPattern );
  1621. swprintf( wszPattern, L"%s*", PROPSTORE2_PREFIX );
  1622. DeleteFilesInCiDir( wszPattern );
  1623. swprintf( wszPattern, L"%s*", VSCOPELIST_PREFIX );
  1624. DeleteFilesInCiDir( wszPattern );
  1625. }
  1626. //+---------------------------------------------------------------------------
  1627. //
  1628. // Member: CiStorage::CopyGivenFile
  1629. //
  1630. // Synopsis: Copies or Moves the given file to the current catalog location.
  1631. //
  1632. // Arguments: [pwszFilePath] - Full path of the source file
  1633. // [fMoveOk] - Set to TRUE if a move is okay. A move is done
  1634. // if the file is on the same drive.
  1635. //
  1636. // History: 3-18-97 srikants Created
  1637. //
  1638. //----------------------------------------------------------------------------
  1639. void CiStorage::CopyGivenFile( WCHAR const * pwszFilePath, BOOL fMoveOk )
  1640. {
  1641. Win4Assert( 0 != pwszFilePath );
  1642. //
  1643. // Locate the file name component in the path.
  1644. //
  1645. WCHAR const * pwszFileName = 0;
  1646. int cwc = (int) wcslen( pwszFilePath );
  1647. for ( int i = cwc; i >=0; i-- )
  1648. {
  1649. if ( pwszFilePath[i] == L'\\' )
  1650. {
  1651. pwszFileName = pwszFilePath+i;
  1652. break;
  1653. }
  1654. }
  1655. if ( 0 == pwszFileName )
  1656. {
  1657. ciDebugOut(( DEB_ITRACE,
  1658. "No file name in path (%ws)\n",
  1659. pwszFilePath ));
  1660. THROW( CException( E_INVALIDARG ) );
  1661. }
  1662. WCHAR wcsDestPath[MAX_PATH];
  1663. wcscpy( wcsDestPath, _xPath.GetPointer() );
  1664. wcscat( wcsDestPath, pwszFileName );
  1665. ciDebugOut(( DEB_ITRACE, "CopyFile to (%ws) \n", wcsDestPath ));
  1666. //
  1667. // First delete any file with the same name in the destination.
  1668. //
  1669. DeleteFilesInCiDir( pwszFileName+1 ); // Backslash is the first char
  1670. //
  1671. // If they are on the same drive and move is okay, then we should move
  1672. // the file rather than copying the file.
  1673. //
  1674. if ( (_xPath.GetPointer()[0] == pwszFilePath[0]) && fMoveOk )
  1675. {
  1676. if ( !MoveFile( pwszFilePath, wcsDestPath ) )
  1677. {
  1678. DWORD dwError = GetLastError();
  1679. ciDebugOut(( DEB_ITRACE,
  1680. "MoveFile (%ws) -> (%ws) failed. Error %d\n",
  1681. pwszFilePath, wcsDestPath, dwError ));
  1682. THROW( CException( HRESULT_FROM_WIN32( dwError ) ) );
  1683. }
  1684. }
  1685. else
  1686. {
  1687. //
  1688. // We have to create a copy of the file.
  1689. //
  1690. if ( !CopyFile( pwszFilePath,
  1691. wcsDestPath,
  1692. FALSE // Don't fail if it exists
  1693. ) )
  1694. {
  1695. DWORD dwError = GetLastError();
  1696. ciDebugOut(( DEB_ITRACE,
  1697. "CopyFile (%ws) -> (%ws) failed. Error %d\n",
  1698. pwszFilePath, wcsDestPath, dwError ));
  1699. THROW( CException( HRESULT_FROM_WIN32( dwError ) ) );
  1700. }
  1701. //
  1702. // If the fMove is set to TRUE, delete the source file
  1703. //
  1704. if ( fMoveOk )
  1705. DeleteFile( pwszFilePath );
  1706. }
  1707. }
  1708. //+---------------------------------------------------------------------------
  1709. //
  1710. // Function: EnumerateFilesInDir
  1711. //
  1712. // Synopsis: Enumerates files in a directory. Does not include directories
  1713. // and there is no recursive traversal.
  1714. //
  1715. // Arguments: [pwszDir] - Directory to enumerate.
  1716. // [enumStr] - Place to add the enumerated files.
  1717. //
  1718. // History: 3-19-97 srikants Created
  1719. //
  1720. //----------------------------------------------------------------------------
  1721. void CiStorage::EnumerateFilesInDir( WCHAR const * pwszDir,
  1722. CEnumString & enumStr )
  1723. {
  1724. CFullPath fullPath( (WCHAR *) pwszDir );
  1725. fullPath.MakePath( L"*.*" );
  1726. WIN32_FIND_DATA fileData;
  1727. HANDLE hFile = FindFirstFile( fullPath.GetBuf(), &fileData );
  1728. if ( INVALID_HANDLE_VALUE == hFile )
  1729. {
  1730. ciDebugOut(( DEB_ITRACE, "Did not find files for (%ws)\n",
  1731. fullPath.GetBuf() ));
  1732. return;
  1733. }
  1734. do
  1735. {
  1736. if ( !(fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) )
  1737. {
  1738. fullPath.MakePath( fileData.cFileName );
  1739. enumStr.Append( fullPath.GetBuf() );
  1740. ciDebugOut(( DEB_ITRACE,
  1741. "EnumerateFiles - Adding File (%ws) \n", fullPath.GetBuf() ));
  1742. }
  1743. else
  1744. {
  1745. ciDebugOut(( DEB_ITRACE,
  1746. "EnumerateFiles - Skipping directory (%ws) \n", fileData.cFileName ));
  1747. }
  1748. }
  1749. while ( FindNextFile( hFile, &fileData ) );
  1750. FindClose( hFile );
  1751. }
  1752. //+---------------------------------------------------------------------------
  1753. //
  1754. // Function: IsValidFile
  1755. //
  1756. // Synopsis: Verifies that the given file is a valid file.
  1757. //
  1758. // Arguments: [pwszFile] - File name
  1759. //
  1760. // History: 3-21-97 srikants Created
  1761. //
  1762. //----------------------------------------------------------------------------
  1763. BOOL CiStorage::IsValidFile( WCHAR const * pwszFile )
  1764. {
  1765. DWORD dwFileAttributes = GetFileAttributes( pwszFile );
  1766. if ( 0xFFFFFFFF == dwFileAttributes )
  1767. {
  1768. DWORD dwError = GetLastError();
  1769. ciDebugOut(( DEB_ITRACE, "GetFileAttributes failed with error %d\n", dwError ));
  1770. return FALSE;
  1771. }
  1772. return 0 == (dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ;
  1773. }
  1774. //+---------------------------------------------------------------------------
  1775. //
  1776. // Function: CheckHasIndexTable
  1777. //
  1778. // Synopsis: Verifies that the given directory is a valid one. Also checks
  1779. // that files INDEX.000, INDEX.001, INDEX.002 are present in the
  1780. // directory.
  1781. //
  1782. // Arguments: [pwszPath] - Path of the directory.
  1783. //
  1784. // Returns: TRUE if valid; FALSE o/w
  1785. //
  1786. // History: 3-21-97 srikants Created
  1787. //
  1788. //----------------------------------------------------------------------------
  1789. BOOL CiStorage::CheckHasIndexTable( WCHAR const * pwszPath )
  1790. {
  1791. CFullPath fullPath( pwszPath );
  1792. fullPath.MakePath( CAT_IDXTABLE_HDR );
  1793. if ( !IsValidFile( fullPath.GetBuf() ) )
  1794. return FALSE;
  1795. fullPath.MakePath( CAT_IDXTABLE_CP1 );
  1796. if ( !IsValidFile( fullPath.GetBuf() ) )
  1797. return FALSE;
  1798. fullPath.MakePath( CAT_IDXTABLE_CP2 );
  1799. if ( !IsValidFile( fullPath.GetBuf() ) )
  1800. return FALSE;
  1801. return TRUE;
  1802. }
  1803. //+---------------------------------------------------------------------------
  1804. //
  1805. // Function: DetermineDriveType
  1806. //
  1807. // Synopsis: Determines the type of drive on which the given path is.
  1808. //
  1809. // Arguments: [pwszPath] - Path of the file.
  1810. //
  1811. // Returns: WIN32 drive type ( values returned by GetDriveType() )
  1812. //
  1813. // History: 3-24-97 srikants Created
  1814. //
  1815. //----------------------------------------------------------------------------
  1816. UINT CiStorage::DetermineDriveType( WCHAR const * pwszPath )
  1817. {
  1818. CPathParser pathParser( pwszPath );
  1819. if ( pathParser.IsUNCName() )
  1820. return DRIVE_REMOTE;
  1821. WCHAR wDrive[MAX_PATH];
  1822. ULONG cc=sizeof(wDrive)/sizeof(WCHAR);
  1823. pathParser.GetFileName( wDrive, cc );
  1824. UINT uType = GetDriveType( wDrive );
  1825. return uType;
  1826. }
  1827. //+-------------------------------------------------------------------------
  1828. //
  1829. // Method: CiStorage::QueryStream, Private
  1830. //
  1831. // Synopsis: Opens a mmstream of name specified
  1832. //
  1833. // Arguments: [wcsFileName] - Name of the file.
  1834. //
  1835. // Returns: CMmStream
  1836. //
  1837. // History: 17-Mar-1998 KitmanH Created
  1838. //
  1839. //--------------------------------------------------------------------------
  1840. PMmStream* CiStorage::QueryStream (WCHAR const * wcsFileName)
  1841. {
  1842. XPtr<CMmStream> xStrm( new CMmStream( _cMegToLeaveOnDisk, _fIsReadOnly ) );
  1843. DWORD dwAccess = _fIsReadOnly ? GENERIC_READ : ( GENERIC_READ | GENERIC_WRITE );
  1844. DWORD sharing = _fIsReadOnly ? ( FILE_SHARE_READ | FILE_SHARE_WRITE ) : FILE_SHARE_READ;
  1845. DWORD openMode = _fIsReadOnly ? OPEN_EXISTING : OPEN_ALWAYS;
  1846. WCHAR wcsFilePath[MAX_PATH];
  1847. wcscpy ( wcsFilePath, _xPath.GetPointer() );
  1848. wcscat ( wcsFilePath, wcsFileName );
  1849. xStrm->Open( wcsFilePath,
  1850. dwAccess, // Access flags
  1851. sharing,
  1852. openMode,
  1853. FILE_ATTRIBUTE_NORMAL,
  1854. FALSE );
  1855. return xStrm.Acquire();
  1856. }
  1857. //+-------------------------------------------------------------------------
  1858. //
  1859. // Method: CiStorage::QueryStringHash
  1860. //
  1861. // Synopsis: Opens a mmstream by calling private function QueryStream
  1862. // with the appropriate filename
  1863. //
  1864. // Arguments: [wcsFileName] - Name of the file.
  1865. //
  1866. // Returns: CMmStream
  1867. //
  1868. // History: 17-Mar-1998 KitmanH Created
  1869. //
  1870. //--------------------------------------------------------------------------
  1871. PMmStream* CiStorage::QueryStringHash()
  1872. {
  1873. return QueryStream( CAT_HASH_FILE );
  1874. }
  1875. //+-------------------------------------------------------------------------
  1876. //
  1877. // Method: CiStorage::QueryFileIdMap
  1878. //
  1879. // Synopsis: Opens a mmstream by calling private function QueryStream
  1880. // with the appropriate filename
  1881. //
  1882. // Arguments: [wcsFileName] - Name of the file.
  1883. //
  1884. // Returns: CMmStream
  1885. //
  1886. // History: 17-Mar-1998 KitmanH Created
  1887. //
  1888. //--------------------------------------------------------------------------
  1889. PMmStream* CiStorage::QueryFileIdMap()
  1890. {
  1891. return QueryStream( CAT_FILEID_MAP_FILE );
  1892. }
  1893. //+-------------------------------------------------------------------------
  1894. //
  1895. // Method: CiStorage::QueryDeletionLog
  1896. //
  1897. // Synopsis: Opens a mmstream by calling private function QueryStream
  1898. // with the appropriate filename
  1899. //
  1900. // Arguments: [wcsFileName] - Name of the file.
  1901. //
  1902. // Returns: CMmStream
  1903. //
  1904. // History: 17-Mar-1998 KitmanH Created
  1905. //
  1906. //--------------------------------------------------------------------------
  1907. PMmStream* CiStorage::QueryDeletionLog()
  1908. {
  1909. Win4Assert( FALSE );
  1910. return 0;
  1911. }