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.

1288 lines
23 KiB

  1. //
  2. // Copyright 2001 - Microsoft Corporation
  3. //
  4. //
  5. // Created By:
  6. // Geoff Pease (GPease) 23-JAN-2001
  7. //
  8. // Maintained By:
  9. // Geoff Pease (GPease) 23-JAN-2001
  10. //
  11. #include "pch.h"
  12. #include "DocProp.h"
  13. #include "DefProp.h"
  14. #include "PropertyCacheItem.h"
  15. #pragma hdrstop
  16. // ***************************************************************************
  17. //
  18. // Class statics
  19. //
  20. // ***************************************************************************
  21. WCHAR CPropertyCacheItem::_szMultipleString[ MAX_PATH ] = { 0 };
  22. // ***************************************************************************
  23. //
  24. // Constructor / Destructor / Initialization
  25. //
  26. // ***************************************************************************
  27. //
  28. // CreateInstance
  29. //
  30. HRESULT
  31. CPropertyCacheItem::CreateInstance(
  32. CPropertyCacheItem ** ppItemOut
  33. )
  34. {
  35. TraceFunc( "" );
  36. HRESULT hr;
  37. Assert( NULL != ppItemOut );
  38. CPropertyCacheItem * pthis = new CPropertyCacheItem;
  39. if ( NULL != pthis )
  40. {
  41. hr = THR( pthis->Init( ) );
  42. if ( SUCCEEDED( hr ) )
  43. {
  44. *ppItemOut = pthis;
  45. }
  46. else
  47. {
  48. pthis->Destroy( );
  49. }
  50. }
  51. else
  52. {
  53. hr = E_OUTOFMEMORY;
  54. }
  55. HRETURN( hr );
  56. }
  57. //
  58. // Constructor
  59. //
  60. CPropertyCacheItem::CPropertyCacheItem( void )
  61. {
  62. TraceFunc( "" );
  63. Assert( NULL == _pNext );
  64. Assert( FALSE == _fReadOnly );
  65. Assert( FALSE == _fDirty );
  66. Assert( IsEqualIID( _fmtid, CLSID_NULL ) );
  67. Assert( 0 == _propid );
  68. Assert( VT_EMPTY == _vt );
  69. Assert( 0 == _uCodePage );
  70. Assert( VT_EMPTY == _propvar.vt );
  71. Assert( 0 == _idxDefProp );
  72. Assert( NULL == _ppui );
  73. Assert( 0 == _wszTitle[ 0 ] );
  74. Assert( 0 == _wszDesc[ 0 ] );
  75. Assert( 0 == _wszValue[ 0 ] );
  76. Assert( 0 == _wszHelpFile[ 0 ] );
  77. Assert( NULL == _pDefVals );
  78. TraceFuncExit( );
  79. }
  80. //
  81. // Initialization
  82. //
  83. HRESULT
  84. CPropertyCacheItem::Init( void )
  85. {
  86. TraceFunc( "" );
  87. HRESULT hr = S_OK;
  88. _idxDefProp = -1L;
  89. HRETURN( hr );
  90. }
  91. //
  92. // Destructor
  93. //
  94. CPropertyCacheItem::~CPropertyCacheItem( void )
  95. {
  96. TraceFunc( "" );
  97. if ( NULL != _ppui )
  98. {
  99. _ppui->Release( );
  100. }
  101. if ( NULL != _pDefVals )
  102. {
  103. for ( ULONG idx = 0; NULL != _pDefVals[ idx ].pszName; idx ++ )
  104. {
  105. TraceFree( _pDefVals[ idx ].pszName );
  106. }
  107. TraceFree( _pDefVals );
  108. }
  109. TraceFuncExit( );
  110. }
  111. //
  112. // Description:
  113. // Attempts to destroy the property item.
  114. //
  115. // Return Values:
  116. // S_OK
  117. // Success!
  118. //
  119. HRESULT
  120. CPropertyCacheItem::Destroy( void )
  121. {
  122. TraceFunc( "" );
  123. HRESULT hr = S_OK;
  124. delete this;
  125. HRETURN( hr );
  126. }
  127. // ***************************************************************************
  128. //
  129. // Private Methods
  130. //
  131. // ***************************************************************************
  132. //
  133. // Description:
  134. // Looks in our "default property list" for a matching fmtid/propid
  135. // combination and sets _idxDefProp to that index.
  136. //
  137. // Return Values:
  138. // S_OK
  139. // Success!
  140. //
  141. // HRESULT_FROM_WIN32(ERROR_NOT_FOUND)
  142. // Entry was not found. _idxDefProp is invalid.
  143. //
  144. HRESULT
  145. CPropertyCacheItem::FindDefPropertyIndex( void )
  146. {
  147. TraceFunc( "" );
  148. HRESULT hr = S_OK;
  149. if ( -1L == _idxDefProp )
  150. {
  151. ULONG idx;
  152. for ( idx = 0; NULL != g_rgDefPropertyItems[ idx ].pFmtID; idx ++ )
  153. {
  154. if ( IsEqualPFID( _fmtid, *g_rgDefPropertyItems[ idx ].pFmtID )
  155. && _propid == g_rgDefPropertyItems[ idx ].propID
  156. )
  157. {
  158. _idxDefProp = idx;
  159. break;
  160. }
  161. }
  162. if ( -1L == _idxDefProp )
  163. {
  164. // don't wrap.
  165. hr = HRESULT_FROM_WIN32( ERROR_NOT_FOUND );
  166. }
  167. }
  168. HRETURN( hr );
  169. }
  170. //
  171. // Description:
  172. // Check the static member _szMultipleString to make sure it has been
  173. // loaded.
  174. //
  175. void
  176. CPropertyCacheItem::EnsureMultipleStringLoaded( void )
  177. {
  178. TraceFunc( "" );
  179. if ( 0 == _szMultipleString[ 0 ] )
  180. {
  181. int iRet = LoadString( g_hInstance, IDS_COMPOSITE_MISMATCH, _szMultipleString, ARRAYSIZE(_szMultipleString) );
  182. AssertMsg( 0 != iRet, "Missing string resource?" );
  183. }
  184. TraceFuncExit( );
  185. }
  186. // ***************************************************************************
  187. //
  188. // Public Methods
  189. //
  190. // ***************************************************************************
  191. //
  192. // Description:
  193. // Stores a IPropetyUI interface to be used for translating the property
  194. // "properties" into different forms.
  195. //
  196. // Return Values:
  197. // S_OK
  198. // Success!
  199. //
  200. HRESULT
  201. CPropertyCacheItem::SetPropertyUIHelper(
  202. IPropertyUI * ppuiIn
  203. )
  204. {
  205. TraceFunc( "" );
  206. HRESULT hr = S_OK;
  207. //
  208. // If we have an existing helper, release it.
  209. //
  210. if ( NULL != _ppui )
  211. {
  212. _ppui->Release( );
  213. }
  214. _ppui = ppuiIn;
  215. if ( NULL != _ppui )
  216. {
  217. _ppui->AddRef( );
  218. }
  219. HRETURN( hr );
  220. }
  221. //
  222. // Description:
  223. // Retrieves a copy (AddRef'ed) of the IPropertyUI interface that this
  224. // property item is using.
  225. //
  226. // Return Values:
  227. // S_OK
  228. // Success! pppuiOut is valid.
  229. //
  230. // S_FALSE
  231. // Success, but pppuiOut is NULL.
  232. //
  233. // E_POINTER
  234. // pppuiOut is NULL.
  235. //
  236. // other HRESULTs.
  237. //
  238. HRESULT
  239. CPropertyCacheItem::GetPropertyUIHelper(
  240. IPropertyUI ** pppuiOut
  241. )
  242. {
  243. TraceFunc( "" );
  244. HRESULT hr = S_OK;
  245. if ( NULL == pppuiOut )
  246. goto InvalidPointer;
  247. //
  248. // If we have an existing helper, release it.
  249. //
  250. if ( NULL == _ppui )
  251. {
  252. *pppuiOut = NULL;
  253. hr = S_FALSE;
  254. }
  255. else
  256. {
  257. hr = THR( _ppui->TYPESAFEQI( *pppuiOut ) );
  258. }
  259. Cleanup:
  260. HRETURN( hr );
  261. InvalidPointer:
  262. hr = THR( E_POINTER );
  263. goto Cleanup;
  264. }
  265. //
  266. // Description:
  267. // Changes the _pNext member variable
  268. //
  269. // Return Values:
  270. // S_OK
  271. // Success!
  272. //
  273. HRESULT
  274. CPropertyCacheItem::SetNextItem(
  275. CPropertyCacheItem * pNextIn
  276. )
  277. {
  278. TraceFunc( "" );
  279. HRESULT hr = S_OK;
  280. _pNext = pNextIn;
  281. HRETURN( hr );
  282. }
  283. //
  284. // Description:
  285. // Retrieves the _pNext member variable
  286. //
  287. // Return Values:
  288. // S_OK
  289. // Success!
  290. //
  291. // S_FALSE
  292. //
  293. //
  294. // E_POINTER
  295. // ppNextOut is NULL.
  296. //
  297. HRESULT
  298. CPropertyCacheItem::GetNextItem(
  299. CPropertyCacheItem ** ppNextOut
  300. )
  301. {
  302. TraceFunc( "" );
  303. HRESULT hr;
  304. if ( NULL != ppNextOut )
  305. {
  306. *ppNextOut = _pNext;
  307. if ( NULL == _pNext )
  308. {
  309. hr = S_FALSE;
  310. }
  311. else
  312. {
  313. hr = S_OK;
  314. }
  315. }
  316. else
  317. {
  318. hr = THR( E_POINTER );
  319. }
  320. HRETURN( hr );
  321. }
  322. //
  323. // Description:
  324. // Sets the FMTID of the property.
  325. //
  326. // Return Values:
  327. // S_OK
  328. // Success!
  329. //
  330. HRESULT
  331. CPropertyCacheItem::SetFmtId(
  332. const FMTID * pFmtIdIn
  333. )
  334. {
  335. TraceFunc( "" );
  336. HRESULT hr = S_OK;
  337. _fmtid = *pFmtIdIn;
  338. _idxDefProp = -1;
  339. HRETURN( hr );
  340. }
  341. //
  342. // Description:
  343. // Retrieves the FMTID of the property.
  344. //
  345. // Return Values:
  346. // S_OK
  347. // Success!
  348. //
  349. // E_POINTER
  350. // pfmtidOut is invalid.
  351. //
  352. HRESULT
  353. CPropertyCacheItem::GetFmtId(
  354. FMTID * pfmtidOut
  355. )
  356. {
  357. TraceFunc( "" );
  358. HRESULT hr;
  359. if ( NULL != pfmtidOut )
  360. {
  361. *pfmtidOut = _fmtid;
  362. hr = S_OK;
  363. }
  364. else
  365. {
  366. hr = THR( E_POINTER );
  367. }
  368. HRETURN( hr );
  369. }
  370. //
  371. // Description:
  372. // Sets the PROPID of the property.
  373. //
  374. // Return Values:
  375. // S_OK
  376. // Success!
  377. //
  378. HRESULT
  379. CPropertyCacheItem::SetPropId(
  380. PROPID propidIn
  381. )
  382. {
  383. TraceFunc( "" );
  384. HRESULT hr = S_OK;
  385. _propid = propidIn;
  386. _idxDefProp = -1;
  387. HRETURN( hr );
  388. }
  389. //
  390. // Description:
  391. // Retrieves the PROPID of the property.
  392. //
  393. // Return Values:
  394. // S_OK
  395. // Success!
  396. //
  397. // E_POINTER
  398. // ppropidOut is invalid.
  399. //
  400. HRESULT
  401. CPropertyCacheItem::GetPropId(
  402. PROPID * ppropidOut
  403. )
  404. {
  405. TraceFunc( "" );
  406. HRESULT hr;
  407. if ( NULL == ppropidOut )
  408. goto InvalidPointer;
  409. *ppropidOut = _propid;
  410. hr = S_OK;
  411. Cleanup:
  412. HRETURN( hr );
  413. InvalidPointer:
  414. hr = THR( E_POINTER );
  415. goto Cleanup;
  416. }
  417. //
  418. // Description:
  419. // Sets the VARTYPE of the property.
  420. //
  421. // Return Values:
  422. // S_OK
  423. // Success!
  424. //
  425. HRESULT
  426. CPropertyCacheItem::SetDefaultVarType(
  427. VARTYPE vtIn
  428. )
  429. {
  430. TraceFunc( "" );
  431. HRESULT hr = S_OK;
  432. _vt = vtIn;
  433. HRETURN( hr );
  434. }
  435. //
  436. // Description:
  437. // Retrieves the VARTYPE of the property.
  438. //
  439. // Return Values:
  440. // S_OK
  441. // Success!
  442. //
  443. // E_POINTER
  444. // pvtOut is invalid.
  445. //
  446. HRESULT
  447. CPropertyCacheItem::GetDefaultVarType(
  448. VARTYPE * pvtOut
  449. )
  450. {
  451. TraceFunc( "" );
  452. HRESULT hr;
  453. if ( NULL != pvtOut )
  454. {
  455. switch ( _vt )
  456. {
  457. case VT_VECTOR | VT_VARIANT:
  458. Assert( _propvar.capropvar.cElems == 2 );
  459. *pvtOut = _propvar.capropvar.pElems[ 1 ].vt;
  460. hr = S_OK;
  461. break;
  462. case VT_VECTOR | VT_LPSTR:
  463. *pvtOut = VT_LPSTR;
  464. hr = S_OK;
  465. break;
  466. case VT_VECTOR | VT_LPWSTR:
  467. *pvtOut = VT_LPWSTR;
  468. hr = S_OK;
  469. break;
  470. default:
  471. *pvtOut = _vt;
  472. hr = S_OK;
  473. break;
  474. }
  475. }
  476. else
  477. {
  478. hr = E_POINTER;
  479. }
  480. HRETURN( hr );
  481. }
  482. //
  483. // Description:
  484. // Stores the Code Page for the property value.
  485. //
  486. // Return Values:
  487. // S_OK
  488. // Success!
  489. //
  490. HRESULT
  491. CPropertyCacheItem::SetCodePage(
  492. UINT uCodePageIn
  493. )
  494. {
  495. TraceFunc( "" );
  496. HRESULT hr = S_OK;
  497. _uCodePage = uCodePageIn;
  498. HRETURN( hr );
  499. }
  500. //
  501. // Description:
  502. // Retrieves the Code Page for the property value.
  503. //
  504. // Return Values:
  505. // S_OK
  506. // Success!
  507. //
  508. // E_POINTER
  509. // puCodePageOut is NULL.
  510. //
  511. HRESULT
  512. CPropertyCacheItem::GetCodePage(
  513. UINT * puCodePageOut
  514. )
  515. {
  516. TraceFunc( "" );
  517. HRESULT hr;
  518. if ( NULL != puCodePageOut )
  519. {
  520. *puCodePageOut = _uCodePage;
  521. hr = S_OK;
  522. }
  523. else
  524. {
  525. hr = THR( E_POINTER );
  526. }
  527. HRETURN( hr );
  528. }
  529. //
  530. // Description:
  531. // Retrieves the property name for this property to be display in the UI.
  532. // The pointer handed out does not need to be freed.
  533. //
  534. // Return Values:
  535. // S_OK
  536. // Success!
  537. //
  538. // E_POINTER
  539. // ppwszOut is NULL.
  540. //
  541. // E_UNEXPECTED
  542. // Need to call SetPropertyUIHelper( ) before calling this method.
  543. //
  544. // HRESULT_FROM_WIN32(ERROR_INTERNAL_ERROR)
  545. // The resource string is malformed.
  546. //
  547. // other HRESULTs
  548. //
  549. HRESULT
  550. CPropertyCacheItem::GetPropertyTitle(
  551. LPCWSTR * ppwszOut
  552. )
  553. {
  554. TraceFunc( "" );
  555. HRESULT hr;
  556. if ( NULL == ppwszOut )
  557. goto InvalidPointer;
  558. *ppwszOut = NULL;
  559. if ( NULL == _ppui )
  560. goto UnexpectedState;
  561. hr = THR( _ppui->GetDisplayName( _fmtid, _propid, PUIFNF_DEFAULT, _wszTitle, ARRAYSIZE(_wszTitle) ) );
  562. // Even if this fails, the buffer will still be valid and empty.
  563. *ppwszOut = _wszTitle;
  564. hr = S_OK;
  565. Cleanup:
  566. HRETURN( hr );
  567. InvalidPointer:
  568. hr = THR( E_POINTER );
  569. goto Cleanup;
  570. UnexpectedState:
  571. hr = THR( E_UNEXPECTED );
  572. goto Cleanup;
  573. }
  574. //
  575. // Description:
  576. // Retrieves the property name for this property to be display in the UI.
  577. // The pointer handed out does not need to be freed.
  578. //
  579. // Return Values:
  580. // S_OK
  581. // Success!
  582. //
  583. // E_POINTER
  584. // ppwszOut is NULL.
  585. //
  586. // E_UNEXPECTED
  587. // Need to call SetPropertyUIHelper( ) before calling this method.
  588. //
  589. // HRESULT_FROM_WIN32(ERROR_INTERNAL_ERROR)
  590. // The resource string is malformed.
  591. //
  592. // other HRESULTs
  593. //
  594. HRESULT
  595. CPropertyCacheItem::GetPropertyDescription(
  596. LPCWSTR * ppwszOut
  597. )
  598. {
  599. TraceFunc( "" );
  600. HRESULT hr;
  601. if ( NULL == ppwszOut )
  602. goto InvalidPointer;
  603. *ppwszOut = NULL;
  604. if ( NULL == _ppui )
  605. goto UnexpectedState;
  606. hr = THR( _ppui->GetPropertyDescription( _fmtid, _propid, _wszDesc, ARRAYSIZE(_wszDesc) ) );
  607. // if it failed, the buffer will still be valid and empty.
  608. *ppwszOut = _wszDesc;
  609. hr = S_OK;
  610. Cleanup:
  611. HRETURN( hr );
  612. InvalidPointer:
  613. hr = THR( E_POINTER );
  614. goto Cleanup;
  615. UnexpectedState:
  616. hr = THR( E_UNEXPECTED );
  617. goto Cleanup;
  618. }
  619. //
  620. // Description:
  621. // Retrieves the help information about a property. The pointer handed
  622. // out to the help file does not need to be freed.
  623. //
  624. // Return Values:
  625. // S_OK
  626. // Success!
  627. //
  628. // E_POINTER
  629. // ppwszFileOut or puHelpIDOut is NULL.
  630. //
  631. // E_UNEXPECTED
  632. // Need to call SetPropertyUIHelper( ) before calling this method.
  633. //
  634. // other HRESULTs
  635. //
  636. HRESULT
  637. CPropertyCacheItem::GetPropertyHelpInfo(
  638. LPCWSTR * ppwszFileOut
  639. , UINT * puHelpIDOut
  640. )
  641. {
  642. TraceFunc( "" );
  643. HRESULT hr;
  644. if (( NULL == ppwszFileOut ) || ( NULL == puHelpIDOut ))
  645. goto InvalidPointer;
  646. *ppwszFileOut = NULL;
  647. *puHelpIDOut = 0;
  648. if ( NULL == _ppui )
  649. goto UnexpectedState;
  650. hr = THR( _ppui->GetHelpInfo( _fmtid, _propid, _wszHelpFile, ARRAYSIZE(_wszHelpFile), puHelpIDOut ) );
  651. if ( FAILED( hr ) )
  652. goto Cleanup;
  653. *ppwszFileOut = _wszHelpFile;
  654. hr = S_OK;
  655. Cleanup:
  656. HRETURN( hr );
  657. InvalidPointer:
  658. hr = THR( E_POINTER );
  659. goto Cleanup;
  660. UnexpectedState:
  661. hr = THR( E_UNEXPECTED );
  662. goto Cleanup;
  663. }
  664. //
  665. // Description:
  666. // Retrieves a LPWSTR the to a buffer (own by the property) that can
  667. // used to display the property as a string. The pointer handed out
  668. // does not need to be freed.
  669. //
  670. // Return Values:
  671. // S_OK
  672. // Success!
  673. //
  674. // E_POINTER
  675. // ppwszOut is NULL.
  676. //
  677. // E_UNEXPECTED
  678. // Need to call SetPropertyUIHelper( ) before calling this method.
  679. //
  680. // other HRESULTs
  681. //
  682. HRESULT
  683. CPropertyCacheItem::GetPropertyStringValue(
  684. LPCWSTR * ppwszOut
  685. )
  686. {
  687. TraceFunc( "" );
  688. HRESULT hr;
  689. if ( NULL == ppwszOut )
  690. goto InvalidPointer;
  691. *ppwszOut = NULL;
  692. if ( NULL == _ppui )
  693. goto UnexpectedState;
  694. //
  695. // If the property has been marked to indicate multiple values, then
  696. // return the "< multiple values >" string.
  697. //
  698. if ( _fMultiple )
  699. {
  700. EnsureMultipleStringLoaded( );
  701. *ppwszOut = _szMultipleString;
  702. hr = S_OK;
  703. goto Cleanup;
  704. }
  705. if ( ( VT_VECTOR | VT_VARIANT ) == _vt )
  706. {
  707. Assert( 2 == _propvar.capropvar.cElems );
  708. hr = THR( _ppui->FormatForDisplay( _fmtid, _propid, &_propvar.capropvar.pElems[ 1 ], PUIFFDF_DEFAULT, _wszValue, ARRAYSIZE(_wszValue) ) );
  709. if ( FAILED( hr ) )
  710. goto Cleanup;
  711. }
  712. else
  713. {
  714. hr = THR( _ppui->FormatForDisplay( _fmtid, _propid, &_propvar, PUIFFDF_DEFAULT, _wszValue, ARRAYSIZE(_wszValue) ) );
  715. if ( FAILED( hr ) )
  716. goto Cleanup;
  717. }
  718. *ppwszOut = _wszValue;
  719. hr = S_OK;
  720. Cleanup:
  721. HRETURN( hr );
  722. InvalidPointer:
  723. hr = THR( E_POINTER );
  724. goto Cleanup;
  725. UnexpectedState:
  726. hr = THR( E_UNEXPECTED );
  727. goto Cleanup;
  728. }
  729. //
  730. // Description:
  731. // Retrieves the Image Index for a property.
  732. //
  733. // Return Values:
  734. // S_OK
  735. // Success!
  736. //
  737. // E_POINTER
  738. // piImageOut is NULL.
  739. //
  740. HRESULT
  741. CPropertyCacheItem::GetImageIndex(
  742. int * piImageOut
  743. )
  744. {
  745. TraceFunc( "" );
  746. HRESULT hr;
  747. if ( NULL == piImageOut )
  748. goto InvalidPointer;
  749. // Initlize to read-only
  750. *piImageOut = PTI_PROP_READONLY;
  751. if ( !_fReadOnly )
  752. {
  753. // don't wrap - this can fail
  754. hr = FindDefPropertyIndex( );
  755. if ( S_OK == hr )
  756. {
  757. if ( !g_rgDefPropertyItems[ _idxDefProp ].fReadOnly )
  758. {
  759. *piImageOut = PTI_PROP_READWRITE;
  760. }
  761. }
  762. }
  763. hr = S_OK;
  764. Cleanup:
  765. HRETURN( hr );
  766. InvalidPointer:
  767. hr = THR( E_POINTER );
  768. goto Cleanup;
  769. }
  770. //
  771. // Description:
  772. // Retrieves the Property Folder IDentifer (PFID) for this property.
  773. //
  774. // Return Values:
  775. // S_OK
  776. // Success!
  777. //
  778. // S_FALSE
  779. // Call succeeded, but there isn't a PFID for this property.
  780. //
  781. // E_POINTER
  782. // ppdifOut is NULL.
  783. //
  784. HRESULT
  785. CPropertyCacheItem::GetPFID(
  786. const PFID ** ppPFIDOut
  787. )
  788. {
  789. TraceFunc( "" );
  790. HRESULT hr;
  791. if ( NULL == ppPFIDOut )
  792. goto InvalidPointer;
  793. *ppPFIDOut = NULL;
  794. // don't wrap - this can fail.
  795. hr = FindDefPropertyIndex( );
  796. if ( S_OK == hr )
  797. {
  798. *ppPFIDOut = g_rgDefPropertyItems[ _idxDefProp ].ppfid;
  799. }
  800. if ( NULL == *ppPFIDOut )
  801. {
  802. hr = S_FALSE;
  803. }
  804. Cleanup:
  805. HRETURN( hr );
  806. InvalidPointer:
  807. hr = THR( E_POINTER );
  808. goto Cleanup;
  809. }
  810. //
  811. // Description:
  812. // Retrieves the CLSID of the control to CoCreate( ) to edit this property.
  813. // The object must support the IEditVariantsInPlace interface. This method
  814. // will return S_FALSE (pclsidOut will be CLSID_NULL) is the property is
  815. // read-only.
  816. //
  817. // Return Values:
  818. // S_OK
  819. // Success!
  820. //
  821. // S_FALSE
  822. // Success, but the CLSID is CLSID_NULL.
  823. //
  824. // E_POINTER
  825. // pclsidOut is NULL.
  826. //
  827. // other HRESULTs
  828. //
  829. HRESULT
  830. CPropertyCacheItem::GetControlCLSID(
  831. CLSID * pclsidOut
  832. )
  833. {
  834. TraceFunc( "" );
  835. HRESULT hr;
  836. if ( NULL == pclsidOut )
  837. goto InvalidPointer;
  838. // don't wrap - this can fail.
  839. hr = FindDefPropertyIndex( );
  840. if ( FAILED( hr ) )
  841. goto Cleanup;
  842. //
  843. // If it is read-only, return S_FALSE and a CLSID of CLSID_NULL.
  844. //
  845. if ( g_rgDefPropertyItems[ _idxDefProp ].fReadOnly )
  846. {
  847. *pclsidOut = CLSID_NULL;
  848. hr = S_FALSE;
  849. goto Cleanup;
  850. }
  851. *pclsidOut = *g_rgDefPropertyItems[ _idxDefProp ].pclsidControl;
  852. if ( CLSID_NULL == *pclsidOut )
  853. {
  854. hr = S_FALSE;
  855. }
  856. Cleanup:
  857. HRETURN( hr );
  858. InvalidPointer:
  859. hr = THR( E_POINTER );
  860. goto Cleanup;
  861. }
  862. //
  863. // Description:
  864. // Retrieve the current property value in the form on a variant. If the
  865. // property is backed by multiple sources, then S_FALSE is returned and
  866. // the variant is empty.
  867. //
  868. // Return Value:
  869. // S_OK
  870. // Success!
  871. //
  872. // S_FALSE
  873. // Multiple value property. Variant is empty.
  874. //
  875. // E_POINTER
  876. // ppvarOut is NULL.
  877. //
  878. // E_FAIL
  879. // Property is READ-ONLY.
  880. //
  881. // other HRESULTs.
  882. //
  883. STDMETHODIMP
  884. CPropertyCacheItem::GetPropertyValue(
  885. PROPVARIANT ** ppvarOut
  886. )
  887. {
  888. TraceFunc( "" );
  889. HRESULT hr;
  890. if ( NULL == ppvarOut )
  891. goto InvalidPointer;
  892. *ppvarOut = &_propvar;
  893. hr = S_OK;
  894. Cleanup:
  895. HRETURN( hr );
  896. InvalidPointer:
  897. hr = THR( E_POINTER );
  898. goto Cleanup;
  899. }
  900. //
  901. // Description:
  902. // Marks the property as being dirty.
  903. //
  904. // Return Values:
  905. // S_OK
  906. // Success!
  907. //
  908. // other HRESULTs.
  909. //
  910. STDMETHODIMP
  911. CPropertyCacheItem::MarkDirty( void )
  912. {
  913. TraceFunc( "" );
  914. HRESULT hr = S_OK;
  915. _fDirty = TRUE;
  916. _fMultiple = FALSE;
  917. HRETURN( hr );
  918. }
  919. //
  920. // Description:
  921. // Checks to see if the property has been marked dirty.
  922. //
  923. // Return Values:
  924. // S_OK
  925. // Success and the property is dirty.
  926. //
  927. // S_FALSE
  928. // Success and the proprety is clean.
  929. //
  930. STDMETHODIMP
  931. CPropertyCacheItem::IsDirty( void )
  932. {
  933. TraceFunc( "" );
  934. HRESULT hr;
  935. if ( _fDirty )
  936. {
  937. hr = S_OK;
  938. }
  939. else
  940. {
  941. hr = S_FALSE;
  942. }
  943. HRETURN( hr );
  944. }
  945. //
  946. // Description:
  947. // Marks the property read-only.
  948. //
  949. // Return Values:
  950. // S_OK
  951. // Success!
  952. //
  953. STDMETHODIMP
  954. CPropertyCacheItem::MarkReadOnly( void )
  955. {
  956. TraceFunc( "" );
  957. HRESULT hr = S_OK;
  958. _fReadOnly = TRUE;
  959. HRETURN( hr );
  960. }
  961. //
  962. // Description:
  963. // Retrieves an array of pointer to an array of strings that are
  964. // zero-indexed. This is used for properties that have well-known
  965. // enumerated states that are indexed (such as "Status").
  966. //
  967. // Return Values:
  968. // S_OK
  969. // Success!
  970. //
  971. // S_FALSE
  972. // Proprety doesn't support enumerated states.
  973. //
  974. // E_INVALIDARG
  975. // ppDefValOut is NULL.
  976. //
  977. // other HRESULTs.
  978. //
  979. STDMETHODIMP
  980. CPropertyCacheItem::GetStateStrings(
  981. DEFVAL ** ppDefValOut
  982. )
  983. {
  984. TraceFunc( "" );
  985. HRESULT hr;
  986. ULONG idx;
  987. ULONG idxEnd;
  988. //
  989. // Check parameters.
  990. //
  991. if ( NULL == ppDefValOut )
  992. goto InvalidPointer;
  993. *ppDefValOut = NULL;
  994. if ( NULL == _ppui )
  995. goto UnexpectedState;
  996. // don't wrap - this can fail.
  997. hr = FindDefPropertyIndex( );
  998. if ( FAILED( hr ) )
  999. goto Cleanup;
  1000. if ( !g_rgDefPropertyItems[ _idxDefProp ].fEnumeratedValues )
  1001. {
  1002. hr = S_FALSE;
  1003. goto Cleanup;
  1004. }
  1005. if ( NULL != _pDefVals )
  1006. {
  1007. *ppDefValOut = _pDefVals;
  1008. hr = S_OK;
  1009. goto Cleanup;
  1010. }
  1011. AssertMsg( NULL != g_rgDefPropertyItems[ _idxDefProp ].pDefVals, "Why did one mark this property as ENUM, but provide no items?" );
  1012. //
  1013. // Since we moved all the string in SHELL32, we need to use our table
  1014. // enumerate the property values to retrieve all the strings. Since
  1015. // our table is read-only, we need to allocate a copy of the DEFVALs
  1016. // for this property and have PropertyUI fill in the blanks.
  1017. //
  1018. _pDefVals = (DEFVAL *) TraceAlloc( HEAP_ZERO_MEMORY, sizeof(DEFVAL) * g_rgDefPropertyItems[ _idxDefProp ].cDefVals );
  1019. if ( NULL == _pDefVals )
  1020. goto OutOfMemory;
  1021. CopyMemory( _pDefVals, g_rgDefPropertyItems[ _idxDefProp ].pDefVals, sizeof(DEFVAL) * g_rgDefPropertyItems[ _idxDefProp ].cDefVals );
  1022. idxEnd = g_rgDefPropertyItems[ _idxDefProp ].cDefVals - 1; // the last entry is always { 0, NULL }
  1023. for ( idx = 0; idx < idxEnd; idx ++ )
  1024. {
  1025. PROPVARIANT propvar;
  1026. propvar.vt = g_rgDefPropertyItems[ _idxDefProp ].vt;
  1027. propvar.ulVal = g_rgDefPropertyItems[ _idxDefProp ].pDefVals[ idx ].ulVal;
  1028. _pDefVals[ idx ].pszName = (LPTSTR) TraceAlloc( HEAP_ZERO_MEMORY, sizeof(_wszValue) );
  1029. if ( NULL == _pDefVals[ idx ].pszName )
  1030. goto OutOfMemory;
  1031. hr = THR( _ppui->FormatForDisplay( _fmtid, _propid, &propvar, PUIFFDF_DEFAULT, _pDefVals[ idx ].pszName, ARRAYSIZE(_wszValue) ) );
  1032. if ( FAILED( hr ) )
  1033. goto Cleanup;
  1034. }
  1035. *ppDefValOut = _pDefVals;
  1036. hr = S_OK;
  1037. Cleanup:
  1038. HRETURN( hr );
  1039. InvalidPointer:
  1040. hr = THR( E_POINTER );
  1041. goto Cleanup;
  1042. OutOfMemory:
  1043. hr = E_OUTOFMEMORY;
  1044. goto Cleanup;
  1045. UnexpectedState:
  1046. hr = THR( E_UNEXPECTED );
  1047. goto Cleanup;
  1048. }
  1049. //
  1050. // Description:
  1051. // Marks a property as having multiple values. This should only be called
  1052. // when multiple source documents have been selected and the values are
  1053. // all different.
  1054. //
  1055. // Return Value:
  1056. // S_OK
  1057. // Success!
  1058. //
  1059. HRESULT
  1060. CPropertyCacheItem::MarkMultiple( void )
  1061. {
  1062. TraceFunc( "" );
  1063. HRESULT hr = S_OK;
  1064. _fMultiple = TRUE;
  1065. PropVariantClear( &_propvar );
  1066. HRETURN( hr );
  1067. }