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.

763 lines
23 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1991 - 2002.
  5. //
  6. // File: PrpStMgr.hxx
  7. //
  8. // Contents: Two-level property store
  9. //
  10. // Classes: CPropStoreManager
  11. //
  12. // History: 22-Oct-97 KrishnaN Created
  13. //
  14. //----------------------------------------------------------------------------
  15. #pragma once
  16. #include <propstor.hxx>
  17. class CCompositePropRecord;
  18. class CCompositePropRecordForWrites;
  19. class CPrimaryPropRecord;
  20. class CPrimaryPropRecordForWrites;
  21. //+-------------------------------------------------------------------------
  22. //
  23. // Class: CPropStoreManager
  24. //
  25. // Purpose: Property store manager.
  26. //
  27. // History: 22-Oct-97 KrishnaN Created
  28. // 01-Nov-98 KLam Added cMegToLeaveOnDisk to constructors
  29. // Added _cMegToLeaveOnDisk private member
  30. //
  31. //--------------------------------------------------------------------------
  32. class CPropStoreManager
  33. {
  34. public:
  35. //
  36. // Two phase construction (to accomadate late-bound storage)
  37. //
  38. CPropStoreManager( ULONG cMegToLeaveOnDisk );
  39. ~CPropStoreManager();
  40. void FastInit( CiStorage * pStorage );
  41. void LongInit( BOOL & fWasDirty, ULONG & cInconsistencies,
  42. T_UpdateDoc pfnUpdateCallback, void const *pUserData );
  43. inline BOOL IsDirty();
  44. void Empty();
  45. //
  46. // Schema manipulation
  47. //
  48. inline BOOL CanStore( PROPID pid );
  49. inline unsigned Size( PROPID pid );
  50. inline ULONG Type( PROPID pid );
  51. inline DWORD StoreLevel( PROPID pid );
  52. inline BOOL CanBeModified( PROPID pid );
  53. ULONG_PTR BeginTransaction();
  54. void Setup( PROPID pid, ULONG vt, DWORD cbMaxLen,
  55. ULONG_PTR ulToken, BOOL fCanBeModified = TRUE,
  56. DWORD dwStoreLevel = PRIMARY_STORE);
  57. void EndTransaction( ULONG_PTR ulToken, BOOL fCommit,
  58. PROPID pidFixedPrimary,
  59. PROPID pidFixedSecondary );
  60. //
  61. // Backup
  62. //
  63. void MakeBackupCopy( IProgressNotify * pIProgressNotify,
  64. BOOL & fAbort,
  65. CiStorage & dstStorage,
  66. ICiEnumWorkids * pIWorkIds,
  67. IEnumString **ppFileList);
  68. //
  69. // Property storage/retrieval.
  70. //
  71. SCODE WriteProperty( WORKID wid, PROPID pid,
  72. CStorageVariant const & var );
  73. SCODE WriteProperty( CCompositePropRecordForWrites & PropRecord, PROPID pid,
  74. CStorageVariant const & var );
  75. SCODE WriteProperty( CPrimaryPropRecordForWrites & PropRecord,
  76. PROPID pid,
  77. CStorageVariant const & var );
  78. SCODE WriteProperty( DWORD dwStoreLevel,
  79. CCompositePropRecordForWrites & PropRecord,
  80. PROPID pid,
  81. CStorageVariant const & var );
  82. SCODE WritePrimaryProperty( WORKID wid, PROPID pid,
  83. CStorageVariant const & var );
  84. SCODE WritePrimaryProperty( CCompositePropRecordForWrites & PropRecord, PROPID pid,
  85. CStorageVariant const & var );
  86. SCODE WritePrimaryProperty( CPrimaryPropRecordForWrites & PropRecord,
  87. PROPID pid,
  88. CStorageVariant const & var );
  89. SCODE WriteSecondaryProperty( CCompositePropRecordForWrites & PropRecord, PROPID pid,
  90. CStorageVariant const & var );
  91. WORKID WritePropertyInNewRecord( PROPID pid,
  92. CStorageVariant const & var );
  93. BOOL ReadProperty( WORKID wid, PROPID pid, PROPVARIANT * pbData, unsigned * pcb);
  94. BOOL ReadProperty( WORKID wid, PROPID pid, PROPVARIANT & var, BYTE * pbExtra, unsigned * pcbExtra );
  95. BOOL ReadProperty( CCompositePropRecord & PropRecord, PROPID pid, PROPVARIANT & var, BYTE * pbExtra, unsigned * pcbExtra );
  96. BOOL ReadProperty( CPrimaryPropRecord & PropRecord, PROPID pid, PROPVARIANT & var, BYTE * pbExtra, unsigned * pcbExtra );
  97. BOOL ReadProperty( CCompositePropRecord & PropRecord, PROPID pid, PROPVARIANT & var );
  98. BOOL ReadProperty( CPrimaryPropRecord & PropRecord, PROPID pid, PROPVARIANT & var );
  99. BOOL ReadProperty( CCompositePropRecord & PropRecord, PROPID pid, PROPVARIANT * pbData, unsigned * pcb);
  100. BOOL ReadProperty( CPrimaryPropRecord & PropRecord, PROPID pid, PROPVARIANT * pbData, unsigned * pcb);
  101. BOOL ReadProperty( WORKID wid, PROPID pid, PROPVARIANT & var );
  102. CCompositePropRecord * OpenRecord( WORKID wid, BYTE * pb );
  103. CPrimaryPropRecord * OpenPrimaryRecord( WORKID wid, BYTE * pb );
  104. void CloseRecord( CCompositePropRecord * pRec );
  105. void CloseRecord( CPrimaryPropRecord * pRec );
  106. CCompositePropRecordForWrites * OpenRecordForWrites( WORKID wid, BYTE * pb );
  107. CPrimaryPropRecordForWrites * OpenPrimaryRecordForWrites( WORKID wid, BYTE * pb );
  108. void CloseRecord( CCompositePropRecordForWrites * pRec );
  109. void CloseRecord( CPrimaryPropRecordForWrites * pRec );
  110. BOOL ReadPrimaryProperty( WORKID wid, PROPID pid, PROPVARIANT & var );
  111. //
  112. // Special path/wid support
  113. //
  114. inline WORKID MaxWorkId();
  115. void DeleteRecord( WORKID wid );
  116. inline ULONG CountRecordsInUse() const;
  117. void Shutdown();
  118. void Flush();
  119. void MarkBackedUpMode()
  120. {
  121. CLock mtxLock( _mtxWrite );
  122. Flush();
  123. _xPrimaryStore->MarkBackedUpMode();
  124. }
  125. void MarkNotBackedUpMode()
  126. {
  127. CLock mtxLock( _mtxWrite );
  128. Flush();
  129. _xPrimaryStore->MarkNotBackedUpMode();
  130. }
  131. BOOL IsBackedUpMode()
  132. {
  133. return _xPrimaryStore->IsBackedUpMode();
  134. }
  135. inline WORKID MaxWorkId() const
  136. {
  137. return _xPrimaryStore->MaxWorkId();
  138. }
  139. //
  140. // get and set parameters
  141. // If incorrect parameter, default to the primary store.
  142. //
  143. void SetBackupSize(ULONG ulBackupSizeInPages, DWORD dwStoreLevel);
  144. ULONG GetBackupSize(DWORD dwStoreLevel);
  145. void SetMappedCacheSize(ULONG ulPSMappedCache, DWORD dwStoreLevel);
  146. ULONG GetMappedCacheSize(DWORD dwStoreLevel);
  147. ULONG GetTotalSizeInKB();
  148. PStorage& GetStorage(DWORD dwStoreLevel);
  149. inline WORKID GetSecondaryTopLevelWid(WORKID wid);
  150. inline WORKID GetSecondaryTopLevelWid(WORKID wid, CPropRecordNoLock & propRec);
  151. //
  152. // Clean Up
  153. //
  154. void ClearNonStorageProperties( CCompositePropRecordForWrites & rec );
  155. private:
  156. friend CPropertyStoreWids;
  157. friend CCompositePropRecord;
  158. friend CCompositePropRecordForWrites;
  159. friend CPrimaryPropRecord;
  160. friend CPrimaryPropRecordForWrites;
  161. CPropStoreManager(CiStorage * pStorage,
  162. CPropertyStore *pPrimary,
  163. CPropertyStore *pSecondary,
  164. ULONG cMegToLeaveOnDisk );
  165. inline CPropertyStore& GetPrimaryStore()
  166. {
  167. return _xPrimaryStore.GetReference();
  168. }
  169. inline CPropertyStore& GetSecondaryStore()
  170. {
  171. return _xSecondaryStore.GetReference();
  172. }
  173. void Transfer( CPropStoreManager & Target, PROPID pidFixedPrimary,
  174. PROPID pidFixedSecondary, BOOL & fAbort,
  175. IProgressNotify * pProgress = 0 );
  176. //
  177. // Data members
  178. //
  179. CMutexSem _mtxWrite; // Taken to add/remove/modify records
  180. XPtr<CPropertyStore> _xPrimaryStore; // primary property store
  181. XPtr<CPropertyStore> _xSecondaryStore; // secondary property store
  182. CiStorage * _pStorage; // Persistent storage object.
  183. XPtr<CPropStoreManager> _xpsNew; // New metadata stored here
  184. DWORD _dwXctionStoreLevel; // tracks the store used in current transaction
  185. ULONG _cMegToLeaveOnDisk; // Number of megabytes to leave on disk
  186. };
  187. //+---------------------------------------------------------------------------
  188. //
  189. // Member: CPropStoreManager::CanStore, public
  190. //
  191. // Arguments: [pid] -- Propid to check.
  192. //
  193. // Returns: TRUE if [pid] can exist in property store (e.g. has been
  194. // registered).
  195. //
  196. // History: 22-Oct-97 KrishnaN Created.
  197. //
  198. //----------------------------------------------------------------------------
  199. inline BOOL CPropStoreManager::CanStore( PROPID pid )
  200. {
  201. return _xPrimaryStore->CanStore( pid ) ||
  202. _xSecondaryStore->CanStore( pid );
  203. }
  204. //+---------------------------------------------------------------------------
  205. //
  206. // Member: CPropStoreManager::Size, public
  207. //
  208. // Arguments: [pid] -- Propid to check.
  209. //
  210. // Returns: Size of property in store, or 0 if it isn't in store.
  211. //
  212. // History: 22-Oct-97 KrishnaN Created.
  213. //
  214. //----------------------------------------------------------------------------
  215. inline unsigned CPropStoreManager::Size( PROPID pid )
  216. {
  217. unsigned size = _xPrimaryStore->Size( pid );
  218. if (size > 0)
  219. {
  220. Win4Assert (0 == _xSecondaryStore->Size( pid ));
  221. }
  222. else
  223. {
  224. size = _xSecondaryStore->Size( pid );
  225. }
  226. return size;
  227. }
  228. //+---------------------------------------------------------------------------
  229. //
  230. // Member: CPropStoreManager::Type, public
  231. //
  232. // Arguments: [pid] -- Propid to check.
  233. //
  234. // Returns: Type of property in store, or VT_EMPTY if it isn't in store.
  235. //
  236. // History: 22-Oct-97 KrishnaN Created.
  237. //
  238. //----------------------------------------------------------------------------
  239. inline ULONG CPropStoreManager::Type( PROPID pid )
  240. {
  241. ULONG type = _xPrimaryStore->Type( pid );
  242. if (VT_EMPTY != type)
  243. {
  244. Win4Assert( VT_EMPTY == _xSecondaryStore->Type(pid) );
  245. }
  246. else
  247. {
  248. type = _xSecondaryStore->Type( pid );
  249. }
  250. return type;
  251. }
  252. //+---------------------------------------------------------------------------
  253. //
  254. // Member: CPropStoreManager::StoreLevel, public
  255. //
  256. // Arguments: [pid] -- Propid to check.
  257. //
  258. // Returns: Primary or secondary store in which the property resides.
  259. //
  260. // History: 22-Oct-97 KrishnaN Created.
  261. //
  262. //----------------------------------------------------------------------------
  263. inline DWORD CPropStoreManager::StoreLevel( PROPID pid )
  264. {
  265. if (_xPrimaryStore->CanStore( pid ))
  266. return PRIMARY_STORE;
  267. else if (_xSecondaryStore->CanStore( pid ))
  268. return SECONDARY_STORE;
  269. else
  270. return INVALID_STORE_LEVEL;
  271. }
  272. //+---------------------------------------------------------------------------
  273. //
  274. // Member: CPropStoreManager::CanBeModified, public
  275. //
  276. // Arguments: [pid] -- Propid to check.
  277. //
  278. // Returns: True or false store depending on if the property can be modified.
  279. //
  280. // History: 22-Oct-97 KrishnaN Created.
  281. //
  282. //----------------------------------------------------------------------------
  283. inline BOOL CPropStoreManager::CanBeModified( PROPID pid )
  284. {
  285. if (_xPrimaryStore->CanStore( pid ))
  286. return _xPrimaryStore->CanBeModified( pid );
  287. else if (_xSecondaryStore->CanStore( pid ))
  288. return _xSecondaryStore->CanBeModified( pid );
  289. else
  290. { // if it not in the store, it doesn't matter what the
  291. // reply is. But we will return TRUE so clients like Admin know that
  292. // they can allow the property metadata to be modified.
  293. return TRUE;
  294. }
  295. }
  296. //+---------------------------------------------------------------------------
  297. //
  298. // Member: CPropStoreManager::CountRecordsInUse, public
  299. //
  300. // Returns: Count of 'top level' records (correspond to user wids)
  301. //
  302. // History: 22-Oct-97 KrishnaN Created.
  303. //
  304. //----------------------------------------------------------------------------
  305. inline ULONG CPropStoreManager::CountRecordsInUse() const
  306. {
  307. return _xPrimaryStore->CountRecordsInUse();
  308. }
  309. //+---------------------------------------------------------------------------
  310. //
  311. // Member: CPropStoreManager::MaxWorkId, public
  312. //
  313. // Returns: Maximum workid which has been allocated.
  314. //
  315. // History: 22-Oct-97 KrishnaN Created.
  316. //
  317. //----------------------------------------------------------------------------
  318. inline WORKID CPropStoreManager::MaxWorkId()
  319. {
  320. return _xPrimaryStore->MaxWorkId();
  321. }
  322. //+---------------------------------------------------------------------------
  323. //
  324. // Member: CPropStoreManager::GetSecondaryTopLevelWid, private
  325. //
  326. // Synopsis: Returns WORKID of record in secondary property store.
  327. //
  328. // Arguments: [wid] -- WORKID of record in primary store.
  329. //
  330. // Returns: WORKID -- WORKID in secondary store.
  331. //
  332. // Notes:
  333. //
  334. //----------------------------------------------------------------------------
  335. inline WORKID CPropStoreManager::GetSecondaryTopLevelWid(WORKID wid)
  336. {
  337. PROPVARIANT var;
  338. if (!(_xPrimaryStore->ReadProperty(wid, pidSecondaryStorage, var ) && VT_UI4 == var.vt))
  339. {
  340. ciDebugOut((DEB_PROPSTORE, "NOT using CPropRecord. Primary's"
  341. " ReadRecord failed or invalid type for wid0x%x (%d)\n",
  342. wid, wid));
  343. return widInvalid;
  344. }
  345. #if CIDBG == 1
  346. if (VT_UI4 != var.vt || widInvalid == (WORKID) var.ulVal)
  347. {
  348. ciDebugOut((DEB_PROPSTORE, "NOT using CPropRecord. Invalid sec top-level wid.\n"
  349. "Primary wid is 0x%x (%d), type is 0x%x (%d), value is 0x%x (%d)",
  350. wid, wid, var.vt, var.vt, var.ulVal, var.ulVal));
  351. }
  352. #endif
  353. return (WORKID)var.ulVal;
  354. }
  355. //+---------------------------------------------------------------------------
  356. //
  357. // Member: CPropStoreManager::GetSecondaryTopLevelWid, private
  358. //
  359. // Synopsis: Returns WORKID of record in secondary property store.
  360. //
  361. // Arguments: [wid] -- WORKID of record in primary store.
  362. // [propRec] -- Property record
  363. //
  364. // Returns: WORKID -- WORKID in secondary store.
  365. //
  366. // Notes:
  367. //
  368. //----------------------------------------------------------------------------
  369. inline WORKID CPropStoreManager::GetSecondaryTopLevelWid(WORKID wid,
  370. CPropRecordNoLock & propRec)
  371. {
  372. PROPVARIANT var;
  373. unsigned cbSize = sizeof var;
  374. if (!(_xPrimaryStore->ReadProperty(propRec, pidSecondaryStorage, &var, &cbSize ) && VT_UI4 == var.vt))
  375. {
  376. ciDebugOut((DEB_PROPSTORE, "Using CPropRecord. Primary's"
  377. " ReadRecord failed or invalid type for wid0x%x (%d)\n",
  378. wid, wid));
  379. return widInvalid;
  380. }
  381. #if CIDBG == 1
  382. if (VT_UI4 != var.vt || widInvalid == (WORKID) var.ulVal)
  383. {
  384. ciDebugOut((DEB_PROPSTORE,
  385. "Using CPropRecord. Invalid sec top-level wid.\n"
  386. "Primary wid is 0x%x (%d), type is 0x%x (%d), value is 0x%x (%d)",
  387. wid, wid, var.vt, var.vt, var.ulVal, var.ulVal));
  388. }
  389. #endif
  390. return (WORKID)var.ulVal;
  391. }
  392. inline BOOL CPropStoreManager::IsDirty()
  393. {
  394. return _xPrimaryStore->IsDirty() ||
  395. _xSecondaryStore->IsDirty();
  396. }
  397. //+-------------------------------------------------------------------------
  398. //
  399. // Class: CCompositeProgressNotifier
  400. //
  401. // Purpose: Use this class to provide accurate progress reports
  402. // by accounting for the presence of multiple property stores
  403. // instead of one. For example, given a composite property store
  404. // containing two individual stores, when the first store is 100%
  405. // done, we should report that the composite two-level store is
  406. // only 50% done.
  407. //
  408. // History: 22-Oct-97 KrishnaN Created
  409. //
  410. //--------------------------------------------------------------------------
  411. class CCompositeProgressNotifier : public IProgressNotify
  412. {
  413. public:
  414. // constructor
  415. // This class will own aulMaxSizes array and delete it at
  416. // the end. The caller should be aware of that.
  417. CCompositeProgressNotifier(IProgressNotify *pProgressNotify,
  418. DWORD aulMaxSizes[],
  419. short cComponents = 2) :
  420. _aulMaxSizes( aulMaxSizes ),
  421. _cComponents( cComponents ),
  422. _cFinishedComponents( 0 ),
  423. _dwCumMaxSize( 0 ),
  424. _dwTotalMaxSize( 0 )
  425. {
  426. if (pProgressNotify)
  427. {
  428. Win4Assert(aulMaxSizes && cComponents);
  429. _xComponentProgressNotifier.Set(pProgressNotify);
  430. pProgressNotify->AddRef();
  431. XArray<DWORD> _xdwTemp(cComponents);
  432. short i;
  433. // scale all the max values to the 0-1000 range.
  434. for (i = 0; i < cComponents; i++)
  435. {
  436. _xdwTemp[i] = (DWORD) (((DOUBLE)_aulMaxSizes[i] / (DOUBLE)0xFFFFFFFF) * 1000.0);
  437. _dwTotalMaxSize += _xdwTemp[i];
  438. }
  439. // avoid divide by zero
  440. _dwTotalMaxSize = _dwTotalMaxSize ? _dwTotalMaxSize : 1;
  441. RtlCopyMemory(aulMaxSizes, _xdwTemp.GetPointer(), cComponents*sizeof(DWORD));
  442. }
  443. }
  444. // Control progress reporting
  445. void IncrementFinishedComponents()
  446. {
  447. _dwCumMaxSize += _aulMaxSizes[_cFinishedComponents];
  448. _cFinishedComponents++;
  449. Win4Assert(_cFinishedComponents <= _cComponents);
  450. }
  451. //
  452. // IUnknown methods.
  453. //
  454. STDMETHOD(QueryInterface) (THIS_ REFIID riid, void ** ppvObj);
  455. STDMETHOD_(ULONG,AddRef) (THIS);
  456. STDMETHOD_(ULONG,Release) (THIS);
  457. //
  458. // IProgressNotify methods.
  459. //
  460. STDMETHOD(OnProgress) ( DWORD dwProgressCurrent, //Amount of data available
  461. DWORD dwProgressMaximum, //Total amount of data to be downloaded
  462. BOOL fAccurate, //Reliability of notifications
  463. BOOL fOwner //Ownership of blocking behavior
  464. );
  465. private:
  466. XInterface<IProgressNotify> _xComponentProgressNotifier;
  467. DWORD *_aulMaxSizes;
  468. short _cComponents;
  469. short _cFinishedComponents;
  470. LONG _ref;
  471. DWORD _dwCumMaxSize;
  472. DWORD _dwTotalMaxSize;
  473. };
  474. //+-------------------------------------------------------------------------
  475. //
  476. // Class: XWriteCompositeRecord
  477. //
  478. // Purpose: Smart pointer for a writable composite property store record
  479. //
  480. // History: 02-Jan-999 dlee Created
  481. //
  482. //--------------------------------------------------------------------------
  483. class XWriteCompositeRecord
  484. {
  485. public:
  486. XWriteCompositeRecord( CPropStoreManager & mgr, WORKID wid ) :
  487. _mgr( mgr )
  488. {
  489. BYTE * pb = (BYTE *) ( ( (ULONG_PTR) ( _aBuf + 1 ) ) & ( ~7 ) );
  490. _pPropRec = _mgr.OpenRecordForWrites( wid, pb );
  491. }
  492. ~XWriteCompositeRecord()
  493. {
  494. Free();
  495. }
  496. void Free()
  497. {
  498. if ( 0 != _pPropRec )
  499. {
  500. _mgr.CloseRecord( _pPropRec );
  501. _pPropRec = 0;
  502. }
  503. }
  504. void Set( CCompositePropRecordForWrites * pPropRec )
  505. {
  506. Win4Assert( 0 == _pPropRec );
  507. _pPropRec = pPropRec;
  508. }
  509. CCompositePropRecordForWrites * Acquire()
  510. {
  511. CCompositePropRecordForWrites * p = _pPropRec;
  512. _pPropRec = 0;
  513. return p;
  514. }
  515. CCompositePropRecordForWrites * Get() { return _pPropRec; }
  516. CCompositePropRecordForWrites & GetReference() { return *_pPropRec; }
  517. private:
  518. CCompositePropRecordForWrites * _pPropRec;
  519. CPropStoreManager & _mgr;
  520. LONGLONG _aBuf[ 1 + ( sizeof_CCompositePropRecord / sizeof( LONGLONG ) ) ];
  521. };
  522. //+-------------------------------------------------------------------------
  523. //
  524. // Class: XWritePrimaryRecord
  525. //
  526. // Purpose: Smart pointer for a writable primary property store record
  527. //
  528. // History: 02-Jan-999 dlee Created
  529. //
  530. //--------------------------------------------------------------------------
  531. class XWritePrimaryRecord
  532. {
  533. public:
  534. XWritePrimaryRecord( CPropStoreManager & mgr, WORKID wid ) :
  535. _mgr( mgr )
  536. {
  537. BYTE * pb = (BYTE *) ( ( (ULONG_PTR) ( _aBuf + 1 ) ) & ( ~7 ) );
  538. _pPropRec = _mgr.OpenPrimaryRecordForWrites( wid, pb );
  539. }
  540. ~XWritePrimaryRecord()
  541. {
  542. Free();
  543. }
  544. void Free()
  545. {
  546. if ( 0 != _pPropRec )
  547. {
  548. _mgr.CloseRecord( _pPropRec );
  549. _pPropRec = 0;
  550. }
  551. }
  552. void Set( CPrimaryPropRecordForWrites * pPropRec )
  553. {
  554. Win4Assert( 0 == _pPropRec );
  555. _pPropRec = pPropRec;
  556. }
  557. CPrimaryPropRecordForWrites * Acquire()
  558. {
  559. CPrimaryPropRecordForWrites * p = _pPropRec;
  560. _pPropRec = 0;
  561. return p;
  562. }
  563. CPrimaryPropRecordForWrites * Get() { return _pPropRec; }
  564. CPrimaryPropRecordForWrites & GetReference() { return *_pPropRec; }
  565. private:
  566. CPrimaryPropRecordForWrites * _pPropRec;
  567. CPropStoreManager & _mgr;
  568. LONGLONG _aBuf[ 1 + ( sizeof_CPropRecord / sizeof( LONGLONG ) ) ];
  569. };
  570. //+-------------------------------------------------------------------------
  571. //
  572. // Class: XPrimaryRecord
  573. //
  574. // Purpose: Smart pointer for a primary property store record
  575. //
  576. // History: 02-Jan-999 dlee Created
  577. //
  578. //--------------------------------------------------------------------------
  579. class XPrimaryRecord
  580. {
  581. public:
  582. XPrimaryRecord( CPropStoreManager & mgr, WORKID wid ) :
  583. _mgr( mgr )
  584. {
  585. BYTE * pb = (BYTE *) ( ( (ULONG_PTR) ( _aBuf + 1 ) ) & ( ~7 ) );
  586. //ciDebugOut(( DEB_FORCE, "_aBuf %#x, pb %#x\n", _aBuf, pb ));
  587. Win4Assert( pb >= (BYTE *) &_aBuf );
  588. _pPropRec = _mgr.OpenPrimaryRecord( wid, pb );
  589. }
  590. ~XPrimaryRecord()
  591. {
  592. Free();
  593. }
  594. void Free()
  595. {
  596. if ( 0 != _pPropRec )
  597. {
  598. _mgr.CloseRecord( _pPropRec );
  599. _pPropRec = 0;
  600. }
  601. }
  602. void Set( CPrimaryPropRecord * pPropRec )
  603. {
  604. Win4Assert( 0 == _pPropRec );
  605. _pPropRec = pPropRec;
  606. }
  607. CPrimaryPropRecord * Acquire()
  608. {
  609. CPrimaryPropRecord * p = _pPropRec;
  610. _pPropRec = 0;
  611. return p;
  612. }
  613. CPrimaryPropRecord * Get() { return _pPropRec; }
  614. CPrimaryPropRecord & GetReference() { return *_pPropRec; }
  615. private:
  616. CPrimaryPropRecord * _pPropRec;
  617. CPropStoreManager & _mgr;
  618. LONGLONG _aBuf[ 1 + ( sizeof_CPropRecord / sizeof( LONGLONG ) ) ];
  619. };