/Main/SevenZipShell/ComPropVariant.h

http://7ZipShell.codeplex.com · C Header · 726 lines · 628 code · 64 blank · 34 comment · 127 complexity · 73ec69b4f750b7d129d1ac500752cd9c MD5 · raw file

  1. //------------------------------------------------------------------------------
  2. // PropVariant.h
  3. //------------------------------------------------------------------------------
  4. // File provided for Microsoft Shared Source.
  5. // Copyright (c) Microsoft Corporation. All rights reserved.
  6. //
  7. // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
  8. // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
  9. // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
  10. // PARTICULAR PURPOSE.
  11. //------------------------------------------------------------------------------
  12. //
  13. // PROPVARIANT wrapper class
  14. //
  15. //------------------------------------------------------------------------------
  16. #pragma once
  17. #include "MemPtr.h"
  18. class CComPropVariant : public tagPROPVARIANT
  19. {
  20. // Constructors
  21. public:
  22. CComPropVariant() throw()
  23. {
  24. ::PropVariantInit(this);
  25. }
  26. ~CComPropVariant() throw()
  27. {
  28. Clear();
  29. }
  30. CComPropVariant(__in const PROPVARIANT& varSrc)
  31. {
  32. vt = VT_EMPTY;
  33. InternalCopy(&varSrc);
  34. }
  35. CComPropVariant(__in const CComPropVariant& varSrc)
  36. {
  37. vt = VT_EMPTY;
  38. InternalCopy(&varSrc);
  39. }
  40. CComPropVariant(__in LPCOLESTR lpszSrc, __in VARTYPE vtSrc = VT_LPWSTR)
  41. {
  42. ATLASSERT(vtSrc == VT_LPWSTR || vtSrc == VT_BSTR);
  43. vt = VT_EMPTY;
  44. *this = lpszSrc;
  45. }
  46. CComPropVariant(__in LPCSTR lpszSrc)
  47. {
  48. vt = VT_EMPTY;
  49. *this = lpszSrc;
  50. }
  51. CComPropVariant(__in bool bSrc)
  52. {
  53. vt = VT_BOOL;
  54. boolVal = bSrc ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE;
  55. }
  56. CComPropVariant(__in int nSrc, __in VARTYPE vtSrc = VT_I4) throw()
  57. {
  58. ATLASSERT(vtSrc == VT_I4 || vtSrc == VT_INT);
  59. vt = vtSrc;
  60. intVal = nSrc;
  61. }
  62. CComPropVariant(__in BYTE nSrc) throw()
  63. {
  64. vt = VT_UI1;
  65. bVal = nSrc;
  66. }
  67. CComPropVariant(__in short nSrc) throw()
  68. {
  69. vt = VT_I2;
  70. iVal = nSrc;
  71. }
  72. CComPropVariant(__in long nSrc, __in VARTYPE vtSrc = VT_I4) throw()
  73. {
  74. ATLASSERT(vtSrc == VT_I4 || vtSrc == VT_ERROR);
  75. vt = vtSrc;
  76. lVal = nSrc;
  77. }
  78. CComPropVariant(__in float fltSrc) throw()
  79. {
  80. vt = VT_R4;
  81. fltVal = fltSrc;
  82. }
  83. CComPropVariant(__in double dblSrc, __in VARTYPE vtSrc = VT_R8) throw()
  84. {
  85. ATLASSERT(vtSrc == VT_R8 || vtSrc == VT_DATE);
  86. vt = vtSrc;
  87. dblVal = dblSrc;
  88. }
  89. CComPropVariant(CY __in cySrc) throw()
  90. {
  91. vt = VT_CY;
  92. cyVal.Hi = cySrc.Hi;
  93. cyVal.Lo = cySrc.Lo;
  94. }
  95. CComPropVariant(__in_opt IDispatch* pSrc) throw()
  96. {
  97. vt = VT_DISPATCH;
  98. pdispVal = pSrc;
  99. // Need to AddRef as VariantClear will Release
  100. if (pdispVal != NULL)
  101. pdispVal->AddRef();
  102. }
  103. CComPropVariant(__in_opt IUnknown* pSrc) throw()
  104. {
  105. vt = VT_UNKNOWN;
  106. punkVal = pSrc;
  107. // Need to AddRef as VariantClear will Release
  108. if (punkVal != NULL)
  109. punkVal->AddRef();
  110. }
  111. CComPropVariant(__in char cSrc) throw()
  112. {
  113. vt = VT_I1;
  114. cVal = cSrc;
  115. }
  116. CComPropVariant(__in unsigned short nSrc) throw()
  117. {
  118. vt = VT_UI2;
  119. uiVal = nSrc;
  120. }
  121. CComPropVariant(__in unsigned long nSrc) throw()
  122. {
  123. vt = VT_UI4;
  124. ulVal = nSrc;
  125. }
  126. CComPropVariant(__in unsigned int nSrc, __in VARTYPE vtSrc = VT_UI4) throw()
  127. {
  128. ATLASSERT(vtSrc == VT_UI4 || vtSrc == VT_UINT);
  129. vt = vtSrc;
  130. uintVal= nSrc;
  131. }
  132. CComPropVariant(__in const CComBSTR& bstrSrc)
  133. {
  134. vt = VT_EMPTY;
  135. *this = bstrSrc;
  136. }
  137. CComPropVariant(__in_opt const SAFEARRAY *pSrc)
  138. {
  139. LPSAFEARRAY pCopy;
  140. if (pSrc != NULL)
  141. {
  142. HRESULT hRes = ::SafeArrayCopy((LPSAFEARRAY)pSrc, &pCopy);
  143. if (SUCCEEDED(hRes) && pCopy != NULL)
  144. {
  145. ::ATL::AtlSafeArrayGetActualVartype((LPSAFEARRAY)pSrc, &vt);
  146. vt |= VT_ARRAY;
  147. parray = pCopy;
  148. }
  149. else
  150. {
  151. vt = VT_ERROR;
  152. scode = hRes;
  153. #ifndef _ATL_NO_VARIANT_THROW
  154. ATLENSURE_THROW(FALSE, E_OUTOFMEMORY);
  155. #endif
  156. }
  157. }
  158. else
  159. {
  160. vt = VT_EMPTY;
  161. }
  162. }
  163. CComPropVariant (__in ULONGLONG ull)
  164. {
  165. vt = VT_UI8;
  166. uhVal.QuadPart = ull;
  167. }
  168. operator ULONG()
  169. {
  170. ATLASSERT(vt == VT_UI4);
  171. return ulVal;
  172. }
  173. operator ULONGLONG()
  174. {
  175. ATLASSERT(vt == VT_UI8);
  176. return uhVal.QuadPart;
  177. }
  178. // Assignment Operators
  179. public:
  180. CComPropVariant& operator=(__in const CComPropVariant& varSrc)
  181. {
  182. if(this!=&varSrc)
  183. {
  184. InternalCopy(&varSrc);
  185. }
  186. return *this;
  187. }
  188. CComPropVariant& operator=(__in const PROPVARIANT& varSrc)
  189. {
  190. if(static_cast<PROPVARIANT *>(this)!=&varSrc)
  191. {
  192. InternalCopy(&varSrc);
  193. }
  194. return *this;
  195. }
  196. CComPropVariant& operator=(__in const CComBSTR& bstrSrc)
  197. {
  198. Clear();
  199. vt = VT_BSTR;
  200. bstrVal = bstrSrc.Copy();
  201. #pragma warning(push)
  202. #pragma warning(disable:4068)
  203. #pragma prefast(push)
  204. #pragma prefast(disable:325, "We are checking allocation semantics here")
  205. if (bstrVal == NULL && bstrSrc.m_str != NULL)
  206. {
  207. vt = VT_ERROR;
  208. scode = E_OUTOFMEMORY;
  209. #ifndef _ATL_NO_VARIANT_THROW
  210. ATLENSURE_THROW(FALSE, E_OUTOFMEMORY);
  211. #endif
  212. }
  213. #pragma prefast(pop)
  214. #pragma warning(pop)
  215. return *this;
  216. }
  217. CComPropVariant& operator=(__in LPCOLESTR lpszSrc)
  218. {
  219. Clear();
  220. vt = VT_LPWSTR;
  221. if (FAILED(SHStrDup(lpszSrc, &pwszVal)))
  222. {
  223. vt = VT_ERROR;
  224. scode = E_OUTOFMEMORY;
  225. #ifndef _ATL_NO_VARIANT_THROW
  226. ATLENSURE_THROW(FALSE, E_OUTOFMEMORY);
  227. #endif
  228. }
  229. return *this;
  230. }
  231. CComPropVariant& operator=(__in LPCSTR lpszSrc)
  232. {
  233. USES_CONVERSION_EX;
  234. Clear();
  235. vt = VT_BSTR;
  236. bstrVal = ::SysAllocString(A2COLE_EX(lpszSrc, _ATL_SAFE_ALLOCA_DEF_THRESHOLD));
  237. if (bstrVal == NULL && lpszSrc != NULL)
  238. {
  239. vt = VT_ERROR;
  240. scode = E_OUTOFMEMORY;
  241. #ifndef _ATL_NO_VARIANT_THROW
  242. ATLENSURE_THROW(FALSE, E_OUTOFMEMORY);
  243. #endif
  244. }
  245. return *this;
  246. }
  247. CComPropVariant& operator=(__in bool bSrc)
  248. {
  249. if (vt != VT_BOOL)
  250. {
  251. Clear();
  252. vt = VT_BOOL;
  253. }
  254. boolVal = bSrc ? ATL_VARIANT_TRUE : ATL_VARIANT_FALSE;
  255. return *this;
  256. }
  257. CComPropVariant& operator=(__in int nSrc) throw()
  258. {
  259. if (vt != VT_I4)
  260. {
  261. Clear();
  262. vt = VT_I4;
  263. }
  264. intVal = nSrc;
  265. return *this;
  266. }
  267. CComPropVariant& operator=(__in BYTE nSrc) throw()
  268. {
  269. if (vt != VT_UI1)
  270. {
  271. Clear();
  272. vt = VT_UI1;
  273. }
  274. bVal = nSrc;
  275. return *this;
  276. }
  277. CComPropVariant& operator=(__in short nSrc) throw()
  278. {
  279. if (vt != VT_I2)
  280. {
  281. Clear();
  282. vt = VT_I2;
  283. }
  284. iVal = nSrc;
  285. return *this;
  286. }
  287. CComPropVariant& operator=(__in long nSrc) throw()
  288. {
  289. if (vt != VT_I4)
  290. {
  291. Clear();
  292. vt = VT_I4;
  293. }
  294. lVal = nSrc;
  295. return *this;
  296. }
  297. CComPropVariant& operator=(__in float fltSrc) throw()
  298. {
  299. if (vt != VT_R4)
  300. {
  301. Clear();
  302. vt = VT_R4;
  303. }
  304. fltVal = fltSrc;
  305. return *this;
  306. }
  307. CComPropVariant& operator=(__in double dblSrc) throw()
  308. {
  309. if (vt != VT_R8)
  310. {
  311. Clear();
  312. vt = VT_R8;
  313. }
  314. dblVal = dblSrc;
  315. return *this;
  316. }
  317. CComPropVariant& operator=(__in CY cySrc) throw()
  318. {
  319. if (vt != VT_CY)
  320. {
  321. Clear();
  322. vt = VT_CY;
  323. }
  324. cyVal.Hi = cySrc.Hi;
  325. cyVal.Lo = cySrc.Lo;
  326. return *this;
  327. }
  328. CComPropVariant& operator=(__in_opt IDispatch* pSrc) throw()
  329. {
  330. Clear();
  331. vt = VT_DISPATCH;
  332. pdispVal = pSrc;
  333. // Need to AddRef as VariantClear will Release
  334. if (pdispVal != NULL)
  335. pdispVal->AddRef();
  336. return *this;
  337. }
  338. CComPropVariant& operator=(__in_opt IUnknown* pSrc) throw()
  339. {
  340. Clear();
  341. vt = VT_UNKNOWN;
  342. punkVal = pSrc;
  343. // Need to AddRef as VariantClear will Release
  344. if (punkVal != NULL)
  345. punkVal->AddRef();
  346. return *this;
  347. }
  348. CComPropVariant& operator=(__in char cSrc) throw()
  349. {
  350. if (vt != VT_I1)
  351. {
  352. Clear();
  353. vt = VT_I1;
  354. }
  355. cVal = cSrc;
  356. return *this;
  357. }
  358. CComPropVariant& operator=(__in unsigned short nSrc) throw()
  359. {
  360. if (vt != VT_UI2)
  361. {
  362. Clear();
  363. vt = VT_UI2;
  364. }
  365. uiVal = nSrc;
  366. return *this;
  367. }
  368. CComPropVariant& operator=(__in unsigned long nSrc) throw()
  369. {
  370. if (vt != VT_UI4)
  371. {
  372. Clear();
  373. vt = VT_UI4;
  374. }
  375. ulVal = nSrc;
  376. return *this;
  377. }
  378. CComPropVariant& operator=(__in unsigned int nSrc) throw()
  379. {
  380. if (vt != VT_UI4)
  381. {
  382. Clear();
  383. vt = VT_UI4;
  384. }
  385. uintVal= nSrc;
  386. return *this;
  387. }
  388. CComPropVariant& operator=(__in_opt BYTE* pbSrc) throw()
  389. {
  390. if (vt != (VT_UI1|VT_BYREF))
  391. {
  392. Clear();
  393. vt = VT_UI1|VT_BYREF;
  394. }
  395. pbVal = pbSrc;
  396. return *this;
  397. }
  398. CComPropVariant& operator=(__in_opt short* pnSrc) throw()
  399. {
  400. if (vt != (VT_I2|VT_BYREF))
  401. {
  402. Clear();
  403. vt = VT_I2|VT_BYREF;
  404. }
  405. piVal = pnSrc;
  406. return *this;
  407. }
  408. #ifdef _NATIVE_WCHAR_T_DEFINED
  409. CComPropVariant& operator=(__in_opt USHORT* pnSrc) throw()
  410. {
  411. if (vt != (VT_UI2|VT_BYREF))
  412. {
  413. Clear();
  414. vt = VT_UI2|VT_BYREF;
  415. }
  416. puiVal = pnSrc;
  417. return *this;
  418. }
  419. #endif
  420. CComPropVariant& operator=(__in_opt int* pnSrc) throw()
  421. {
  422. if (vt != (VT_I4|VT_BYREF))
  423. {
  424. Clear();
  425. vt = VT_I4|VT_BYREF;
  426. }
  427. pintVal = pnSrc;
  428. return *this;
  429. }
  430. CComPropVariant& operator=(__in_opt UINT* pnSrc) throw()
  431. {
  432. if (vt != (VT_UI4|VT_BYREF))
  433. {
  434. Clear();
  435. vt = VT_UI4|VT_BYREF;
  436. }
  437. puintVal = pnSrc;
  438. return *this;
  439. }
  440. CComPropVariant& operator=(__in_opt long* pnSrc) throw()
  441. {
  442. if (vt != (VT_I4|VT_BYREF))
  443. {
  444. Clear();
  445. vt = VT_I4|VT_BYREF;
  446. }
  447. plVal = pnSrc;
  448. return *this;
  449. }
  450. CComPropVariant& operator=(__in_opt ULONG* pnSrc) throw()
  451. {
  452. if (vt != (VT_UI4|VT_BYREF))
  453. {
  454. Clear();
  455. vt = VT_UI4|VT_BYREF;
  456. }
  457. pulVal = pnSrc;
  458. return *this;
  459. }
  460. CComPropVariant& operator=(__in_opt float* pfSrc) throw()
  461. {
  462. if (vt != (VT_R4|VT_BYREF))
  463. {
  464. Clear();
  465. vt = VT_R4|VT_BYREF;
  466. }
  467. pfltVal = pfSrc;
  468. return *this;
  469. }
  470. CComPropVariant& operator=(__in_opt double* pfSrc) throw()
  471. {
  472. if (vt != (VT_R8|VT_BYREF))
  473. {
  474. Clear();
  475. vt = VT_R8|VT_BYREF;
  476. }
  477. pdblVal = pfSrc;
  478. return *this;
  479. }
  480. CComPropVariant& operator=(__in_opt const SAFEARRAY *pSrc)
  481. {
  482. Clear();
  483. LPSAFEARRAY pCopy;
  484. if (pSrc != NULL)
  485. {
  486. HRESULT hRes = ::SafeArrayCopy((LPSAFEARRAY)pSrc, &pCopy);
  487. if (SUCCEEDED(hRes) && pCopy != NULL)
  488. {
  489. ::ATL::AtlSafeArrayGetActualVartype((LPSAFEARRAY)pSrc, &vt);
  490. vt |= VT_ARRAY;
  491. parray = pCopy;
  492. }
  493. else
  494. {
  495. vt = VT_ERROR;
  496. scode = hRes;
  497. #ifndef _ATL_NO_VARIANT_THROW
  498. ATLENSURE_THROW(FALSE, E_OUTOFMEMORY);
  499. #endif
  500. }
  501. }
  502. return *this;
  503. }
  504. // Comparison Operators
  505. public:
  506. bool operator==(__in const PROPVARIANT& varSrc) const throw()
  507. {
  508. // For backwards compatibility
  509. if (vt == VT_NULL && varSrc.vt == VT_NULL)
  510. {
  511. return true;
  512. }
  513. // Variants not equal if types don't match
  514. if (vt != varSrc.vt)
  515. {
  516. return false;
  517. }
  518. return PropVariantCompare(*this, varSrc) == static_cast<HRESULT>(VARCMP_EQ);
  519. }
  520. bool operator!=(__in const PROPVARIANT& varSrc) const throw()
  521. {
  522. return !operator==(varSrc);
  523. }
  524. bool operator<(__in const PROPVARIANT& varSrc) const throw()
  525. {
  526. if (vt == VT_NULL && varSrc.vt == VT_NULL)
  527. return false;
  528. return PropVariantCompare(*this, varSrc)== static_cast<HRESULT>(VARCMP_LT);
  529. }
  530. bool operator>(__in const PROPVARIANT& varSrc) const throw()
  531. {
  532. if (vt == VT_NULL && varSrc.vt == VT_NULL)
  533. return false;
  534. return PropVariantCompare(*this, varSrc)== static_cast<HRESULT>(VARCMP_GT);
  535. }
  536. // Operations
  537. public:
  538. HRESULT Clear() { return ::PropVariantClear(this); }
  539. HRESULT Copy(__in const PROPVARIANT* pSrc) { return ::PropVariantCopy(this, const_cast<PROPVARIANT*>(pSrc)); }
  540. // copy VARIANT to BSTR
  541. HRESULT CopyTo(__out BSTR *pstrDest)
  542. {
  543. ATLASSERT(pstrDest != NULL && vt == VT_BSTR);
  544. HRESULT hRes = E_POINTER;
  545. if (pstrDest != NULL && vt == VT_BSTR)
  546. {
  547. *pstrDest = ::SysAllocStringByteLen(reinterpret_cast<LPCSTR>(bstrVal), ::SysStringByteLen(bstrVal));
  548. if (*pstrDest == NULL)
  549. hRes = E_OUTOFMEMORY;
  550. else
  551. hRes = S_OK;
  552. }
  553. else if (vt != VT_BSTR)
  554. hRes = DISP_E_TYPEMISMATCH;
  555. return hRes;
  556. }
  557. HRESULT Attach(__in PROPVARIANT* pSrc)
  558. {
  559. if(pSrc == NULL)
  560. return E_INVALIDARG;
  561. // Clear out the variant
  562. HRESULT hr = Clear();
  563. if (!FAILED(hr))
  564. {
  565. // Copy the contents and give control to CComPropVariant
  566. Checked::memcpy_s(this, sizeof(CComPropVariant), pSrc, sizeof(PROPVARIANT));
  567. pSrc->vt = VT_EMPTY;
  568. hr = S_OK;
  569. }
  570. return hr;
  571. }
  572. HRESULT Detach(__out PROPVARIANT* pDest)
  573. {
  574. ATLASSERT(pDest != NULL);
  575. if(pDest == NULL)
  576. return E_POINTER;
  577. // Clear out the variant
  578. HRESULT hr = ::PropVariantClear(pDest);
  579. if (!FAILED(hr))
  580. {
  581. // Copy the contents and remove control from CComPropVariant
  582. Checked::memcpy_s(pDest, sizeof(PROPVARIANT), this, sizeof(PROPVARIANT));
  583. vt = VT_EMPTY;
  584. hr = S_OK;
  585. }
  586. return hr;
  587. }
  588. HRESULT ChangeType(__in VARTYPE vtNew, __in_opt const PROPVARIANT* pSrc = NULL)
  589. {
  590. PROPVARIANT* pVar = const_cast<PROPVARIANT*>(pSrc);
  591. // Convert in place if pSrc is NULL
  592. if (pVar == NULL)
  593. pVar = this;
  594. // Do nothing if doing in place convert and vts not different
  595. return ::PropVariantChangeType(this, *pVar, 0, vtNew);
  596. }
  597. template< typename T >
  598. void SetByRef( __in T* pT ) throw()
  599. {
  600. Clear();
  601. vt = CVarTypeInfo< T >::VT|VT_BYREF;
  602. byref = pT;
  603. }
  604. HRESULT WriteToStream(__inout IStream* pStream);
  605. HRESULT ReadFromStream(__inout IStream* pStream);
  606. HRESULT ToBoolean(__out BOOL * pBool) const
  607. {
  608. return ::PropVariantToBoolean(*this, pBool);
  609. }
  610. HRESULT ToString(__deref_out LPWSTR * pStr) const
  611. {
  612. return ::PropVariantToStringAlloc(*this, pStr);
  613. }
  614. HRESULT ToString(CStringW & Str) const
  615. {
  616. CComMemPtr<WCHAR> Buffer;
  617. HRESULT hr;
  618. if (SUCCEEDED(hr = ToString(&Buffer)))
  619. {
  620. Str = Buffer;
  621. }
  622. return hr;
  623. }
  624. HRESULT ToStrRet(__out STRRET * pStrRet) const
  625. {
  626. return ::PropVariantToStrRet(*this, pStrRet);
  627. }
  628. HRESULT ToVariant(__out LPVARIANT pVar) const
  629. {
  630. return ::PropVariantToVariant(this, pVar);
  631. }
  632. // Return the size in bytes of the current contents
  633. ULONG GetSize() const;
  634. // Implementation
  635. public:
  636. HRESULT InternalClear()
  637. {
  638. HRESULT hr = Clear();
  639. ATLASSERT(SUCCEEDED(hr));
  640. if (FAILED(hr))
  641. {
  642. vt = VT_ERROR;
  643. scode = hr;
  644. #ifndef _ATL_NO_VARIANT_THROW
  645. AtlThrow(hr);
  646. #endif
  647. }
  648. return hr;
  649. }
  650. void InternalCopy(__in const PROPVARIANT* pSrc)
  651. {
  652. HRESULT hr = Copy(pSrc);
  653. if (FAILED(hr))
  654. {
  655. vt = VT_ERROR;
  656. scode = hr;
  657. #ifndef _ATL_NO_VARIANT_THROW
  658. AtlThrow(hr);
  659. #endif
  660. }
  661. }
  662. };