olevar.cpp 69 KB

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