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.

461 lines
8.0 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // File: dvariant.h
  4. //
  5. // Contents: dvariant
  6. //
  7. // History: Sep-09-99 Davepl Like dvariant, but with type operators
  8. //
  9. //--------------------------------------------------------------------------
  10. #ifndef __DVARIANT_H__
  11. #define __DVARIANT_H__
  12. #include "dexception.h"
  13. class dvariant : public tagVARIANT
  14. {
  15. // Constructors
  16. public:
  17. dvariant()
  18. {
  19. vt = VT_EMPTY;
  20. }
  21. ~dvariant()
  22. {
  23. Clear();
  24. }
  25. dvariant(const VARIANT& varSrc)
  26. {
  27. vt = VT_EMPTY;
  28. InternalCopy(&varSrc);
  29. }
  30. dvariant(const dvariant& varSrc)
  31. {
  32. vt = VT_EMPTY;
  33. InternalCopy(&varSrc);
  34. }
  35. dvariant(BSTR bstrSrc)
  36. {
  37. vt = VT_EMPTY;
  38. *this = bstrSrc;
  39. }
  40. dvariant(LPCOLESTR lpszSrc)
  41. {
  42. vt = VT_EMPTY;
  43. *this = lpszSrc;
  44. }
  45. #ifndef OLE2ANSI
  46. dvariant(LPCSTR lpszSrc)
  47. {
  48. vt = VT_EMPTY;
  49. *this = lpszSrc;
  50. }
  51. #endif
  52. dvariant(bool bSrc)
  53. {
  54. vt = VT_BOOL;
  55. #pragma warning(disable: 4310) // cast truncates constant value
  56. boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
  57. #pragma warning(default: 4310) // cast truncates constant value
  58. }
  59. dvariant(int nSrc)
  60. {
  61. vt = VT_I4;
  62. lVal = nSrc;
  63. }
  64. dvariant(BYTE nSrc)
  65. {
  66. vt = VT_UI1;
  67. bVal = nSrc;
  68. }
  69. dvariant(short nSrc)
  70. {
  71. vt = VT_I2;
  72. iVal = nSrc;
  73. }
  74. dvariant(long nSrc, VARTYPE vtSrc = VT_I4)
  75. {
  76. ATLASSERT(vtSrc == VT_I4 || vtSrc == VT_ERROR);
  77. vt = vtSrc;
  78. lVal = nSrc;
  79. }
  80. dvariant(float fltSrc)
  81. {
  82. vt = VT_R4;
  83. fltVal = fltSrc;
  84. }
  85. dvariant(double dblSrc)
  86. {
  87. vt = VT_R8;
  88. dblVal = dblSrc;
  89. }
  90. dvariant(CY cySrc)
  91. {
  92. vt = VT_CY;
  93. cyVal.Hi = cySrc.Hi;
  94. cyVal.Lo = cySrc.Lo;
  95. }
  96. dvariant(IDispatch* pSrc)
  97. {
  98. vt = VT_DISPATCH;
  99. pdispVal = pSrc;
  100. // Need to AddRef as VariantClear will Release
  101. if (pdispVal != NULL)
  102. pdispVal->AddRef();
  103. }
  104. dvariant(IUnknown* pSrc)
  105. {
  106. vt = VT_UNKNOWN;
  107. punkVal = pSrc;
  108. // Need to AddRef as VariantClear will Release
  109. if (punkVal != NULL)
  110. punkVal->AddRef();
  111. }
  112. // Assignment Operators
  113. public:
  114. dvariant& operator=(const dvariant& varSrc)
  115. {
  116. InternalCopy(&varSrc);
  117. return *this;
  118. }
  119. dvariant& operator=(const VARIANT& varSrc)
  120. {
  121. InternalCopy(&varSrc);
  122. return *this;
  123. }
  124. dvariant& operator=(BSTR bstrSrc)
  125. {
  126. InternalClear();
  127. vt = VT_BSTR;
  128. bstrVal = ::SysAllocString(bstrSrc);
  129. if (bstrVal == NULL && bstrSrc != NULL)
  130. {
  131. vt = VT_ERROR;
  132. scode = E_OUTOFMEMORY;
  133. }
  134. return *this;
  135. }
  136. dvariant& operator=(LPCOLESTR lpszSrc)
  137. {
  138. InternalClear();
  139. vt = VT_BSTR;
  140. bstrVal = ::SysAllocString(lpszSrc);
  141. if (bstrVal == NULL && lpszSrc != NULL)
  142. {
  143. vt = VT_ERROR;
  144. scode = E_OUTOFMEMORY;
  145. }
  146. return *this;
  147. }
  148. #ifndef OLE2ANSI
  149. dvariant& operator=(LPCSTR lpszSrc)
  150. {
  151. USES_CONVERSION;
  152. InternalClear();
  153. vt = VT_BSTR;
  154. bstrVal = ::SysAllocString(A2COLE(lpszSrc));
  155. if (bstrVal == NULL && lpszSrc != NULL)
  156. {
  157. vt = VT_ERROR;
  158. scode = E_OUTOFMEMORY;
  159. }
  160. return *this;
  161. }
  162. #endif
  163. dvariant& operator=(bool bSrc)
  164. {
  165. if (vt != VT_BOOL)
  166. {
  167. InternalClear();
  168. vt = VT_BOOL;
  169. }
  170. #pragma warning(disable: 4310) // cast truncates constant value
  171. boolVal = bSrc ? VARIANT_TRUE : VARIANT_FALSE;
  172. #pragma warning(default: 4310) // cast truncates constant value
  173. return *this;
  174. }
  175. dvariant& operator=(int nSrc)
  176. {
  177. if (vt != VT_I4)
  178. {
  179. InternalClear();
  180. vt = VT_I4;
  181. }
  182. lVal = nSrc;
  183. return *this;
  184. }
  185. dvariant& operator=(BYTE nSrc)
  186. {
  187. if (vt != VT_UI1)
  188. {
  189. InternalClear();
  190. vt = VT_UI1;
  191. }
  192. bVal = nSrc;
  193. return *this;
  194. }
  195. dvariant& operator=(short nSrc)
  196. {
  197. if (vt != VT_I2)
  198. {
  199. InternalClear();
  200. vt = VT_I2;
  201. }
  202. iVal = nSrc;
  203. return *this;
  204. }
  205. dvariant& operator=(long nSrc)
  206. {
  207. if (vt != VT_I4)
  208. {
  209. InternalClear();
  210. vt = VT_I4;
  211. }
  212. lVal = nSrc;
  213. return *this;
  214. }
  215. dvariant& operator=(float fltSrc)
  216. {
  217. if (vt != VT_R4)
  218. {
  219. InternalClear();
  220. vt = VT_R4;
  221. }
  222. fltVal = fltSrc;
  223. return *this;
  224. }
  225. dvariant& operator=(double dblSrc)
  226. {
  227. if (vt != VT_R8)
  228. {
  229. InternalClear();
  230. vt = VT_R8;
  231. }
  232. dblVal = dblSrc;
  233. return *this;
  234. }
  235. dvariant& operator=(CY cySrc)
  236. {
  237. if (vt != VT_CY)
  238. {
  239. InternalClear();
  240. vt = VT_CY;
  241. }
  242. cyVal.Hi = cySrc.Hi;
  243. cyVal.Lo = cySrc.Lo;
  244. return *this;
  245. }
  246. dvariant& operator=(IDispatch* pSrc)
  247. {
  248. InternalClear();
  249. vt = VT_DISPATCH;
  250. pdispVal = pSrc;
  251. // Need to AddRef as VariantClear will Release
  252. if (pdispVal != NULL)
  253. pdispVal->AddRef();
  254. return *this;
  255. }
  256. dvariant& operator=(IUnknown* pSrc)
  257. {
  258. InternalClear();
  259. vt = VT_UNKNOWN;
  260. punkVal = pSrc;
  261. // Need to AddRef as VariantClear will Release
  262. if (punkVal != NULL)
  263. punkVal->AddRef();
  264. return *this;
  265. }
  266. // Comparison Operators
  267. public:
  268. bool operator==(const VARIANT& varSrc) const
  269. {
  270. if (this == &varSrc)
  271. return true;
  272. // Variants not equal if types don't match
  273. if (vt != varSrc.vt)
  274. return false;
  275. // Check type specific values
  276. switch (vt)
  277. {
  278. case VT_EMPTY:
  279. case VT_NULL:
  280. return true;
  281. case VT_BOOL:
  282. return boolVal == varSrc.boolVal;
  283. case VT_UI1:
  284. return bVal == varSrc.bVal;
  285. case VT_I2:
  286. return iVal == varSrc.iVal;
  287. case VT_I4:
  288. return lVal == varSrc.lVal;
  289. case VT_R4:
  290. return fltVal == varSrc.fltVal;
  291. case VT_R8:
  292. return dblVal == varSrc.dblVal;
  293. case VT_BSTR:
  294. return (::SysStringByteLen(bstrVal) == ::SysStringByteLen(varSrc.bstrVal)) &&
  295. (::memcmp(bstrVal, varSrc.bstrVal, ::SysStringByteLen(bstrVal)) == 0);
  296. case VT_ERROR:
  297. return scode == varSrc.scode;
  298. case VT_DISPATCH:
  299. return pdispVal == varSrc.pdispVal;
  300. case VT_UNKNOWN:
  301. return punkVal == varSrc.punkVal;
  302. default:
  303. ATLASSERT(false);
  304. // fall through
  305. }
  306. return false;
  307. }
  308. bool operator!=(const VARIANT& varSrc) const {return !operator==(varSrc);}
  309. bool operator<(const VARIANT& varSrc) const {return VarCmp((VARIANT*)this, (VARIANT*)&varSrc, LOCALE_USER_DEFAULT)==VARCMP_LT;}
  310. bool operator>(const VARIANT& varSrc) const {return VarCmp((VARIANT*)this, (VARIANT*)&varSrc, LOCALE_USER_DEFAULT)==VARCMP_GT;}
  311. // Operations
  312. public:
  313. HRESULT Clear() { return ::VariantClear(this); }
  314. HRESULT Copy(const VARIANT* pSrc) { return ::VariantCopy(this, const_cast<VARIANT*>(pSrc)); }
  315. HRESULT Attach(VARIANT* pSrc)
  316. {
  317. // Clear out the variant
  318. HRESULT hr = Clear();
  319. if (!FAILED(hr))
  320. {
  321. // Copy the contents and give control to dvariant
  322. memcpy(this, pSrc, sizeof(VARIANT));
  323. pSrc->vt = VT_EMPTY;
  324. hr = S_OK;
  325. }
  326. return hr;
  327. }
  328. HRESULT Detach(VARIANT* pDest)
  329. {
  330. // Clear out the variant
  331. HRESULT hr = ::VariantClear(pDest);
  332. if (!FAILED(hr))
  333. {
  334. // Copy the contents and remove control from dvariant
  335. memcpy(pDest, this, sizeof(VARIANT));
  336. vt = VT_EMPTY;
  337. hr = S_OK;
  338. }
  339. return hr;
  340. }
  341. HRESULT ChangeType(VARTYPE vtNew, const VARIANT* pSrc = NULL)
  342. {
  343. VARIANT* pVar = const_cast<VARIANT*>(pSrc);
  344. // Convert in place if pSrc is NULL
  345. if (pVar == NULL)
  346. pVar = this;
  347. // Do nothing if doing in place convert and vts not different
  348. return ::VariantChangeType(this, pVar, 0, vtNew);
  349. }
  350. HRESULT WriteToStream(IStream* pStream);
  351. HRESULT ReadFromStream(IStream* pStream);
  352. // Implementation
  353. public:
  354. HRESULT InternalClear()
  355. {
  356. HRESULT hr = Clear();
  357. ATLASSERT(SUCCEEDED(hr));
  358. if (FAILED(hr))
  359. {
  360. vt = VT_ERROR;
  361. scode = hr;
  362. }
  363. return hr;
  364. }
  365. void InternalCopy(const VARIANT* pSrc)
  366. {
  367. HRESULT hr = Copy(pSrc);
  368. if (FAILED(hr))
  369. {
  370. vt = VT_ERROR;
  371. scode = hr;
  372. }
  373. }
  374. // Need other operators? Add them...
  375. operator BSTR()
  376. {
  377. if (vt != VT_BSTR)
  378. THROW_IF_FAILS( ChangeType(VT_BSTR) );
  379. return bstrVal;
  380. }
  381. operator tstring()
  382. {
  383. return tstring( (BSTR)*this );
  384. }
  385. operator long()
  386. {
  387. if (vt != VT_I4)
  388. THROW_IF_FAILS( ChangeType(VT_I4) );
  389. return lVal;
  390. }
  391. operator FILETIME()
  392. {
  393. if (vt != VT_FILETIME)
  394. THROW_IF_FAILS( ChangeType(VT_DATE) );
  395. SYSTEMTIME st;
  396. if (!VariantTimeToSystemTime( date, &st))
  397. throw win32error();
  398. FILETIME ft;
  399. if (!SystemTimeToFileTime(&st, &ft))
  400. throw win32error();
  401. return ft;
  402. }
  403. };
  404. #endif // __DVARIANT_H__