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.

1599 lines
40 KiB

  1. #ifndef _CPROPVAR_HXX_
  2. #define _CPROPVAR_HXX_
  3. #ifndef _MAC
  4. #include <wtypes.h>
  5. #include <objidl.h>
  6. #include <oaidl.h>
  7. #endif
  8. #include "CHResult.hxx"
  9. #include <olechar.h>
  10. #ifndef ASSERT
  11. #if DBG==1
  12. #ifdef _MAC
  13. #define ASSERT(assertion) PROPASSERT(assertion)
  14. #else
  15. #include "debnot.h"
  16. #define ASSERT(assertion) {if(!(assertion)) Win4AssertEx(__FILE__, __LINE__, (#assertion));}
  17. #endif
  18. #else
  19. #define ASSERT(assertion)
  20. #endif
  21. #endif
  22. class CClipData;
  23. class CBlob;
  24. class CPropVariant;
  25. class CClipData : private CLIPDATA
  26. {
  27. public:
  28. ~CClipData()
  29. {
  30. if( NULL != pClipData)
  31. CoTaskMemFree( pClipData);
  32. }
  33. CClipData()
  34. {
  35. cbSize = sizeof( ulClipFmt );
  36. ulClipFmt = (ULONG) -1;
  37. pClipData = NULL;
  38. }
  39. CClipData( ULONG ul, const void *p, ULONG cb )
  40. {
  41. HRESULT hr;
  42. this->CClipData::CClipData();
  43. hr = Set( ul, p, cb );
  44. ASSERT( SUCCEEDED(hr) );
  45. }
  46. CClipData( LPSTR psz )
  47. {
  48. this->CClipData::CClipData( (ULONG) -1, psz, strlen(psz) + 1 );
  49. }
  50. CClipData( LPWSTR pwsz )
  51. {
  52. this->CClipData::CClipData( (ULONG) -1, pwsz,
  53. sizeof(WCHAR) * (wcslen(pwsz) + 1) );
  54. }
  55. CClipData( CClipData &cClipData )
  56. {
  57. HRESULT hr;
  58. hr = Set( cClipData.ulClipFmt,
  59. cClipData.pClipData,
  60. cClipData.cbSize - sizeof(ulClipFmt));
  61. ASSERT( SUCCEEDED(hr) );
  62. }
  63. CClipData& operator =(CClipData &cClipData)
  64. {
  65. HRESULT hr;
  66. hr = Set( cClipData.ulClipFmt,
  67. cClipData.pClipData,
  68. cClipData.cbSize - sizeof(ulClipFmt));
  69. ASSERT( SUCCEEDED(hr) );
  70. return( *this );
  71. }
  72. HRESULT Set( ULONG ul, const void *p, ULONG cb )
  73. {
  74. if( NULL != pClipData )
  75. {
  76. cb = sizeof( ulClipFmt );
  77. ulClipFmt = (ULONG) -1;
  78. CoTaskMemFree( pClipData );
  79. }
  80. if( NULL != p )
  81. {
  82. pClipData = (BYTE*) CoTaskMemAlloc( cb );
  83. if( NULL == pClipData )
  84. return( (HRESULT) E_OUTOFMEMORY );
  85. memcpy( pClipData, p, cb );
  86. }
  87. cbSize = sizeof( ulClipFmt ) + cb;
  88. ulClipFmt = ul;
  89. return( S_OK );
  90. }
  91. operator const CLIPDATA*()
  92. {
  93. return( this );
  94. }
  95. operator CLIPDATA*()
  96. {
  97. return( this );
  98. }
  99. };
  100. #define INVALID_SUBSCRIPT 0
  101. template< VARENUM tpltVT, class tpltType >
  102. void TCPropVarAssignmentOperator( CPropVariant *pThis, tpltType Type )
  103. {
  104. if( INVALID_SUBSCRIPT == pThis->wReserved1 )
  105. {
  106. PropVariantClear(pThis);
  107. pThis->Set(tpltVT, (void*) &Type, INVALID_SUBSCRIPT );
  108. return;
  109. }
  110. else
  111. {
  112. if( !(pThis->vt & VT_VECTOR)
  113. ||
  114. (pThis->vt & ~VT_VECTOR) != tpltVT )
  115. {
  116. WORD wReserved1Save = pThis->wReserved1;
  117. PropVariantClear(pThis);
  118. pThis->wReserved1 = wReserved1Save;
  119. }
  120. pThis->Set( tpltVT | VT_VECTOR, (void*) &Type, pThis->wReserved1 - 1);
  121. pThis->wReserved1 = INVALID_SUBSCRIPT;
  122. return;
  123. }
  124. }
  125. template< VARENUM tpltVT, class TCountedArray, class TProperty >
  126. TProperty
  127. TCPropVarConversionOperator( CPropVariant *pThis, TCountedArray *pca, TProperty *pSingleton )
  128. {
  129. if( pThis->vt & VT_VECTOR )
  130. {
  131. ASSERT( pThis->vt == (tpltVT | VT_VECTOR)
  132. ||
  133. pThis->vt == (VT_VARIANT | VT_VECTOR) );
  134. ASSERT( pThis->wReserved1 > 0 );
  135. if( pThis->wReserved1 > 0
  136. &&
  137. pca->cElems > 0
  138. &&
  139. pThis->wReserved1 <= (pca->cElems) )
  140. {
  141. USHORT usSubscript = pThis->wReserved1 - 1;
  142. pThis->wReserved1 = 0;
  143. if( (pThis->vt & ~VT_VECTOR) == VT_VARIANT )
  144. return( (TProperty) *(CPropVariant*)(PROPVARIANT*)
  145. &((CAPROPVARIANT*)pca)->pElems[usSubscript] );
  146. else
  147. return( pca->pElems[ usSubscript ] );
  148. }
  149. else
  150. {
  151. throw CHRESULT( (HRESULT) E_INVALIDARG, OLESTR("Index not set on conversion of vector") );
  152. // This unnecessary statement avoids a compiler error.
  153. return pca->pElems[ 0 ];
  154. }
  155. }
  156. else
  157. {
  158. ASSERT( vt == tpltVT );
  159. return( *pSingleton );
  160. }
  161. }
  162. #define DECLARE_CPROPVARIANT_ASSIGNMENT_OPERATOR(Type) \
  163. CPropVariant & operator =( Type);
  164. #define DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(VT, Type ) \
  165. \
  166. CPropVariant & CPropVariant::operator =( Type pType) \
  167. { \
  168. if( INVALID_SUBSCRIPT == wReserved1 ) \
  169. { \
  170. PropVariantClear(this); \
  171. this->CPropVariant::CPropVariant(pType); \
  172. return (*this); \
  173. } \
  174. else \
  175. { \
  176. if( !(vt & VT_VECTOR) \
  177. || \
  178. (vt & ~VT_VECTOR) != VT_##VT ) \
  179. { \
  180. WORD wReserved1Save = wReserved1; \
  181. PropVariantClear(this); \
  182. this->CPropVariant::CPropVariant( VT_##VT, \
  183. wReserved1Save ); \
  184. wReserved1 = wReserved1Save; \
  185. } \
  186. \
  187. Set##VT( pType, wReserved1 - 1); \
  188. wReserved1 = 0; \
  189. return (*this); \
  190. } \
  191. }
  192. #define DECLARE_CPROPVARIANT_CONVERSION_OPERATOR(VarType) \
  193. operator VarType();
  194. #define DEFINE_CPROPVARIANT_CONVERSION_OPERATOR(VarType, CAName, SingletonName) \
  195. CPropVariant::operator VarType() \
  196. { \
  197. if( vt & VT_VECTOR ) \
  198. { \
  199. ASSERT( vt == (VT_##VarType | VT_VECTOR) \
  200. || \
  201. vt == (VT_VARIANT | VT_VECTOR) ); \
  202. ASSERT( wReserved1 > 0 ); \
  203. \
  204. if( wReserved1 > 0 \
  205. && \
  206. ##CAName.cElems > 0 \
  207. && \
  208. wReserved1 <= (##CAName.cElems) ) \
  209. { \
  210. USHORT usSubscript = wReserved1 - 1; \
  211. wReserved1 = 0; \
  212. if( (vt & ~VT_VECTOR) == VT_VARIANT ) \
  213. return( capropvar.pElems[ usSubscript ].##SingletonName );\
  214. else \
  215. return( ##CAName.pElems[ usSubscript ] ); \
  216. } \
  217. else \
  218. return( NULL ); \
  219. } \
  220. else \
  221. { \
  222. ASSERT( vt == VT_##VarType ); \
  223. return( ##SingletonName ); \
  224. } \
  225. }
  226. class CPropVariant : public tagPROPVARIANT
  227. {
  228. public:
  229. // --------------------------------
  230. // Default Constructor & Destructor
  231. // --------------------------------
  232. CPropVariant()
  233. {
  234. Init();
  235. wReserved1 = INVALID_SUBSCRIPT;
  236. }
  237. ~CPropVariant()
  238. {
  239. Clear();
  240. }
  241. CPropVariant( CPropVariant &cpropvar )
  242. {
  243. Init();
  244. PropVariantCopy( this, &cpropvar );
  245. }
  246. // -------------------
  247. // Generic Set routine
  248. // -------------------
  249. void Set( VARTYPE vtSet, void *pv, ULONG pos );
  250. // ------------------------------------------------------------
  251. // Constructors, assignment operators, and conversion functions
  252. // ------------------------------------------------------------
  253. // VT_I1 (CHAR)
  254. CPropVariant(CHAR c)
  255. {
  256. Init();
  257. SetI1(c);
  258. }
  259. void SetI1(CHAR c)
  260. {
  261. Clear();
  262. vt = VT_I1;
  263. cVal = c;
  264. }
  265. void SetI1( CHAR c, ULONG pos )
  266. {
  267. if( vt != (VT_I1 | VT_VECTOR) ) Clear();
  268. _AddScalerToVector( pos, &c, sizeof(c) );
  269. vt = VT_I1 | VT_VECTOR;
  270. }
  271. UCHAR GetI1()
  272. {
  273. _ValidateGet( VT_I1 );
  274. return( cVal );
  275. }
  276. UCHAR GetI1( ULONG pos )
  277. {
  278. _ValidateGet( VT_I1, pos );
  279. return( cac.pElems[pos] );
  280. }
  281. CPropVariant & operator =(CHAR c)
  282. {
  283. TCPropVarAssignmentOperator<VT_I1,CHAR>(this, c );
  284. return (*this);
  285. }
  286. operator CHAR()
  287. {
  288. return TCPropVarConversionOperator<VT_I1,CAC,CHAR>
  289. ( this, &cac, &cVal );
  290. }
  291. // VT_UI1 (UCHAR)
  292. CPropVariant(UCHAR b)
  293. {
  294. Init();
  295. SetUI1(b);
  296. }
  297. void SetUI1(UCHAR b)
  298. {
  299. Clear();
  300. vt = VT_UI1;
  301. bVal = b;
  302. }
  303. void SetUI1( UCHAR b, ULONG pos )
  304. {
  305. if( vt != (VT_UI1 | VT_VECTOR) ) Clear();
  306. _AddScalerToVector( pos, &b, sizeof(b) );
  307. vt = VT_UI1 | VT_VECTOR;
  308. }
  309. UCHAR GetUI1()
  310. {
  311. _ValidateGet( VT_UI1 );
  312. return( bVal );
  313. }
  314. UCHAR GetUI1( ULONG pos )
  315. {
  316. _ValidateGet( VT_UI1, pos );
  317. return( caub.pElems[pos] );
  318. }
  319. CPropVariant & operator =(UCHAR b)
  320. {
  321. TCPropVarAssignmentOperator<VT_UI1,UCHAR>(this, b );
  322. return (*this);
  323. }
  324. operator UCHAR()
  325. {
  326. return TCPropVarConversionOperator<VT_UI1,CAUB,UCHAR>
  327. ( this, &caub, &bVal );
  328. }
  329. // VT_I2 (short)
  330. CPropVariant(short i)
  331. {
  332. Init();
  333. SetI2(i);
  334. }
  335. void SetI2(short i)
  336. {
  337. Clear();
  338. vt = VT_I2;
  339. iVal = i;
  340. }
  341. void SetI2( short i, ULONG pos )
  342. {
  343. if( vt != (VT_I2 | VT_VECTOR) ) Clear();
  344. _AddScalerToVector( pos, &i, sizeof(i) );
  345. vt = VT_I2 | VT_VECTOR;
  346. }
  347. short GetI2()
  348. {
  349. _ValidateGet( VT_I2 );
  350. return(iVal);
  351. }
  352. short GetI2( ULONG pos )
  353. {
  354. _ValidateGet( VT_I2, pos );
  355. return( cai.pElems[pos] );
  356. }
  357. CPropVariant & operator =(short i)
  358. {
  359. TCPropVarAssignmentOperator<VT_I2,short>(this, i);
  360. return (*this);
  361. }
  362. operator short()
  363. {
  364. return TCPropVarConversionOperator<VT_I2,CAI,short>
  365. ( this, &cai, &iVal );
  366. }
  367. // VT_UI2 (USHORT)
  368. CPropVariant(USHORT ui)
  369. {
  370. Init();
  371. SetUI2(ui);
  372. }
  373. void SetUI2(USHORT ui)
  374. {
  375. Clear();
  376. vt = VT_UI2;
  377. uiVal = ui;
  378. }
  379. void SetUI2( USHORT ui, ULONG pos )
  380. {
  381. if( vt != (VT_UI2 | VT_VECTOR) ) Clear();
  382. _AddScalerToVector( pos, &ui, sizeof(ui) );
  383. vt = VT_UI2 | VT_VECTOR;
  384. }
  385. USHORT GetUI2()
  386. {
  387. _ValidateGet( VT_UI2 );
  388. return( uiVal );
  389. }
  390. USHORT GetUI2( ULONG pos )
  391. {
  392. _ValidateGet( VT_UI2, pos );
  393. return( caui.pElems[pos] );
  394. }
  395. CPropVariant & operator =(USHORT ui)
  396. {
  397. TCPropVarAssignmentOperator<VT_UI2,USHORT>(this, ui);
  398. return (*this);
  399. }
  400. operator USHORT()
  401. {
  402. return TCPropVarConversionOperator<VT_UI2,CAUI,USHORT>
  403. ( this, &caui, &uiVal );
  404. }
  405. // VT_I4 (long)
  406. CPropVariant(long l)
  407. {
  408. Init();
  409. SetI4(l);
  410. }
  411. void SetI4(long l)
  412. {
  413. Clear();
  414. vt = VT_I4;
  415. lVal = l;
  416. }
  417. void SetI4( long l, ULONG pos )
  418. {
  419. if( vt != (VT_I4 | VT_VECTOR) ) Clear();
  420. _AddScalerToVector( pos, &l, sizeof(l) );
  421. vt = VT_I4 | VT_VECTOR;
  422. }
  423. long GetI4()
  424. {
  425. _ValidateGet( VT_I4 );
  426. return( lVal );
  427. }
  428. long GetI4( ULONG pos )
  429. {
  430. _ValidateGet( VT_I4, pos );
  431. return( cal.pElems[ pos ] );
  432. }
  433. CPropVariant & operator =(long l)
  434. {
  435. TCPropVarAssignmentOperator<VT_I4,long>(this, l);
  436. return (*this);
  437. }
  438. CPropVariant & operator =(int i) // Assume sizeof(int)==sizeof(long)
  439. {
  440. TCPropVarAssignmentOperator<VT_I4,long>(this, i);
  441. return (*this);
  442. }
  443. operator long()
  444. {
  445. return TCPropVarConversionOperator<VT_I4,CAL,long>
  446. ( this, &cal, &lVal );
  447. }
  448. // VT_INT (long)
  449. void SetINT(long l)
  450. {
  451. Clear();
  452. vt = VT_INT;
  453. intVal = l;
  454. }
  455. long GetINT()
  456. {
  457. _ValidateGet( VT_INT );
  458. return( intVal );
  459. }
  460. // VT_UI4 (ULONG)
  461. CPropVariant(ULONG ul)
  462. {
  463. Init();
  464. SetUI4(ul);
  465. }
  466. void SetUI4(ULONG ul)
  467. {
  468. Clear();
  469. vt = VT_UI4;
  470. ulVal = ul;
  471. }
  472. void SetUI4( ULONG ul, ULONG pos )
  473. {
  474. if( vt != (VT_UI4 | VT_VECTOR) ) Clear();
  475. _AddScalerToVector( pos, &ul, sizeof(ul) );
  476. vt = VT_UI4 | VT_VECTOR;
  477. }
  478. ULONG GetUI4()
  479. {
  480. _ValidateGet( VT_UI4 );
  481. return( ulVal );
  482. }
  483. ULONG GetUI4( ULONG pos )
  484. {
  485. _ValidateGet( VT_UI4, pos );
  486. return( caul.pElems[ pos ] );
  487. }
  488. CPropVariant & operator =(ULONG ul)
  489. {
  490. TCPropVarAssignmentOperator<VT_UI4,ULONG>(this, ul);
  491. return (*this);
  492. }
  493. operator ULONG()
  494. {
  495. return TCPropVarConversionOperator<VT_UI4,CAUL,ULONG>
  496. ( this, &caul, &ulVal );
  497. }
  498. // VT_UINT (unsigned long)
  499. void SetUINT(ULONG ul)
  500. {
  501. Clear();
  502. vt = VT_UINT;
  503. uintVal = ul;
  504. }
  505. long GetUINT()
  506. {
  507. _ValidateGet( VT_UINT );
  508. return( uintVal );
  509. }
  510. // VT_I8 (LARGE_INTEGER)
  511. CPropVariant(LARGE_INTEGER h)
  512. {
  513. Init();
  514. SetI8(h);
  515. }
  516. void SetI8(LARGE_INTEGER h)
  517. {
  518. Clear();
  519. vt = VT_I8;
  520. hVal = h;
  521. }
  522. void SetI8( LARGE_INTEGER h, ULONG pos )
  523. {
  524. if( vt != (VT_I8 | VT_VECTOR) ) Clear();
  525. _AddScalerToVector( pos, &h, sizeof(h) );
  526. vt = VT_I8 | VT_VECTOR;
  527. }
  528. LARGE_INTEGER GetI8()
  529. {
  530. _ValidateGet( VT_I8 );
  531. return( hVal );
  532. }
  533. LARGE_INTEGER GetI8( ULONG pos )
  534. {
  535. _ValidateGet( VT_I8, pos );
  536. return( cah.pElems[ pos ] );
  537. }
  538. CPropVariant & operator=(LARGE_INTEGER h)
  539. {
  540. TCPropVarAssignmentOperator<VT_I8,LARGE_INTEGER>(this, h);
  541. return (*this);
  542. }
  543. operator LARGE_INTEGER()
  544. {
  545. return TCPropVarConversionOperator<VT_I8,CAH,LARGE_INTEGER>
  546. ( this, &cah, &hVal );
  547. }
  548. // VT_UI8 (ULARGE_INTEGER)
  549. CPropVariant(ULARGE_INTEGER uh)
  550. {
  551. Init();
  552. SetUI8(uh);
  553. }
  554. void SetUI8(ULARGE_INTEGER uh)
  555. {
  556. Clear();
  557. vt = VT_UI8;
  558. uhVal = uh;
  559. }
  560. void SetUI8( ULARGE_INTEGER uh, ULONG pos )
  561. {
  562. if( vt != (VT_UI8 | VT_VECTOR) ) Clear();
  563. _AddScalerToVector( pos, &uh, sizeof(uh) );
  564. vt = VT_UI8 | VT_VECTOR;
  565. }
  566. ULARGE_INTEGER GetUI8()
  567. {
  568. _ValidateGet( VT_UI8 );
  569. return( uhVal );
  570. }
  571. ULARGE_INTEGER GetUI8( ULONG pos )
  572. {
  573. _ValidateGet( VT_UI8, pos );
  574. return( cauh.pElems[ pos ] );
  575. }
  576. CPropVariant & operator=(ULARGE_INTEGER uh)
  577. {
  578. TCPropVarAssignmentOperator<VT_UI8,ULARGE_INTEGER>(this, uh);
  579. return (*this);
  580. }
  581. operator ULARGE_INTEGER()
  582. {
  583. return TCPropVarConversionOperator<VT_UI8,CAUH,ULARGE_INTEGER>
  584. ( this, &cauh, &uhVal );
  585. }
  586. // VT_R4 (float)
  587. CPropVariant(float flt)
  588. {
  589. Init();
  590. SetR4(flt);
  591. }
  592. void SetR4(float flt)
  593. {
  594. Clear();
  595. vt = VT_R4;
  596. fltVal = flt;
  597. }
  598. void SetR4( float flt, ULONG pos )
  599. {
  600. if( vt != (VT_R4 | VT_VECTOR) ) Clear();
  601. _AddScalerToVector( pos, &flt, sizeof(flt) );
  602. vt = VT_R4 | VT_VECTOR;
  603. }
  604. float GetR4()
  605. {
  606. _ValidateGet( VT_R4 );
  607. return( fltVal );
  608. }
  609. float GetR4( ULONG pos )
  610. {
  611. _ValidateGet( VT_R4, pos );
  612. return( caflt.pElems[ pos ] );
  613. }
  614. CPropVariant & operator=(float flt)
  615. {
  616. TCPropVarAssignmentOperator<VT_R4,float>(this, flt);
  617. return (*this);
  618. }
  619. operator float()
  620. {
  621. return TCPropVarConversionOperator<VT_R4,CAFLT,float>
  622. ( this, &caflt, &fltVal );
  623. }
  624. // VT_R8 (double)
  625. CPropVariant(double dbl)
  626. {
  627. Init();
  628. SetR8(dbl);
  629. }
  630. void SetR8(double dbl)
  631. {
  632. Clear();
  633. vt = VT_R8;
  634. dblVal = dbl;
  635. }
  636. void SetR8( double dbl, ULONG pos )
  637. {
  638. if( vt != (VT_R8 | VT_VECTOR) ) Clear();
  639. _AddScalerToVector( pos, &dbl, sizeof(dbl) );
  640. vt = VT_R8 | VT_VECTOR;
  641. }
  642. double GetR8()
  643. {
  644. _ValidateGet( VT_R8 );
  645. return( dblVal );
  646. }
  647. double GetR8( ULONG pos )
  648. {
  649. _ValidateGet( VT_R8, pos );
  650. return( cadbl.pElems[ pos ] );
  651. }
  652. CPropVariant & operator=(double dbl)
  653. {
  654. TCPropVarAssignmentOperator<VT_R8,double>(this, dbl);
  655. return (*this);
  656. }
  657. operator double()
  658. {
  659. return TCPropVarConversionOperator<VT_R8,CADBL,double>
  660. ( this, &cadbl, &dblVal );
  661. }
  662. // VT_CY (CY)
  663. CPropVariant(CY cy)
  664. {
  665. Init();
  666. SetCY(cy);
  667. }
  668. void SetCY(const CY &cy)
  669. {
  670. Clear();
  671. vt = VT_CY;
  672. cyVal = cy;
  673. }
  674. void SetCY( const CY &cy, ULONG pos )
  675. {
  676. if( vt != (VT_CY | VT_VECTOR) ) Clear();
  677. _AddScalerToVector( pos, &cy, sizeof(cy) );
  678. vt = VT_CY | VT_VECTOR;
  679. }
  680. CPropVariant & operator=(const CY &cy)
  681. {
  682. TCPropVarAssignmentOperator<VT_CY,CY>(this, cy);
  683. return (*this);
  684. }
  685. CY GetCY()
  686. {
  687. _ValidateGet( VT_CY );
  688. return( cyVal );
  689. }
  690. CY GetCY( ULONG pos )
  691. {
  692. _ValidateGet( VT_CY, pos );
  693. return( cacy.pElems[ pos ] );
  694. }
  695. operator CY()
  696. {
  697. return TCPropVarConversionOperator<VT_CY,CACY,CY>
  698. ( this, &cacy, &cyVal );
  699. }
  700. // VT_FILETIME (FILETIME)
  701. CPropVariant(const FILETIME &filetime)
  702. {
  703. Init();
  704. SetFILETIME(filetime);
  705. }
  706. void SetFILETIME(const FILETIME &ft)
  707. {
  708. Clear();
  709. vt = VT_FILETIME;
  710. filetime = ft;
  711. }
  712. void SetFILETIME( const FILETIME &ft, ULONG pos )
  713. {
  714. if( vt != (VT_FILETIME | VT_VECTOR) ) Clear();
  715. _AddScalerToVector( pos, &ft, sizeof(ft) );
  716. vt = VT_FILETIME | VT_VECTOR;
  717. }
  718. FILETIME GetFILETIME()
  719. {
  720. _ValidateGet( VT_FILETIME );
  721. return( filetime );
  722. }
  723. FILETIME GetFILETIME( ULONG pos )
  724. {
  725. _ValidateGet( VT_FILETIME, pos );
  726. return( cafiletime.pElems[ pos ] );
  727. }
  728. CPropVariant & operator=(const FILETIME &ft)
  729. {
  730. TCPropVarAssignmentOperator<VT_FILETIME,FILETIME>(this, ft);
  731. return (*this);
  732. }
  733. operator FILETIME()
  734. {
  735. return TCPropVarConversionOperator<VT_FILETIME,CAFILETIME,FILETIME>
  736. ( this, &cafiletime, &filetime );
  737. }
  738. // VT_CLSID (CLSID)
  739. CPropVariant(CLSID *pclsid)
  740. {
  741. Init();
  742. SetCLSID(pclsid);
  743. }
  744. void SetCLSID(const CLSID *pclsid);
  745. void SetCLSID(const CLSID &clsid)
  746. {
  747. SetCLSID( &clsid );
  748. }
  749. void SetCLSID(const CLSID *pclsid, unsigned pos);
  750. void SetCLSID(const CLSID &clsid, unsigned pos )
  751. {
  752. if( vt != (VT_CLSID | VT_VECTOR) )
  753. {
  754. Clear();
  755. vt = VT_CLSID | VT_VECTOR;
  756. }
  757. SetCLSID( &clsid, pos );
  758. }
  759. CLSID* GetCLSID()
  760. {
  761. _ValidateGet( VT_CLSID );
  762. return( puuid );
  763. }
  764. CLSID* GetCLSID( ULONG pos )
  765. {
  766. _ValidateGet( VT_CLSID, pos );
  767. return( &cauuid.pElems[ pos ] );
  768. }
  769. CPropVariant & operator=(const CLSID *pclsid)
  770. {
  771. TCPropVarAssignmentOperator<VT_CLSID,const CLSID*>(this, pclsid);
  772. return( *this );
  773. }
  774. CPropVariant & operator=(const CLSID &clsid)
  775. {
  776. TCPropVarAssignmentOperator<VT_CLSID,const CLSID*>(this, &clsid);
  777. return( *this );
  778. }
  779. operator CLSID()
  780. {
  781. return TCPropVarConversionOperator<VT_CLSID,CACLSID,CLSID>
  782. ( this, &cauuid, puuid );
  783. }
  784. // VT_STREAM (IStream*)
  785. CPropVariant( IStream *pStm )
  786. {
  787. Init();
  788. SetSTREAM( pStm );
  789. }
  790. void SetSTREAM( IStream *pStm )
  791. {
  792. Clear();
  793. vt = VT_STREAM;
  794. pStream = pStm;
  795. if( NULL != pStream )
  796. pStream->AddRef();
  797. }
  798. IStream* GetSTREAM()
  799. {
  800. _ValidateGet( VT_STREAM );
  801. return( pStream );
  802. }
  803. CPropVariant & operator= ( IStream *pStm )
  804. {
  805. Clear();
  806. SetSTREAM( pStm );
  807. return (*this);
  808. }
  809. operator IStream*()
  810. {
  811. return( GetSTREAM() );
  812. }
  813. // VT_VERSIONED_STREAM
  814. CPropVariant( VERSIONEDSTREAM& verstream )
  815. {
  816. Init();
  817. SetVERSIONEDSTREAM( &verstream );
  818. }
  819. void SetVERSIONEDSTREAM( VERSIONEDSTREAM *pverstream)
  820. {
  821. Clear();
  822. vt = VT_VERSIONED_STREAM;
  823. pVersionedStream = (LPVERSIONEDSTREAM) CoTaskMemAlloc( sizeof(*pVersionedStream) );
  824. if( NULL == pVersionedStream )
  825. throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Failed CoTaskMemAlloc for VT_VERSIONED_STREAM") );
  826. pVersionedStream->guidVersion = pverstream->guidVersion;
  827. if( NULL != pverstream->pStream )
  828. pverstream->pStream->AddRef();
  829. pVersionedStream->pStream = pverstream->pStream;
  830. }
  831. VERSIONEDSTREAM GetVERSIONEDSTREAM()
  832. {
  833. _ValidateGet( VT_VERSIONED_STREAM );
  834. return( *pVersionedStream );
  835. }
  836. CPropVariant & operator= ( VERSIONEDSTREAM &verstream )
  837. {
  838. Clear();
  839. SetVERSIONEDSTREAM( &verstream );
  840. return (*this);
  841. }
  842. operator VERSIONEDSTREAM()
  843. {
  844. return( GetVERSIONEDSTREAM() );
  845. }
  846. // VT_STORAGE (IStorage*)
  847. CPropVariant( IStorage *pStg )
  848. {
  849. Init();
  850. SetSTORAGE( pStg );
  851. }
  852. void SetSTORAGE( IStorage *pStg )
  853. {
  854. vt = VT_STORAGE;
  855. pStorage = pStg;
  856. if( NULL != pStorage )
  857. pStorage->AddRef();
  858. }
  859. IStorage* GetSTORAGE()
  860. {
  861. _ValidateGet( VT_STORAGE );
  862. return( pStorage );
  863. }
  864. CPropVariant & operator = ( IStorage *pStg )
  865. {
  866. Clear();
  867. SetSTORAGE( pStg );
  868. return (*this);
  869. }
  870. operator IStorage*()
  871. {
  872. return( GetSTORAGE() );
  873. }
  874. // VT_LPSTR (LPSTR)
  875. CPropVariant( const LPSTR psz )
  876. {
  877. Init();
  878. SetLPSTR(psz);
  879. }
  880. void SetLPSTR(const LPSTR psz)
  881. {
  882. Clear();
  883. pszVal = (LPSTR) CoTaskMemAlloc( strlen(psz) + 1 );
  884. if( NULL == pszVal )
  885. throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Failed CoTaskMemAlloc for VT_LPSTR") );
  886. vt = VT_LPSTR;
  887. strcpy( pszVal, psz );
  888. }
  889. void SetLPSTR( const LPSTR psz, ULONG pos )
  890. {
  891. if( vt != (VT_LPSTR | VT_VECTOR) ) Clear();
  892. _AddStringToVector( pos, psz, strlen(psz) + 1, VT_LPSTR );
  893. vt = VT_LPSTR | VT_VECTOR;
  894. }
  895. LPSTR GetLPSTR()
  896. {
  897. _ValidateGet( VT_LPSTR );
  898. return( pszVal );
  899. }
  900. LPSTR GetLPSTR( ULONG pos )
  901. {
  902. _ValidateGet( VT_LPSTR, pos );
  903. return( calpstr.pElems[ pos ] );
  904. }
  905. CPropVariant & operator=(const LPSTR psz)
  906. {
  907. TCPropVarAssignmentOperator<VT_LPSTR,LPSTR>(this, psz);
  908. return (*this);
  909. }
  910. operator LPSTR()
  911. {
  912. return TCPropVarConversionOperator<VT_LPSTR,CALPSTR,LPSTR>
  913. ( this, &calpstr, &pszVal );
  914. }
  915. // VT_LPWSTR (LPWSTR)
  916. CPropVariant( const LPWSTR pwsz )
  917. {
  918. Init();
  919. SetLPWSTR(pwsz);
  920. }
  921. void SetLPWSTR(const LPWSTR pwsz)
  922. {
  923. Clear();
  924. pwszVal = (LPWSTR) CoTaskMemAlloc( sizeof(WCHAR) * (wcslen(pwsz) + 1) );
  925. if( NULL == pwszVal )
  926. throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Failed CoTaskMemAlloc for VT_LPWSTR") );
  927. vt = VT_LPWSTR;
  928. wcscpy( pwszVal, pwsz );
  929. }
  930. void SetLPWSTR( const LPWSTR pwsz, ULONG pos )
  931. {
  932. if( vt != (VT_LPWSTR | VT_VECTOR) ) Clear();
  933. _AddStringToVector( pos, pwsz, 2 * (wcslen(pwsz) + 1), VT_LPWSTR );
  934. vt = VT_LPWSTR | VT_VECTOR;
  935. }
  936. LPWSTR GetLPWSTR()
  937. {
  938. _ValidateGet( VT_LPWSTR );
  939. return( pwszVal );
  940. }
  941. LPWSTR GetLPWSTR( ULONG pos )
  942. {
  943. _ValidateGet( VT_LPWSTR, pos );
  944. return( calpwstr.pElems[ pos ] );
  945. }
  946. CPropVariant & operator=(const LPWSTR pwsz)
  947. {
  948. TCPropVarAssignmentOperator<VT_LPWSTR,LPWSTR>(this, pwsz);
  949. return (*this);
  950. }
  951. operator LPWSTR()
  952. {
  953. return TCPropVarConversionOperator<VT_LPWSTR,CALPWSTR,LPWSTR>
  954. ( this, &calpwstr, &pwszVal );
  955. }
  956. // VT_CF (CLIPDATA*)
  957. CPropVariant( const CLIPDATA *pclip )
  958. {
  959. Init();
  960. SetCF(pclip);
  961. }
  962. void SetCF( const CLIPDATA *pclip );
  963. void SetCF( const CLIPDATA *pclip, ULONG pos );
  964. CLIPDATA* GetCF()
  965. {
  966. _ValidateGet( VT_CF );
  967. return( pclipdata );
  968. }
  969. CLIPDATA* GetCF( ULONG pos )
  970. {
  971. _ValidateGet( VT_CF, pos );
  972. return( &caclipdata.pElems[ pos ] );
  973. }
  974. CPropVariant & operator= ( const CLIPDATA *pclip )
  975. {
  976. TCPropVarAssignmentOperator<VT_CF,const CLIPDATA*>(this, pclip);
  977. return (*this);
  978. }
  979. CPropVariant & operator= ( const CLIPDATA &clip )
  980. {
  981. TCPropVarAssignmentOperator<VT_CF,const CLIPDATA*>(this, &clip);
  982. return (*this);
  983. }
  984. CPropVariant & operator= ( CClipData &cclipdata )
  985. {
  986. // This parameter should be const, but when it is, the compiler won't
  987. // convert it to (const CLIPDATA*).
  988. TCPropVarAssignmentOperator<VT_CF,const CLIPDATA*>(this, (const CLIPDATA*)cclipdata);
  989. return (*this);
  990. }
  991. operator CLIPDATA*()
  992. {
  993. // We can't use TCPropVarConversionOperator template, because the caclipdata
  994. // member holds different types (CLIPDATA) than does the pclipdata
  995. // member (CLIPDATA*). The template assumes that the singleton properties
  996. // and vector properties are of the same type.
  997. if( wReserved1 > 0 )
  998. {
  999. USHORT usSubscript = wReserved1 - 1;
  1000. wReserved1 = 0;
  1001. return GetCF( usSubscript );
  1002. }
  1003. else
  1004. {
  1005. return GetCF();
  1006. }
  1007. }
  1008. // VT_BLOB (BLOB*)
  1009. CPropVariant(const BLOB &blobIn)
  1010. {
  1011. Init();
  1012. SetBLOB(blobIn);
  1013. }
  1014. void SetBLOB(const BLOB &blobIn)
  1015. {
  1016. Clear();
  1017. blob.pBlobData = (BYTE*) CoTaskMemAlloc( blobIn.cbSize );
  1018. if( NULL == blob.pBlobData )
  1019. throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("CPropVariant couldn't alloc for VT_BLOB") );
  1020. memcpy( blob.pBlobData, blobIn.pBlobData, blobIn.cbSize );
  1021. blob.cbSize = blobIn.cbSize;
  1022. vt = VT_BLOB;
  1023. }
  1024. BLOB GetBLOB()
  1025. {
  1026. _ValidateGet( VT_BLOB );
  1027. return( blob );
  1028. }
  1029. CPropVariant & operator=(const BLOB &blobIn)
  1030. {
  1031. TCPropVarAssignmentOperator<VT_BLOB,BLOB>(this, blobIn);
  1032. return (*this);
  1033. }
  1034. operator BLOB()
  1035. {
  1036. return( GetBLOB() );
  1037. }
  1038. CPropVariant( const CBlob &cblobIn )
  1039. {
  1040. Init();
  1041. SetBLOB( *(BLOB*) &cblobIn );
  1042. }
  1043. CPropVariant &operator = (CBlob &cblobIn)
  1044. {
  1045. TCPropVarAssignmentOperator<VT_BLOB,BLOB>(this, *(BLOB*)&cblobIn );
  1046. return( *this );
  1047. }
  1048. // VT_BSTR (BSTR)
  1049. void SetBSTR(const BSTR bstrIn)
  1050. {
  1051. Clear();
  1052. bstrVal = SysAllocString( bstrIn );
  1053. if( NULL == bstrIn )
  1054. throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Failed CoTaskMemAlloc for VT_BSTR") );
  1055. vt = VT_BSTR;
  1056. }
  1057. void SetBSTR( const BSTR bstrIn, ULONG pos );
  1058. LPWSTR GetBSTR()
  1059. {
  1060. _ValidateGet( VT_BSTR );
  1061. return( bstrVal );
  1062. }
  1063. LPWSTR GetBSTR( ULONG pos )
  1064. {
  1065. _ValidateGet( VT_BSTR, pos );
  1066. return( cabstr.pElems[ pos ] );
  1067. }
  1068. // VT_BOOL (VARIANT_BOOL)
  1069. void SetBOOL( VARIANT_BOOL boolIn)
  1070. {
  1071. Clear();
  1072. boolVal = boolIn;
  1073. vt = VT_BOOL;
  1074. }
  1075. void SetBOOL( VARIANT_BOOL boolIn, ULONG pos )
  1076. {
  1077. if( vt != (VT_BOOL | VT_VECTOR) ) Clear();
  1078. _AddScalerToVector( pos, &boolIn, sizeof(boolIn) );
  1079. vt = VT_BOOL | VT_VECTOR;
  1080. }
  1081. BOOL GetBOOL()
  1082. {
  1083. _ValidateGet( VT_BOOL );
  1084. return( boolVal );
  1085. }
  1086. BOOL GetBOOL( ULONG pos )
  1087. {
  1088. _ValidateGet( VT_BOOL, pos );
  1089. return( cabool.pElems[ pos ] );
  1090. }
  1091. // VT_ERROR (SCODE)
  1092. void SetERROR( SCODE scodeIn)
  1093. {
  1094. Clear();
  1095. scode = scodeIn;
  1096. vt = VT_ERROR;
  1097. }
  1098. void SetERROR( SCODE scodeIn, ULONG pos )
  1099. {
  1100. if( vt != (VT_ERROR | VT_VECTOR) ) Clear();
  1101. _AddScalerToVector( pos, &scodeIn, sizeof(scodeIn) );
  1102. vt = VT_ERROR | VT_VECTOR;
  1103. }
  1104. BOOL GetERROR()
  1105. {
  1106. _ValidateGet( VT_ERROR );
  1107. return( scode );
  1108. }
  1109. BOOL GetERROR( ULONG pos )
  1110. {
  1111. _ValidateGet( VT_ERROR, pos );
  1112. return( cascode.pElems[ pos ] );
  1113. }
  1114. // VT_DATE (DATE)
  1115. void SetDATE( DATE dateIn)
  1116. {
  1117. Clear();
  1118. date = dateIn;
  1119. vt = VT_DATE;
  1120. }
  1121. void SetDATE( DATE dateIn, ULONG pos)
  1122. {
  1123. if( vt != (VT_DATE | VT_VECTOR) ) Clear();
  1124. _AddScalerToVector( pos, &dateIn, sizeof(dateIn) );
  1125. vt = VT_DATE | VT_VECTOR;
  1126. }
  1127. DATE GetDATE()
  1128. {
  1129. _ValidateGet( VT_DATE );
  1130. return( date );
  1131. }
  1132. DATE GetDATE( ULONG pos )
  1133. {
  1134. _ValidateGet( VT_DATE, pos );
  1135. return( cadate.pElems[ pos ] );
  1136. }
  1137. // VT_VARIANT (PROPVARIANT)
  1138. void SetPROPVARIANT( PROPVARIANT &propvar, ULONG pos );
  1139. PROPVARIANT &GetPROPVARIANT( ULONG pos )
  1140. {
  1141. _ValidateGet( VT_VARIANT, pos );
  1142. return( capropvar.pElems[ pos ] );
  1143. }
  1144. CPropVariant & operator=(PROPVARIANT &propvar);
  1145. operator PROPVARIANT&()
  1146. {
  1147. return( GetPROPVARIANT( wReserved1 ) );
  1148. }
  1149. // VT_DECIMAL (DECIMAL)
  1150. void SetDECIMAL( const DECIMAL &decimal )
  1151. {
  1152. Clear();
  1153. decVal = decimal;
  1154. vt = VT_DECIMAL;
  1155. }
  1156. DECIMAL GetDECIMAL()
  1157. {
  1158. _ValidateGet( VT_DECIMAL );
  1159. return( decVal );
  1160. }
  1161. CPropVariant & operator=(const DECIMAL &decimal)
  1162. {
  1163. TCPropVarAssignmentOperator<VT_DECIMAL,DECIMAL>(this, decimal);
  1164. return (*this);
  1165. }
  1166. operator DECIMAL()
  1167. {
  1168. return( GetDECIMAL() );
  1169. }
  1170. public:
  1171. CPropVariant & operator[] (int nSubscript)
  1172. {
  1173. wReserved1 = (WORD) nSubscript + 1;
  1174. return (*this);
  1175. }
  1176. LPPROPVARIANT operator&()
  1177. {
  1178. return( this );
  1179. }
  1180. public:
  1181. VARTYPE VarType() const
  1182. {
  1183. return( vt );
  1184. }
  1185. void Clear()
  1186. {
  1187. PropVariantClear( this );
  1188. }
  1189. void Init()
  1190. {
  1191. PropVariantInit( this );
  1192. wReserved1 = INVALID_SUBSCRIPT;
  1193. }
  1194. ULONG Count() const
  1195. {
  1196. if( vt & VT_VECTOR )
  1197. return caui.cElems;
  1198. else
  1199. return 0;
  1200. }
  1201. void SetVarType(VARTYPE vtNew)
  1202. {
  1203. PropVariantClear( this );
  1204. vt = vtNew;
  1205. }
  1206. public:
  1207. static HRESULT Compare( PROPVARIANT* ppropvar1, PROPVARIANT *ppropvar2 );
  1208. private:
  1209. VOID *_AddStringToVector(
  1210. unsigned pos,
  1211. const VOID *pv,
  1212. ULONG cb,
  1213. VARTYPE vtNew );
  1214. VOID *_AddScalerToVector(
  1215. unsigned pos,
  1216. const VOID *pv,
  1217. ULONG cb);
  1218. void _ValidateGet( const VARTYPE vtGet )
  1219. {
  1220. if( vtGet != vt )
  1221. throw CHRESULT( (HRESULT) ERROR_INVALID_DATATYPE, OLESTR("Attempt to get incorrect type") );
  1222. }
  1223. void _ValidateGet( const VARTYPE vtGet, const ULONG pos )
  1224. {
  1225. _ValidateGet( (VARTYPE) (vtGet | VT_VECTOR) );
  1226. if( INVALID_SUBSCRIPT == pos
  1227. ||
  1228. pos >= caub.cElems
  1229. )
  1230. {
  1231. throw CHRESULT( (HRESULT) ERROR_INVALID_DATATYPE, OLESTR("Attempt to get a non-existent vector element") );
  1232. }
  1233. }
  1234. };
  1235. class CPropSpec : public PROPSPEC
  1236. {
  1237. public:
  1238. CPropSpec()
  1239. {
  1240. ulKind = PRSPEC_PROPID;
  1241. propid = 0;
  1242. }
  1243. ~CPropSpec()
  1244. {
  1245. FreeResources();
  1246. this->CPropSpec::CPropSpec();
  1247. }
  1248. void FreeResources()
  1249. {
  1250. if( PRSPEC_LPWSTR == ulKind )
  1251. {
  1252. CoTaskMemFree( lpwstr );
  1253. lpwstr = NULL;
  1254. }
  1255. }
  1256. void Alloc( ULONG cch )
  1257. {
  1258. ULONG cb = sizeof(OLECHAR)*cch + sizeof(OLECHAR);
  1259. lpwstr = (LPOLESTR) CoTaskMemAlloc( cb );
  1260. }
  1261. operator PROPSPEC*()
  1262. {
  1263. return( this );
  1264. }
  1265. PROPSPEC* operator&()
  1266. {
  1267. return( this );
  1268. }
  1269. operator CPropSpec&()
  1270. {
  1271. return( *this );
  1272. }
  1273. CPropSpec( LPCOLESTR posz )
  1274. {
  1275. memset( this, 0, sizeof(PROPSPEC) );
  1276. this->operator=(posz);
  1277. }
  1278. CPropSpec & operator = (LPCOLESTR posz)
  1279. {
  1280. FreeResources();
  1281. Alloc( ocslen(posz) );
  1282. if( NULL != lpwstr )
  1283. {
  1284. ocscpy( lpwstr, posz );
  1285. ulKind = PRSPEC_LPWSTR;
  1286. }
  1287. return( *this );
  1288. }
  1289. CPropSpec & operator = (PROPID propidNew)
  1290. {
  1291. FreeResources();
  1292. ulKind = PRSPEC_PROPID;
  1293. propid = propidNew;
  1294. return( *this );
  1295. }
  1296. OLECHAR & operator[]( int i )
  1297. {
  1298. ulKind = PRSPEC_LPWSTR;
  1299. return( this->lpwstr[ i ] );
  1300. }
  1301. OLECHAR & operator[]( ULONG i )
  1302. {
  1303. ulKind = PRSPEC_LPWSTR;
  1304. return( this->lpwstr[ i ] );
  1305. }
  1306. };
  1307. class CBlob : public BLOB
  1308. {
  1309. public:
  1310. ~CBlob()
  1311. {
  1312. if( NULL != pBlobData )
  1313. CoTaskMemFree( pBlobData );
  1314. }
  1315. CBlob( LPSTR psz )
  1316. {
  1317. ULONG cb = 0;
  1318. if( NULL != psz )
  1319. {
  1320. cb = strlen( psz ) + sizeof(CHAR);
  1321. }
  1322. pBlobData = (BYTE*) CoTaskMemAlloc( cb );
  1323. if( NULL == pBlobData )
  1324. throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Couldn't allocate for CBlob") );
  1325. cbSize = cb;
  1326. memcpy( pBlobData, psz, cbSize );
  1327. }
  1328. CBlob( LPWSTR pwsz )
  1329. {
  1330. ULONG cb = 0;
  1331. if( NULL != pwsz )
  1332. {
  1333. cb = wcslen( pwsz ) + sizeof(WCHAR);
  1334. }
  1335. pBlobData = (BYTE*) CoTaskMemAlloc( cb + sizeof(cb) );
  1336. if( NULL == pBlobData )
  1337. throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Couldn't allocate for CBlob") );
  1338. cbSize = cb;
  1339. memcpy( pBlobData, pwsz, cbSize );
  1340. }
  1341. CBlob( ULONG cb )
  1342. {
  1343. pBlobData = (BYTE*) CoTaskMemAlloc( cb );
  1344. if( NULL == pBlobData )
  1345. throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("Couldn't allocate for CBlob") );
  1346. cbSize = cb;
  1347. memset( pBlobData, 0, cb );
  1348. }
  1349. CBlob( int cb )
  1350. {
  1351. this->CBlob::CBlob( (ULONG) cb );
  1352. }
  1353. };
  1354. inline BOOL operator == ( CPropVariant &cpropvar1, CPropVariant &cpropvar2 )
  1355. {
  1356. return( S_OK == CPropVariant::Compare(&cpropvar1, &cpropvar2) );
  1357. }
  1358. inline BOOL operator == ( CPropVariant &cpropvar, PROPVARIANT &propvar )
  1359. {
  1360. return( (HRESULT) S_OK == CPropVariant::Compare(&cpropvar, &propvar) );
  1361. }
  1362. inline BOOL operator == ( PROPVARIANT &propvar, CPropVariant &cpropvar )
  1363. {
  1364. return( (HRESULT) S_OK == CPropVariant::Compare(&cpropvar, &propvar) );
  1365. }
  1366. inline BOOL operator == ( PROPVARIANT propvar1, PROPVARIANT propvar2)
  1367. {
  1368. return( (HRESULT) S_OK == CPropVariant::Compare(&propvar1, &propvar2) );
  1369. }
  1370. inline BOOL operator != ( CPropVariant &cpropvar1, CPropVariant &cpropvar2 )
  1371. {
  1372. return( (HRESULT) S_FALSE == CPropVariant::Compare(&cpropvar1, &cpropvar2) );
  1373. }
  1374. inline BOOL operator != ( CPropVariant &cpropvar, PROPVARIANT &propvar )
  1375. {
  1376. return( (HRESULT) S_FALSE == CPropVariant::Compare(&cpropvar, &propvar) );
  1377. }
  1378. inline BOOL operator != ( PROPVARIANT &propvar, CPropVariant &cpropvar )
  1379. {
  1380. return( (HRESULT) S_FALSE == CPropVariant::Compare(&cpropvar, &propvar) );
  1381. }
  1382. inline BOOL operator != ( PROPVARIANT &propvar1, PROPVARIANT &propvar2)
  1383. {
  1384. return( (HRESULT) S_FALSE == CPropVariant::Compare(&propvar1, &propvar2) );
  1385. }
  1386. #endif // !_CPROPVAR_HXX_