Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

744 lines
17 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. *ppfs = NULL; // should be NULL on failure for ReleaseGetFreeStruct
  169. sc = CPagedVector::GetTable(iTable, dwFlags, (void **)ppfs);
  170. if (sc == STG_S_NEWPAGE)
  171. {
  172. (*ppfs)->Init(_csectBlock);
  173. }
  174. return sc;
  175. }
  176. //CSEG determines the maximum number of segments that will be
  177. //returned by a single Contig call.
  178. #define CSEG 32
  179. //+-------------------------------------------------------------------------
  180. //
  181. // Class: SSegment (seg)
  182. //
  183. // Purpose: Used for contiguity tables for multi-sector reads and
  184. // writes.
  185. //
  186. // Interface: None.
  187. //
  188. // History: 16-Aug-91 PhilipLa Created.
  189. //
  190. // Notes:
  191. //
  192. //--------------------------------------------------------------------------
  193. struct SSegment {
  194. public:
  195. ULONG ulOffset;
  196. SECT sectStart;
  197. ULONG cSect;
  198. };
  199. inline SECT SegStart(SSegment seg)
  200. {
  201. return seg.sectStart;
  202. }
  203. inline SECT SegEnd(SSegment seg)
  204. {
  205. return seg.sectStart + seg.cSect - 1;
  206. }
  207. inline ULONG SegLength(SSegment seg)
  208. {
  209. return seg.cSect;
  210. }
  211. inline ULONG SegStartOffset(SSegment seg)
  212. {
  213. return seg.ulOffset;
  214. }
  215. inline ULONG SegEndOffset(SSegment seg)
  216. {
  217. return seg.ulOffset + seg.cSect - 1;
  218. }
  219. class CMStream;
  220. #define GF_READONLY TRUE
  221. #define GF_WRITE FALSE
  222. class CFat;
  223. SAFE_DFBASED_PTR(CBasedFatPtr, CFat);
  224. //+----------------------------------------------------------------------
  225. //
  226. // Class: CFat (fat)
  227. //
  228. // Purpose: Main interface to allocation routines
  229. //
  230. // Interface: Allocate - allocates new chain in the FAT
  231. // Extend - Extends an existing FAT chain
  232. // GetNext - Returns next sector in a chain
  233. // GetSect - Returns nth sector in a chain
  234. // GetESect - Returns nth sector in a chain, extending
  235. // if necessary
  236. // GetLength - Returns the # of sectors in a chain
  237. // setup - Initializes for an existing stream
  238. // setupnew - Initializes for a new stream
  239. //
  240. // checksanity - Debugging routine
  241. //
  242. // History: 18-Jul-91 PhilipLa Created.
  243. // 17-Aug-91 PhilipLa Added dirty and full bits
  244. // Notes:
  245. //
  246. //-----------------------------------------------------------------------
  247. struct SGetFreeStruct;
  248. class CFat
  249. {
  250. public:
  251. CFat(SID sid);
  252. CFat(CFat *pfatOld);
  253. ~CFat();
  254. VOID Empty(VOID);
  255. inline void SetNoScratch(CFat *pfatNoScratch);
  256. inline void SetNoSnapshot(SECT sectNoSnapshot);
  257. inline SECT GetNoSnapshot(void);
  258. inline SECT GetNoSnapshotFree(void);
  259. inline void ResetNoSnapshotFree(void);
  260. SCODE ResizeNoSnapshot(void);
  261. inline SCODE Allocate(ULONG ulSize, SECT *psectFirst);
  262. SCODE GetNext(const SECT sect, SECT * psRet);
  263. SCODE GetSect(
  264. SECT sectStart,
  265. ULONG ulOffset,
  266. SECT *psectReturn);
  267. SCODE GetESect(
  268. SECT sectStart,
  269. ULONG ulOffset,
  270. SECT *psectReturn);
  271. SCODE SetNext(SECT sectFirst, SECT sectNext);
  272. SCODE GetFree(ULONG ulCount, SECT * sect, BOOL fReadOnly);
  273. SCODE GetFreeContig(ULONG ulCount,
  274. SSegment STACKBASED *aseg,
  275. ULONG cSeg,
  276. ULONG *pcSegReturned);
  277. SCODE ReserveSects(ULONG cSect);
  278. SCODE GetLength(SECT sect, ULONG * pulRet);
  279. SCODE SetChainLength(SECT,ULONG);
  280. SCODE Init(
  281. CMStream *pmsParent,
  282. FSINDEX cFatSect,
  283. BOOL fConvert);
  284. SCODE InitNew(CMStream *pmsParent);
  285. void InitCopy(CFat *pfatOld);
  286. SCODE InitConvert(
  287. CMStream *pmsParent,
  288. ULONG cbSize);
  289. SCODE InitScratch(CFat *pfat, BOOL fNew);
  290. SCODE Remap(
  291. SECT sectStart,
  292. ULONG oStart,
  293. ULONG ulRunLength,
  294. SECT *psectOldStart,
  295. SECT *psectNewStart,
  296. SECT *psectOldEnd,
  297. SECT *psectNewEnd);
  298. inline SCODE QueryRemapped(const SECT sect);
  299. SCODE DirtyAll();
  300. inline SECT GetLast(VOID) const;
  301. inline SCODE GetFreeSectCount(ULONG *pcFreeSects);
  302. SCODE CountSectType(ULONG * pulRet,
  303. SECT sectStart,
  304. SECT sectEnd,
  305. SECT sectType);
  306. inline VOID ResetCopyOnWrite(VOID);
  307. inline VOID SetCopyOnWrite(CFat *pfat, SECT sectLast);
  308. inline VOID ResetUnmarkedSects(VOID);
  309. SCODE FindLast(SECT *psectRet);
  310. SCODE FindMaxSect(SECT *psectRet);
  311. inline SCODE GetMaxSect(SECT *psectRet);
  312. SCODE Contig(
  313. SSegment STACKBASED *aseg,
  314. BOOL fWrite,
  315. SECT sect,
  316. ULONG ulLength,
  317. ULONG *pcSeg);
  318. inline SCODE Flush(VOID);
  319. inline void SetParent(CMStream *pms);
  320. SCODE Resize(ULONG);
  321. inline BOOL IsRangeLocksSector (SECT sect);
  322. #if DBG == 1
  323. SCODE checksanity(SECT);
  324. void CheckFreeCount(void);
  325. #else
  326. #define CheckFreeCount()
  327. #endif
  328. private:
  329. inline SCODE IsFree(SECT sect);
  330. inline SCODE IsSectType(SECT sect, SECT sectType);
  331. inline SCODE MarkSect(SGetFreeStruct *pgf);
  332. inline void InitGetFreeStruct(SGetFreeStruct *pgf);
  333. inline void ReleaseGetFreeStruct(SGetFreeStruct *pgf);
  334. CFatVector _fv;
  335. CBasedMStreamPtr _pmsParent;
  336. const SID _sid;
  337. CBasedFatPtr _pfatReal;
  338. CBasedFatPtr _pfatNoScratch;
  339. //When committing in no-snapshot mode, all free sectors must
  340. // be greater than _sectNoSnapshot.
  341. SECT _sectNoSnapshot;
  342. SECT _sectNoSnapshotFree;
  343. USHORT _uFatShift;
  344. USHORT _uFatMask;
  345. FSINDEX _cfsTable;
  346. ULONG _ulFreeSects;
  347. ULONG _cUnmarkedSects;
  348. SECT _sectFirstFree;
  349. SECT _sectLastUsed;
  350. SECT _sectMax;
  351. FSINDEX _ipfsRangeLocks;
  352. FSOFFSET _isectRangeLocks;
  353. SCODE CountFree(ULONG * ulRet);
  354. SCODE Extend(SECT,ULONG);
  355. inline VOID SectToPair(
  356. SECT sect,
  357. FSINDEX *pipfs,
  358. FSOFFSET *pisect) const;
  359. inline SECT PairToSect(FSINDEX ipfs, FSOFFSET isect) const;
  360. friend class CDIFat;
  361. inline void InitRangeLocksSector ();
  362. inline ULONG GetFatVectorLength ();
  363. };
  364. inline SECT CFat::GetLast(VOID) const
  365. {
  366. return _sectLastUsed;
  367. }
  368. inline SCODE CFat::GetFreeSectCount(ULONG *pcFreeSects)
  369. {
  370. SCODE sc = S_OK;
  371. if(MAX_ULONG == _ulFreeSects)
  372. {
  373. msfChk(CountFree(&_ulFreeSects));
  374. }
  375. *pcFreeSects = _ulFreeSects;
  376. Err:
  377. return sc;
  378. }
  379. inline VOID CFat::ResetCopyOnWrite(VOID)
  380. {
  381. _sectLastUsed = 0;
  382. //Reset _sectFirstFree since this change can conceivably open up
  383. // new free sectors before the _sectFirstFree used in COW mode.
  384. _ulFreeSects = MAX_ULONG;
  385. _sectFirstFree = 0;
  386. _sectMax = ENDOFCHAIN;
  387. _fv.ResetBits();
  388. _pfatReal = NULL;
  389. _cUnmarkedSects = 0;
  390. }
  391. inline VOID CFat::ResetUnmarkedSects(VOID)
  392. {
  393. _cUnmarkedSects = 0;
  394. CheckFreeCount();
  395. }
  396. inline VOID CFat::SetCopyOnWrite(CFat *pfat, SECT sectLast)
  397. {
  398. msfAssert((_cUnmarkedSects == 0) &&
  399. aMsg("Unmarked sectors at enter copy-on-write."));
  400. _pfatReal = P_TO_BP(CBasedFatPtr, pfat);
  401. _sectLastUsed = sectLast;
  402. _sectFirstFree = 0;
  403. if (_pfatNoScratch != NULL)
  404. {
  405. _ulFreeSects = MAX_ULONG;
  406. _fv.ResetBits();
  407. }
  408. #if DBG == 1
  409. CheckFreeCount();
  410. #endif
  411. }
  412. inline VOID CFat::SectToPair(SECT sect,
  413. FSINDEX *pipfs,
  414. FSOFFSET *pisect) const
  415. {
  416. *pipfs = (FSINDEX)(sect >> _uFatShift);
  417. *pisect = (FSOFFSET)(sect & _uFatMask);
  418. }
  419. inline SECT CFat::PairToSect(FSINDEX ipfs, FSOFFSET isect) const
  420. {
  421. return (ipfs << _uFatShift) + isect;
  422. }
  423. inline SCODE CFat::GetMaxSect(SECT *psectRet)
  424. {
  425. SCODE sc;
  426. msfChk(FindMaxSect(&_sectMax));
  427. *psectRet = _sectMax;
  428. Err:
  429. return sc;
  430. }
  431. inline SCODE CFat::QueryRemapped(const SECT sect)
  432. {
  433. SCODE sc = S_FALSE;
  434. SECT sectNew;
  435. if ((sect == ENDOFCHAIN) || (sect >= _sectLastUsed))
  436. {
  437. sc = S_OK;
  438. }
  439. else
  440. {
  441. msfChk(_pfatReal->GetNext(sect, &sectNew));
  442. if (sectNew == FREESECT)
  443. {
  444. sc = S_OK;
  445. }
  446. else
  447. {
  448. sc = S_FALSE;
  449. }
  450. }
  451. Err:
  452. return sc;
  453. }
  454. inline void CFat::SetParent(CMStream *pms)
  455. {
  456. _pmsParent = P_TO_BP(CBasedMStreamPtr, pms);
  457. _fv.SetParent(pms);
  458. }
  459. //+-------------------------------------------------------------------------
  460. //
  461. // Member: CFat::Flush, public
  462. //
  463. // Synposis: Write all modified FatSects out to stream
  464. //
  465. // Effects: Resets all dirty bit fields on FatSects
  466. //
  467. // Arguments: Void
  468. //
  469. // Returns: S_OK if call completed OK.
  470. // Error code of parent write otherwise.
  471. //
  472. // Algorithm: Linearly scan through FatSects, writing any sector
  473. // that has the dirty bit set. Reset all dirty bits.
  474. //
  475. // History: 17-Aug-91 PhilipLa Created.
  476. //
  477. // Notes:
  478. //
  479. //---------------------------------------------------------------------------
  480. inline SCODE CFat::Flush(VOID)
  481. {
  482. return _fv.Flush();
  483. }
  484. //+-------------------------------------------------------------------------
  485. //
  486. // Member: CFat::Allocate, public
  487. //
  488. // Synposis: Allocates a chain within a FAT
  489. //
  490. // Effects: Modifies a single sector within the fat. Causes a
  491. // one sector stream write.
  492. //
  493. // Arguments: [ulSize] -- Number of sectors to allocate in chain
  494. //
  495. // Returns: Sector ID of first sector in chain
  496. //
  497. // Algorithm: Use repetitive calls to GetFree to construct a new chain
  498. //
  499. // History: 18-Jul-91 PhilipLa Created.
  500. // 17-Aug-91 PhilipLa Added dirty bits opt (Dump)
  501. //
  502. // Notes:
  503. //
  504. //---------------------------------------------------------------------------
  505. inline SCODE CFat::Allocate(ULONG ulSize, SECT * psectFirst)
  506. {
  507. return GetFree(ulSize, psectFirst, GF_WRITE);
  508. }
  509. //+---------------------------------------------------------------------------
  510. //
  511. // Member: CFat::SetNoScratch, public
  512. //
  513. // Synopsis: Set the fat for use in noscratch processing
  514. //
  515. // Arguments: [pfatNoScratch] -- Pointer to fat to use
  516. //
  517. // Returns: void
  518. //
  519. // History: 10-Mar-95 PhilipLa Created
  520. //
  521. //----------------------------------------------------------------------------
  522. inline void CFat::SetNoScratch(CFat *pfatNoScratch)
  523. {
  524. _pfatNoScratch = P_TO_BP(CBasedFatPtr, pfatNoScratch);
  525. }
  526. //+---------------------------------------------------------------------------
  527. //
  528. // Member: CFat::SetNoSnapshot, public
  529. //
  530. // Synopsis: Set the no-snapshot sect marker for commits
  531. //
  532. // Arguments: [sectNosnapshot] -- Sect to set.
  533. //
  534. // Returns: void
  535. //
  536. // History: 18-Oct-95 PhilipLa Created
  537. //
  538. //----------------------------------------------------------------------------
  539. inline void CFat::SetNoSnapshot(SECT sectNoSnapshot)
  540. {
  541. _sectNoSnapshot = sectNoSnapshot;
  542. if (sectNoSnapshot != 0)
  543. {
  544. _ulFreeSects = MAX_ULONG;
  545. _sectNoSnapshotFree = _sectNoSnapshot;
  546. _sectMax = _sectNoSnapshot;
  547. #if DBG == 1
  548. SCODE sc;
  549. SECT sectLast;
  550. msfChk(FindLast(&sectLast));
  551. msfAssert((_sectMax == sectLast) &&
  552. aMsg("_sectMax doesn't match actual last sector"));
  553. Err:
  554. ;
  555. #endif
  556. }
  557. }
  558. inline SECT CFat::GetNoSnapshot(void)
  559. {
  560. return _sectNoSnapshot;
  561. }
  562. inline SECT CFat::GetNoSnapshotFree(void)
  563. {
  564. return _sectNoSnapshotFree;
  565. }
  566. inline void CFat::ResetNoSnapshotFree(void)
  567. {
  568. _sectNoSnapshotFree = ENDOFCHAIN;
  569. }
  570. inline void CFat::InitRangeLocksSector ()
  571. {
  572. msfAssert (_uFatShift != 0);
  573. const ULONG ulHeaderSize = 1 << (_uFatShift + 2);
  574. SECT sect = (OLOCKREGIONEND - ulHeaderSize) >> (_uFatShift + 2);
  575. SectToPair(sect, &_ipfsRangeLocks, &_isectRangeLocks);
  576. }
  577. inline BOOL CFat::IsRangeLocksSector (SECT sect)
  578. {
  579. FSINDEX ipfs;
  580. FSOFFSET isect;
  581. SectToPair(sect, &ipfs, &isect);
  582. return (ipfs == _ipfsRangeLocks && isect == _isectRangeLocks);
  583. }
  584. inline ULONG CFat::GetFatVectorLength ()
  585. {
  586. return _cfsTable;
  587. }
  588. #endif //__FAT_HXX__