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.

742 lines
16 KiB

  1. //+-------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  5. //
  6. // File: fat.hxx
  7. //
  8. // Contents: Header file for fat classes
  9. //
  10. // Classes: CFatSect - sector sized array of sector info
  11. // CFatVector - resizable array of CFatSect
  12. // CFat - Grouping of FatSect
  13. //
  14. // History: 18-Jul-91 PhilipLa Created.
  15. //
  16. //--------------------------------------------------------------------
  17. #ifndef __FAT_HXX__
  18. #define __FAT_HXX__
  19. #include <vect.hxx>
  20. #define DEB_FAT (DEB_ITRACE|0x00010000)
  21. //+----------------------------------------------------------------------
  22. //
  23. // Class: CFatSect (fs)
  24. //
  25. // Purpose: Holds one sector worth of FAT data
  26. //
  27. // Interface: getsize - Returns the size of the FAT (in sectors)
  28. // contents - Returns contents of any given FAT entry
  29. //
  30. // History: 18-Jul-91 PhilipLa Created.
  31. //
  32. // Notes:
  33. //
  34. //-----------------------------------------------------------------------
  35. #if _MSC_VER == 700
  36. #pragma warning(disable:4001)
  37. #elif _MSC_VER >= 800
  38. #pragma warning(disable:4200)
  39. #endif
  40. class CFatSect
  41. {
  42. public:
  43. SCODE Init(FSOFFSET uEntries);
  44. SCODE InitCopy(USHORT uSize, CFatSect *pfsOld);
  45. inline SECT GetSect(const FSOFFSET sect) const;
  46. inline void SetSect(const FSOFFSET sect,const SECT sectNew);
  47. inline SECT GetNextFat(USHORT uSize) const;
  48. inline void SetNextFat(USHORT uSize, const SECT sect);
  49. private:
  50. SECT _asectEntry[];
  51. };
  52. #if _MSC_VER == 700
  53. #pragma warning(default:4001)
  54. #elif _MSC_VER >= 800
  55. #pragma warning(default:4200)
  56. #endif
  57. inline SECT CFatSect::GetSect(const FSOFFSET sect) const
  58. {
  59. return _asectEntry[sect];
  60. }
  61. inline void CFatSect::SetSect(const FSOFFSET sect,
  62. const SECT sectNew)
  63. {
  64. _asectEntry[sect] = sectNew;
  65. }
  66. inline SECT CFatSect::GetNextFat(USHORT uSize) const
  67. {
  68. return _asectEntry[uSize];
  69. }
  70. inline void CFatSect::SetNextFat(USHORT uSize, const SECT sect)
  71. {
  72. _asectEntry[uSize] = sect;
  73. }
  74. //+-------------------------------------------------------------------------
  75. //
  76. // Class: CFatVector (fv)
  77. //
  78. // Purpose: *Finish This*
  79. //
  80. // Interface:
  81. //
  82. // History: 02-Sep-92 PhilipLa Created.
  83. //
  84. // Notes:
  85. //
  86. //--------------------------------------------------------------------------
  87. class CFatVector: public CPagedVector
  88. {
  89. public:
  90. inline CFatVector(
  91. const SID sid);
  92. inline void InitCommon(FSOFFSET csectBlock, FSOFFSET csectTable);
  93. SCODE InitPage(FSINDEX iPage);
  94. inline FSOFFSET GetSectBlock() const;
  95. inline FSOFFSET GetSectTable() const;
  96. inline SCODE GetTable(
  97. const FSINDEX iTable,
  98. const DWORD dwFlags,
  99. CFatSect **pfs);
  100. private:
  101. FSOFFSET _csectTable;
  102. FSOFFSET _csectBlock;
  103. };
  104. inline CFatVector::CFatVector(
  105. const SID sid)
  106. : CPagedVector(sid)
  107. {
  108. }
  109. inline void CFatVector::InitCommon(
  110. FSOFFSET csectBlock,
  111. FSOFFSET csectTable)
  112. {
  113. _csectBlock = csectBlock;
  114. _csectTable = csectTable;
  115. }
  116. //+-------------------------------------------------------------------------
  117. //
  118. // Method: CFatVector::GetSectTable, public
  119. //
  120. // Synopsis: Returns count of sector entries per table
  121. //
  122. // Returns: count of sector entries per table
  123. //
  124. // History: 08-Jul-92 AlexT Created.
  125. //
  126. //--------------------------------------------------------------------------
  127. inline FSOFFSET CFatVector::GetSectTable() const
  128. {
  129. return _csectTable;
  130. }
  131. //+-------------------------------------------------------------------------
  132. //
  133. // Method: CFatVector::GetSectBlock, public
  134. //
  135. // Synopsis: Returns count of sector entries per block
  136. //
  137. // Returns: count of sector entries per block
  138. //
  139. // History: 01-Sep-92 PhilipLa Created.
  140. //
  141. //--------------------------------------------------------------------------
  142. inline FSOFFSET CFatVector::GetSectBlock() const
  143. {
  144. return _csectBlock;
  145. }
  146. //+-------------------------------------------------------------------------
  147. //
  148. // Method: CFatVector::GetTable, public
  149. //
  150. // Synopsis: Return a pointer to a FatSect for the given index
  151. // into the vector.
  152. //
  153. // Arguments: [iTable] -- index into vector
  154. //
  155. // Returns: Pointer to CFatSect indicated by index
  156. //
  157. // History: 27-Dec-91 PhilipLa Created.
  158. //
  159. // Notes:
  160. //
  161. //--------------------------------------------------------------------------
  162. inline SCODE CFatVector::GetTable(
  163. const FSINDEX iTable,
  164. const DWORD dwFlags,
  165. CFatSect **ppfs)
  166. {
  167. SCODE sc;
  168. sc = CPagedVector::GetTable(iTable, dwFlags, (void **)ppfs);
  169. if (sc == STG_S_NEWPAGE)
  170. {
  171. (*ppfs)->Init(_csectBlock);
  172. }
  173. return sc;
  174. }
  175. //CSEG determines the maximum number of segments that will be
  176. //returned by a single Contig call.
  177. #define CSEG 32
  178. //+-------------------------------------------------------------------------
  179. //
  180. // Class: SSegment (seg)
  181. //
  182. // Purpose: Used for contiguity tables for multi-sector reads and
  183. // writes.
  184. //
  185. // Interface: None.
  186. //
  187. // History: 16-Aug-91 PhilipLa Created.
  188. //
  189. // Notes:
  190. //
  191. //--------------------------------------------------------------------------
  192. struct SSegment {
  193. public:
  194. ULONG ulOffset;
  195. SECT sectStart;
  196. ULONG cSect;
  197. };
  198. inline SECT SegStart(SSegment seg)
  199. {
  200. return seg.sectStart;
  201. }
  202. inline SECT SegEnd(SSegment seg)
  203. {
  204. return seg.sectStart + seg.cSect - 1;
  205. }
  206. inline ULONG SegLength(SSegment seg)
  207. {
  208. return seg.cSect;
  209. }
  210. inline ULONG SegStartOffset(SSegment seg)
  211. {
  212. return seg.ulOffset;
  213. }
  214. inline ULONG SegEndOffset(SSegment seg)
  215. {
  216. return seg.ulOffset + seg.cSect - 1;
  217. }
  218. class CMStream;
  219. #define GF_READONLY TRUE
  220. #define GF_WRITE FALSE
  221. class CFat;
  222. SAFE_DFBASED_PTR(CBasedFatPtr, CFat);
  223. //+----------------------------------------------------------------------
  224. //
  225. // Class: CFat (fat)
  226. //
  227. // Purpose: Main interface to allocation routines
  228. //
  229. // Interface: Allocate - allocates new chain in the FAT
  230. // Extend - Extends an existing FAT chain
  231. // GetNext - Returns next sector in a chain
  232. // GetSect - Returns nth sector in a chain
  233. // GetESect - Returns nth sector in a chain, extending
  234. // if necessary
  235. // GetLength - Returns the # of sectors in a chain
  236. // setup - Initializes for an existing stream
  237. // setupnew - Initializes for a new stream
  238. //
  239. // checksanity - Debugging routine
  240. //
  241. // History: 18-Jul-91 PhilipLa Created.
  242. // 17-Aug-91 PhilipLa Added dirty and full bits
  243. // Notes:
  244. //
  245. //-----------------------------------------------------------------------
  246. struct SGetFreeStruct;
  247. class CFat
  248. {
  249. public:
  250. CFat(SID sid);
  251. CFat(CFat *pfatOld);
  252. ~CFat();
  253. VOID Empty(VOID);
  254. inline void SetNoScratch(CFat *pfatNoScratch);
  255. inline void SetNoSnapshot(SECT sectNoSnapshot);
  256. inline SECT GetNoSnapshot(void);
  257. inline SECT GetNoSnapshotFree(void);
  258. inline void ResetNoSnapshotFree(void);
  259. SCODE ResizeNoSnapshot(void);
  260. inline SCODE Allocate(ULONG ulSize, SECT *psectFirst);
  261. SCODE GetNext(const SECT sect, SECT * psRet);
  262. SCODE GetSect(
  263. SECT sectStart,
  264. ULONG ulOffset,
  265. SECT *psectReturn);
  266. SCODE GetESect(
  267. SECT sectStart,
  268. ULONG ulOffset,
  269. SECT *psectReturn);
  270. SCODE SetNext(SECT sectFirst, SECT sectNext);
  271. SCODE GetFree(ULONG ulCount, SECT * sect, BOOL fReadOnly);
  272. SCODE GetFreeContig(ULONG ulCount,
  273. SSegment STACKBASED *aseg,
  274. ULONG cSeg,
  275. ULONG *pcSegReturned);
  276. SCODE ReserveSects(ULONG cSect);
  277. SCODE GetLength(SECT sect, ULONG * pulRet);
  278. SCODE SetChainLength(SECT,ULONG);
  279. SCODE Init(
  280. CMStream *pmsParent,
  281. FSINDEX cFatSect,
  282. BOOL fConvert);
  283. SCODE InitNew(CMStream *pmsParent);
  284. void InitCopy(CFat *pfatOld);
  285. SCODE InitConvert(
  286. CMStream *pmsParent,
  287. ULONG cbSize);
  288. SCODE InitScratch(CFat *pfat, BOOL fNew);
  289. SCODE Remap(
  290. SECT sectStart,
  291. ULONG oStart,
  292. ULONG ulRunLength,
  293. SECT *psectOldStart,
  294. SECT *psectNewStart,
  295. SECT *psectOldEnd,
  296. SECT *psectNewEnd);
  297. inline SCODE QueryRemapped(const SECT sect);
  298. SCODE DirtyAll();
  299. inline SECT GetLast(VOID) const;
  300. inline SCODE GetFreeSectCount(ULONG *pcFreeSects);
  301. SCODE CountSectType(ULONG * pulRet,
  302. SECT sectStart,
  303. SECT sectEnd,
  304. SECT sectType);
  305. inline VOID ResetCopyOnWrite(VOID);
  306. inline VOID SetCopyOnWrite(CFat *pfat, SECT sectLast);
  307. inline VOID ResetUnmarkedSects(VOID);
  308. SCODE FindLast(SECT *psectRet);
  309. SCODE FindMaxSect(SECT *psectRet);
  310. inline SCODE GetMaxSect(SECT *psectRet);
  311. SCODE Contig(
  312. SSegment STACKBASED *aseg,
  313. BOOL fWrite,
  314. SECT sect,
  315. ULONG ulLength,
  316. ULONG *pcSeg);
  317. inline SCODE Flush(VOID);
  318. inline void SetParent(CMStream *pms);
  319. SCODE Resize(ULONG);
  320. inline BOOL IsRangeLocksSector (SECT sect);
  321. #if DBG == 1
  322. SCODE checksanity(SECT);
  323. void CheckFreeCount(void);
  324. #else
  325. #define CheckFreeCount()
  326. #endif
  327. private:
  328. inline SCODE IsFree(SECT sect);
  329. inline SCODE IsSectType(SECT sect, SECT sectType);
  330. inline SCODE MarkSect(SGetFreeStruct *pgf);
  331. inline void InitGetFreeStruct(SGetFreeStruct *pgf);
  332. inline void ReleaseGetFreeStruct(SGetFreeStruct *pgf);
  333. CFatVector _fv;
  334. CBasedMStreamPtr _pmsParent;
  335. const SID _sid;
  336. CBasedFatPtr _pfatReal;
  337. CBasedFatPtr _pfatNoScratch;
  338. //When committing in no-snapshot mode, all free sectors must
  339. // be greater than _sectNoSnapshot.
  340. SECT _sectNoSnapshot;
  341. SECT _sectNoSnapshotFree;
  342. USHORT _uFatShift;
  343. USHORT _uFatMask;
  344. FSINDEX _cfsTable;
  345. ULONG _ulFreeSects;
  346. ULONG _cUnmarkedSects;
  347. SECT _sectFirstFree;
  348. SECT _sectLastUsed;
  349. SECT _sectMax;
  350. FSINDEX _ipfsRangeLocks;
  351. FSOFFSET _isectRangeLocks;
  352. SCODE CountFree(ULONG * ulRet);
  353. SCODE Extend(SECT,ULONG);
  354. inline VOID SectToPair(
  355. SECT sect,
  356. FSINDEX *pipfs,
  357. FSOFFSET *pisect) const;
  358. inline SECT PairToSect(FSINDEX ipfs, FSOFFSET isect) const;
  359. friend class CDIFat;
  360. inline void InitRangeLocksSector ();
  361. inline ULONG GetFatVectorLength ();
  362. };
  363. inline SECT CFat::GetLast(VOID) const
  364. {
  365. return _sectLastUsed;
  366. }
  367. inline SCODE CFat::GetFreeSectCount(ULONG *pcFreeSects)
  368. {
  369. SCODE sc;
  370. if(MAX_ULONG == _ulFreeSects)
  371. {
  372. msfChk(CountFree(&_ulFreeSects));
  373. }
  374. *pcFreeSects = _ulFreeSects;
  375. Err:
  376. return sc;
  377. }
  378. inline VOID CFat::ResetCopyOnWrite(VOID)
  379. {
  380. _sectLastUsed = 0;
  381. //Reset _sectFirstFree since this change can conceivably open up
  382. // new free sectors before the _sectFirstFree used in COW mode.
  383. _ulFreeSects = MAX_ULONG;
  384. _sectFirstFree = 0;
  385. _sectMax = ENDOFCHAIN;
  386. _fv.ResetBits();
  387. _pfatReal = NULL;
  388. _cUnmarkedSects = 0;
  389. }
  390. inline VOID CFat::ResetUnmarkedSects(VOID)
  391. {
  392. _cUnmarkedSects = 0;
  393. CheckFreeCount();
  394. }
  395. inline VOID CFat::SetCopyOnWrite(CFat *pfat, SECT sectLast)
  396. {
  397. msfAssert((_cUnmarkedSects == 0) &&
  398. aMsg("Unmarked sectors at enter copy-on-write."));
  399. _pfatReal = P_TO_BP(CBasedFatPtr, pfat);
  400. _sectLastUsed = sectLast;
  401. _sectFirstFree = 0;
  402. if (_pfatNoScratch != NULL)
  403. {
  404. _ulFreeSects = MAX_ULONG;
  405. _fv.ResetBits();
  406. }
  407. #if DBG == 1
  408. CheckFreeCount();
  409. #endif
  410. }
  411. inline VOID CFat::SectToPair(SECT sect,
  412. FSINDEX *pipfs,
  413. FSOFFSET *pisect) const
  414. {
  415. *pipfs = (FSINDEX)(sect >> _uFatShift);
  416. *pisect = (FSOFFSET)(sect & _uFatMask);
  417. }
  418. inline SECT CFat::PairToSect(FSINDEX ipfs, FSOFFSET isect) const
  419. {
  420. return (ipfs << _uFatShift) + isect;
  421. }
  422. inline SCODE CFat::GetMaxSect(SECT *psectRet)
  423. {
  424. SCODE sc;
  425. msfChk(FindMaxSect(&_sectMax));
  426. *psectRet = _sectMax;
  427. Err:
  428. return sc;
  429. }
  430. inline SCODE CFat::QueryRemapped(const SECT sect)
  431. {
  432. SCODE sc = S_FALSE;
  433. SECT sectNew;
  434. if ((sect == ENDOFCHAIN) || (sect >= _sectLastUsed))
  435. {
  436. sc = S_OK;
  437. }
  438. else
  439. {
  440. msfChk(_pfatReal->GetNext(sect, &sectNew));
  441. if (sectNew == FREESECT)
  442. {
  443. sc = S_OK;
  444. }
  445. else
  446. {
  447. sc = S_FALSE;
  448. }
  449. }
  450. Err:
  451. return sc;
  452. }
  453. inline void CFat::SetParent(CMStream *pms)
  454. {
  455. _pmsParent = P_TO_BP(CBasedMStreamPtr, pms);
  456. _fv.SetParent(pms);
  457. }
  458. //+-------------------------------------------------------------------------
  459. //
  460. // Member: CFat::Flush, public
  461. //
  462. // Synposis: Write all modified FatSects out to stream
  463. //
  464. // Effects: Resets all dirty bit fields on FatSects
  465. //
  466. // Arguments: Void
  467. //
  468. // Returns: S_OK if call completed OK.
  469. // Error code of parent write otherwise.
  470. //
  471. // Algorithm: Linearly scan through FatSects, writing any sector
  472. // that has the dirty bit set. Reset all dirty bits.
  473. //
  474. // History: 17-Aug-91 PhilipLa Created.
  475. //
  476. // Notes:
  477. //
  478. //---------------------------------------------------------------------------
  479. inline SCODE CFat::Flush(VOID)
  480. {
  481. return _fv.Flush();
  482. }
  483. //+-------------------------------------------------------------------------
  484. //
  485. // Member: CFat::Allocate, public
  486. //
  487. // Synposis: Allocates a chain within a FAT
  488. //
  489. // Effects: Modifies a single sector within the fat. Causes a
  490. // one sector stream write.
  491. //
  492. // Arguments: [ulSize] -- Number of sectors to allocate in chain
  493. //
  494. // Returns: Sector ID of first sector in chain
  495. //
  496. // Algorithm: Use repetitive calls to GetFree to construct a new chain
  497. //
  498. // History: 18-Jul-91 PhilipLa Created.
  499. // 17-Aug-91 PhilipLa Added dirty bits opt (Dump)
  500. //
  501. // Notes:
  502. //
  503. //---------------------------------------------------------------------------
  504. inline SCODE CFat::Allocate(ULONG ulSize, SECT * psectFirst)
  505. {
  506. return GetFree(ulSize, psectFirst, GF_WRITE);
  507. }
  508. //+---------------------------------------------------------------------------
  509. //
  510. // Member: CFat::SetNoScratch, public
  511. //
  512. // Synopsis: Set the fat for use in noscratch processing
  513. //
  514. // Arguments: [pfatNoScratch] -- Pointer to fat to use
  515. //
  516. // Returns: void
  517. //
  518. // History: 10-Mar-95 PhilipLa Created
  519. //
  520. //----------------------------------------------------------------------------
  521. inline void CFat::SetNoScratch(CFat *pfatNoScratch)
  522. {
  523. _pfatNoScratch = P_TO_BP(CBasedFatPtr, pfatNoScratch);
  524. }
  525. //+---------------------------------------------------------------------------
  526. //
  527. // Member: CFat::SetNoSnapshot, public
  528. //
  529. // Synopsis: Set the no-snapshot sect marker for commits
  530. //
  531. // Arguments: [sectNosnapshot] -- Sect to set.
  532. //
  533. // Returns: void
  534. //
  535. // History: 18-Oct-95 PhilipLa Created
  536. //
  537. //----------------------------------------------------------------------------
  538. inline void CFat::SetNoSnapshot(SECT sectNoSnapshot)
  539. {
  540. _sectNoSnapshot = sectNoSnapshot;
  541. if (sectNoSnapshot != 0)
  542. {
  543. _ulFreeSects = MAX_ULONG;
  544. _sectNoSnapshotFree = _sectNoSnapshot;
  545. _sectMax = _sectNoSnapshot;
  546. #if DBG == 1
  547. SCODE sc;
  548. SECT sectLast;
  549. msfChk(FindLast(&sectLast));
  550. msfAssert((_sectMax == sectLast) &&
  551. aMsg("_sectMax doesn't match actual last sector"));
  552. Err:
  553. ;
  554. #endif
  555. }
  556. }
  557. inline SECT CFat::GetNoSnapshot(void)
  558. {
  559. return _sectNoSnapshot;
  560. }
  561. inline SECT CFat::GetNoSnapshotFree(void)
  562. {
  563. return _sectNoSnapshotFree;
  564. }
  565. inline void CFat::ResetNoSnapshotFree(void)
  566. {
  567. _sectNoSnapshotFree = ENDOFCHAIN;
  568. }
  569. inline void CFat::InitRangeLocksSector ()
  570. {
  571. msfAssert (_uFatShift != 0);
  572. const ULONG ulHeaderSize = 1 << (_uFatShift + 2);
  573. SECT sect = (OLOCKREGIONEND - ulHeaderSize) >> (_uFatShift + 2);
  574. SectToPair(sect, &_ipfsRangeLocks, &_isectRangeLocks);
  575. }
  576. inline BOOL CFat::IsRangeLocksSector (SECT sect)
  577. {
  578. FSINDEX ipfs;
  579. FSOFFSET isect;
  580. SectToPair(sect, &ipfs, &isect);
  581. return (ipfs == _ipfsRangeLocks && isect == _isectRangeLocks);
  582. }
  583. inline ULONG CFat::GetFatVectorLength ()
  584. {
  585. return _cfsTable;
  586. }
  587. #endif //__FAT_HXX__