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.

3252 lines
96 KiB

  1. #include <malloc.h>
  2. #include <urlint.h>
  3. #include <map_kv.h>
  4. #include "coll.hxx"
  5. #ifndef unix
  6. #include "COleTime.hxx"
  7. #else
  8. #include "coletime.hxx"
  9. #endif /* unix */
  10. #include "cvar.hxx"
  11. //void * _cdecl operator new(size_t sizeEl, ULONG cEl);
  12. void * _cdecl operator new(size_t sizeEl, COleVariant *pCVar);
  13. void * _cdecl operator new(size_t sizeEl, COleVariant *pCVar)
  14. {
  15. return 0;
  16. }
  17. /*
  18. struct AFX_EXCEPTION_LINK
  19. {
  20. #ifdef _AFX_OLD_EXCEPTIONS
  21. union
  22. {
  23. _AFX_JUMPBUF m_jumpBuf;
  24. struct
  25. {
  26. void (PASCAL* pfnCleanup)(AFX_EXCEPTION_LINK* pLink);
  27. void* pvData; // extra data follows
  28. } m_callback; // callback for cleanup (nType != 0)
  29. };
  30. UINT m_nType; // 0 for setjmp, !=0 for user extension
  31. #endif //!_AFX_OLD_EXCEPTIONS
  32. AFX_EXCEPTION_LINK* m_pLinkPrev; // previous top, next in handler chain
  33. CException* m_pException; // current exception (NULL in TRY block)
  34. AFX_EXCEPTION_LINK(); // for initialization and linking
  35. ~AFX_EXCEPTION_LINK() // for cleanup and unlinking
  36. { AfxTryCleanup(); };
  37. };
  38. */
  39. #define TRY { AFX_EXCEPTION_LINK _afxExceptionLink; try {
  40. #define CATCH(class, e) } catch (class* e) \
  41. { ASSERT(e->IsKindOf(RUNTIME_CLASS(class))); \
  42. _afxExceptionLink.m_pException = e;
  43. #define AND_CATCH(class, e) } catch (class* e) \
  44. { ASSERT(e->IsKindOf(RUNTIME_CLASS(class))); \
  45. _afxExceptionLink.m_pException = e;
  46. #define END_CATCH } }
  47. #define THROW(e) throw e
  48. #define THROW_LAST() (AfxThrowLastCleanup(), throw)
  49. // Advanced macros for smaller code
  50. #define CATCH_ALL(e) } catch (CException* e) \
  51. { { ASSERT(e->IsKindOf(RUNTIME_CLASS(CException))); \
  52. _afxExceptionLink.m_pException = e;
  53. #define AND_CATCH_ALL(e) } catch (CException* e) \
  54. { { ASSERT(e->IsKindOf(RUNTIME_CLASS(CException))); \
  55. _afxExceptionLink.m_pException = e;
  56. #define END_CATCH_ALL } } }
  57. #define END_TRY } catch (CException* e) \
  58. { ASSERT(e->IsKindOf(RUNTIME_CLASS(CException))); \
  59. _afxExceptionLink.m_pException = e; } }
  60. #define AFX_OLE_FALSE 0
  61. #define AFX_OLE_TRUE (-1)
  62. #ifndef _DEBUG
  63. #define USES_CONVERSION int _convert; _convert
  64. #else
  65. #define USES_CONVERSION int _convert = 0;
  66. #endif
  67. #ifdef _DEBUG
  68. #define UNUSED(x)
  69. #else
  70. #define UNUSED(x) x
  71. #endif
  72. #define UNUSED_ALWAYS(x) x
  73. /////////////////////////////////////////////////////////////////////////////
  74. // Global UNICODE<>ANSI translation helpers
  75. LPWSTR AFXAPI AfxA2WHelper(LPWSTR lpw, LPCSTR lpa, int nChars);
  76. LPSTR AFXAPI AfxW2AHelper(LPSTR lpa, LPCWSTR lpw, int nChars);
  77. #define A2CW(lpa) (\
  78. ((LPCSTR)lpa == NULL) ? NULL : (\
  79. _convert = (lstrlenA(lpa)+1),\
  80. (LPCWSTR)AfxA2WHelper((LPWSTR) alloca(_convert*2), lpa, _convert)\
  81. )\
  82. )
  83. #define A2W(lpa) (\
  84. ((LPCSTR)lpa == NULL) ? NULL : (\
  85. _convert = (lstrlenA(lpa)+1),\
  86. AfxA2WHelper((LPWSTR) alloca(_convert*2), lpa, _convert)\
  87. )\
  88. )
  89. #define W2CA(lpw) (\
  90. ((LPCWSTR)lpw == NULL) ? NULL : (\
  91. _convert = (wcslen(lpw)+1)*2,\
  92. (LPCSTR)AfxW2AHelper((LPSTR) alloca(_convert), lpw, _convert)\
  93. )\
  94. )
  95. #define W2A(lpw) (\
  96. ((LPCWSTR)lpw == NULL) ? NULL : (\
  97. _convert = (wcslen(lpw)+1)*2,\
  98. AfxW2AHelper((LPSTR) alloca(_convert), lpw, _convert)\
  99. )\
  100. )
  101. #if defined(_UNICODE)
  102. // in these cases the default (TCHAR) is the same as OLECHAR
  103. #define DEVMODEOLE DEVMODEW
  104. #define LPDEVMODEOLE LPDEVMODEW
  105. #define TEXTMETRICOLE TEXTMETRICW
  106. #define LPTEXTMETRICOLE LPTEXTMETRICW
  107. inline size_t ocslen(LPCOLESTR x) { return wcslen(x); }
  108. inline OLECHAR* ocscpy(LPOLESTR dest, LPCOLESTR src) { return wcscpy(dest, src); }
  109. inline LPCOLESTR T2COLE(LPCTSTR lp) { return lp; }
  110. inline LPCTSTR OLE2CT(LPCOLESTR lp) { return lp; }
  111. inline LPOLESTR T2OLE(LPTSTR lp) { return lp; }
  112. inline LPTSTR OLE2T(LPOLESTR lp) { return lp; }
  113. inline LPOLESTR TASKSTRINGT2OLE(LPOLESTR lp) { return lp; }
  114. inline LPTSTR TASKSTRINGOLE2T(LPOLESTR lp) { return lp; }
  115. inline LPDEVMODEW DEVMODEOLE2T(LPDEVMODEOLE lp) { return lp; }
  116. inline LPDEVMODEOLE DEVMODET2OLE(LPDEVMODEW lp) { return lp; }
  117. inline LPTEXTMETRICW TEXTMETRICOLE2T(LPTEXTMETRICOLE lp) { return lp; }
  118. inline LPTEXTMETRICOLE TEXTMETRICT2OLE(LPTEXTMETRICW lp) { return lp; }
  119. inline BSTR BSTR2TBSTR(BSTR bstr) { return bstr;}
  120. #elif defined(OLE2ANSI)
  121. // in these cases the default (TCHAR) is the same as OLECHAR
  122. #define DEVMODEOLE DEVMODEA
  123. #define LPDEVMODEOLE LPDEVMODEA
  124. #define TEXTMETRICOLE TEXTMETRICA
  125. #define LPTEXTMETRICOLE LPTEXTMETRICA
  126. inline size_t ocslen(LPCOLESTR x) { return lstrlenA(x); }
  127. inline OLECHAR* ocscpy(LPOLESTR dest, LPCOLESTR src) { return lstrcpyA(dest, src); }
  128. inline LPCOLESTR T2COLE(LPCTSTR lp) { return lp; }
  129. inline LPCTSTR OLE2CT(LPCOLESTR lp) { return lp; }
  130. inline LPOLESTR T2OLE(LPTSTR lp) { return lp; }
  131. inline LPTSTR OLE2T(LPOLESTR lp) { return lp; }
  132. inline LPOLESTR TASKSTRINGT2OLE(LPOLESTR lp) { return lp; }
  133. inline LPTSTR TASKSTRINGOLE2T(LPOLESTR lp) { return lp; }
  134. inline LPDEVMODE DEVMODEOLE2T(LPDEVMODEOLE lp) { return lp; }
  135. inline LPDEVMODEOLE DEVMODET2OLE(LPDEVMODE lp) { return lp; }
  136. inline LPTEXTMETRIC TEXTMETRICOLE2T(LPTEXTMETRICOLE lp) { return lp; }
  137. inline LPTEXTMETRICOLE TEXTMETRICT2OLE(LPTEXTMETRIC lp) { return lp; }
  138. inline BSTR BSTR2TBSTR(BSTR bstr) { return bstr; }
  139. #else
  140. #define DEVMODEOLE DEVMODEW
  141. #define LPDEVMODEOLE LPDEVMODEW
  142. #define TEXTMETRICOLE TEXTMETRICW
  143. #define LPTEXTMETRICOLE LPTEXTMETRICW
  144. inline size_t ocslen(LPCOLESTR x) { return wcslen(x); }
  145. inline OLECHAR* ocscpy(LPOLESTR dest, LPCOLESTR src) { return wcscpy(dest, src); }
  146. #define T2COLE(lpa) A2CW(lpa)
  147. #define T2OLE(lpa) A2W(lpa)
  148. #define OLE2CT(lpo) W2CA(lpo)
  149. #define OLE2T(lpo) W2A(lpo)
  150. #define TASKSTRINGT2OLE(lpa) AfxTaskStringA2W(lpa)
  151. #define TASKSTRINGOLE2T(lpo) AfxTaskStringW2A(lpo)
  152. #define DEVMODEOLE2T(lpo) DEVMODEW2A(lpo)
  153. #define DEVMODET2OLE(lpa) DEVMODEA2W(lpa)
  154. #define TEXTMETRICOLE2T(lptmw) TEXTMETRICW2A(lptmw)
  155. #define TEXTMETRICT2OLE(lptma) TEXTMETRICA2W(lptma)
  156. #define BSTR2TBSTR(bstr) AfxBSTR2ABSTR(bstr)
  157. #endif
  158. #ifdef OLE2ANSI
  159. #define W2OLE W2A
  160. #define W2COLE W2CA
  161. #define OLE2W A2W
  162. #define OLE2CW A2CW
  163. inline LPOLESTR A2OLE(LPSTR lp) { return lp; }
  164. inline LPCOLESTR A2COLE(LPCSTR lp) { return lp; }
  165. inline LPSTR OLE2A(LPOLESTR lp) { return lp; }
  166. inline LPCSTR OLE2CA(LPCOLESTR lp) { return lp; }
  167. #else
  168. #define A2OLE A2W
  169. #define A2COLE A2CW
  170. #define OLE2A W2A
  171. #define OLE2CA W2CA
  172. inline LPOLESTR W2OLE(LPWSTR lp) { return lp; }
  173. inline LPCOLESTR W2COLE(LPCWSTR lp) { return lp; }
  174. inline LPWSTR OLE2W(LPOLESTR lp) { return lp; }
  175. inline LPCWSTR OLE2CW(LPCOLESTR lp) { return lp; }
  176. #endif
  177. /////////////////////////////////////////////////////////////////////////////
  178. // helpers
  179. static void PASCAL CheckError(SCODE sc);
  180. static BOOL PASCAL CompareSafeArrays(SAFEARRAY* parray1, SAFEARRAY* parray2);
  181. static void PASCAL CreateOneDimArray(VARIANT& varSrc, DWORD dwSize);
  182. static void PASCAL CopyBinaryData(SAFEARRAY* parray,
  183. const void* pSrc, DWORD dwSize);
  184. /////////////////////////////////////////////////////////////////////////////
  185. // COleVariant class
  186. COleVariant::COleVariant(const VARIANT& varSrc)
  187. {
  188. AfxVariantInit(this);
  189. CheckError(::VariantCopy(this, (LPVARIANT)&varSrc));
  190. }
  191. COleVariant::COleVariant(LPCVARIANT pSrc)
  192. {
  193. AfxVariantInit(this);
  194. CheckError(::VariantCopy(this, (LPVARIANT)pSrc));
  195. }
  196. COleVariant::COleVariant(const COleVariant& varSrc)
  197. {
  198. AfxVariantInit(this);
  199. CheckError(::VariantCopy(this, (LPVARIANT)&varSrc));
  200. }
  201. COleVariant::COleVariant(LPCTSTR lpszSrc, VARTYPE vtSrc)
  202. {
  203. USES_CONVERSION;
  204. ASSERT(vtSrc == VT_BSTR || vtSrc == VT_BSTRT);
  205. UNUSED(vtSrc);
  206. vt = VT_BSTR;
  207. bstrVal = NULL;
  208. if (lpszSrc != NULL)
  209. {
  210. #ifndef _UNICODE
  211. if (vtSrc == VT_BSTRT)
  212. {
  213. int nLen = lstrlen(lpszSrc);
  214. bstrVal = ::SysAllocStringByteLen(lpszSrc, nLen);
  215. }
  216. else
  217. #endif
  218. {
  219. bstrVal = ::SysAllocString(T2COLE(lpszSrc));
  220. }
  221. /*
  222. BUGBUG:
  223. if (bstrVal == NULL)
  224. AfxThrowMemoryException();
  225. */
  226. }
  227. }
  228. void COleVariant::SetString(LPCTSTR lpszSrc, VARTYPE vtSrc)
  229. {
  230. USES_CONVERSION;
  231. ASSERT(vtSrc == VT_BSTR || vtSrc == VT_BSTRT);
  232. UNUSED(vtSrc);
  233. // Free up previous VARIANT
  234. Clear();
  235. vt = VT_BSTR;
  236. bstrVal = NULL;
  237. if (lpszSrc != NULL)
  238. {
  239. #ifndef _UNICODE
  240. if (vtSrc == VT_BSTRT)
  241. {
  242. int nLen = lstrlen(lpszSrc);
  243. bstrVal = ::SysAllocStringByteLen(lpszSrc, nLen);
  244. }
  245. else
  246. #endif
  247. {
  248. bstrVal = ::SysAllocString(T2COLE(lpszSrc));
  249. }
  250. /*
  251. BUGBUG:
  252. if (bstrVal == NULL)
  253. AfxThrowMemoryException();
  254. */
  255. }
  256. }
  257. COleVariant::COleVariant(short nSrc, VARTYPE vtSrc)
  258. {
  259. ASSERT(vtSrc == VT_I2 || vtSrc == VT_BOOL);
  260. if (vtSrc == VT_BOOL)
  261. {
  262. vt = VT_BOOL;
  263. if (nSrc == FALSE)
  264. V_BOOL(this) = AFX_OLE_FALSE;
  265. else
  266. V_BOOL(this) = AFX_OLE_TRUE;
  267. }
  268. else
  269. {
  270. vt = VT_I2;
  271. iVal = nSrc;
  272. }
  273. }
  274. COleVariant::COleVariant(long lSrc, VARTYPE vtSrc)
  275. {
  276. ASSERT(vtSrc == VT_I4 || vtSrc == VT_ERROR || vtSrc == VT_BOOL);
  277. if (vtSrc == VT_ERROR)
  278. {
  279. vt = VT_ERROR;
  280. scode = lSrc;
  281. }
  282. else if (vtSrc == VT_BOOL)
  283. {
  284. vt = VT_BOOL;
  285. if (lSrc == FALSE)
  286. V_BOOL(this) = AFX_OLE_FALSE;
  287. else
  288. V_BOOL(this) = AFX_OLE_TRUE;
  289. }
  290. else
  291. {
  292. vt = VT_I4;
  293. lVal = lSrc;
  294. }
  295. }
  296. // Operations
  297. void COleVariant::Clear()
  298. {
  299. VERIFY(::VariantClear(this) == NOERROR);
  300. }
  301. void COleVariant::ChangeType(VARTYPE vartype, LPVARIANT pSrc)
  302. {
  303. // If pSrc is NULL, convert type in place
  304. if (pSrc == NULL)
  305. pSrc = this;
  306. if (pSrc != this || vartype != vt)
  307. CheckError(::VariantChangeType(this, pSrc, 0, vartype));
  308. }
  309. void COleVariant::Attach(VARIANT& varSrc)
  310. {
  311. // Free up previous VARIANT
  312. Clear();
  313. // give control of data to COleVariant
  314. memcpy(this, &varSrc, sizeof(varSrc));
  315. varSrc.vt = VT_EMPTY;
  316. }
  317. VARIANT COleVariant::Detach()
  318. {
  319. VARIANT varResult = *this;
  320. vt = VT_EMPTY;
  321. return varResult;
  322. }
  323. // Literal comparison. Types and values must match.
  324. BOOL COleVariant::operator==(const VARIANT& var) const
  325. {
  326. if (&var == this)
  327. return TRUE;
  328. // Variants not equal if types don't match
  329. if (var.vt != vt)
  330. return FALSE;
  331. // Check type specific values
  332. switch (vt)
  333. {
  334. case VT_EMPTY:
  335. case VT_NULL:
  336. return TRUE;
  337. case VT_BOOL:
  338. return V_BOOL(&var) == V_BOOL(this);
  339. case VT_UI1:
  340. return var.bVal == bVal;
  341. case VT_I2:
  342. return var.iVal == iVal;
  343. case VT_I4:
  344. return var.lVal == lVal;
  345. case VT_CY:
  346. return (var.cyVal.Hi == cyVal.Hi && var.cyVal.Lo == cyVal.Lo);
  347. case VT_R4:
  348. return var.fltVal == fltVal;
  349. case VT_R8:
  350. return var.dblVal == dblVal;
  351. case VT_DATE:
  352. return var.date == date;
  353. case VT_BSTR:
  354. return SysStringByteLen(var.bstrVal) == SysStringByteLen(bstrVal) &&
  355. memcmp(var.bstrVal, bstrVal, SysStringByteLen(bstrVal)) == 0;
  356. case VT_ERROR:
  357. return var.scode == scode;
  358. case VT_DISPATCH:
  359. case VT_UNKNOWN:
  360. return var.punkVal == punkVal;
  361. default:
  362. if (vt & VT_ARRAY && !(vt & VT_BYREF))
  363. return CompareSafeArrays(var.parray, parray);
  364. else
  365. ASSERT(FALSE); // VT_BYREF not supported
  366. // fall through
  367. }
  368. return FALSE;
  369. }
  370. const COleVariant& COleVariant::operator=(const VARIANT& varSrc)
  371. {
  372. CheckError(::VariantCopy(this, (LPVARIANT)&varSrc));
  373. return *this;
  374. }
  375. const COleVariant& COleVariant::operator=(LPCVARIANT pSrc)
  376. {
  377. CheckError(::VariantCopy(this, (LPVARIANT)pSrc));
  378. return *this;
  379. }
  380. const COleVariant& COleVariant::operator=(const COleVariant& varSrc)
  381. {
  382. CheckError(::VariantCopy(this, (LPVARIANT)&varSrc));
  383. return *this;
  384. }
  385. const COleVariant& COleVariant::operator=(const LPCTSTR lpszSrc)
  386. {
  387. USES_CONVERSION;
  388. // Free up previous VARIANT
  389. Clear();
  390. vt = VT_BSTR;
  391. if (lpszSrc == NULL)
  392. bstrVal = NULL;
  393. else
  394. {
  395. bstrVal = ::SysAllocString(T2COLE(lpszSrc));
  396. /*
  397. BUGBUG:
  398. if (bstrVal == NULL)
  399. AfxThrowMemoryException();
  400. */
  401. }
  402. return *this;
  403. }
  404. const COleVariant& COleVariant::operator=(const CString& strSrc)
  405. {
  406. USES_CONVERSION;
  407. // Free up previous VARIANT
  408. Clear();
  409. vt = VT_BSTR;
  410. bstrVal = ::SysAllocString(T2COLE(strSrc));
  411. /*
  412. BUGBUG:
  413. if (bstrVal == NULL)
  414. AfxThrowMemoryException();
  415. */
  416. return *this;
  417. }
  418. const COleVariant& COleVariant::operator=(BYTE nSrc)
  419. {
  420. // Free up previous VARIANT if necessary
  421. if (vt != VT_UI1)
  422. {
  423. Clear();
  424. vt = VT_UI1;
  425. }
  426. bVal = nSrc;
  427. return *this;
  428. }
  429. const COleVariant& COleVariant::operator=(short nSrc)
  430. {
  431. if (vt == VT_I2)
  432. iVal = nSrc;
  433. else if (vt == VT_BOOL)
  434. {
  435. if (nSrc == FALSE)
  436. V_BOOL(this) = AFX_OLE_FALSE;
  437. else
  438. V_BOOL(this) = AFX_OLE_TRUE;
  439. }
  440. else
  441. {
  442. // Free up previous VARIANT
  443. Clear();
  444. vt = VT_I2;
  445. iVal = nSrc;
  446. }
  447. return *this;
  448. }
  449. const COleVariant& COleVariant::operator=(long lSrc)
  450. {
  451. if (vt == VT_I4)
  452. lVal = lSrc;
  453. else if (vt == VT_ERROR)
  454. scode = lSrc;
  455. else if (vt == VT_BOOL)
  456. {
  457. if (lSrc == FALSE)
  458. V_BOOL(this) = AFX_OLE_FALSE;
  459. else
  460. V_BOOL(this) = AFX_OLE_TRUE;
  461. }
  462. else
  463. {
  464. // Free up previous VARIANT
  465. Clear();
  466. vt = VT_I4;
  467. lVal = lSrc;
  468. }
  469. return *this;
  470. }
  471. /*
  472. const COleVariant& COleVariant::operator=(const COleCurrency& curSrc)
  473. {
  474. // Free up previous VARIANT if necessary
  475. if (vt != VT_CY)
  476. {
  477. Clear();
  478. vt = VT_CY;
  479. }
  480. cyVal = curSrc.m_cur;
  481. return *this;
  482. }
  483. */
  484. const COleVariant& COleVariant::operator=(float fltSrc)
  485. {
  486. // Free up previous VARIANT if necessary
  487. if (vt != VT_R4)
  488. {
  489. Clear();
  490. vt = VT_R4;
  491. }
  492. fltVal = fltSrc;
  493. return *this;
  494. }
  495. const COleVariant& COleVariant::operator=(double dblSrc)
  496. {
  497. // Free up previous VARIANT if necessary
  498. if (vt != VT_R8)
  499. {
  500. Clear();
  501. vt = VT_R8;
  502. }
  503. dblVal = dblSrc;
  504. return *this;
  505. }
  506. const COleVariant& COleVariant::operator=(const COleDateTime& dateSrc)
  507. {
  508. // Free up previous VARIANT if necessary
  509. if (vt != VT_DATE)
  510. {
  511. Clear();
  512. vt = VT_DATE;
  513. }
  514. date = dateSrc.m_dt;
  515. return *this;
  516. }
  517. /*
  518. const COleVariant& COleVariant::operator=(const CByteArray& arrSrc)
  519. {
  520. int nSize = arrSrc.GetSize();
  521. // Set the correct type and make sure SafeArray can hold data
  522. CreateOneDimArray(*this, (DWORD)nSize);
  523. // Copy the data into the SafeArray
  524. CopyBinaryData(parray, arrSrc.GetData(), (DWORD)nSize);
  525. return *this;
  526. }
  527. const COleVariant& COleVariant::operator=(const CLongBinary& lbSrc)
  528. {
  529. // Set the correct type and make sure SafeArray can hold data
  530. CreateOneDimArray(*this, lbSrc.m_dwDataLength);
  531. // Copy the data into the SafeArray
  532. BYTE* pData = (BYTE*)::GlobalLock(lbSrc.m_hData);
  533. CopyBinaryData(parray, pData, lbSrc.m_dwDataLength);
  534. ::GlobalUnlock(lbSrc.m_hData);
  535. return *this;
  536. }
  537. */
  538. void AFXAPI AfxVariantInit(LPVARIANT pVar)
  539. {
  540. memset(pVar, 0, sizeof(*pVar));
  541. }
  542. /////////////////////////////////////////////////////////////////////////////
  543. // Diagnostics
  544. #ifdef _DEBUG
  545. CDumpContext& AFXAPI operator <<(CDumpContext& dc, COleVariant varSrc)
  546. {
  547. LPCVARIANT pSrc = (LPCVARIANT)varSrc;
  548. dc << "\nCOleVariant Object:";
  549. dc << "\n\t vt = " << pSrc->vt;
  550. // No support for VT_BYREF & VT_ARRAY
  551. if (pSrc->vt & VT_BYREF || pSrc->vt & VT_ARRAY)
  552. return dc;
  553. switch (pSrc->vt)
  554. {
  555. case VT_BOOL:
  556. return dc << "\n\t VT_BOOL = " << V_BOOL(pSrc);
  557. case VT_UI1:
  558. return dc << "\n\t bVal = " << pSrc->bVal;
  559. case VT_I2:
  560. return dc << "\n\t iVal = " << pSrc->iVal;
  561. case VT_I4:
  562. return dc << "\n\t lVal = " << pSrc->lVal;
  563. case VT_CY:
  564. {
  565. COleVariant var(varSrc);
  566. var.ChangeType(VT_BSTR);
  567. return dc << "\n\t cyVal = " << (LPCTSTR)var.bstrVal;
  568. }
  569. case VT_R4:
  570. return dc << "\n\t fltVal = " << pSrc->fltVal;
  571. case VT_R8:
  572. return dc << "\n\t dblVal = " << pSrc->dblVal;
  573. case VT_DATE:
  574. {
  575. COleVariant var(varSrc);
  576. var.ChangeType(VT_BSTR);
  577. return dc << "\n\t date = " << (LPCTSTR)var.bstrVal;
  578. }
  579. case VT_BSTR:
  580. return dc << "\n\t bstrVal = " << (LPCTSTR)pSrc->bstrVal;
  581. case VT_ERROR:
  582. return dc << "\n\t scode = " << pSrc->scode;
  583. case VT_DISPATCH:
  584. case VT_UNKNOWN:
  585. return dc << "\n\t punkVal = " << pSrc->punkVal;
  586. case VT_EMPTY:
  587. case VT_NULL:
  588. return dc;
  589. default:
  590. ASSERT(FALSE);
  591. return dc;
  592. }
  593. }
  594. #endif // _DEBUG
  595. #ifdef _with_archive_
  596. CArchive& AFXAPI operator<<(CArchive& ar, COleVariant varSrc)
  597. {
  598. LPCVARIANT pSrc = (LPCVARIANT)varSrc;
  599. ar << pSrc->vt;
  600. // No support for VT_BYREF & VT_ARRAY
  601. if (pSrc->vt & VT_BYREF || pSrc->vt & VT_ARRAY)
  602. return ar;
  603. switch (pSrc->vt)
  604. {
  605. case VT_BOOL:
  606. return ar << (WORD)V_BOOL(pSrc);
  607. case VT_UI1:
  608. return ar << pSrc->bVal;
  609. case VT_I2:
  610. return ar << (WORD)pSrc->iVal;
  611. case VT_I4:
  612. return ar << pSrc->lVal;
  613. case VT_CY:
  614. ar << pSrc->cyVal.Lo;
  615. return ar << pSrc->cyVal.Hi;
  616. case VT_R4:
  617. return ar << pSrc->fltVal;
  618. case VT_R8:
  619. return ar << pSrc->dblVal;
  620. case VT_DATE:
  621. return ar << pSrc->date;
  622. case VT_BSTR:
  623. {
  624. DWORD nLen = SysStringByteLen(pSrc->bstrVal);
  625. ar << nLen;
  626. if (nLen > 0)
  627. ar.Write(pSrc->bstrVal, nLen * sizeof(BYTE));
  628. return ar;
  629. }
  630. case VT_ERROR:
  631. return ar << pSrc->scode;
  632. #ifdef _WITH_PUNK_
  633. case VT_DISPATCH:
  634. case VT_UNKNOWN:
  635. {
  636. LPPERSISTSTREAM pPersistStream;
  637. //BUGBUG
  638. //CArchiveStream stm(&ar);
  639. // QI for IPersistStream or IPeristStreamInit
  640. SCODE sc = pSrc->punkVal->QueryInterface(
  641. IID_IPersistStream, (void**)&pPersistStream);
  642. //#ifndef _AFX_NO_OCC_SUPPORT
  643. #ifdef _AFX_OCC_SUPPORT
  644. if (FAILED(sc))
  645. sc = pSrc->punkVal->QueryInterface(
  646. IID_IPersistStreamInit, (void**)&pPersistStream);
  647. #endif
  648. CheckError(sc);
  649. TRY
  650. {
  651. // Get and archive the CLSID (GUID)
  652. CLSID clsid;
  653. CheckError(pPersistStream->GetClassID(&clsid));
  654. ar << clsid.Data1;
  655. ar << clsid.Data2;
  656. ar << clsid.Data3;
  657. ar.Write(&clsid.Data4[0], sizeof clsid.Data4);
  658. // Always assume object is dirty
  659. CheckError(pPersistStream->Save(&stm, TRUE));
  660. }
  661. CATCH_ALL(e)
  662. {
  663. pPersistStream->Release();
  664. THROW_LAST();
  665. }
  666. END_CATCH_ALL
  667. pPersistStream->Release();
  668. }
  669. return ar;
  670. #endif //_WITH_PUNK_
  671. case VT_EMPTY:
  672. case VT_NULL:
  673. // do nothing
  674. return ar;
  675. default:
  676. ASSERT(FALSE);
  677. return ar;
  678. }
  679. }
  680. CArchive& AFXAPI operator>>(CArchive& ar, COleVariant& varSrc)
  681. {
  682. LPVARIANT pSrc = &varSrc;
  683. // Free up current data if necessary
  684. if (pSrc->vt != VT_EMPTY)
  685. VariantClear(pSrc);
  686. ar >> pSrc->vt;
  687. // No support for VT_BYREF & VT_ARRAY
  688. if (pSrc->vt & VT_BYREF || pSrc->vt & VT_ARRAY)
  689. return ar;
  690. switch (pSrc->vt)
  691. {
  692. case VT_BOOL:
  693. return ar >> (WORD&)V_BOOL(pSrc);
  694. case VT_UI1:
  695. return ar >> pSrc->bVal;
  696. case VT_I2:
  697. return ar >> (WORD&)pSrc->iVal;
  698. case VT_I4:
  699. return ar >> pSrc->lVal;
  700. case VT_CY:
  701. ar >> pSrc->cyVal.Lo;
  702. return ar >> pSrc->cyVal.Hi;
  703. case VT_R4:
  704. return ar >> pSrc->fltVal;
  705. case VT_R8:
  706. return ar >> pSrc->dblVal;
  707. case VT_DATE:
  708. return ar >> pSrc->date;
  709. case VT_BSTR:
  710. {
  711. DWORD nLen;
  712. ar >> nLen;
  713. if (nLen > 0)
  714. {
  715. pSrc->bstrVal = SysAllocStringByteLen(NULL, nLen);
  716. //BUGBUG:
  717. //if (pSrc->bstrVal == NULL)
  718. // AfxThrowMemoryException();
  719. ar.Read(pSrc->bstrVal, nLen * sizeof(BYTE));
  720. }
  721. else
  722. pSrc->bstrVal = NULL;
  723. return ar;
  724. }
  725. break;
  726. case VT_ERROR:
  727. return ar >> pSrc->scode;
  728. #ifdef _WITH_PUNK_
  729. case VT_DISPATCH:
  730. case VT_UNKNOWN:
  731. {
  732. LPPERSISTSTREAM pPersistStream = NULL;
  733. CArchiveStream stm(&ar);
  734. // Retrieve the CLSID (GUID) and create an instance
  735. CLSID clsid;
  736. ar >> clsid.Data1;
  737. ar >> clsid.Data2;
  738. ar >> clsid.Data3;
  739. ar.Read(&clsid.Data4[0], sizeof clsid.Data4);
  740. // Create the object
  741. SCODE sc = CoCreateInstance(clsid, NULL, CLSCTX_ALL | CLSCTX_REMOTE_SERVER,
  742. pSrc->vt == VT_UNKNOWN ? IID_IUnknown : IID_IDispatch,
  743. (void**)&pSrc->punkVal);
  744. if (sc == E_INVALIDARG)
  745. {
  746. // may not support CLSCTX_REMOTE_SERVER, so try without
  747. sc = CoCreateInstance(clsid, NULL,
  748. CLSCTX_ALL & ~CLSCTX_REMOTE_SERVER,
  749. pSrc->vt == VT_UNKNOWN ? IID_IUnknown : IID_IDispatch,
  750. (void**)&pSrc->punkVal);
  751. }
  752. CheckError(sc);
  753. TRY
  754. {
  755. // QI for IPersistStream or IPeristStreamInit
  756. sc = pSrc->punkVal->QueryInterface(
  757. IID_IPersistStream, (void**)&pPersistStream);
  758. #ifndef _AFX_NO_OCC_SUPPORT
  759. if (FAILED(sc))
  760. sc = pSrc->punkVal->QueryInterface(
  761. IID_IPersistStreamInit, (void**)&pPersistStream);
  762. #endif
  763. CheckError(sc);
  764. // Always assumes object is dirty
  765. CheckError(pPersistStream->Load(&stm));
  766. }
  767. CATCH_ALL(e)
  768. {
  769. // Clean up
  770. if (pPersistStream != NULL)
  771. pPersistStream->Release();
  772. pSrc->punkVal->Release();
  773. THROW_LAST();
  774. }
  775. END_CATCH_ALL
  776. pPersistStream->Release();
  777. }
  778. return ar;
  779. #endif //_WITH_PUNK_
  780. case VT_EMPTY:
  781. case VT_NULL:
  782. // do nothing
  783. return ar;
  784. default:
  785. ASSERT(FALSE);
  786. return ar;
  787. }
  788. }
  789. #endif //_with_archive_
  790. /////////////////////////////////////////////////////////////////////////////
  791. // COleVariant Helpers
  792. template<>
  793. void AFXAPI ConstructElements(COleVariant* pElements, int nCount)
  794. {
  795. ASSERT(nCount == 0 ||
  796. AfxIsValidAddress(pElements, nCount * sizeof(COleVariant)));
  797. for (; nCount--; ++pElements)
  798. new(pElements) COleVariant;
  799. }
  800. template<>
  801. void AFXAPI DestructElements(COleVariant* pElements, int nCount)
  802. {
  803. ASSERT(nCount == 0 ||
  804. AfxIsValidAddress(pElements, nCount * sizeof(COleVariant)));
  805. for (; nCount--; ++pElements)
  806. pElements->~COleVariant();
  807. }
  808. template<>
  809. void AFXAPI CopyElements(COleVariant* pDest, const COleVariant* pSrc, int nCount)
  810. {
  811. ASSERT(nCount == 0 ||
  812. AfxIsValidAddress(pDest, nCount * sizeof(COleVariant)));
  813. ASSERT(nCount == 0 ||
  814. AfxIsValidAddress(pSrc, nCount * sizeof(COleVariant)));
  815. for (; nCount--; ++pDest, ++pSrc)
  816. *pDest = *pSrc;
  817. }
  818. #ifdef _with_archive_
  819. template<>
  820. void AFXAPI SerializeElements(CArchive& ar, COleVariant* pElements, int nCount)
  821. {
  822. ASSERT(nCount == 0 ||
  823. AfxIsValidAddress(pElements, nCount * sizeof(COleVariant)));
  824. if (ar.IsStoring())
  825. {
  826. for (; nCount--; ++pElements)
  827. ar << *pElements;
  828. }
  829. else
  830. {
  831. for (; nCount--; ++pElements)
  832. ar >> *pElements;
  833. }
  834. }
  835. #endif //_with_archive_
  836. #ifdef _DEBUG
  837. template<>
  838. void AFXAPI DumpElements(CDumpContext& dc, COleVariant* pElements, int nCount)
  839. {
  840. for (; nCount--; ++pElements)
  841. dc << *pElements;
  842. }
  843. #endif // _DEBUG
  844. template<>
  845. UINT AFXAPI HashKey(const struct tagVARIANT& var)
  846. {
  847. switch (var.vt)
  848. {
  849. case VT_EMPTY:
  850. case VT_NULL:
  851. return 0;
  852. case VT_I2:
  853. return HashKey((DWORD)var.iVal);
  854. case VT_I4:
  855. return HashKey((DWORD)var.lVal);
  856. case VT_R4:
  857. return (UINT)(var.fltVal / 16);
  858. case VT_R8:
  859. case VT_CY:
  860. return (UINT)(var.dblVal / 16);
  861. case VT_BOOL:
  862. return HashKey((DWORD)V_BOOL(&var));
  863. case VT_ERROR:
  864. return HashKey((DWORD)var.scode);
  865. case VT_DATE:
  866. return (UINT)(var.date / 16);
  867. case VT_BSTR:
  868. return HashKey(var.bstrVal);
  869. case VT_DISPATCH:
  870. case VT_UNKNOWN:
  871. return HashKey((DWORD_PTR)var.punkVal);
  872. default:
  873. // No support for VT_BYREF & VT_ARRAY
  874. ASSERT(FALSE);
  875. // Fall through
  876. }
  877. return 0;
  878. }
  879. static void PASCAL CheckError(SCODE sc)
  880. {
  881. if (FAILED(sc))
  882. {
  883. /*
  884. BUGBUG:
  885. if (sc == E_OUTOFMEMORY)
  886. AfxThrowMemoryException();
  887. else
  888. AfxThrowOleException(sc);
  889. */
  890. }
  891. }
  892. static BOOL PASCAL CompareSafeArrays(SAFEARRAY* parray1, SAFEARRAY* parray2)
  893. {
  894. return FALSE;
  895. }
  896. #ifdef _CURRENCY_ALSO_
  897. static BOOL PASCAL CompareSafeArrays(SAFEARRAY* parray1, SAFEARRAY* parray2)
  898. {
  899. BOOL bCompare = FALSE;
  900. // If one is NULL they must both be NULL to compare
  901. if (parray1 == NULL || parray2 == NULL)
  902. {
  903. return parray1 == parray2;
  904. }
  905. // Dimension must match and if 0, then arrays compare
  906. DWORD dwDim1 = ::SafeArrayGetDim(parray1);
  907. DWORD dwDim2 = ::SafeArrayGetDim(parray2);
  908. if (dwDim1 != dwDim2)
  909. return FALSE;
  910. else if (dwDim1 == 0)
  911. return TRUE;
  912. // Element size must match
  913. DWORD dwSize1 = ::SafeArrayGetElemsize(parray1);
  914. DWORD dwSize2 = ::SafeArrayGetElemsize(parray2);
  915. if (dwSize1 != dwSize2)
  916. return FALSE;
  917. long* pLBound1 = NULL;
  918. long* pLBound2 = NULL;
  919. long* pUBound1 = NULL;
  920. long* pUBound2 = NULL;
  921. void* pData1 = NULL;
  922. void* pData2 = NULL;
  923. TRY
  924. {
  925. // Bounds must match
  926. pLBound1 = new long[dwDim1];
  927. pLBound2 = new long[dwDim2];
  928. pUBound1 = new long[dwDim1];
  929. pUBound2 = new long[dwDim2];
  930. size_t nTotalElements = 1;
  931. // Get and compare bounds
  932. for (DWORD dwIndex = 0; dwIndex < dwDim1; dwIndex++)
  933. {
  934. CheckError(::SafeArrayGetLBound(
  935. parray1, dwIndex+1, &pLBound1[dwIndex]));
  936. CheckError(::SafeArrayGetLBound(
  937. parray2, dwIndex+1, &pLBound2[dwIndex]));
  938. CheckError(::SafeArrayGetUBound(
  939. parray1, dwIndex+1, &pUBound1[dwIndex]));
  940. CheckError(::SafeArrayGetUBound(
  941. parray2, dwIndex+1, &pUBound2[dwIndex]));
  942. // Check the magnitude of each bound
  943. if (pUBound1[dwIndex] - pLBound1[dwIndex] !=
  944. pUBound2[dwIndex] - pLBound2[dwIndex])
  945. {
  946. delete[] pLBound1;
  947. delete[] pLBound2;
  948. delete[] pUBound1;
  949. delete[] pUBound2;
  950. return FALSE;
  951. }
  952. // Increment the element count
  953. nTotalElements *= pUBound1[dwIndex] - pLBound1[dwIndex] + 1;
  954. }
  955. // Access the data
  956. CheckError(::SafeArrayAccessData(parray1, &pData1));
  957. CheckError(::SafeArrayAccessData(parray2, &pData2));
  958. // Calculate the number of bytes of data and compare
  959. size_t nSize = nTotalElements * dwSize1;
  960. int nOffset = memcmp(pData1, pData2, nSize);
  961. bCompare = nOffset == 0;
  962. // Release the array locks
  963. CheckError(::SafeArrayUnaccessData(parray1));
  964. CheckError(::SafeArrayUnaccessData(parray2));
  965. }
  966. CATCH_ALL(e)
  967. {
  968. // Clean up bounds arrays
  969. delete[] pLBound1;
  970. delete[] pLBound2;
  971. delete[] pUBound1;
  972. delete[] pUBound2;
  973. // Release the array locks
  974. if (pData1 != NULL)
  975. CheckError(::SafeArrayUnaccessData(parray1));
  976. if (pData2 != NULL)
  977. CheckError(::SafeArrayUnaccessData(parray2));
  978. THROW_LAST();
  979. }
  980. END_CATCH_ALL
  981. // Clean up bounds arrays
  982. delete[] pLBound1;
  983. delete[] pLBound2;
  984. delete[] pUBound1;
  985. delete[] pUBound2;
  986. return bCompare;
  987. }
  988. static void PASCAL CreateOneDimArray(VARIANT& varSrc, DWORD dwSize)
  989. {
  990. UINT nDim;
  991. // Clear VARIANT and re-create SafeArray if necessary
  992. if (varSrc.vt != (VT_UI1 | VT_ARRAY) ||
  993. (nDim = ::SafeArrayGetDim(varSrc.parray)) != 1)
  994. {
  995. VERIFY(::VariantClear(&varSrc) == NOERROR);
  996. varSrc.vt = VT_UI1 | VT_ARRAY;
  997. SAFEARRAYBOUND bound;
  998. bound.cElements = dwSize;
  999. bound.lLbound = 0;
  1000. varSrc.parray = ::SafeArrayCreate(VT_UI1, 1, &bound);
  1001. if (varSrc.parray == NULL)
  1002. AfxThrowMemoryException();
  1003. }
  1004. else
  1005. {
  1006. // Must redimension array if necessary
  1007. long lLower, lUpper;
  1008. CheckError(::SafeArrayGetLBound(varSrc.parray, 1, &lLower));
  1009. CheckError(::SafeArrayGetUBound(varSrc.parray, 1, &lUpper));
  1010. // Upper bound should always be greater than lower bound
  1011. long lSize = lUpper - lLower;
  1012. if (lSize < 0)
  1013. {
  1014. ASSERT(FALSE);
  1015. lSize = 0;
  1016. }
  1017. if ((DWORD)lSize != dwSize)
  1018. {
  1019. SAFEARRAYBOUND bound;
  1020. bound.cElements = dwSize;
  1021. bound.lLbound = lLower;
  1022. CheckError(::SafeArrayRedim(varSrc.parray, &bound));
  1023. }
  1024. }
  1025. }
  1026. static void PASCAL CopyBinaryData(SAFEARRAY* parray, const void* pvSrc, DWORD dwSize)
  1027. {
  1028. // Access the data, copy it and unaccess it.
  1029. void* pDest;
  1030. CheckError(::SafeArrayAccessData(parray, &pDest));
  1031. memcpy(pDest, pvSrc, dwSize);
  1032. CheckError(::SafeArrayUnaccessData(parray));
  1033. }
  1034. /////////////////////////////////////////////////////////////////////////////
  1035. // COleCurrency class helpers
  1036. // Return the highest order bit composing dwTarget in wBit
  1037. #define HI_BIT(dwTarget, wBit) \
  1038. do \
  1039. { \
  1040. if (dwTarget != 0) \
  1041. for (wBit = 32; (dwTarget & (0x00000001 << wBit-1)) == 0; wBit--);\
  1042. else \
  1043. wBit = 0; \
  1044. } while (0)
  1045. // Left shift an (assumed unsigned) currency by wBits
  1046. #define LSHIFT_UCUR(cur, wBits) \
  1047. do \
  1048. { \
  1049. for (WORD wTempBits = wBits; wTempBits > 0; wTempBits--) \
  1050. { \
  1051. cur.m_cur.Hi = ((DWORD)cur.m_cur.Hi << 1); \
  1052. cur.m_cur.Hi |= (cur.m_cur.Lo & 0x80000000) >> 31; \
  1053. cur.m_cur.Lo = cur.m_cur.Lo << 1; \
  1054. } \
  1055. } while (0)
  1056. // Right shift an (assumed unsigned) currency by wBits
  1057. #define RSHIFT_UCUR(cur, wBits) \
  1058. do \
  1059. { \
  1060. for (WORD wTempBits = wBits; wTempBits > 0; wTempBits--) \
  1061. { \
  1062. cur.m_cur.Lo = cur.m_cur.Lo >> 1; \
  1063. cur.m_cur.Lo |= (cur.m_cur.Hi & 0x00000001) << 31; \
  1064. cur.m_cur.Hi = ((DWORD)cur.m_cur.Hi >> 1); \
  1065. } \
  1066. } while (0)
  1067. /////////////////////////////////////////////////////////////////////////////
  1068. // COleCurrency class (internally currency is 8-byte int scaled by 10,000)
  1069. COleCurrency::COleCurrency(long nUnits, long nFractionalUnits)
  1070. {
  1071. SetCurrency(nUnits, nFractionalUnits);
  1072. SetStatus(valid);
  1073. }
  1074. const COleCurrency& COleCurrency::operator=(CURRENCY cySrc)
  1075. {
  1076. m_cur = cySrc;
  1077. SetStatus(valid);
  1078. return *this;
  1079. }
  1080. const COleCurrency& COleCurrency::operator=(const COleCurrency& curSrc)
  1081. {
  1082. m_cur = curSrc.m_cur;
  1083. m_status = curSrc.m_status;
  1084. return *this;
  1085. }
  1086. const COleCurrency& COleCurrency::operator=(const VARIANT& varSrc)
  1087. {
  1088. if (varSrc.vt != VT_CY)
  1089. {
  1090. TRY
  1091. {
  1092. COleVariant varTemp(varSrc);
  1093. varTemp.ChangeType(VT_CY);
  1094. m_cur = varTemp.cyVal;
  1095. SetStatus(valid);
  1096. }
  1097. // Catch COleException from ChangeType, but not CMemoryException
  1098. CATCH(COleException, e)
  1099. {
  1100. // Not able to convert VARIANT to CURRENCY
  1101. m_cur.Hi = 0;
  1102. m_cur.Lo = 0;
  1103. SetStatus(invalid);
  1104. DELETE_EXCEPTION(e);
  1105. }
  1106. END_CATCH
  1107. }
  1108. else
  1109. {
  1110. m_cur = varSrc.cyVal;
  1111. SetStatus(valid);
  1112. }
  1113. return *this;
  1114. }
  1115. BOOL COleCurrency::operator<(const COleCurrency& cur) const
  1116. {
  1117. ASSERT(GetStatus() == valid);
  1118. ASSERT(cur.GetStatus() == valid);
  1119. return((m_cur.Hi == cur.m_cur.Hi) ?
  1120. (m_cur.Lo < cur.m_cur.Lo) : (m_cur.Hi < cur.m_cur.Hi));
  1121. }
  1122. BOOL COleCurrency::operator>(const COleCurrency& cur) const
  1123. {
  1124. ASSERT(GetStatus() == valid);
  1125. ASSERT(cur.GetStatus() == valid);
  1126. return((m_cur.Hi == cur.m_cur.Hi) ?
  1127. (m_cur.Lo > cur.m_cur.Lo) : (m_cur.Hi > cur.m_cur.Hi));
  1128. }
  1129. BOOL COleCurrency::operator<=(const COleCurrency& cur) const
  1130. {
  1131. ASSERT(GetStatus() == valid);
  1132. ASSERT(cur.GetStatus() == valid);
  1133. return((m_cur.Hi == cur.m_cur.Hi) ?
  1134. (m_cur.Lo <= cur.m_cur.Lo) : (m_cur.Hi < cur.m_cur.Hi));
  1135. }
  1136. BOOL COleCurrency::operator>=(const COleCurrency& cur) const
  1137. {
  1138. ASSERT(GetStatus() == valid);
  1139. ASSERT(cur.GetStatus() == valid);
  1140. return((m_cur.Hi == cur.m_cur.Hi) ?
  1141. (m_cur.Lo >= cur.m_cur.Lo) : (m_cur.Hi > cur.m_cur.Hi));
  1142. }
  1143. COleCurrency COleCurrency::operator+(const COleCurrency& cur) const
  1144. {
  1145. COleCurrency curResult;
  1146. // If either operand Null, result Null
  1147. if (GetStatus() == null || cur.GetStatus() == null)
  1148. {
  1149. curResult.SetStatus(null);
  1150. return curResult;
  1151. }
  1152. // If either operand Invalid, result Invalid
  1153. if (GetStatus() == invalid || cur.GetStatus() == invalid)
  1154. {
  1155. curResult.SetStatus(invalid);
  1156. return curResult;
  1157. }
  1158. // Add separate CURRENCY components
  1159. curResult.m_cur.Hi = m_cur.Hi + cur.m_cur.Hi;
  1160. curResult.m_cur.Lo = m_cur.Lo + cur.m_cur.Lo;
  1161. // Increment Hi if Lo overflows
  1162. if (m_cur.Lo > curResult.m_cur.Lo)
  1163. curResult.m_cur.Hi++;
  1164. // Overflow if operands same sign and result sign different
  1165. if (!((m_cur.Hi ^ cur.m_cur.Hi) & 0x80000000) &&
  1166. ((m_cur.Hi ^ curResult.m_cur.Hi) & 0x80000000))
  1167. {
  1168. curResult.SetStatus(invalid);
  1169. }
  1170. return curResult;
  1171. }
  1172. COleCurrency COleCurrency::operator-(const COleCurrency& cur) const
  1173. {
  1174. COleCurrency curResult;
  1175. // If either operand Null, result Null
  1176. if (GetStatus() == null || cur.GetStatus() == null)
  1177. {
  1178. curResult.SetStatus(null);
  1179. return curResult;
  1180. }
  1181. // If either operand Invalid, result Invalid
  1182. if (GetStatus() == invalid || cur.GetStatus() == invalid)
  1183. {
  1184. curResult.SetStatus(invalid);
  1185. return curResult;
  1186. }
  1187. // Subtract separate CURRENCY components
  1188. curResult.m_cur.Hi = m_cur.Hi - cur.m_cur.Hi;
  1189. curResult.m_cur.Lo = m_cur.Lo - cur.m_cur.Lo;
  1190. // Decrement Hi if Lo overflows
  1191. if (m_cur.Lo < curResult.m_cur.Lo)
  1192. curResult.m_cur.Hi--;
  1193. // Overflow if operands not same sign and result not same sign
  1194. if (((m_cur.Hi ^ cur.m_cur.Hi) & 0x80000000) &&
  1195. ((m_cur.Hi ^ curResult.m_cur.Hi) & 0x80000000))
  1196. {
  1197. curResult.SetStatus(invalid);
  1198. }
  1199. return curResult;
  1200. }
  1201. COleCurrency COleCurrency::operator-() const
  1202. {
  1203. // If operand not Valid, just return
  1204. if (!GetStatus() == valid)
  1205. return *this;
  1206. COleCurrency curResult;
  1207. // Negating MIN_CURRENCY,will set invalid
  1208. if (m_cur.Hi == 0x80000000 && m_cur.Lo == 0x00000000)
  1209. {
  1210. curResult.SetStatus(invalid);
  1211. }
  1212. curResult.m_cur.Hi = ~m_cur.Hi;
  1213. curResult.m_cur.Lo = -(long)m_cur.Lo;
  1214. // If cy was -1 make sure Hi correctly set
  1215. if (curResult.m_cur.Lo == 0)
  1216. curResult.m_cur.Hi++;
  1217. return curResult;
  1218. }
  1219. COleCurrency COleCurrency::operator*(long nOperand) const
  1220. {
  1221. // If operand not Valid, just return
  1222. if (!GetStatus() == valid)
  1223. return *this;
  1224. COleCurrency curResult(m_cur);
  1225. DWORD nTempOp;
  1226. // Return now if one operand is 0 (optimization)
  1227. if ((m_cur.Hi == 0x00000000 && m_cur.Lo == 0x00000000) || nOperand == 0)
  1228. {
  1229. curResult.m_cur.Hi = 0;
  1230. curResult.m_cur.Lo = 0;
  1231. return curResult;
  1232. }
  1233. // Handle only valid case of multiplying MIN_CURRENCY
  1234. if (m_cur.Hi == 0x80000000 && m_cur.Lo == 0x00000000 && nOperand == 1)
  1235. return curResult;
  1236. // Compute absolute values.
  1237. if (m_cur.Hi < 0)
  1238. curResult = -curResult;
  1239. nTempOp = labs(nOperand);
  1240. // Check for overflow
  1241. if (curResult.m_cur.Hi != 0)
  1242. {
  1243. WORD wHiBitCur, wHiBitOp;
  1244. HI_BIT(curResult.m_cur.Hi, wHiBitCur);
  1245. HI_BIT(nTempOp, wHiBitOp);
  1246. // 63-bit limit on result. (n bits)*(m bits) = (n+m-1) bits.
  1247. if (wHiBitCur + wHiBitOp - 1 > 63)
  1248. {
  1249. // Overflow!
  1250. curResult.SetStatus(invalid);
  1251. // Set to maximum negative value
  1252. curResult.m_cur.Hi = 0x80000000;
  1253. curResult.m_cur.Lo = 0x00000000;
  1254. return curResult;
  1255. }
  1256. }
  1257. // Break up into WORDs
  1258. WORD wCy4, wCy3, wCy2, wCy1, wL2, wL1;
  1259. wCy4 = HIWORD(curResult.m_cur.Hi);
  1260. wCy3 = LOWORD(curResult.m_cur.Hi);
  1261. wCy2 = HIWORD(curResult.m_cur.Lo);
  1262. wCy1 = LOWORD(curResult.m_cur.Lo);
  1263. wL2 = HIWORD(nTempOp);
  1264. wL1 = LOWORD(nTempOp);
  1265. // Multiply each set of WORDs
  1266. DWORD dwRes11, dwRes12, dwRes21, dwRes22;
  1267. DWORD dwRes31, dwRes32, dwRes41; // Don't need dwRes42
  1268. dwRes11 = wCy1 * wL1;
  1269. dwRes12 = wCy1 * wL2;
  1270. dwRes21 = wCy2 * wL1;
  1271. dwRes22 = wCy2 * wL2;
  1272. dwRes31 = wCy3 * wL1;
  1273. dwRes32 = wCy3 * wL2;
  1274. dwRes41 = wCy4 * wL1;
  1275. // Add up low order pieces
  1276. dwRes11 += dwRes12<<16;
  1277. curResult.m_cur.Lo = dwRes11 + (dwRes21<<16);
  1278. // Check if carry required
  1279. if (dwRes11 < dwRes12<<16 || (DWORD)curResult.m_cur.Lo < dwRes11)
  1280. curResult.m_cur.Hi = 1;
  1281. else
  1282. curResult.m_cur.Hi = 0;
  1283. // Add up the high order pieces
  1284. curResult.m_cur.Hi += dwRes31 + (dwRes32<<16) + (dwRes41<<16) +
  1285. dwRes22 + (dwRes12>>16) + (dwRes21>>16);
  1286. // Compute result sign
  1287. if ((m_cur.Hi ^ nOperand) & 0x80000000)
  1288. curResult = -curResult;
  1289. return curResult;
  1290. }
  1291. COleCurrency COleCurrency::operator/(long nOperand) const
  1292. {
  1293. // If operand not Valid, just return
  1294. if (!GetStatus() == valid)
  1295. return *this;
  1296. COleCurrency curTemp(m_cur);
  1297. DWORD nTempOp;
  1298. // Check for divide by 0
  1299. if (nOperand == 0)
  1300. {
  1301. curTemp.SetStatus(invalid);
  1302. // Set to maximum negative value
  1303. curTemp.m_cur.Hi = 0x80000000;
  1304. curTemp.m_cur.Lo = 0x00000000;
  1305. return curTemp;
  1306. }
  1307. // Compute absolute values
  1308. if (curTemp.m_cur.Hi < 0)
  1309. curTemp = -curTemp;
  1310. nTempOp = labs(nOperand);
  1311. // Optimization - division is simple if Hi == 0
  1312. if (curTemp.m_cur.Hi == 0x0000)
  1313. {
  1314. curTemp.m_cur.Lo = m_cur.Lo / nTempOp;
  1315. // Compute result sign
  1316. if ((m_cur.Hi ^ nOperand) & 0x80000000)
  1317. curTemp = -curTemp;
  1318. return curTemp;
  1319. }
  1320. // Now curTemp represents remainder
  1321. COleCurrency curResult; // Initializes to zero
  1322. COleCurrency curTempResult;
  1323. COleCurrency curOperand;
  1324. curOperand.m_cur.Lo = nTempOp;
  1325. WORD wHiBitRem;
  1326. WORD wScaleOp;
  1327. // Quit if remainder can be truncated
  1328. while (curTemp >= curOperand)
  1329. {
  1330. // Scale up and divide Hi portion
  1331. HI_BIT(curTemp.m_cur.Hi, wHiBitRem);
  1332. if (wHiBitRem != 0)
  1333. wHiBitRem += 32;
  1334. else
  1335. HI_BIT(curTemp.m_cur.Lo, wHiBitRem);
  1336. WORD wShift = (WORD)(64 - wHiBitRem);
  1337. LSHIFT_UCUR(curTemp, wShift);
  1338. // If Operand bigger than Hi it must be scaled
  1339. wScaleOp = (WORD)((nTempOp > (DWORD)curTemp.m_cur.Hi) ? 1 : 0);
  1340. // Perform synthetic division
  1341. curTempResult.m_cur.Hi =
  1342. (DWORD)curTemp.m_cur.Hi / (nTempOp >> wScaleOp);
  1343. // Scale back to get correct result and remainder
  1344. RSHIFT_UCUR(curTemp, wShift);
  1345. wShift = (WORD)(wShift - wScaleOp);
  1346. RSHIFT_UCUR(curTempResult, wShift);
  1347. // Now calculate result and remainder
  1348. curResult += curTempResult;
  1349. curTemp -= curTempResult * nTempOp;
  1350. }
  1351. // Compute result sign
  1352. if ((m_cur.Hi ^ nOperand) & 0x80000000)
  1353. curResult = -curResult;
  1354. return curResult;
  1355. }
  1356. void COleCurrency::SetCurrency(long nUnits, long nFractionalUnits)
  1357. {
  1358. COleCurrency curUnits; // Initializes to 0
  1359. COleCurrency curFractionalUnits; // Initializes to 0
  1360. // Set temp currency value to Units (need to multiply by 10,000)
  1361. curUnits.m_cur.Lo = (DWORD)labs(nUnits);
  1362. curUnits = curUnits * 10000;
  1363. if (nUnits < 0)
  1364. curUnits = -curUnits;
  1365. curFractionalUnits.m_cur.Lo = (DWORD)labs(nFractionalUnits);
  1366. if (nFractionalUnits < 0)
  1367. curFractionalUnits = -curFractionalUnits;
  1368. // Now add together Units and FractionalUnits
  1369. *this = curUnits + curFractionalUnits;
  1370. SetStatus(valid);
  1371. }
  1372. BOOL COleCurrency::ParseCurrency(LPCTSTR lpszCurrency,
  1373. DWORD dwFlags, LCID lcid)
  1374. {
  1375. USES_CONVERSION;
  1376. CString strCurrency = lpszCurrency;
  1377. SCODE sc;
  1378. if ( FAILED(sc = VarCyFromStr((LPOLESTR)T2COLE(strCurrency),
  1379. lcid, dwFlags, &m_cur)))
  1380. {
  1381. if (sc == DISP_E_TYPEMISMATCH)
  1382. {
  1383. // Can't convert string to CURRENCY, set 0 & invalid
  1384. m_cur.Hi = 0x00000000;
  1385. m_cur.Lo = 0x00000000;
  1386. SetStatus(invalid);
  1387. return FALSE;
  1388. }
  1389. else if (sc == DISP_E_OVERFLOW)
  1390. {
  1391. // Can't convert string to CURRENCY, set max neg & invalid
  1392. m_cur.Hi = 0x80000000;
  1393. m_cur.Lo = 0x00000000;
  1394. SetStatus(invalid);
  1395. return FALSE;
  1396. }
  1397. else
  1398. {
  1399. TRACE0("\nCOleCurrency VarCyFromStr call failed.\n\t");
  1400. if (sc == E_OUTOFMEMORY)
  1401. AfxThrowMemoryException();
  1402. else
  1403. AfxThrowOleException(sc);
  1404. }
  1405. }
  1406. SetStatus(valid);
  1407. return TRUE;
  1408. }
  1409. CString COleCurrency::Format(DWORD dwFlags, LCID lcid) const
  1410. {
  1411. USES_CONVERSION;
  1412. CString strCur;
  1413. // If null, return empty string
  1414. if (GetStatus() == null)
  1415. return strCur;
  1416. // If invalid, return Currency resource string
  1417. if (GetStatus() == invalid)
  1418. {
  1419. VERIFY(strCur.LoadString(AFX_IDS_INVALID_CURRENCY));
  1420. return strCur;
  1421. }
  1422. COleVariant var;
  1423. // Don't need to trap error. Should not fail due to type mismatch
  1424. CheckError(VarBstrFromCy(m_cur, lcid, dwFlags, &V_BSTR(&var)));
  1425. var.vt = VT_BSTR;
  1426. return OLE2CT(V_BSTR(&var));
  1427. }
  1428. // serialization
  1429. #ifdef _DEBUG
  1430. CDumpContext& AFXAPI operator<<(CDumpContext& dc, COleCurrency curSrc)
  1431. {
  1432. dc << "\nCOleCurrency Object:";
  1433. dc << "\n\tm_status = " << (long)curSrc.m_status;
  1434. COleVariant var(curSrc);
  1435. var.ChangeType(VT_CY);
  1436. return dc << "\n\tCurrency = " << (LPCTSTR)var.bstrVal;
  1437. }
  1438. #endif // _DEBUG
  1439. #ifdef _with_archive_
  1440. CArchive& AFXAPI operator<<(CArchive& ar, COleCurrency curSrc)
  1441. {
  1442. ar << (long)curSrc.m_status;
  1443. ar << curSrc.m_cur.Hi;
  1444. return ar << curSrc.m_cur.Lo;
  1445. }
  1446. CArchive& AFXAPI operator>>(CArchive& ar, COleCurrency& curSrc)
  1447. {
  1448. ar >> (long&)curSrc.m_status;
  1449. ar >> curSrc.m_cur.Hi;
  1450. return ar >> curSrc.m_cur.Lo;
  1451. }
  1452. #endif //_with_archive_
  1453. /////////////////////////////////////////////////////////////////////////////
  1454. // COleDateTime class HELPER definitions
  1455. // Verifies will fail if the needed buffer size is too large
  1456. #define MAX_TIME_BUFFER_SIZE 128 // matches that in timecore.cpp
  1457. #define MIN_DATE (-657434L) // about year 100
  1458. #define MAX_DATE 2958465L // about year 9999
  1459. // Half a second, expressed in days
  1460. #define HALF_SECOND (1.0/172800.0)
  1461. // One-based array of days in year at month start
  1462. static int rgMonthDays[13] =
  1463. {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
  1464. static BOOL OleDateFromTm(WORD wYear, WORD wMonth, WORD wDay,
  1465. WORD wHour, WORD wMinute, WORD wSecond, DATE& dtDest);
  1466. static BOOL TmFromOleDate(DATE dtSrc, struct tm& tmDest);
  1467. static void TmConvertToStandardFormat(struct tm& tmSrc);
  1468. static double DoubleFromDate(DATE dt);
  1469. static DATE DateFromDouble(double dbl);
  1470. /////////////////////////////////////////////////////////////////////////////
  1471. // COleDateTime class
  1472. COleDateTime PASCAL COleDateTime::GetCurrentTime()
  1473. {
  1474. return COleDateTime(::time(NULL));
  1475. }
  1476. int COleDateTime::GetYear() const
  1477. {
  1478. struct tm tmTemp;
  1479. if (GetStatus() == valid && TmFromOleDate(m_dt, tmTemp))
  1480. return tmTemp.tm_year;
  1481. else
  1482. return AFX_OLE_DATETIME_ERROR;
  1483. }
  1484. int COleDateTime::GetMonth() const
  1485. {
  1486. struct tm tmTemp;
  1487. if (GetStatus() == valid && TmFromOleDate(m_dt, tmTemp))
  1488. return tmTemp.tm_mon;
  1489. else
  1490. return AFX_OLE_DATETIME_ERROR;
  1491. }
  1492. int COleDateTime::GetDay() const
  1493. {
  1494. struct tm tmTemp;
  1495. if (GetStatus() == valid && TmFromOleDate(m_dt, tmTemp))
  1496. return tmTemp.tm_mday;
  1497. else
  1498. return AFX_OLE_DATETIME_ERROR;
  1499. }
  1500. int COleDateTime::GetHour() const
  1501. {
  1502. struct tm tmTemp;
  1503. if (GetStatus() == valid && TmFromOleDate(m_dt, tmTemp))
  1504. return tmTemp.tm_hour;
  1505. else
  1506. return AFX_OLE_DATETIME_ERROR;
  1507. }
  1508. int COleDateTime::GetMinute() const
  1509. {
  1510. struct tm tmTemp;
  1511. if (GetStatus() == valid && TmFromOleDate(m_dt, tmTemp))
  1512. return tmTemp.tm_min;
  1513. else
  1514. return AFX_OLE_DATETIME_ERROR;
  1515. }
  1516. int COleDateTime::GetSecond() const
  1517. {
  1518. struct tm tmTemp;
  1519. if (GetStatus() == valid && TmFromOleDate(m_dt, tmTemp))
  1520. return tmTemp.tm_sec;
  1521. else
  1522. return AFX_OLE_DATETIME_ERROR;
  1523. }
  1524. int COleDateTime::GetDayOfWeek() const
  1525. {
  1526. struct tm tmTemp;
  1527. if (GetStatus() == valid && TmFromOleDate(m_dt, tmTemp))
  1528. return tmTemp.tm_wday;
  1529. else
  1530. return AFX_OLE_DATETIME_ERROR;
  1531. }
  1532. int COleDateTime::GetDayOfYear() const
  1533. {
  1534. struct tm tmTemp;
  1535. if (GetStatus() == valid && TmFromOleDate(m_dt, tmTemp))
  1536. return tmTemp.tm_yday;
  1537. else
  1538. return AFX_OLE_DATETIME_ERROR;
  1539. }
  1540. const COleDateTime& COleDateTime::operator=(const VARIANT& varSrc)
  1541. {
  1542. if (varSrc.vt != VT_DATE)
  1543. {
  1544. TRY
  1545. {
  1546. COleVariant varTemp(varSrc);
  1547. varTemp.ChangeType(VT_DATE);
  1548. m_dt = varTemp.date;
  1549. SetStatus(valid);
  1550. }
  1551. // Catch COleException from ChangeType, but not CMemoryException
  1552. CATCH(COleException, e)
  1553. {
  1554. // Not able to convert VARIANT to DATE
  1555. DELETE_EXCEPTION(e);
  1556. m_dt = 0;
  1557. SetStatus(invalid);
  1558. }
  1559. END_CATCH
  1560. }
  1561. else
  1562. {
  1563. m_dt = varSrc.date;
  1564. SetStatus(valid);
  1565. }
  1566. return *this;
  1567. }
  1568. const COleDateTime& COleDateTime::operator=(DATE dtSrc)
  1569. {
  1570. m_dt = dtSrc;
  1571. SetStatus(valid);
  1572. return *this;
  1573. }
  1574. const COleDateTime& COleDateTime::operator=(const time_t& timeSrc)
  1575. {
  1576. // Convert time_t to struct tm
  1577. tm *ptm = localtime(&timeSrc);
  1578. if (ptm != NULL)
  1579. {
  1580. m_status = OleDateFromTm((WORD)ptm->tm_year + 1900,
  1581. (WORD)(ptm->tm_mon + 1), (WORD)ptm->tm_mday,
  1582. (WORD)ptm->tm_hour, (WORD)ptm->tm_min,
  1583. (WORD)ptm->tm_sec, m_dt) ? valid : invalid;
  1584. }
  1585. else
  1586. {
  1587. // Local time must have failed (timsSrc before 1/1/70 12am)
  1588. SetStatus(invalid);
  1589. ASSERT(FALSE);
  1590. }
  1591. return *this;
  1592. }
  1593. const COleDateTime& COleDateTime::operator=(const SYSTEMTIME& systimeSrc)
  1594. {
  1595. m_status = OleDateFromTm(systimeSrc.wYear, systimeSrc.wMonth,
  1596. systimeSrc.wDay, systimeSrc.wHour, systimeSrc.wMinute,
  1597. systimeSrc.wSecond, m_dt) ? valid : invalid;
  1598. return *this;
  1599. }
  1600. const COleDateTime& COleDateTime::operator=(const FILETIME& filetimeSrc)
  1601. {
  1602. // Assume UTC FILETIME, so convert to LOCALTIME
  1603. FILETIME filetimeLocal;
  1604. if (!FileTimeToLocalFileTime( &filetimeSrc, &filetimeLocal))
  1605. {
  1606. #ifdef _DEBUG
  1607. DWORD dwError = GetLastError();
  1608. TRACE1("\nFileTimeToLocalFileTime failed. Error = %lu.\n\t", dwError);
  1609. #endif // _DEBUG
  1610. m_status = invalid;
  1611. }
  1612. else
  1613. {
  1614. // Take advantage of SYSTEMTIME -> FILETIME conversion
  1615. SYSTEMTIME systime;
  1616. m_status = FileTimeToSystemTime(&filetimeLocal, &systime) ?
  1617. valid : invalid;
  1618. // At this point systime should always be valid, but...
  1619. if (GetStatus() == valid)
  1620. {
  1621. m_status = OleDateFromTm(systime.wYear, systime.wMonth,
  1622. systime.wDay, systime.wHour, systime.wMinute,
  1623. systime.wSecond, m_dt) ? valid : invalid;
  1624. }
  1625. }
  1626. return *this;
  1627. }
  1628. BOOL COleDateTime::operator<(const COleDateTime& date) const
  1629. {
  1630. ASSERT(GetStatus() == valid);
  1631. ASSERT(date.GetStatus() == valid);
  1632. // Handle negative dates
  1633. return DoubleFromDate(m_dt) < DoubleFromDate(date.m_dt);
  1634. }
  1635. BOOL COleDateTime::operator>(const COleDateTime& date) const
  1636. { ASSERT(GetStatus() == valid);
  1637. ASSERT(date.GetStatus() == valid);
  1638. // Handle negative dates
  1639. return DoubleFromDate(m_dt) > DoubleFromDate(date.m_dt);
  1640. }
  1641. BOOL COleDateTime::operator<=(const COleDateTime& date) const
  1642. {
  1643. ASSERT(GetStatus() == valid);
  1644. ASSERT(date.GetStatus() == valid);
  1645. // Handle negative dates
  1646. return DoubleFromDate(m_dt) <= DoubleFromDate(date.m_dt);
  1647. }
  1648. BOOL COleDateTime::operator>=(const COleDateTime& date) const
  1649. {
  1650. ASSERT(GetStatus() == valid);
  1651. ASSERT(date.GetStatus() == valid);
  1652. // Handle negative dates
  1653. return DoubleFromDate(m_dt) >= DoubleFromDate(date.m_dt);
  1654. }
  1655. COleDateTime COleDateTime::operator+(const COleDateTimeSpan& dateSpan) const
  1656. {
  1657. COleDateTime dateResult; // Initializes m_status to valid
  1658. // If either operand NULL, result NULL
  1659. if (GetStatus() == null || dateSpan.GetStatus() == null)
  1660. {
  1661. dateResult.SetStatus(null);
  1662. return dateResult;
  1663. }
  1664. // If either operand invalid, result invalid
  1665. if (GetStatus() == invalid || dateSpan.GetStatus() == invalid)
  1666. {
  1667. dateResult.SetStatus(invalid);
  1668. return dateResult;
  1669. }
  1670. // Compute the actual date difference by adding underlying dates
  1671. dateResult = DateFromDouble(DoubleFromDate(m_dt) + dateSpan.m_span);
  1672. // Validate within range
  1673. dateResult.CheckRange();
  1674. return dateResult;
  1675. }
  1676. COleDateTime COleDateTime::operator-(const COleDateTimeSpan& dateSpan) const
  1677. {
  1678. COleDateTime dateResult; // Initializes m_status to valid
  1679. // If either operand NULL, result NULL
  1680. if (GetStatus() == null || dateSpan.GetStatus() == null)
  1681. {
  1682. dateResult.SetStatus(null);
  1683. return dateResult;
  1684. }
  1685. // If either operand invalid, result invalid
  1686. if (GetStatus() == invalid || dateSpan.GetStatus() == invalid)
  1687. {
  1688. dateResult.SetStatus(invalid);
  1689. return dateResult;
  1690. }
  1691. // Compute the actual date difference by subtracting underlying dates
  1692. dateResult = DateFromDouble(DoubleFromDate(m_dt) - dateSpan.m_span);
  1693. // Validate within range
  1694. dateResult.CheckRange();
  1695. return dateResult;
  1696. }
  1697. COleDateTimeSpan COleDateTime::operator-(const COleDateTime& date) const
  1698. {
  1699. COleDateTimeSpan spanResult;
  1700. // If either operand NULL, result NULL
  1701. if (GetStatus() == null || date.GetStatus() == null)
  1702. {
  1703. spanResult.SetStatus(COleDateTimeSpan::null);
  1704. return spanResult;
  1705. }
  1706. // If either operand invalid, result invalid
  1707. if (GetStatus() == invalid || date.GetStatus() == invalid)
  1708. {
  1709. spanResult.SetStatus(COleDateTimeSpan::invalid);
  1710. return spanResult;
  1711. }
  1712. // Return result (span can't be invalid, so don't check range)
  1713. return DoubleFromDate(m_dt) - DoubleFromDate(date.m_dt);
  1714. }
  1715. BOOL COleDateTime::SetDateTime(int nYear, int nMonth, int nDay,
  1716. int nHour, int nMin, int nSec)
  1717. {
  1718. return m_status = OleDateFromTm((WORD)nYear, (WORD)nMonth,
  1719. (WORD)nDay, (WORD)nHour, (WORD)nMin, (WORD)nSec, m_dt) ?
  1720. valid : invalid;
  1721. }
  1722. BOOL COleDateTime::ParseDateTime(LPCTSTR lpszDate, DWORD dwFlags, LCID lcid)
  1723. {
  1724. USES_CONVERSION;
  1725. CString strDate = lpszDate;
  1726. SCODE sc;
  1727. if (FAILED(sc = VarDateFromStr((LPOLESTR)T2COLE(strDate), lcid,
  1728. dwFlags, &m_dt)))
  1729. {
  1730. if (sc == DISP_E_TYPEMISMATCH)
  1731. {
  1732. // Can't convert string to date, set 0 and invalidate
  1733. m_dt = 0;
  1734. SetStatus(invalid);
  1735. return FALSE;
  1736. }
  1737. else if (sc == DISP_E_OVERFLOW)
  1738. {
  1739. // Can't convert string to date, set -1 and invalidate
  1740. m_dt = -1;
  1741. SetStatus(invalid);
  1742. return FALSE;
  1743. }
  1744. else
  1745. {
  1746. TRACE0("\nCOleDateTime VarDateFromStr call failed.\n\t");
  1747. if (sc == E_OUTOFMEMORY)
  1748. AfxThrowMemoryException();
  1749. else
  1750. AfxThrowOleException(sc);
  1751. }
  1752. }
  1753. SetStatus(valid);
  1754. return TRUE;
  1755. }
  1756. CString COleDateTime::Format(DWORD dwFlags, LCID lcid) const
  1757. {
  1758. USES_CONVERSION;
  1759. CString strDate;
  1760. // If null, return empty string
  1761. if (GetStatus() == null)
  1762. return strDate;
  1763. // If invalid, return DateTime resource string
  1764. if (GetStatus() == invalid)
  1765. {
  1766. VERIFY(strDate.LoadString(AFX_IDS_INVALID_DATETIME));
  1767. return strDate;
  1768. }
  1769. COleVariant var;
  1770. // Don't need to trap error. Should not fail due to type mismatch
  1771. CheckError(VarBstrFromDate(m_dt, lcid, dwFlags, &V_BSTR(&var)));
  1772. var.vt = VT_BSTR;
  1773. return OLE2CT(V_BSTR(&var));
  1774. }
  1775. CString COleDateTime::Format(LPCTSTR pFormat) const
  1776. {
  1777. CString strDate;
  1778. struct tm tmTemp;
  1779. // If null, return empty string
  1780. if (GetStatus() == null)
  1781. return strDate;
  1782. // If invalid, return DateTime resource string
  1783. if (GetStatus() == invalid || !TmFromOleDate(m_dt, tmTemp))
  1784. {
  1785. VERIFY(strDate.LoadString(AFX_IDS_INVALID_DATETIME));
  1786. return strDate;
  1787. }
  1788. // Convert tm from afx internal format to standard format
  1789. TmConvertToStandardFormat(tmTemp);
  1790. // Fill in the buffer, disregard return value as it's not necessary
  1791. LPTSTR lpszTemp = strDate.GetBufferSetLength(MAX_TIME_BUFFER_SIZE);
  1792. _tcsftime(lpszTemp, strDate.GetLength(), pFormat, &tmTemp);
  1793. strDate.ReleaseBuffer();
  1794. return strDate;
  1795. }
  1796. CString COleDateTime::Format(UINT nFormatID) const
  1797. {
  1798. CString strFormat;
  1799. VERIFY(strFormat.LoadString(nFormatID) != 0);
  1800. return Format(strFormat);
  1801. }
  1802. void COleDateTime::CheckRange()
  1803. {
  1804. if (m_dt > MAX_DATE || m_dt < MIN_DATE) // about year 100 to about 9999
  1805. SetStatus(invalid);
  1806. }
  1807. // serialization
  1808. #ifdef _DEBUG
  1809. CDumpContext& AFXAPI operator<<(CDumpContext& dc, COleDateTime dateSrc)
  1810. {
  1811. dc << "\nCOleDateTime Object:";
  1812. dc << "\n\tm_status = " << (long)dateSrc.m_status;
  1813. COleVariant var(dateSrc);
  1814. var.ChangeType(VT_BSTR);
  1815. return dc << "\n\tdate = " << (LPCTSTR)var.bstrVal;
  1816. }
  1817. #endif // _DEBUG
  1818. #ifdef _with_archive_
  1819. CArchive& AFXAPI operator<<(CArchive& ar, COleDateTime dateSrc)
  1820. {
  1821. ar << (long)dateSrc.m_status;
  1822. return ar << dateSrc.m_dt;
  1823. }
  1824. CArchive& AFXAPI operator>>(CArchive& ar, COleDateTime& dateSrc)
  1825. {
  1826. ar >> (long&)dateSrc.m_status;
  1827. return ar >> dateSrc.m_dt;
  1828. }
  1829. #endif //_with_archive_
  1830. /////////////////////////////////////////////////////////////////////////////
  1831. // COleDateTimeSpan class helpers
  1832. #define MAX_DAYS_IN_SPAN 3615897L
  1833. /////////////////////////////////////////////////////////////////////////////
  1834. // COleDateTimeSpan class
  1835. long COleDateTimeSpan::GetHours() const
  1836. {
  1837. ASSERT(GetStatus() == valid);
  1838. double dblTemp;
  1839. // Truncate days and scale up
  1840. dblTemp = modf(m_span, &dblTemp);
  1841. return (long)(dblTemp * 24);
  1842. }
  1843. long COleDateTimeSpan::GetMinutes() const
  1844. {
  1845. ASSERT(GetStatus() == valid);
  1846. double dblTemp;
  1847. // Truncate hours and scale up
  1848. dblTemp = modf(m_span * 24, &dblTemp);
  1849. return (long)(dblTemp * 60);
  1850. }
  1851. long COleDateTimeSpan::GetSeconds() const
  1852. {
  1853. ASSERT(GetStatus() == valid);
  1854. double dblTemp;
  1855. // Truncate minutes and scale up
  1856. dblTemp = modf(m_span * 24 * 60, &dblTemp);
  1857. return (long)(dblTemp * 60);
  1858. }
  1859. const COleDateTimeSpan& COleDateTimeSpan::operator=(double dblSpanSrc)
  1860. {
  1861. m_span = dblSpanSrc;
  1862. SetStatus(valid);
  1863. return *this;
  1864. }
  1865. const COleDateTimeSpan& COleDateTimeSpan::operator=(const COleDateTimeSpan& dateSpanSrc)
  1866. {
  1867. m_span = dateSpanSrc.m_span;
  1868. m_status = dateSpanSrc.m_status;
  1869. return *this;
  1870. }
  1871. COleDateTimeSpan COleDateTimeSpan::operator+(const COleDateTimeSpan& dateSpan) const
  1872. {
  1873. COleDateTimeSpan dateSpanTemp;
  1874. // If either operand Null, result Null
  1875. if (GetStatus() == null || dateSpan.GetStatus() == null)
  1876. {
  1877. dateSpanTemp.SetStatus(null);
  1878. return dateSpanTemp;
  1879. }
  1880. // If either operand Invalid, result Invalid
  1881. if (GetStatus() == invalid || dateSpan.GetStatus() == invalid)
  1882. {
  1883. dateSpanTemp.SetStatus(invalid);
  1884. return dateSpanTemp;
  1885. }
  1886. // Add spans and validate within legal range
  1887. dateSpanTemp.m_span = m_span + dateSpan.m_span;
  1888. dateSpanTemp.CheckRange();
  1889. return dateSpanTemp;
  1890. }
  1891. COleDateTimeSpan COleDateTimeSpan::operator-(const COleDateTimeSpan& dateSpan) const
  1892. {
  1893. COleDateTimeSpan dateSpanTemp;
  1894. // If either operand Null, result Null
  1895. if (GetStatus() == null || dateSpan.GetStatus() == null)
  1896. {
  1897. dateSpanTemp.SetStatus(null);
  1898. return dateSpanTemp;
  1899. }
  1900. // If either operand Invalid, result Invalid
  1901. if (GetStatus() == invalid || dateSpan.GetStatus() == invalid)
  1902. {
  1903. dateSpanTemp.SetStatus(invalid);
  1904. return dateSpanTemp;
  1905. }
  1906. // Subtract spans and validate within legal range
  1907. dateSpanTemp.m_span = m_span - dateSpan.m_span;
  1908. dateSpanTemp.CheckRange();
  1909. return dateSpanTemp;
  1910. }
  1911. void COleDateTimeSpan::SetDateTimeSpan(
  1912. long lDays, int nHours, int nMins, int nSecs)
  1913. {
  1914. // Set date span by breaking into fractional days (all input ranges valid)
  1915. m_span = lDays + ((double)nHours)/24 + ((double)nMins)/(24*60) +
  1916. ((double)nSecs)/(24*60*60);
  1917. SetStatus(valid);
  1918. }
  1919. CString COleDateTimeSpan::Format(LPCTSTR pFormat) const
  1920. {
  1921. CString strSpan;
  1922. struct tm tmTemp;
  1923. // If null, return empty string
  1924. if (GetStatus() == null)
  1925. return strSpan;
  1926. // If invalid, return DateTimeSpan resource string
  1927. if (GetStatus() == invalid || !TmFromOleDate(m_span, tmTemp))
  1928. {
  1929. VERIFY(strSpan.LoadString(AFX_IDS_INVALID_DATETIMESPAN));
  1930. return strSpan;
  1931. }
  1932. // Convert tm from afx internal format to standard format
  1933. TmConvertToStandardFormat(tmTemp);
  1934. // Fill in the buffer, disregard return value as it's not necessary
  1935. LPTSTR lpszTemp = strSpan.GetBufferSetLength(MAX_TIME_BUFFER_SIZE);
  1936. _tcsftime(lpszTemp, strSpan.GetLength(), pFormat, &tmTemp);
  1937. strSpan.ReleaseBuffer();
  1938. return strSpan;
  1939. }
  1940. CString COleDateTimeSpan::Format(UINT nFormatID) const
  1941. {
  1942. CString strFormat;
  1943. VERIFY(strFormat.LoadString(nFormatID) != 0);
  1944. return Format(strFormat);
  1945. }
  1946. void COleDateTimeSpan::CheckRange()
  1947. {
  1948. if(m_span < -MAX_DAYS_IN_SPAN || m_span > MAX_DAYS_IN_SPAN)
  1949. SetStatus(invalid);
  1950. }
  1951. // serialization
  1952. #ifdef _DEBUG
  1953. CDumpContext& AFXAPI operator<<(CDumpContext& dc, COleDateTimeSpan dateSpanSrc)
  1954. {
  1955. dc << "\nCOleDateTimeSpan Object:";
  1956. dc << "\n\tm_status = " << (long)dateSpanSrc.m_status;
  1957. COleVariant var(dateSpanSrc.m_span);
  1958. var.ChangeType(VT_BSTR);
  1959. return dc << "\n\tdateSpan = " << (LPCTSTR)var.bstrVal;
  1960. }
  1961. #endif // _DEBUG
  1962. #ifdef _with_archive_
  1963. CArchive& AFXAPI operator<<(CArchive& ar, COleDateTimeSpan dateSpanSrc)
  1964. {
  1965. ar << (long)dateSpanSrc.m_status;
  1966. return ar << dateSpanSrc.m_span;
  1967. }
  1968. CArchive& AFXAPI operator>>(CArchive& ar, COleDateTimeSpan& dateSpanSrc)
  1969. {
  1970. ar >> (long&)dateSpanSrc.m_status;
  1971. return ar >> dateSpanSrc.m_span;
  1972. }
  1973. #endif //_with_archive_
  1974. /////////////////////////////////////////////////////////////////////////////
  1975. // COleDateTime class HELPERS - implementation
  1976. BOOL OleDateFromTm(WORD wYear, WORD wMonth, WORD wDay,
  1977. WORD wHour, WORD wMinute, WORD wSecond, DATE& dtDest)
  1978. {
  1979. // Validate year and month (ignore day of week and milliseconds)
  1980. if (wYear > 9999 || wMonth < 1 || wMonth > 12)
  1981. return FALSE;
  1982. // Check for leap year and set the number of days in the month
  1983. BOOL bLeapYear = ((wYear & 3) == 0) &&
  1984. ((wYear % 100) != 0 || (wYear % 400) == 0);
  1985. int nDaysInMonth =
  1986. rgMonthDays[wMonth] - rgMonthDays[wMonth-1] +
  1987. ((bLeapYear && wDay == 29 && wMonth == 2) ? 1 : 0);
  1988. // Finish validating the date
  1989. if (wDay < 1 || wDay > nDaysInMonth ||
  1990. wHour > 23 || wMinute > 59 ||
  1991. wSecond > 59)
  1992. {
  1993. return FALSE;
  1994. }
  1995. // Cache the date in days and time in fractional days
  1996. long nDate;
  1997. double dblTime;
  1998. //It is a valid date; make Jan 1, 1AD be 1
  1999. nDate = wYear*365L + wYear/4 - wYear/100 + wYear/400 +
  2000. rgMonthDays[wMonth-1] + wDay;
  2001. // If leap year and it's before March, subtract 1:
  2002. if (wMonth <= 2 && bLeapYear)
  2003. --nDate;
  2004. // Offset so that 12/30/1899 is 0
  2005. nDate -= 693959L;
  2006. dblTime = (((long)wHour * 3600L) + // hrs in seconds
  2007. ((long)wMinute * 60L) + // mins in seconds
  2008. ((long)wSecond)) / 86400.;
  2009. dtDest = (double) nDate + ((nDate >= 0) ? dblTime : -dblTime);
  2010. return TRUE;
  2011. }
  2012. BOOL TmFromOleDate(DATE dtSrc, struct tm& tmDest)
  2013. {
  2014. // The legal range does not actually span year 0 to 9999.
  2015. if (dtSrc > MAX_DATE || dtSrc < MIN_DATE) // about year 100 to about 9999
  2016. return FALSE;
  2017. long nDays; // Number of days since Dec. 30, 1899
  2018. long nDaysAbsolute; // Number of days since 1/1/0
  2019. long nSecsInDay; // Time in seconds since midnight
  2020. long nMinutesInDay; // Minutes in day
  2021. long n400Years; // Number of 400 year increments since 1/1/0
  2022. long n400Century; // Century within 400 year block (0,1,2 or 3)
  2023. long n4Years; // Number of 4 year increments since 1/1/0
  2024. long n4Day; // Day within 4 year block
  2025. // (0 is 1/1/yr1, 1460 is 12/31/yr4)
  2026. long n4Yr; // Year within 4 year block (0,1,2 or 3)
  2027. BOOL bLeap4 = TRUE; // TRUE if 4 year block includes leap year
  2028. double dblDate = dtSrc; // tempory serial date
  2029. // If a valid date, then this conversion should not overflow
  2030. nDays = (long)dblDate;
  2031. // Round to the second
  2032. dblDate += ((dtSrc > 0.0) ? HALF_SECOND : -HALF_SECOND);
  2033. nDaysAbsolute = (long)dblDate + 693959L; // Add days from 1/1/0 to 12/30/1899
  2034. dblDate = fabs(dblDate);
  2035. nSecsInDay = (long)((dblDate - floor(dblDate)) * 86400.);
  2036. // Calculate the day of week (sun=1, mon=2...)
  2037. // -1 because 1/1/0 is Sat. +1 because we want 1-based
  2038. tmDest.tm_wday = (int)((nDaysAbsolute - 1) % 7L) + 1;
  2039. // Leap years every 4 yrs except centuries not multiples of 400.
  2040. n400Years = (long)(nDaysAbsolute / 146097L);
  2041. // Set nDaysAbsolute to day within 400-year block
  2042. nDaysAbsolute %= 146097L;
  2043. // -1 because first century has extra day
  2044. n400Century = (long)((nDaysAbsolute - 1) / 36524L);
  2045. // Non-leap century
  2046. if (n400Century != 0)
  2047. {
  2048. // Set nDaysAbsolute to day within century
  2049. nDaysAbsolute = (nDaysAbsolute - 1) % 36524L;
  2050. // +1 because 1st 4 year increment has 1460 days
  2051. n4Years = (long)((nDaysAbsolute + 1) / 1461L);
  2052. if (n4Years != 0)
  2053. n4Day = (long)((nDaysAbsolute + 1) % 1461L);
  2054. else
  2055. {
  2056. bLeap4 = FALSE;
  2057. n4Day = (long)nDaysAbsolute;
  2058. }
  2059. }
  2060. else
  2061. {
  2062. // Leap century - not special case!
  2063. n4Years = (long)(nDaysAbsolute / 1461L);
  2064. n4Day = (long)(nDaysAbsolute % 1461L);
  2065. }
  2066. if (bLeap4)
  2067. {
  2068. // -1 because first year has 366 days
  2069. n4Yr = (n4Day - 1) / 365;
  2070. if (n4Yr != 0)
  2071. n4Day = (n4Day - 1) % 365;
  2072. }
  2073. else
  2074. {
  2075. n4Yr = n4Day / 365;
  2076. n4Day %= 365;
  2077. }
  2078. // n4Day is now 0-based day of year. Save 1-based day of year, year number
  2079. tmDest.tm_yday = (int)n4Day + 1;
  2080. tmDest.tm_year = n400Years * 400 + n400Century * 100 + n4Years * 4 + n4Yr;
  2081. // Handle leap year: before, on, and after Feb. 29.
  2082. if (n4Yr == 0 && bLeap4)
  2083. {
  2084. // Leap Year
  2085. if (n4Day == 59)
  2086. {
  2087. /* Feb. 29 */
  2088. tmDest.tm_mon = 2;
  2089. tmDest.tm_mday = 29;
  2090. goto DoTime;
  2091. }
  2092. // Pretend it's not a leap year for month/day comp.
  2093. if (n4Day >= 60)
  2094. --n4Day;
  2095. }
  2096. // Make n4DaY a 1-based day of non-leap year and compute
  2097. // month/day for everything but Feb. 29.
  2098. ++n4Day;
  2099. // Month number always >= n/32, so save some loop time */
  2100. for (tmDest.tm_mon = (n4Day >> 5) + 1;
  2101. n4Day > rgMonthDays[tmDest.tm_mon]; tmDest.tm_mon++);
  2102. tmDest.tm_mday = (int)(n4Day - rgMonthDays[tmDest.tm_mon-1]);
  2103. DoTime:
  2104. if (nSecsInDay == 0)
  2105. tmDest.tm_hour = tmDest.tm_min = tmDest.tm_sec = 0;
  2106. else
  2107. {
  2108. tmDest.tm_sec = (int)nSecsInDay % 60L;
  2109. nMinutesInDay = nSecsInDay / 60L;
  2110. tmDest.tm_min = (int)nMinutesInDay % 60;
  2111. tmDest.tm_hour = (int)nMinutesInDay / 60;
  2112. }
  2113. return TRUE;
  2114. }
  2115. void TmConvertToStandardFormat(struct tm& tmSrc)
  2116. {
  2117. // Convert afx internal tm to format expected by runtimes (_tcsftime, etc)
  2118. tmSrc.tm_year -= 1900; // year is based on 1900
  2119. tmSrc.tm_mon -= 1; // month of year is 0-based
  2120. tmSrc.tm_wday -= 1; // day of week is 0-based
  2121. tmSrc.tm_yday -= 1; // day of year is 0-based
  2122. }
  2123. double DoubleFromDate(DATE dt)
  2124. {
  2125. // No problem if positive
  2126. if (dt >= 0)
  2127. return dt;
  2128. // If negative, must convert since negative dates not continuous
  2129. // (examples: -1.25 to -.75, -1.50 to -.50, -1.75 to -.25)
  2130. double temp = ceil(dt);
  2131. return temp - (dt - temp);
  2132. }
  2133. DATE DateFromDouble(double dbl)
  2134. {
  2135. // No problem if positive
  2136. if (dbl >= 0)
  2137. return dbl;
  2138. // If negative, must convert since negative dates not continuous
  2139. // (examples: -.75 to -1.25, -.50 to -1.50, -.25 to -1.75)
  2140. double temp = floor(dbl); // dbl is now whole part
  2141. return temp + (temp - dbl);
  2142. }
  2143. /////////////////////////////////////////////////////////////////////////////
  2144. // COleSafeArray class
  2145. COleSafeArray::COleSafeArray(const SAFEARRAY& saSrc, VARTYPE vtSrc)
  2146. {
  2147. AfxSafeArrayInit(this);
  2148. vt = vtSrc | VT_ARRAY;
  2149. CheckError(::SafeArrayCopy((LPSAFEARRAY)&saSrc, &parray));
  2150. m_dwDims = GetDim();
  2151. m_dwElementSize = GetElemSize();
  2152. }
  2153. COleSafeArray::COleSafeArray(LPCSAFEARRAY pSrc, VARTYPE vtSrc)
  2154. {
  2155. AfxSafeArrayInit(this);
  2156. vt = vtSrc | VT_ARRAY;
  2157. CheckError(::SafeArrayCopy((LPSAFEARRAY)pSrc, &parray));
  2158. m_dwDims = GetDim();
  2159. m_dwElementSize = GetElemSize();
  2160. }
  2161. COleSafeArray::COleSafeArray(const COleSafeArray& saSrc)
  2162. {
  2163. AfxSafeArrayInit(this);
  2164. *this = saSrc;
  2165. m_dwDims = GetDim();
  2166. m_dwElementSize = GetElemSize();
  2167. }
  2168. COleSafeArray::COleSafeArray(const VARIANT& varSrc)
  2169. {
  2170. AfxSafeArrayInit(this);
  2171. *this = varSrc;
  2172. m_dwDims = GetDim();
  2173. m_dwElementSize = GetElemSize();
  2174. }
  2175. COleSafeArray::COleSafeArray(LPCVARIANT pSrc)
  2176. {
  2177. AfxSafeArrayInit(this);
  2178. *this = pSrc;
  2179. m_dwDims = GetDim();
  2180. m_dwElementSize = GetElemSize();
  2181. }
  2182. // Operations
  2183. void COleSafeArray::Attach(VARIANT& varSrc)
  2184. {
  2185. ASSERT(varSrc.vt & VT_ARRAY);
  2186. // Free up previous safe array if necessary
  2187. Clear();
  2188. // give control of data to COleSafeArray
  2189. memcpy(this, &varSrc, sizeof(varSrc));
  2190. varSrc.vt = VT_EMPTY;
  2191. }
  2192. VARIANT COleSafeArray::Detach()
  2193. {
  2194. VARIANT varResult = *this;
  2195. vt = VT_EMPTY;
  2196. return varResult;
  2197. }
  2198. // Assignment operators
  2199. COleSafeArray& COleSafeArray::operator=(const COleSafeArray& saSrc)
  2200. {
  2201. ASSERT(saSrc.vt & VT_ARRAY);
  2202. CheckError(::VariantCopy(this, (LPVARIANT)&saSrc));
  2203. return *this;
  2204. }
  2205. COleSafeArray& COleSafeArray::operator=(const VARIANT& varSrc)
  2206. {
  2207. ASSERT(varSrc.vt & VT_ARRAY);
  2208. CheckError(::VariantCopy(this, (LPVARIANT)&varSrc));
  2209. return *this;
  2210. }
  2211. COleSafeArray& COleSafeArray::operator=(LPCVARIANT pSrc)
  2212. {
  2213. ASSERT(pSrc->vt & VT_ARRAY);
  2214. CheckError(::VariantCopy(this, (LPVARIANT)pSrc));
  2215. return *this;
  2216. }
  2217. COleSafeArray& COleSafeArray::operator=(const COleVariant& varSrc)
  2218. {
  2219. ASSERT(varSrc.vt & VT_ARRAY);
  2220. CheckError(::VariantCopy(this, (LPVARIANT)&varSrc));
  2221. return *this;
  2222. }
  2223. // Comparison operators
  2224. BOOL COleSafeArray::operator==(const SAFEARRAY& saSrc) const
  2225. {
  2226. return CompareSafeArrays(parray, (LPSAFEARRAY)&saSrc);
  2227. }
  2228. BOOL COleSafeArray::operator==(LPCSAFEARRAY pSrc) const
  2229. {
  2230. return CompareSafeArrays(parray, (LPSAFEARRAY)pSrc);
  2231. }
  2232. BOOL COleSafeArray::operator==(const COleSafeArray& saSrc) const
  2233. {
  2234. if (vt != saSrc.vt)
  2235. return FALSE;
  2236. return CompareSafeArrays(parray, saSrc.parray);
  2237. }
  2238. BOOL COleSafeArray::operator==(const VARIANT& varSrc) const
  2239. {
  2240. if (vt != varSrc.vt)
  2241. return FALSE;
  2242. return CompareSafeArrays(parray, varSrc.parray);
  2243. }
  2244. BOOL COleSafeArray::operator==(LPCVARIANT pSrc) const
  2245. {
  2246. if (vt != pSrc->vt)
  2247. return FALSE;
  2248. return CompareSafeArrays(parray, pSrc->parray);
  2249. }
  2250. BOOL COleSafeArray::operator==(const COleVariant& varSrc) const
  2251. {
  2252. if (vt != varSrc.vt)
  2253. return FALSE;
  2254. return CompareSafeArrays(parray, varSrc.parray);
  2255. }
  2256. void COleSafeArray::CreateOneDim(VARTYPE vtSrc, DWORD dwElements,
  2257. void* pvSrcData, long nLBound)
  2258. {
  2259. ASSERT(dwElements > 0);
  2260. // Setup the bounds and create the array
  2261. SAFEARRAYBOUND rgsabound;
  2262. rgsabound.cElements = dwElements;
  2263. rgsabound.lLbound = nLBound;
  2264. Create(vtSrc, 1, &rgsabound);
  2265. // Copy over the data if neccessary
  2266. if (pvSrcData != NULL)
  2267. {
  2268. void* pvDestData;
  2269. AccessData(&pvDestData);
  2270. memcpy(pvDestData, pvSrcData, GetElemSize() * dwElements);
  2271. UnaccessData();
  2272. }
  2273. }
  2274. DWORD COleSafeArray::GetOneDimSize()
  2275. {
  2276. ASSERT(GetDim() == 1);
  2277. long nUBound, nLBound;
  2278. GetUBound(1, &nUBound);
  2279. GetLBound(1, &nLBound);
  2280. return nUBound + 1 - nLBound;
  2281. }
  2282. void COleSafeArray::ResizeOneDim(DWORD dwElements)
  2283. {
  2284. ASSERT(GetDim() == 1);
  2285. SAFEARRAYBOUND rgsabound;
  2286. rgsabound.cElements = dwElements;
  2287. rgsabound.lLbound = 0;
  2288. Redim(&rgsabound);
  2289. }
  2290. void COleSafeArray::Create(VARTYPE vtSrc, DWORD dwDims, DWORD* rgElements)
  2291. {
  2292. ASSERT(rgElements != NULL);
  2293. // Allocate and fill proxy array of bounds (with lower bound of zero)
  2294. SAFEARRAYBOUND* rgsaBounds = new SAFEARRAYBOUND[dwDims];
  2295. for (DWORD dwIndex = 0; dwIndex < dwDims; dwIndex++)
  2296. {
  2297. // Assume lower bound is 0 and fill in element count
  2298. rgsaBounds[dwIndex].lLbound = 0;
  2299. rgsaBounds[dwIndex].cElements = rgElements[dwIndex];
  2300. }
  2301. TRY
  2302. {
  2303. Create(vtSrc, dwDims, rgsaBounds);
  2304. }
  2305. CATCH_ALL(e)
  2306. {
  2307. // Must free up memory
  2308. delete [] rgsaBounds;
  2309. THROW_LAST();
  2310. }
  2311. END_CATCH_ALL
  2312. delete [] rgsaBounds;
  2313. }
  2314. void COleSafeArray::Create(VARTYPE vtSrc, DWORD dwDims, SAFEARRAYBOUND* rgsabound)
  2315. {
  2316. ASSERT(dwDims > 0);
  2317. ASSERT(rgsabound != NULL);
  2318. // Validate the VARTYPE for SafeArrayCreate call
  2319. ASSERT(!(vtSrc & VT_ARRAY));
  2320. ASSERT(!(vtSrc & VT_BYREF));
  2321. ASSERT(!(vtSrc & VT_VECTOR));
  2322. ASSERT(vtSrc != VT_EMPTY);
  2323. ASSERT(vtSrc != VT_NULL);
  2324. // Free up old safe array if necessary
  2325. Clear();
  2326. parray = ::SafeArrayCreate(vtSrc, dwDims, rgsabound);
  2327. if (parray == NULL)
  2328. AfxThrowMemoryException();
  2329. vt = unsigned short(vtSrc | VT_ARRAY);
  2330. m_dwDims = dwDims;
  2331. m_dwElementSize = GetElemSize();
  2332. }
  2333. void COleSafeArray::AccessData(void** ppvData)
  2334. {
  2335. CheckError(::SafeArrayAccessData(parray, ppvData));
  2336. }
  2337. void COleSafeArray::UnaccessData()
  2338. {
  2339. CheckError(::SafeArrayUnaccessData(parray));
  2340. }
  2341. void COleSafeArray::AllocData()
  2342. {
  2343. CheckError(::SafeArrayAllocData(parray));
  2344. }
  2345. void COleSafeArray::AllocDescriptor(DWORD dwDims)
  2346. {
  2347. CheckError(::SafeArrayAllocDescriptor(dwDims, &parray));
  2348. }
  2349. void COleSafeArray::Copy(LPSAFEARRAY* ppsa)
  2350. {
  2351. CheckError(::SafeArrayCopy(parray, ppsa));
  2352. }
  2353. void COleSafeArray::GetLBound(DWORD dwDim, long* pLbound)
  2354. {
  2355. CheckError(::SafeArrayGetLBound(parray, dwDim, pLbound));
  2356. }
  2357. void COleSafeArray::GetUBound(DWORD dwDim, long* pUbound)
  2358. {
  2359. CheckError(::SafeArrayGetUBound(parray, dwDim, pUbound));
  2360. }
  2361. void COleSafeArray::GetElement(long* rgIndices, void* pvData)
  2362. {
  2363. CheckError(::SafeArrayGetElement(parray, rgIndices, pvData));
  2364. }
  2365. void COleSafeArray::PtrOfIndex(long* rgIndices, void** ppvData)
  2366. {
  2367. CheckError(::SafeArrayPtrOfIndex(parray, rgIndices, ppvData));
  2368. }
  2369. void COleSafeArray::PutElement(long* rgIndices, void* pvData)
  2370. {
  2371. CheckError(::SafeArrayPutElement(parray, rgIndices, pvData));
  2372. }
  2373. void COleSafeArray::Redim(SAFEARRAYBOUND* psaboundNew)
  2374. {
  2375. CheckError(::SafeArrayRedim(parray, psaboundNew));
  2376. }
  2377. void COleSafeArray::Lock()
  2378. {
  2379. CheckError(::SafeArrayLock(parray));
  2380. }
  2381. void COleSafeArray::Unlock()
  2382. {
  2383. CheckError(::SafeArrayUnlock(parray));
  2384. }
  2385. void COleSafeArray::Destroy()
  2386. {
  2387. CheckError(::SafeArrayDestroy(parray));
  2388. }
  2389. void COleSafeArray::DestroyData()
  2390. {
  2391. CheckError(::SafeArrayDestroyData(parray));
  2392. }
  2393. void COleSafeArray::DestroyDescriptor()
  2394. {
  2395. CheckError(::SafeArrayDestroyDescriptor(parray));
  2396. }
  2397. ///////////////////////////////////////////////////////////////////////////////
  2398. // COleSafeArray Helpers
  2399. void AFXAPI AfxSafeArrayInit(COleSafeArray* psa)
  2400. {
  2401. memset(psa, 0, sizeof(*psa));
  2402. }
  2403. /////////////////////////////////////////////////////////////////////////////
  2404. // Simple field formatting to text item - see dlgdata.cpp for base types
  2405. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, COleDateTime& value)
  2406. {
  2407. HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
  2408. if (pDX->m_bSaveAndValidate)
  2409. {
  2410. int nLen = ::GetWindowTextLength(hWndCtrl);
  2411. CString strTemp;
  2412. ::GetWindowText(hWndCtrl, strTemp.GetBufferSetLength(nLen), nLen+1);
  2413. strTemp.ReleaseBuffer();
  2414. if (!value.ParseDateTime(strTemp)) // throws exception
  2415. {
  2416. // Can't convert string to datetime
  2417. AfxMessageBox(AFX_IDP_PARSE_DATETIME);
  2418. pDX->Fail(); // throws exception
  2419. }
  2420. }
  2421. else
  2422. {
  2423. CString strTemp = value.Format();
  2424. AfxSetWindowText(hWndCtrl, strTemp);
  2425. }
  2426. }
  2427. void AFXAPI DDX_Text(CDataExchange* pDX, int nIDC, COleCurrency& value)
  2428. {
  2429. HWND hWndCtrl = pDX->PrepareEditCtrl(nIDC);
  2430. if (pDX->m_bSaveAndValidate)
  2431. {
  2432. int nLen = ::GetWindowTextLength(hWndCtrl);
  2433. CString strTemp;
  2434. ::GetWindowText(hWndCtrl, strTemp.GetBufferSetLength(nLen), nLen+1);
  2435. strTemp.ReleaseBuffer();
  2436. if (!value.ParseCurrency(strTemp)) // throws exception
  2437. {
  2438. // Can't convert string to currency
  2439. AfxMessageBox(AFX_IDP_PARSE_CURRENCY);
  2440. pDX->Fail(); // throws exception
  2441. }
  2442. }
  2443. else
  2444. {
  2445. CString strTemp = value.Format();
  2446. AfxSetWindowText(hWndCtrl, strTemp);
  2447. }
  2448. }
  2449. /////////////////////////////////////////////////////////////////////////////
  2450. #endif //_CURRENCY_ALSO_
  2451. //+---------------------------------------------------------------------------
  2452. //
  2453. // Method: COleVariant::Save
  2454. //
  2455. // Synopsis: saves a variant to a stream
  2456. //
  2457. // Arguments: [pStm] --
  2458. // [fClearDirty] --
  2459. //
  2460. // Returns:
  2461. //
  2462. // History: 1-15-1997 JohannP (Johann Posch) Created
  2463. //
  2464. // Notes: BUGBUG:NOT COMPLETE!
  2465. //
  2466. //----------------------------------------------------------------------------
  2467. HRESULT COleVariant::Save(IStream *pStm, BOOL fClearDirty)
  2468. {
  2469. LPVARIANT pSrc = (LPVARIANT)this;
  2470. HRESULT hr = NOERROR;
  2471. ULONG cbSaved;
  2472. COleVariant CVar;
  2473. if (pSrc->vt & VT_BYREF || pSrc->vt & VT_ARRAY)
  2474. {
  2475. // No support for VT_BYREF & VT_ARRAY
  2476. pSrc = (LPVARIANT)&CVar;
  2477. }
  2478. // write the variant
  2479. hr = pStm->Write(pSrc, sizeof(VARIANT), &cbSaved);
  2480. TransAssert(( sizeof(VARIANT) == cbSaved));
  2481. if (hr == NOERROR)
  2482. {
  2483. switch (pSrc->vt)
  2484. {
  2485. case VT_DISPATCH:
  2486. TransAssert((FALSE));
  2487. hr = E_FAIL;
  2488. break;
  2489. case VT_UNKNOWN:
  2490. {
  2491. ULONG cbInterface = 0;
  2492. IUnknown *pUnk = pSrc->punkVal;
  2493. hr = CoGetMarshalSizeMax(&cbInterface, IID_IUnknown, pUnk, MSHCTX_LOCAL, 0, MSHLFLAGS_NORMAL);
  2494. if (hr == S_OK)
  2495. {
  2496. // write the size of
  2497. hr = pStm->Write(&cbInterface, sizeof(ULONG), &cbSaved);
  2498. // need to marshal table strong
  2499. hr = CoMarshalInterface(pStm, IID_IUnknown, pUnk, MSHCTX_LOCAL, 0, MSHLFLAGS_NORMAL);
  2500. }
  2501. }
  2502. break;
  2503. default:
  2504. case VT_EMPTY:
  2505. case VT_NULL:
  2506. // do nothing
  2507. break;
  2508. case VT_BSTR:
  2509. {
  2510. DWORD nLen = SysStringByteLen(pSrc->bstrVal);
  2511. hr = pStm->Write(&nLen, sizeof(DWORD), &cbSaved);
  2512. if ( (hr == NOERROR)
  2513. && (nLen > 0))
  2514. {
  2515. hr = pStm->Write(pSrc->bstrVal, nLen * sizeof(BYTE), &cbSaved);
  2516. }
  2517. }
  2518. break;
  2519. #ifdef _unused_
  2520. case VT_BOOL:
  2521. hr = pStm->Write((WORD)V_BOOL(pSrc), sizeof(WORD), &cbSaved);
  2522. break;
  2523. case VT_UI1:
  2524. hr = pStm->Write(pSrc->bVal, sizeof(WORD), &cbSaved);
  2525. break;
  2526. case VT_I2:
  2527. hr = pStm->Write((WORD)pSrc->iVal, sizeof(WORD), &cbSaved);
  2528. break;
  2529. case VT_I4:
  2530. hr = pStm->Write(pSrc->lVal, sizeof(DWORD), &cbSaved);
  2531. break;
  2532. case VT_CY:
  2533. hr = pStm->Write(pSrc->cyVal.Lo, sizeof(WORD), &cbSaved);
  2534. hr = pStm->Write(pSrc->cyVal.Hi, sizeof(WORD), &cbSaved);
  2535. break;
  2536. case VT_R4:
  2537. hr = pStm->Write(pSrc->fltVal, sizeof(WORD), &cbSaved);
  2538. break;
  2539. case VT_R8:
  2540. hr = pStm->Write(pSrc->dblVal, sizeof(DOUBLE), &cbSaved);
  2541. break;
  2542. case VT_DATE:
  2543. hr = pStm->Write(pSrc->date;
  2544. break;
  2545. case VT_ERROR:
  2546. hr = pStm->Write(pSrc->scode;
  2547. break;
  2548. #endif //_unused_
  2549. }
  2550. }
  2551. return hr;
  2552. }
  2553. //+---------------------------------------------------------------------------
  2554. //
  2555. // Method: COleVariant::Load
  2556. //
  2557. // Synopsis: loads a variant from a stream
  2558. //
  2559. // Arguments: [pStm] --
  2560. //
  2561. // Returns:
  2562. //
  2563. // History: 1-15-1997 JohannP (Johann Posch) Created
  2564. //
  2565. // Notes: BUGBUG:NOT COMPLETE!
  2566. //
  2567. //----------------------------------------------------------------------------
  2568. HRESULT COleVariant::Load(IStream *pStm)
  2569. {
  2570. LPVARIANT pSrc = (LPVARIANT)this;
  2571. HRESULT hr = NOERROR;
  2572. ULONG cbSaved;
  2573. COleVariant CVar;
  2574. // Read the variant
  2575. hr = pStm->Read(pSrc, sizeof(VARIANT), &cbSaved);
  2576. TransAssert(( sizeof(VARIANT) == cbSaved));
  2577. if (pSrc->vt & VT_BYREF || pSrc->vt & VT_ARRAY)
  2578. {
  2579. // No support for VT_BYREF & VT_ARRAY
  2580. pSrc = (LPVARIANT)&CVar;
  2581. }
  2582. if (hr == NOERROR)
  2583. {
  2584. switch (pSrc->vt)
  2585. {
  2586. case VT_DISPATCH:
  2587. TransAssert((FALSE));
  2588. hr = E_FAIL;
  2589. break;
  2590. case VT_UNKNOWN:
  2591. {
  2592. ULONG cbInterface = 0;
  2593. IUnknown *pUnk = 0;
  2594. // write the size of
  2595. hr = pStm->Read(&cbInterface, sizeof(ULONG), &cbSaved);
  2596. if ( (hr == S_OK)
  2597. && cbInterface)
  2598. {
  2599. hr = CoUnmarshalInterface(pStm, IID_IUnknown, (void **) &pUnk);
  2600. if(hr == S_OK)
  2601. {
  2602. pSrc->punkVal = pUnk;
  2603. }
  2604. else
  2605. {
  2606. pSrc->punkVal = 0;
  2607. }
  2608. }
  2609. else
  2610. {
  2611. pSrc->punkVal = 0;
  2612. }
  2613. hr = NOERROR;
  2614. }
  2615. break;
  2616. default:
  2617. case VT_EMPTY:
  2618. case VT_NULL:
  2619. // do nothing
  2620. break;
  2621. case VT_BSTR:
  2622. {
  2623. DWORD nLen = 0;
  2624. hr = pStm->Read(&nLen, sizeof(DWORD), &cbSaved);
  2625. if (nLen > 0)
  2626. {
  2627. pSrc->bstrVal = SysAllocStringByteLen(NULL, nLen);
  2628. if (pSrc->bstrVal)
  2629. {
  2630. hr = pStm->Read(pSrc->bstrVal, nLen * sizeof(BYTE), &cbSaved);
  2631. }
  2632. else
  2633. {
  2634. hr = E_OUTOFMEMORY;
  2635. }
  2636. }
  2637. }
  2638. break;
  2639. #ifdef _unused_
  2640. case VT_BOOL:
  2641. hr = pStm->Read((WORD)V_BOOL(pSrc), sizeof(WORD), &cbSaved);
  2642. break;
  2643. case VT_UI1:
  2644. hr = pStm->Read(pSrc->bVal, sizeof(WORD), &cbSaved);
  2645. break;
  2646. case VT_I2:
  2647. hr = pStm->Read((WORD)pSrc->iVal, sizeof(WORD), &cbSaved);
  2648. break;
  2649. case VT_I4:
  2650. hr = pStm->Read(pSrc->lVal, sizeof(DWORD), &cbSaved);
  2651. break;
  2652. case VT_CY:
  2653. hr = pStm->Read(pSrc->cyVal.Lo, sizeof(WORD), &cbSaved);
  2654. hr = pStm->Read(pSrc->cyVal.Hi, sizeof(WORD), &cbSaved);
  2655. break;
  2656. case VT_R4:
  2657. hr = pStm->Read(pSrc->fltVal, sizeof(WORD), &cbSaved);
  2658. break;
  2659. case VT_R8:
  2660. hr = pStm->Read(pSrc->dblVal, sizeof(DOUBLE), &cbSaved);
  2661. break;
  2662. case VT_DATE:
  2663. hr = pStm->Read(pSrc->date;
  2664. break;
  2665. case VT_ERROR:
  2666. hr = pStm->Read(pSrc->scode;
  2667. break;
  2668. #endif //_unused_
  2669. }
  2670. }
  2671. return hr;
  2672. }