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.

770 lines
22 KiB

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