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.

1090 lines
33 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1995
  5. //
  6. // File: PropRec.hxx
  7. //
  8. // Contents: Record format for persistent property store
  9. //
  10. // Classes: CPropertyRecord
  11. //
  12. // History: 28-Dec-19 KyleP Created
  13. //
  14. //----------------------------------------------------------------------------
  15. #if !defined( __PROPREC_HXX__ )
  16. #define __PROPREC_HXX__
  17. class CStorageVariant;
  18. //+-------------------------------------------------------------------------
  19. //
  20. // Class: COnDiskPropertyRecord
  21. //
  22. // Purpose: Manipulates property values for single object/record
  23. //
  24. // History: 28-Dec-95 KyleP Created
  25. //
  26. // Notes: This class is like a template, that applies structure to a
  27. // single record of a memory-mapped file. Layout of data
  28. // members corresponds exactly to the on-disk version of the
  29. // property store.
  30. //
  31. // Layout of a record is as follows:
  32. // 1) Per-record state.
  33. // Count of additional records appended physically
  34. // to this one. Low bit used to indicate record
  35. // is in use.
  36. // Used space in variable property area (in dwords)
  37. // Link to overflow record.
  38. // 2) Existence bitmap. One dword / 16 properties, rounded up
  39. // to nearest dword. First bit (of two) indicates existence.
  40. // Second indicates existence is on overflow.
  41. // 3) Fixed length property storage.
  42. // 4) Variable length property storage. For each property:
  43. // Dword for size.
  44. // High word is size (in dwords) used by current property.
  45. // Low word is allocated size (in dwords).
  46. // Allocated space.
  47. //
  48. //--------------------------------------------------------------------------
  49. #pragma pack(4)
  50. class COnDiskPropertyRecord
  51. {
  52. enum ERecType { eVirgin = 0x0000,
  53. eTopLevel = 0xAAAA,
  54. eOverflow = 0x5555,
  55. eFree = 0xBBBB };
  56. public:
  57. inline void * operator new( size_t size, ULONG record, BYTE * pBase, ULONG culRec );
  58. inline void operator delete( void * p );
  59. inline static ULONG MinStreamSize( ULONG record, ULONG culRec );
  60. //
  61. // Block linking
  62. //
  63. inline WORKID OverflowBlock() const;
  64. inline void SetOverflowBlock( WORKID wid );
  65. inline WORKID PreviousBlock() const;
  66. inline void SetPreviousBlock( WORKID wid );
  67. //
  68. // Simple reads / writes.
  69. //
  70. void ReadFixed( ULONG Ordinal,
  71. ULONG Mask,
  72. ULONG oStart,
  73. ULONG cTotal,
  74. ULONG Type,
  75. PROPVARIANT & var,
  76. BYTE * pbExtra,
  77. unsigned * pcbExtra );
  78. BOOL ReadVariable( ULONG Ordinal,
  79. ULONG Mask,
  80. ULONG oStart,
  81. ULONG cTotal,
  82. ULONG cFixed,
  83. PROPVARIANT & var,
  84. BYTE * pbExtra,
  85. unsigned * pcbExtra );
  86. void WriteFixed( ULONG Ordinal,
  87. ULONG Mask,
  88. ULONG oStart,
  89. ULONG Type,
  90. ULONG cTotal,
  91. CStorageVariant const & var );
  92. BOOL WriteVariable( ULONG Ordinal,
  93. ULONG Mask,
  94. ULONG oStart,
  95. ULONG cTotal,
  96. ULONG cFixed,
  97. ULONG culRec,
  98. CStorageVariant const & var );
  99. //
  100. // Multi-record properties.
  101. //
  102. inline BOOL IsLongRecord();
  103. inline ULONG CountRecords() const;
  104. inline void MakeLongRecord( ULONG cRecords );
  105. inline BOOL IsValidType() const;
  106. inline BOOL IsValidInUseRecord( WORKID wid, ULONG cRecPerPage ) const;
  107. inline BOOL IsValidLength( WORKID wid, ULONG cRecPerPage ) const;
  108. inline BOOL AreLinksValid( WORKID widMax ) const;
  109. static ULONG CountRecordsToStore( ULONG cTotal, ULONG culRec, CStorageVariant const & var );
  110. //
  111. // Free list management
  112. //
  113. inline void MakeFreeRecord( ULONG cRecords, WORKID widNextFree,
  114. ULONG cNextFree, ULONG culRec );
  115. inline void MakeFreeRecord( WORKID widNextFree,
  116. ULONG cNextFree, ULONG culRec );
  117. inline ULONG GetNextFreeRecord() const;
  118. inline ULONG GetPreviousFreeRecord() const;
  119. inline ULONG GetNextFreeSize() const;
  120. inline void SetNextFree( WORKID widNextFree, ULONG cNextFree );
  121. inline void SetPreviousFreeRecord( WORKID widPreviousFree );
  122. //
  123. // Overflow records chaining.
  124. //
  125. inline ULONG GetOverflowChainLength() const;
  126. inline void IncrementOverflowChainLength();
  127. inline void SetOverflowChainLength( ULONG cOvfl );
  128. //
  129. // Existence / Use
  130. //
  131. inline BOOL IsInUse() const;
  132. inline BOOL IsTopLevel() const;
  133. inline BOOL IsOverflow() const;
  134. inline BOOL IsFreeRecord() const;
  135. inline void MakeNewTopLevel();
  136. inline void MakeNewOverflow();
  137. inline void ForceOverflow();
  138. inline void Clear( ULONG culRec );
  139. inline void ClearAll( ULONG culRec );
  140. inline BOOL HasProperties( ULONG cTotal );
  141. //
  142. // Reader / Writer
  143. //
  144. inline BOOL IsBeingWritten();
  145. inline BOOL IsBeingRead();
  146. inline void AddReader();
  147. inline void RemoveReader();
  148. inline void AddWriter();
  149. inline void RemoveWriter();
  150. # if CIDBG == 1
  151. inline BOOL LokIsBeingWrittenTwice();
  152. inline BOOL IsEmpty( ULONG culRec );
  153. # endif
  154. inline static ULONG FixedOverhead();
  155. inline BOOL IsStored( ULONG Ordinal, ULONG mask );
  156. inline BOOL IsStoredOnOverflow( ULONG Ordinal, ULONG mask );
  157. private:
  158. inline void SetStored( ULONG Ordinal, ULONG mask );
  159. inline void ClearStored( ULONG Ordinal, ULONG mask );
  160. inline void SetStoredOnOverflow( ULONG Ordinal, ULONG mask );
  161. inline void ClearStoredOnOverflow( ULONG Ordinal, ULONG mask );
  162. inline static ULONG UsedSize( ULONG ul );
  163. inline static ULONG AllocatedSize( ULONG ul ) { return (ul & 0xFFFF); }
  164. inline static void SetUsedSize( ULONG * pul, ULONG ul );
  165. inline static void SetAllocatedSize( ULONG * pul, ULONG ul );
  166. inline static void MarkOverflow( ULONG * pul );
  167. inline static BOOL IsOverflow( ULONG ul );
  168. inline ULONG FreeVariableSpace( ULONG cTotal, ULONG cFixed, ULONG oStart, ULONG cbRec );
  169. inline ULONG * FindVariableProp( ULONG Ordinal, ULONG cFixed, ULONG cTotal, ULONG oStart );
  170. static void RightCompress( ULONG * pul, ULONG cul, ULONG cRemaining );
  171. static ULONG * LeftCompress( ULONG * pul, ULONG cul, ULONG * pulEnd );
  172. USHORT _type; // Type of the record
  173. USHORT _cAdditionalRecords; // For long records, size (in records) of long record.
  174. DWORD _dwFlags; // Reserved for future use
  175. ULONG _culVariableUsed; // Bytes of record that are in use. Variable section only.
  176. WORKID _ulOverflow; // Pointer to overflow block.
  177. WORKID _ulPrev; // Pointer to the previous record. For toplevel
  178. // records, this will be the length of the
  179. // chain.
  180. ULONG _aul[1]; // Rest of block is variable:
  181. // a) Existence bits
  182. // b) Fixed size properties
  183. // c) Variable size properties
  184. };
  185. #pragma pack()
  186. //+---------------------------------------------------------------------------
  187. //
  188. // Member: COnDiskPropertyRecord::operator new, public
  189. //
  190. // Synopsis: Special operator new (computes offset of record in file)
  191. //
  192. // Arguments: [size] -- Required (and unused) parameter
  193. // [record] -- Record number
  194. // [pBase] -- Address of record 0
  195. // [culRec] -- Size in dwords of single record
  196. //
  197. // History: 27-Dec-95 KyleP Created.
  198. //
  199. //----------------------------------------------------------------------------
  200. inline void * COnDiskPropertyRecord::operator new( size_t size,
  201. ULONG record,
  202. BYTE * pBase,
  203. ULONG culRec )
  204. {
  205. ciDebugOut(( DEB_PROPSTORE,
  206. "PROPSTORE: Opening record at offset 0x%x (%d)\n",
  207. record * culRec * 4,
  208. record * culRec * 4 ));
  209. return pBase + record * culRec * 4;
  210. }
  211. //+---------------------------------------------------------------------------
  212. //
  213. // Member: COnDiskPropertyRecord::operator delete, public
  214. //
  215. // Synopsis: Just to make sure it isn't called...
  216. //
  217. // History: 27-Dec-95 KyleP Created.
  218. //
  219. //----------------------------------------------------------------------------
  220. inline void COnDiskPropertyRecord::operator delete( void * p )
  221. {
  222. // No action. This is mapped onto a file.
  223. }
  224. //+---------------------------------------------------------------------------
  225. //
  226. // Member: COnDiskPropertyRecord::IsLongRecord, public
  227. //
  228. // Returns: TRUE if record is long (consists of more than one
  229. // physically contiguous record).
  230. //
  231. // History: 27-Dec-95 KyleP Created.
  232. //
  233. //----------------------------------------------------------------------------
  234. inline BOOL COnDiskPropertyRecord::IsLongRecord()
  235. {
  236. return (_cAdditionalRecords != 0);
  237. }
  238. //+---------------------------------------------------------------------------
  239. //
  240. // Member: COnDiskPropertyRecord::CountRecords, public
  241. //
  242. // Returns: Size of record (in one-records)
  243. //
  244. // History: 27-Dec-95 KyleP Created.
  245. //
  246. //----------------------------------------------------------------------------
  247. inline ULONG COnDiskPropertyRecord::CountRecords() const
  248. {
  249. return _cAdditionalRecords + 1;
  250. }
  251. //+---------------------------------------------------------------------------
  252. //
  253. // Member: COnDiskPropertyRecord::MakeLongRecord, public
  254. //
  255. // Synopsis: Indicates record is long.
  256. //
  257. // Arguments: [cRecords] -- Number of physically contiguous records.
  258. //
  259. // History: 27-Dec-95 KyleP Created.
  260. //
  261. //----------------------------------------------------------------------------
  262. inline void COnDiskPropertyRecord::MakeLongRecord( ULONG cRecords )
  263. {
  264. Win4Assert( cRecords >= 1 );
  265. // Win4Assert( !HasProperties( 1 ) );
  266. _cAdditionalRecords = (USHORT) (cRecords - 1);
  267. }
  268. //+---------------------------------------------------------------------------
  269. //
  270. // Member: COnDiskProperyRecord::IsFreeRecord
  271. //
  272. // Synopsis: Tests if the current record is a Free record.
  273. //
  274. // History: 2-23-96 srikants Created
  275. //
  276. //----------------------------------------------------------------------------
  277. inline BOOL COnDiskPropertyRecord::IsFreeRecord() const
  278. {
  279. Win4Assert( 0 == _dwFlags ); // until we have some use for flags
  280. return eFree == _type;
  281. }
  282. //+---------------------------------------------------------------------------
  283. //
  284. // Member: COnDiskPropertyRecord::MakeFreeRecord
  285. //
  286. // Synopsis: Makes the current record a free record.
  287. //
  288. // Arguments: [ulNextFree] - The workid of the next free record
  289. // [cFree] - Size of next free record
  290. // [culRec] - Count of ULONGs per record.
  291. //
  292. // History: 4-11-96 srikants Created
  293. //
  294. // Notes: It is assumed that the "_cAdditionalRecords" is correctly set
  295. //
  296. //----------------------------------------------------------------------------
  297. inline void COnDiskPropertyRecord::MakeFreeRecord( WORKID ulNextFree,
  298. ULONG cFree,
  299. ULONG culRec )
  300. {
  301. Clear( culRec );
  302. SetNextFree( ulNextFree, cFree );
  303. }
  304. //+---------------------------------------------------------------------------
  305. //
  306. // Member: COnDiskPropertyRecord::MakeFreeRecord
  307. //
  308. // Synopsis: Makes the current record a free record of length "cRecords"
  309. //
  310. // Arguments: [cRecords] - Length of this block in "records"
  311. // [ulNextFree] - The next free record wid
  312. // [cFree] - Size of next free record
  313. // [culRec] - Count of ULONGs per record
  314. //
  315. // History: 4-11-96 srikants Created
  316. //
  317. //----------------------------------------------------------------------------
  318. inline void COnDiskPropertyRecord::MakeFreeRecord( ULONG cRecords,
  319. WORKID ulNextFree,
  320. ULONG cFree,
  321. ULONG culRec )
  322. {
  323. MakeLongRecord( cRecords );
  324. MakeFreeRecord( ulNextFree, cFree, culRec );
  325. }
  326. inline void COnDiskPropertyRecord::SetNextFree( WORKID widNextFree,
  327. ULONG cNextFree )
  328. {
  329. _ulOverflow = widNextFree;
  330. _culVariableUsed = cNextFree;
  331. }
  332. inline void COnDiskPropertyRecord::SetPreviousFreeRecord( WORKID widPrevFree )
  333. {
  334. _ulPrev = widPrevFree;
  335. }
  336. inline ULONG COnDiskPropertyRecord::GetNextFreeRecord() const
  337. {
  338. Win4Assert( eFree == _type );
  339. return _ulOverflow;
  340. }
  341. inline ULONG COnDiskPropertyRecord::GetPreviousFreeRecord() const
  342. {
  343. Win4Assert( eFree == _type );
  344. return _ulPrev;
  345. }
  346. inline ULONG COnDiskPropertyRecord::GetNextFreeSize() const
  347. {
  348. Win4Assert( eFree == _type );
  349. return _culVariableUsed;
  350. }
  351. //+---------------------------------------------------------------------------
  352. //
  353. // Member: COnDiskPropertyRecord::MinStreamSize, public
  354. //
  355. // Synopsis: Computes position of record in stream
  356. //
  357. // Arguments: [record] -- Record number
  358. // [culRec] -- Size in dwords of single record
  359. //
  360. // Returns: Minimum size stream that can hold this record.
  361. //
  362. // History: 27-Dec-95 KyleP Created.
  363. //
  364. //----------------------------------------------------------------------------
  365. inline ULONG COnDiskPropertyRecord::MinStreamSize( ULONG record, ULONG culRec )
  366. {
  367. return (record + 1) * culRec * 4;
  368. }
  369. //+---------------------------------------------------------------------------
  370. //
  371. // Member: COnDiskPropertyRecord::OverflowBlock, public
  372. //
  373. // Returns: Overflow block id (zero if no overflow block)
  374. //
  375. // History: 27-Dec-95 KyleP Created.
  376. //
  377. // Notes: For a free list record, this will be a link to the
  378. // next free block in the list.
  379. //
  380. //----------------------------------------------------------------------------
  381. inline WORKID COnDiskPropertyRecord::OverflowBlock() const
  382. {
  383. return _ulOverflow;
  384. }
  385. //+---------------------------------------------------------------------------
  386. //
  387. // Member: COnDiskPropertyRecord::SetOverflowBlock, public
  388. //
  389. // Synopsis: Sets overflow block id (zero if no overflow block)
  390. //
  391. // Arguments: [wid] -- Workid (record number) of link
  392. //
  393. // History: 27-Dec-95 KyleP Created.
  394. //
  395. //----------------------------------------------------------------------------
  396. inline void COnDiskPropertyRecord::SetOverflowBlock( WORKID wid )
  397. {
  398. _ulOverflow = wid;
  399. }
  400. //+---------------------------------------------------------------------------
  401. //
  402. // Member: COnDiskPropertyRecord::PreviousBlock
  403. //
  404. // Synopsis: Returns the previous block value.
  405. //
  406. // History: 4-10-96 srikants Created
  407. //
  408. // Notes: For a top-level record, this will be the length of the
  409. // overflow chain records.
  410. // For a free list record, this will be the size of the next
  411. // free block in the list.
  412. //
  413. //----------------------------------------------------------------------------
  414. inline WORKID COnDiskPropertyRecord::PreviousBlock() const
  415. {
  416. return _ulPrev;
  417. }
  418. //+---------------------------------------------------------------------------
  419. //
  420. // Member: COnDiskPropertyRecord::SetPreviousBlock
  421. //
  422. // Synopsis: Updates the previous block value.
  423. //
  424. // Arguments: [widPrev] - Value of the previous block
  425. //
  426. // History: 4-10-96 srikants Created
  427. //
  428. //----------------------------------------------------------------------------
  429. inline void COnDiskPropertyRecord::SetPreviousBlock( WORKID widPrev )
  430. {
  431. Win4Assert( eOverflow == _type );
  432. _ulPrev = widPrev;
  433. }
  434. inline ULONG COnDiskPropertyRecord::GetOverflowChainLength() const
  435. {
  436. Win4Assert( eTopLevel == _type );
  437. return _ulPrev;
  438. }
  439. inline void COnDiskPropertyRecord::IncrementOverflowChainLength()
  440. {
  441. Win4Assert( eTopLevel == _type );
  442. _ulPrev++;
  443. }
  444. inline void COnDiskPropertyRecord::SetOverflowChainLength( ULONG cCount )
  445. {
  446. _ulPrev = cCount;
  447. }
  448. //+---------------------------------------------------------------------------
  449. //
  450. // Member: COnDiskPropertyRecord::IsInUse, public
  451. //
  452. // Returns: TRUE if record is in use.
  453. //
  454. // History: 27-Dec-95 KyleP Created.
  455. //
  456. //----------------------------------------------------------------------------
  457. inline BOOL COnDiskPropertyRecord::IsInUse() const
  458. {
  459. return eTopLevel == _type || eOverflow == _type;
  460. }
  461. //+---------------------------------------------------------------------------
  462. //
  463. // Member: COnDiskPropertyRecord::HasProperties, public
  464. //
  465. // Arguments: [cTotal] -- Total number of properties in record.
  466. //
  467. // Returns: TRUE if record has properties stored on it. May be
  468. // in use. Used for debugging.
  469. //
  470. // History: 22-Feb-96 KyleP Created.
  471. //
  472. //----------------------------------------------------------------------------
  473. inline BOOL COnDiskPropertyRecord::HasProperties( ULONG cTotal )
  474. {
  475. for ( ULONG cBitWords = ((cTotal-1) / 16) + 1; cBitWords > 0; cBitWords-- )
  476. {
  477. if ( _aul[cBitWords-1] != 0 )
  478. return TRUE;
  479. }
  480. return FALSE;
  481. }
  482. //+---------------------------------------------------------------------------
  483. //
  484. // Member: COnDiskPropertyRecord::MakeNewTopLevel
  485. //
  486. // Synopsis: Marks the current record as a top level record.
  487. //
  488. // History: 2-23-96 srikants Created
  489. //
  490. //----------------------------------------------------------------------------
  491. inline void COnDiskPropertyRecord::MakeNewTopLevel()
  492. {
  493. _type = eTopLevel;
  494. _ulPrev = _ulOverflow = 0; // Setting the length of overflow chain
  495. _culVariableUsed = 0;
  496. }
  497. //+---------------------------------------------------------------------------
  498. //
  499. // Member: COnDiskProperyRecord::IsTopLevel
  500. //
  501. // Synopsis: Tests if the current record is a TopLevel record.
  502. //
  503. // History: 2-23-96 srikants Created
  504. //
  505. //----------------------------------------------------------------------------
  506. inline BOOL COnDiskPropertyRecord::IsTopLevel() const
  507. {
  508. Win4Assert( 0 == _dwFlags ); // until we have some use for flags
  509. return eTopLevel == _type;
  510. }
  511. //+---------------------------------------------------------------------------
  512. //
  513. // Member: COnDiskPropertyRecord::MakeNewOverflow
  514. //
  515. // Synopsis: Marks the record as an overflow record
  516. //
  517. // History: 4-10-96 srikants Created
  518. //
  519. //----------------------------------------------------------------------------
  520. inline void COnDiskPropertyRecord::MakeNewOverflow()
  521. {
  522. _type = eOverflow;
  523. _ulPrev = _ulOverflow = 0;
  524. _culVariableUsed = 0;
  525. }
  526. inline void COnDiskPropertyRecord::ForceOverflow()
  527. {
  528. _type = eOverflow;
  529. }
  530. //+---------------------------------------------------------------------------
  531. //
  532. // Member: COnDiskPropertyRecord::IsOverflow
  533. //
  534. // Synopsis: Tests if this is an overflow record.
  535. //
  536. // History: 4-10-96 srikants Created
  537. //
  538. //----------------------------------------------------------------------------
  539. inline BOOL COnDiskPropertyRecord::IsOverflow() const
  540. {
  541. Win4Assert( 0 == _dwFlags ); // until we have some use for flags
  542. return eOverflow == _type;
  543. }
  544. //+---------------------------------------------------------------------------
  545. //
  546. // Member: COnDiskPropertyRecord::IsValidLength
  547. //
  548. // Synopsis: Tests if the length is valid for this record for the given
  549. // WORKID and records per page. A record can never span page and
  550. // so the WORKID will help us determine if the length is valid
  551. // or not.
  552. //
  553. // Arguments: [wid] - WORKID of this record
  554. // [cRecPerPage] - Number of records per page.
  555. //
  556. // History: 4-10-96 srikants Created
  557. //
  558. //----------------------------------------------------------------------------
  559. inline BOOL COnDiskPropertyRecord::IsValidLength( WORKID wid, ULONG cRecPerPage ) const
  560. {
  561. WORKID offset = wid % cRecPerPage;
  562. return offset+_cAdditionalRecords < cRecPerPage;
  563. }
  564. inline BOOL COnDiskPropertyRecord::IsValidInUseRecord( WORKID wid, ULONG cRecPerPage ) const
  565. {
  566. if ( eTopLevel == _type || eOverflow == _type )
  567. {
  568. return IsValidLength( wid, cRecPerPage );
  569. }
  570. else
  571. return FALSE;
  572. }
  573. inline BOOL COnDiskPropertyRecord::IsValidType() const
  574. {
  575. return eTopLevel == _type ||
  576. eOverflow == _type ||
  577. eFree == _type ||
  578. eVirgin == _type;
  579. }
  580. //+---------------------------------------------------------------------------
  581. //
  582. // Member: COnDiskPropertyRecord::AreLinksValid
  583. //
  584. // Synopsis: Tests if the forward and backward links are valid given the
  585. // widMax.
  586. //
  587. // Arguments: [widMax] - The maximum workid that is in use for the entire
  588. // property store.
  589. //
  590. // History: 4-10-96 srikants Created
  591. //
  592. //----------------------------------------------------------------------------
  593. inline BOOL COnDiskPropertyRecord::AreLinksValid( WORKID widMax ) const
  594. {
  595. return _ulOverflow <= widMax && _ulPrev <= widMax;
  596. }
  597. //+---------------------------------------------------------------------------
  598. //
  599. // Member: COnDiskPropertyRecord::Clear, public
  600. //
  601. // Synopsis: Zero complete record.
  602. //
  603. // Arguments: [culRec] -- Size in dwords of record
  604. //
  605. // History: 27-Dec-95 KyleP Created.
  606. //
  607. //----------------------------------------------------------------------------
  608. inline void COnDiskPropertyRecord::Clear( ULONG culRec )
  609. {
  610. Win4Assert( 2 == offsetof( COnDiskPropertyRecord, _cAdditionalRecords ) );
  611. Win4Assert( 4 == offsetof( COnDiskPropertyRecord, _dwFlags ) );
  612. RtlZeroMemory( &this->_dwFlags,
  613. culRec * CountRecords() * sizeof (ULONG) -
  614. offsetof( COnDiskPropertyRecord, _dwFlags ) );
  615. _type = eFree;
  616. }
  617. //+---------------------------------------------------------------------------
  618. //
  619. // Member: COnDiskPropertyRecord::ClearAll
  620. //
  621. // Synopsis: Clears the entire record to be 0 filled.
  622. //
  623. // Arguments: [culRec] -
  624. //
  625. // History: 3-25-96 srikants Created
  626. //
  627. //----------------------------------------------------------------------------
  628. inline void COnDiskPropertyRecord::ClearAll( ULONG culRec )
  629. {
  630. Clear( culRec );
  631. _cAdditionalRecords = 0;
  632. _type = 0;
  633. }
  634. //+---------------------------------------------------------------------------
  635. //
  636. // Member: COnDiskPropertyRecord::FixedOverhead, public
  637. //
  638. // Returns: Size of class, sans uninterpreted variable area.
  639. //
  640. // History: 27-Dec-95 KyleP Created.
  641. //
  642. //----------------------------------------------------------------------------
  643. inline ULONG COnDiskPropertyRecord::FixedOverhead()
  644. {
  645. return ((ULONG) &((COnDiskPropertyRecord *)0)->_aul[0]) / 4;
  646. }
  647. //+---------------------------------------------------------------------------
  648. //
  649. // Member: COnDiskPropertyRecord::IsStored, public
  650. //
  651. // Synopsis: Test property existence.
  652. //
  653. // Arguments: [Ordinal] -- Position of property in list.
  654. // [mask] -- Bitmask of ordinal. Pre-computed for efficiency.
  655. //
  656. // Returns: TRUE if property at [Ordinal] is stored.
  657. //
  658. // History: 27-Dec-95 KyleP Created.
  659. //
  660. //----------------------------------------------------------------------------
  661. inline BOOL COnDiskPropertyRecord::IsStored( ULONG Ordinal, ULONG mask )
  662. {
  663. return ( (_aul[Ordinal / 16] & mask) != 0 );
  664. }
  665. //+---------------------------------------------------------------------------
  666. //
  667. // Member: COnDiskPropertyRecord::SetStored, public
  668. //
  669. // Synopsis: Marks property as stored.
  670. //
  671. // Arguments: [Ordinal] -- Position of property in list.
  672. // [mask] -- Bitmask of ordinal. Pre-computed for efficiency.
  673. //
  674. // History: 27-Dec-95 KyleP Created.
  675. //
  676. //----------------------------------------------------------------------------
  677. inline void COnDiskPropertyRecord::SetStored( ULONG Ordinal, ULONG mask )
  678. {
  679. _aul[Ordinal / 16] |= mask;
  680. }
  681. //+---------------------------------------------------------------------------
  682. //
  683. // Member: COnDiskPropertyRecord::ClearStored, public
  684. //
  685. // Synopsis: Marks property as not stored.
  686. //
  687. // Arguments: [Ordinal] -- Position of property in list.
  688. // [mask] -- Bitmask of ordinal. Pre-computed for efficiency.
  689. //
  690. // History: 27-Dec-95 KyleP Created.
  691. //
  692. //----------------------------------------------------------------------------
  693. inline void COnDiskPropertyRecord::ClearStored( ULONG Ordinal, ULONG mask )
  694. {
  695. _aul[Ordinal / 16] &= ~mask;
  696. }
  697. //+---------------------------------------------------------------------------
  698. //
  699. // Member: COnDiskPropertyRecord::IsStoredOnOverflow, public
  700. //
  701. // Synopsis: Test property overflow.
  702. //
  703. // Arguments: [Ordinal] -- Position of property in list.
  704. // [mask] -- Bitmask of ordinal. Pre-computed for efficiency.
  705. //
  706. // Returns: TRUE if property at [Ordinal] is stored on overflow record.
  707. //
  708. // History: 27-Dec-95 KyleP Created.
  709. //
  710. //----------------------------------------------------------------------------
  711. inline BOOL COnDiskPropertyRecord::IsStoredOnOverflow( ULONG Ordinal, ULONG mask )
  712. {
  713. Win4Assert( ( mask & (mask - 1) ) == 0 );
  714. return ( (_aul[Ordinal / 16] & (mask << 1)) != 0 );
  715. }
  716. //+---------------------------------------------------------------------------
  717. //
  718. // Member: COnDiskPropertyRecord::SetStoredOnOverflow, public
  719. //
  720. // Synopsis: Marks property as stored on overflow record.
  721. //
  722. // Arguments: [Ordinal] -- Position of property in list.
  723. // [mask] -- Bitmask of ordinal. Pre-computed for efficiency.
  724. //
  725. // History: 27-Dec-95 KyleP Created.
  726. //
  727. //----------------------------------------------------------------------------
  728. inline void COnDiskPropertyRecord::SetStoredOnOverflow( ULONG Ordinal, ULONG mask )
  729. {
  730. Win4Assert( ( mask & (mask - 1) ) == 0 );
  731. _aul[Ordinal / 16] |= (mask << 1);
  732. }
  733. //+---------------------------------------------------------------------------
  734. //
  735. // Member: COnDiskPropertyRecord::ClearStoredOnOverflow, public
  736. //
  737. // Synopsis: Marks property as not stored on overflow record.
  738. //
  739. // Arguments: [Ordinal] -- Position of property in list.
  740. // [mask] -- Bitmask of ordinal. Pre-computed for efficiency.
  741. //
  742. // History: 27-Dec-95 KyleP Created.
  743. //
  744. //----------------------------------------------------------------------------
  745. inline void COnDiskPropertyRecord::ClearStoredOnOverflow( ULONG Ordinal, ULONG mask )
  746. {
  747. Win4Assert( ( mask & (mask - 1) ) == 0 );
  748. _aul[Ordinal / 16] &= ~(mask << 1);
  749. }
  750. //+---------------------------------------------------------------------------
  751. //
  752. // Member: COnDiskPropertyRecord::UsedSize, public
  753. //
  754. // Arguments: [ul] -- Dword containing used/alloced size fields.
  755. //
  756. // Returns: Used size.
  757. //
  758. // History: 27-Dec-95 KyleP Created.
  759. //
  760. //----------------------------------------------------------------------------
  761. inline ULONG COnDiskPropertyRecord::UsedSize( ULONG ul )
  762. {
  763. ULONG size = ul >> 16;
  764. if ( size == 0xFFFF)
  765. size = 0;
  766. return size;
  767. }
  768. //+---------------------------------------------------------------------------
  769. //
  770. // Member: COnDiskPropertyRecord::SetUsedSize, public
  771. //
  772. // Synopsis: Sets used size.
  773. //
  774. // Arguments: [pul] -- Pointer to dword containing used/alloced size fields.
  775. // [ul] -- New used size
  776. //
  777. // History: 27-Dec-95 KyleP Created.
  778. //
  779. //----------------------------------------------------------------------------
  780. inline void COnDiskPropertyRecord::SetUsedSize( ULONG * pul, ULONG ul )
  781. {
  782. Win4Assert( AllocatedSize(*pul) >= ul || ul == 0xFFFF );
  783. *pul = (*pul & 0xFFFF) | (ul << 16);
  784. }
  785. //+---------------------------------------------------------------------------
  786. //
  787. // Member: COnDiskPropertyRecord::SetAllocatedSize, public
  788. //
  789. // Synopsis: Sets allocated size.
  790. //
  791. // Arguments: [pul] -- Pointer to dword containing used/alloced size fields.
  792. // [ul] -- New allocated size
  793. //
  794. // History: 27-Dec-95 KyleP Created.
  795. //
  796. //----------------------------------------------------------------------------
  797. inline void COnDiskPropertyRecord::SetAllocatedSize( ULONG * pul, ULONG ul )
  798. {
  799. Win4Assert( (ul >> 16) == 0 );
  800. *pul = (*pul & 0xFFFF0000) | ul;
  801. }
  802. //+---------------------------------------------------------------------------
  803. //
  804. // Member: COnDiskPropertyRecord::MarkOverflow, public
  805. //
  806. // Synopsis: Indicates variable stored in overflow record.
  807. //
  808. // Arguments: [pul] -- Pointer to dword containing used/alloced size fields.
  809. //
  810. // History: 27-Dec-95 KyleP Created.
  811. //
  812. //----------------------------------------------------------------------------
  813. inline void COnDiskPropertyRecord::MarkOverflow( ULONG * pul )
  814. {
  815. SetUsedSize( pul, 0xFFFF );
  816. }
  817. //+---------------------------------------------------------------------------
  818. //
  819. // Member: COnDiskPropertyRecord::IsOverflow, public
  820. //
  821. // Arguments: [ul] -- dword containing used/alloced size fields.
  822. //
  823. // Returns: TRUE if variable is in overflow record.
  824. //
  825. // History: 27-Dec-95 KyleP Created.
  826. //
  827. //----------------------------------------------------------------------------
  828. inline BOOL COnDiskPropertyRecord::IsOverflow( ULONG ul )
  829. {
  830. return ((ul & 0xFFFF0000) == 0xFFFF0000);
  831. }
  832. //+---------------------------------------------------------------------------
  833. //
  834. // Member: COnDiskPropertyRecord::FreeVariableSpace, public
  835. //
  836. // Synopsis: Compute free space.
  837. //
  838. // Arguments: [cTotal] -- Total number of properties in record.
  839. // [cFixed] -- Count of fixed properties in record.
  840. // [oStart] -- Offset to start of variable storage area
  841. // [culRec] -- Size in dwords of record.
  842. //
  843. // Returns: Unused variable space in record.
  844. //
  845. // History: 27-Dec-95 KyleP Created.
  846. //
  847. //----------------------------------------------------------------------------
  848. inline ULONG COnDiskPropertyRecord::FreeVariableSpace( ULONG cTotal,
  849. ULONG cFixed,
  850. ULONG oStart,
  851. ULONG culRec )
  852. {
  853. LONG lFree = (culRec * CountRecords()) - // Record size
  854. FixedOverhead() - // Fixed overhead
  855. ((cTotal - 1) / 16 + 1) - // Existence bitmap
  856. oStart - // Fixed property storage
  857. (cTotal - cFixed) - // Used/Alloc sizes
  858. _culVariableUsed; // Variable properties
  859. Win4Assert(lFree >= 0);
  860. return (ULONG) lFree;
  861. }
  862. //+---------------------------------------------------------------------------
  863. //
  864. // Member: COnDiskPropertyRecord::FindVariableProp, public
  865. //
  866. // Synopsis: Locate start of property.
  867. //
  868. // Arguments: [Ordinal] -- Ordinal of property to locate.
  869. // [cFixed] -- Count of fixed properties in record.
  870. // [cTotal] -- Total number of properties in record.
  871. // [oStart] -- Offset to start of variable storage area.
  872. //
  873. // Returns: Pointer to start of property
  874. //
  875. // History: 27-Dec-95 KyleP Created.
  876. //
  877. //----------------------------------------------------------------------------
  878. inline ULONG * COnDiskPropertyRecord::FindVariableProp( ULONG Ordinal,
  879. ULONG cFixed,
  880. ULONG cTotal,
  881. ULONG oStart )
  882. {
  883. ciDebugOut(( DEB_PROPSTORE,
  884. "Ordinal = %d, %d fixed, %d total, offset = 0x%x\n",
  885. Ordinal, cFixed, cTotal, oStart ));
  886. //
  887. // Start is after existance bitmap and fixed properties.
  888. //
  889. ULONG * pulVarRecord = &_aul[ (cTotal-1) / 16 + 1 + oStart];
  890. #if CIDBG
  891. ULONG culUsed = 0;
  892. #endif // CIDBG
  893. //
  894. // Skip over variable props. The "+1" is for the allocation dword.
  895. //
  896. for ( ULONG i = cFixed; i < Ordinal; i++ )
  897. {
  898. ciDebugOut(( DEB_PROPSTORE, "Ordinal %d starts at offset 0x%x (%d)\n",
  899. i,
  900. (ULONG)pulVarRecord - (ULONG)this,
  901. (ULONG)pulVarRecord - (ULONG)this ));
  902. #if CIDBG
  903. culUsed += UsedSize(*pulVarRecord);
  904. #endif
  905. pulVarRecord += AllocatedSize(*pulVarRecord) + 1;
  906. }
  907. ciDebugOut(( DEB_PROPSTORE, "Ordinal %d starts at offset 0x%x (%d)\n",
  908. i,
  909. (ULONG)pulVarRecord - (ULONG)this,
  910. (ULONG)pulVarRecord - (ULONG)this ));
  911. Win4Assert( culUsed + UsedSize(*pulVarRecord) <= _culVariableUsed );
  912. return pulVarRecord;
  913. }
  914. #if CIDBG == 1
  915. inline BOOL COnDiskPropertyRecord::IsEmpty( ULONG culRec )
  916. {
  917. BOOL fEmpty = ( 0 == _culVariableUsed &&
  918. 0 == _ulOverflow &&
  919. 0 == _ulPrev );
  920. for ( ULONG i = 0; i < (culRec-5); i++ )
  921. {
  922. if ( 0 != _aul[i] )
  923. {
  924. fEmpty = FALSE;
  925. break;
  926. }
  927. }
  928. return fEmpty;
  929. }
  930. #endif // CIDBG
  931. #endif // __PROPREC_HXX__