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.

541 lines
10 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. #include "PropertyCache.h"
  16. #pragma hdrstop
  17. // ***************************************************************************
  18. //
  19. // Constructor / Destructor / Initialization
  20. //
  21. // ***************************************************************************
  22. //
  23. // CreateInstance
  24. //
  25. HRESULT
  26. CPropertyCache::CreateInstance(
  27. CPropertyCache ** ppOut
  28. )
  29. {
  30. TraceFunc( "" );
  31. HRESULT hr;
  32. Assert( NULL != ppOut );
  33. CPropertyCache * pthis = new CPropertyCache;
  34. if ( NULL != pthis )
  35. {
  36. hr = THR( pthis->Init( ) );
  37. if ( SUCCEEDED( hr ) )
  38. {
  39. *ppOut = pthis;
  40. }
  41. else
  42. {
  43. delete pthis;
  44. }
  45. }
  46. else
  47. {
  48. hr = E_OUTOFMEMORY;
  49. }
  50. HRETURN( hr );
  51. }
  52. //
  53. // Constructor
  54. //
  55. CPropertyCache::CPropertyCache( void )
  56. {
  57. TraceFunc( "" );
  58. Assert( NULL == _pPropertyCacheList );
  59. Assert( NULL == _ppui );
  60. TraceFuncExit( );
  61. }
  62. //
  63. // Initialization
  64. //
  65. HRESULT
  66. CPropertyCache::Init( void )
  67. {
  68. TraceFunc( "" );
  69. HRESULT hr = S_OK;
  70. //
  71. // Create the Shell's Property UI helper.
  72. //
  73. hr = THR( CoCreateInstance( CLSID_PropertiesUI
  74. , NULL
  75. , CLSCTX_INPROC_SERVER
  76. , TYPESAFEPARAMS( _ppui )
  77. ) );
  78. HRETURN( hr );
  79. }
  80. //
  81. // Destructor
  82. //
  83. CPropertyCache::~CPropertyCache( void )
  84. {
  85. TraceFunc( "" );
  86. if ( NULL != _ppui )
  87. {
  88. _ppui->Release( );
  89. }
  90. while ( NULL != _pPropertyCacheList )
  91. {
  92. CPropertyCacheItem * pNext;
  93. STHR( _pPropertyCacheList->GetNextItem( &pNext ) );
  94. _pPropertyCacheList->Destroy( );
  95. _pPropertyCacheList = pNext;
  96. }
  97. TraceFuncExit( );
  98. }
  99. //
  100. // Destroy
  101. //
  102. HRESULT
  103. CPropertyCache::Destroy( void )
  104. {
  105. TraceFunc( "" );
  106. HRESULT hr = S_OK;
  107. delete this;
  108. HRETURN( hr );
  109. }
  110. // ***************************************************************************
  111. //
  112. // Public Methods
  113. //
  114. // ***************************************************************************
  115. //
  116. // Description:
  117. // Create a new Property Cache Item and fill in its details.
  118. //
  119. // Return Values:
  120. // S_OK
  121. // Success!
  122. //
  123. // other HRESULTs.
  124. //
  125. HRESULT
  126. CPropertyCache::AddNewPropertyCacheItem(
  127. const FMTID * pFmtIdIn
  128. , PROPID propidIn
  129. , VARTYPE vtIn
  130. , UINT uCodePageIn
  131. , BOOL fForceReadOnlyIn
  132. , IPropertyStorage * ppsIn // optional - can be NULL for new items
  133. , CPropertyCacheItem ** ppItemOut // optional - can be NULL
  134. )
  135. {
  136. TraceFunc( "" );
  137. HRESULT hr;
  138. PROPVARIANT * ppropvar;
  139. PROPSPEC propspec = { PRSPEC_PROPID, 0 };
  140. CPropertyCacheItem * pItem = NULL;
  141. if ( NULL != ppItemOut )
  142. {
  143. *ppItemOut = NULL;
  144. }
  145. hr = THR( CPropertyCacheItem::CreateInstance( &pItem ) );
  146. if ( FAILED( hr ) )
  147. goto Cleanup;
  148. hr = THR( pItem->SetPropertyUIHelper( _ppui ) );
  149. if ( FAILED( hr ) )
  150. goto Cleanup;
  151. hr = THR( pItem->SetFmtId( pFmtIdIn ) );
  152. if ( FAILED( hr ) )
  153. goto Cleanup;
  154. hr = THR( pItem->SetPropId( propidIn ) );
  155. if ( FAILED( hr ) )
  156. goto Cleanup;
  157. hr = THR( pItem->SetDefaultVarType( vtIn ) );
  158. if ( FAILED( hr ) )
  159. goto Cleanup;
  160. hr = THR( pItem->SetCodePage( uCodePageIn ) );
  161. if ( FAILED( hr ) )
  162. goto Cleanup;
  163. if ( fForceReadOnlyIn )
  164. {
  165. hr = THR( pItem->MarkReadOnly( ) );
  166. if ( FAILED( hr ) )
  167. goto Cleanup;
  168. }
  169. if ( NULL != ppsIn )
  170. {
  171. //
  172. // Have the property retrieve its value from the storage.
  173. //
  174. hr = THR( pItem->GetPropertyValue( &ppropvar ) );
  175. if ( FAILED( hr ) )
  176. goto Cleanup;
  177. //
  178. // Read the property's value
  179. //
  180. propspec.propid = propidIn;
  181. hr = THR( SHPropStgReadMultiple( ppsIn, uCodePageIn, 1, &propspec, ppropvar ) );
  182. if ( SUCCEEDED( hr ) )
  183. {
  184. if ( vtIn != ppropvar->vt )
  185. {
  186. //
  187. // Adjust vartype to agree with any type normalization done by
  188. // SHPropStgReadMultiple.
  189. //
  190. hr = THR( pItem->SetDefaultVarType( ppropvar->vt ) );
  191. // ignore error
  192. }
  193. }
  194. }
  195. //
  196. // Finally, add it to the property linked-list.
  197. //
  198. hr = THR( pItem->SetNextItem( _pPropertyCacheList ) );
  199. if ( FAILED( hr ) )
  200. goto Cleanup;
  201. if ( NULL != ppItemOut )
  202. {
  203. *ppItemOut = pItem;
  204. }
  205. _pPropertyCacheList = pItem;
  206. pItem = NULL;
  207. hr = S_OK;
  208. Cleanup:
  209. if ( NULL != pItem )
  210. {
  211. pItem->Destroy( );
  212. }
  213. HRETURN( hr );
  214. }
  215. //
  216. // Description:
  217. // Adds an CPropertyCacheItem to the property cache list.
  218. //
  219. // Return Values:
  220. // S_OK
  221. // Success!
  222. //
  223. // E_INVALIDARG
  224. // pItemIn is NULL.
  225. //
  226. // other HRESULTs.
  227. //
  228. HRESULT
  229. CPropertyCache::AddExistingItem(
  230. CPropertyCacheItem * pItemIn
  231. )
  232. {
  233. TraceFunc( "" );
  234. HRESULT hr;
  235. if ( NULL == pItemIn )
  236. goto InvalidArg;
  237. hr = THR( pItemIn->SetNextItem( _pPropertyCacheList ) );
  238. if ( FAILED( hr ) )
  239. goto Cleanup;
  240. _pPropertyCacheList = pItemIn;
  241. Assert( S_OK == hr );
  242. Cleanup:
  243. HRETURN( hr );
  244. InvalidArg:
  245. hr = THR( E_INVALIDARG );
  246. goto Cleanup;
  247. }
  248. //
  249. // Description:
  250. // Retrieves the next item in the property cache.
  251. //
  252. // Return Values:
  253. // S_OK
  254. // Success!
  255. //
  256. // S_FALSE
  257. // Success, but the list is empty. A NULL pointer was returned.
  258. //
  259. // E_POINTER
  260. // ppItemOut is NULL.
  261. //
  262. // other HRESULTs
  263. //
  264. HRESULT
  265. CPropertyCache::GetNextItem(
  266. CPropertyCacheItem * pItemIn,
  267. CPropertyCacheItem ** ppItemOut
  268. )
  269. {
  270. TraceFunc( "" );
  271. HRESULT hr;
  272. if ( NULL == ppItemOut )
  273. goto InvalidPointer;
  274. *ppItemOut = NULL;
  275. if ( NULL == pItemIn )
  276. {
  277. *ppItemOut = _pPropertyCacheList;
  278. if ( NULL == _pPropertyCacheList )
  279. {
  280. hr = S_FALSE;
  281. }
  282. else
  283. {
  284. hr = S_OK;
  285. }
  286. }
  287. else
  288. {
  289. hr = STHR( pItemIn->GetNextItem( ppItemOut ) );
  290. }
  291. Cleanup:
  292. HRETURN( hr );
  293. InvalidPointer:
  294. hr = THR( E_POINTER );
  295. goto Cleanup;
  296. }
  297. //
  298. // Description:
  299. // Searches the cache for an item that matches the criteria specified.
  300. //
  301. // Return Values:
  302. // S_OK
  303. // Success! Found an item that matches.
  304. //
  305. // S_FALSE
  306. // Success... but no items match the criteria.
  307. //
  308. // E_INVALIDARG
  309. // pFmtIdIn is NULL.
  310. //
  311. HRESULT
  312. CPropertyCache::FindItemEntry(
  313. const FMTID * pFmtIdIn
  314. , PROPID propIdIn
  315. , CPropertyCacheItem ** ppItemOut // optional - can be NULL
  316. )
  317. {
  318. TraceFunc( "" );
  319. HRESULT hr;
  320. CPropertyCacheItem * pItem;
  321. //
  322. // Check parameters
  323. //
  324. if ( NULL == pFmtIdIn )
  325. goto InvalidArg;
  326. //
  327. // Clear out parameters.
  328. //
  329. if ( NULL != ppItemOut )
  330. {
  331. *ppItemOut = NULL;
  332. }
  333. //
  334. // Follow the linked list looking for an item that matches the criteria.
  335. //
  336. pItem = _pPropertyCacheList;
  337. while( NULL != pItem )
  338. {
  339. FMTID fmtId;
  340. PROPID propId;
  341. hr = THR( pItem->GetFmtId( &fmtId ) );
  342. if ( FAILED( hr ) )
  343. goto Cleanup;
  344. hr = THR( pItem->GetPropId( &propId ) );
  345. if ( FAILED( hr ) )
  346. goto Cleanup;
  347. if ( fmtId == *pFmtIdIn && propId == propIdIn )
  348. {
  349. if ( NULL != ppItemOut )
  350. {
  351. *ppItemOut = pItem;
  352. }
  353. hr = S_OK;
  354. goto Cleanup; // exit condition
  355. }
  356. hr = STHR( pItem->GetNextItem( &pItem ) );
  357. if ( S_OK != hr )
  358. break; // exit condition
  359. }
  360. hr = S_FALSE; // not found
  361. Cleanup:
  362. HRETURN( hr );
  363. InvalidArg:
  364. hr = THR( E_INVALIDARG );
  365. goto Cleanup;
  366. }
  367. //
  368. // Description:
  369. // Removes pItemIn from the list.
  370. //
  371. // Return Values:
  372. // S_OK
  373. // Success!
  374. //
  375. // S_FALSE
  376. // The item wasn't found so nothing was removed.
  377. //
  378. // E_INVALIDARG
  379. // pItemIn is NULL.
  380. //
  381. // other HRESULTs
  382. //
  383. HRESULT
  384. CPropertyCache::RemoveItem(
  385. CPropertyCacheItem * pItemIn
  386. )
  387. {
  388. TraceFunc( "" );
  389. HRESULT hr;
  390. CPropertyCacheItem * pItem;
  391. CPropertyCacheItem * pItemLast;
  392. if ( NULL == pItemIn )
  393. goto InvalidArg;
  394. pItemLast = NULL;
  395. pItem = _pPropertyCacheList;
  396. while ( NULL != pItem )
  397. {
  398. if ( pItemIn == pItem )
  399. {
  400. //
  401. // Matched the item.... remove it from the list.
  402. //
  403. CPropertyCacheItem * pItemNext;
  404. hr = STHR( pItem->GetNextItem( &pItemNext ) );
  405. if ( FAILED( hr ) )
  406. goto Cleanup;
  407. if ( NULL == pItemLast )
  408. {
  409. //
  410. // The item is the first in the list.
  411. //
  412. Assert( _pPropertyCacheList == pItem );
  413. _pPropertyCacheList = pItemNext;
  414. }
  415. else
  416. {
  417. //
  418. // The item is in the middle of the list.
  419. //
  420. hr = THR( pItemLast->SetNextItem( pItemNext ) );
  421. if ( FAILED( hr ) )
  422. goto Cleanup;
  423. }
  424. THR( pItem->Destroy( ) );
  425. // ignore error.
  426. hr = S_OK;
  427. break; // exit loop
  428. }
  429. else
  430. {
  431. pItemLast = pItem;
  432. hr = STHR( pItem->GetNextItem( &pItem ) );
  433. if ( S_OK != hr )
  434. goto Cleanup;
  435. }
  436. }
  437. Cleanup:
  438. HRETURN( hr );
  439. InvalidArg:
  440. hr = THR( E_INVALIDARG );
  441. goto Cleanup;
  442. }