Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1441 lines
45 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1998 - 2000.
  5. //
  6. // File: odbvarnt.cxx
  7. //
  8. // Contents: Helper class for PROPVARIANTs, OLE-DB variant types and
  9. // Automation variant types in tables
  10. //
  11. // Classes: COLEDBVariant - derives from CTableVariant
  12. //
  13. // Functions:
  14. //
  15. // History: 09 Jan 1998 VikasMan Created
  16. //
  17. //--------------------------------------------------------------------------
  18. #include "pch.cxx"
  19. #pragma hdrstop
  20. #include <bigtable.hxx>
  21. #include <odbvarnt.hxx>
  22. #include <initguid.h>
  23. #define DBINITCONSTANTS
  24. #include <msdadc.h> // oledb data conversion (IDataConvert) interface
  25. #include <msdaguid.h>
  26. #include "tabledbg.hxx"
  27. //+-------------------------------------------------------------------------
  28. //
  29. // Method: COLEDBVariant::OLEDBConvert, public.
  30. //
  31. // Synopsis: Data conversion routine, which uses the OLEDB data
  32. // conversion library (MSDADC.DLL) to do the conversion.
  33. //
  34. // Arguments: [pbDstBuf] -- the Destination data buffer
  35. // [cbDstBuf] -- the size of Dst. buffer
  36. // [vtDst] -- the Destination type.
  37. // [rPool] -- pool to use for destination buffers
  38. // [rcbDstLength] -- size of destination data
  39. // [xDataConvert] -- the OLEDB IDataConvert interface
  40. // [bPrecision] -- The precision of the output data in bytes,
  41. // if applicable. This argument is used when
  42. // converting to DBTYPE_NUMERIC data only.
  43. // [bScale] -- The scale of the output data in bytes,
  44. // if applicable. This argument is used when
  45. // converting to DBTYPE_NUMERIC data only.
  46. //
  47. // Returns: DBSTATUS_S_OK if conversion is successful,
  48. // else other DBSTATUS values.
  49. //
  50. // Notes: pbDstBuf should have (enough) memory allocated, else
  51. // truncation can happen.
  52. //
  53. // This routine is subdivided into 3 parts:
  54. // - It checks first if we are dealing with Automation Vars.
  55. // - Then it calls CTableVaraint::CopyOrCoerce to the job
  56. // - If unsuccessful, it uses the OLE-DB library
  57. //
  58. // History: 09 Jan 1998 VikasMan Created
  59. //
  60. //--------------------------------------------------------------------------
  61. DBSTATUS COLEDBVariant::OLEDBConvert(
  62. BYTE * pbDstBuf,
  63. DBLENGTH cbDstBuf,
  64. VARTYPE vtDst,
  65. PVarAllocator & rPool,
  66. DBLENGTH & rcbDstLength,
  67. XInterface<IDataConvert>& xDataConvert,
  68. BOOL fExtTypes, /* = TRUE */
  69. BYTE bPrecision, /* = 0 */
  70. BYTE bScale /* = 0 */ ) const
  71. {
  72. void* pbSrcBuf;
  73. ULONG cbSrcSize;
  74. DBTYPE dbtypeSrc, dbtypeDst;
  75. DBLENGTH cbDstBufNeeded;
  76. DBSTATUS DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  77. // Check if fExtTypes is false and we are dealing with automation variants
  78. if ( VT_VARIANT == vtDst || DBTYPE_PROPVARIANT == vtDst )
  79. {
  80. Win4Assert(cbDstBuf == sizeof PROPVARIANT);
  81. rcbDstLength = sizeof (PROPVARIANT);
  82. if ( ! IsArray( vt) &&
  83. ( fExtTypes || DBTYPE_PROPVARIANT == vtDst ||
  84. VT_BSTR == vt || (IsSimpleOAType( vt ) && ! IsVector( vt )) ) )
  85. {
  86. Copy( (CTableVariant*) pbDstBuf, rPool, (USHORT) VarDataSize() );
  87. DstStatus = DBSTATUS_S_OK;
  88. }
  89. else
  90. {
  91. DstStatus = _CopyToOAVariant( (VARIANT *) pbDstBuf, rPool );
  92. }
  93. if ( VT_EMPTY == vt )
  94. DstStatus = DBSTATUS_S_ISNULL;
  95. }
  96. else
  97. {
  98. // try converting using CTableVariant's CopyOrCoerce
  99. DstStatus = CopyOrCoerce( pbDstBuf,
  100. cbDstBuf,
  101. vtDst,
  102. rcbDstLength,
  103. rPool );
  104. }
  105. if ( DBStatusOK( DstStatus ))
  106. {
  107. // we are done here
  108. return DstStatus;
  109. }
  110. if (DBTYPE_HCHAPTER == vtDst)
  111. {
  112. if (VT_I4 == vt || VT_UI4 == vt)
  113. {
  114. * (ULONG *) pbDstBuf = lVal;
  115. DstStatus = DBSTATUS_S_OK;
  116. }
  117. return DstStatus;
  118. }
  119. // WORKAROUND: The following switch stmt is needed only until
  120. // OLEDB library supports VT_FILETIME. Once it does that,
  121. // we can get rid of this.
  122. switch ( vtDst )
  123. {
  124. case VT_DATE:
  125. // allow coercions from I8, UI8, R8, and FILETIME
  126. if (VT_I8 == vt || VT_UI8 == vt)
  127. {
  128. * (LONGLONG *) pbDstBuf = hVal.QuadPart;
  129. }
  130. else if (VT_R8 == vt)
  131. {
  132. * (DATE *) pbDstBuf = dblVal;
  133. }
  134. else
  135. {
  136. DstStatus = _StoreDate(pbDstBuf, cbDstBuf, vtDst);
  137. }
  138. rcbDstLength = sizeof (DATE);
  139. break;
  140. case VT_FILETIME:
  141. // allow coercions from I8, UI8, and DATE
  142. if (VT_I8 == vt || VT_UI8 == vt)
  143. {
  144. * (LONGLONG *) pbDstBuf = hVal.QuadPart;
  145. }
  146. else
  147. {
  148. DstStatus = _StoreDate(pbDstBuf, cbDstBuf, vtDst);
  149. }
  150. rcbDstLength = sizeof (FILETIME);
  151. break;
  152. case DBTYPE_DBDATE:
  153. DstStatus = _StoreDate(pbDstBuf, cbDstBuf, vtDst);
  154. rcbDstLength = sizeof (DBDATE);
  155. break;
  156. case DBTYPE_DBTIME:
  157. DstStatus = _StoreDate(pbDstBuf, cbDstBuf, vtDst);
  158. rcbDstLength = sizeof (DBTIME);
  159. break;
  160. case DBTYPE_DBTIMESTAMP:
  161. DstStatus = _StoreDate(pbDstBuf, cbDstBuf, vtDst);
  162. rcbDstLength = sizeof (DBTIMESTAMP);
  163. break;
  164. }
  165. if ( DBStatusOK( DstStatus ))
  166. {
  167. // we are done here
  168. return DstStatus;
  169. }
  170. tbDebugOut(( DEB_ITRACE, "COLEDBVaraint::OLEDBConvert - Using OLEDB library for conversion\n" ));
  171. // this looks like a job for ole-db
  172. // check if we have the IDataConvert interface
  173. if ( xDataConvert.IsNull( ) )
  174. {
  175. // let's get it then
  176. if ( !_GetIDataConvert( xDataConvert ) )
  177. {
  178. // for some reason we could not get the IDataConvert interface
  179. return DBSTATUS_E_CANTCONVERTVALUE;
  180. }
  181. }
  182. // get the source data pointer
  183. pbSrcBuf = _GetDataPointer();
  184. if ( 0 == pbSrcBuf )
  185. {
  186. tbDebugOut(( DEB_ERROR, "OLEDBConvert - _GetDataPointer returned NULL\n" ));
  187. return DBSTATUS_E_CANTCONVERTVALUE;
  188. }
  189. // get the source data size
  190. cbSrcSize = VarDataSize();
  191. // get the OLEDB source type
  192. SCODE sc = _GetOLEDBType( vt, dbtypeSrc );
  193. if ( S_OK != sc )
  194. {
  195. // can't use the OLEDB Conversion library
  196. tbDebugOut(( DEB_ERROR,
  197. "OLEDBConvert - _GetOLEDBType returned error 0x%x for type %x\n",
  198. sc, vt ));
  199. return DBSTATUS_E_CANTCONVERTVALUE;
  200. }
  201. // the destination type has to be an OLE-DB type
  202. dbtypeDst = vtDst;
  203. // get the needed Destination size
  204. sc = xDataConvert->GetConversionSize( dbtypeSrc,
  205. dbtypeDst,
  206. 0,
  207. &cbDstBufNeeded,
  208. pbSrcBuf );
  209. if ( sc != S_OK )
  210. {
  211. tbDebugOut(( DEB_ITRACE,
  212. "OLEDBConvert - GetConversionSize returned error 0x%x\n",
  213. sc ));
  214. return DBSTATUS_E_CANTCONVERTVALUE;
  215. }
  216. BYTE* pbDest = 0;
  217. // we need to allocate memory if ...
  218. if ( ( IsLPWSTR( dbtypeDst ) ) ||
  219. ( IsLPSTR( dbtypeDst ) ) ||
  220. ( (DBTYPE_BYREF | DBTYPE_WSTR) == dbtypeDst ) ||
  221. ( (DBTYPE_BYREF | DBTYPE_STR) == dbtypeDst )
  222. )
  223. {
  224. // If we hit this assert, then we got a few things to think about
  225. Win4Assert( !(IsLPWSTR( dbtypeDst ) || IsLPSTR( dbtypeDst )) );
  226. pbDest = (BYTE*) rPool.Allocate( (ULONG) cbDstBufNeeded );
  227. }
  228. else if ( DBTYPE_BSTR == dbtypeDst )
  229. {
  230. pbDest = (BYTE*) rPool.AllocBSTR( (ULONG) cbDstBufNeeded );
  231. }
  232. else
  233. {
  234. // bogus assert
  235. // Win4Assert ( (dbtypeDst & DBTYPE_BYREF) == 0 );
  236. // memory is already allocated
  237. // use the size which is less
  238. // if cbDstBuf is less than cbDstBufNeeded, truncation might happen
  239. cbDstBufNeeded = ( cbDstBufNeeded < cbDstBuf ? cbDstBufNeeded : cbDstBuf );
  240. }
  241. // do the conversion
  242. sc = xDataConvert->DataConvert( dbtypeSrc,
  243. dbtypeDst,
  244. cbSrcSize,
  245. &rcbDstLength,
  246. pbSrcBuf,
  247. pbDest ? (void*)&pbDest : pbDstBuf,
  248. cbDstBufNeeded,
  249. DstStatus,
  250. &DstStatus,
  251. bPrecision,
  252. bScale,
  253. DBDATACONVERT_DEFAULT);
  254. if ( sc != S_OK )
  255. {
  256. tbDebugOut(( DEB_ITRACE,
  257. "OLEDBConvert - DataConvert returned error 0x%x\n",
  258. sc ));
  259. return DBSTATUS_E_CANTCONVERTVALUE;
  260. }
  261. // if memory was allocated, put that ptr in pbDstBuf
  262. if ( pbDest )
  263. {
  264. *((BYTE**)(pbDstBuf)) = pbDest;
  265. }
  266. return DstStatus;
  267. }
  268. //+-------------------------------------------------------------------------
  269. //
  270. // Method: COLEDBVariant::GetDstLength, public.
  271. //
  272. // Synopsis: Returns the length required after the conversion without
  273. // actually doing the conversion.
  274. //
  275. // History: 10-12-98 DanLeg Created
  276. //
  277. //--------------------------------------------------------------------------
  278. DBSTATUS COLEDBVariant::GetDstLength(
  279. XInterface<IDataConvert>& xDataConvert,
  280. DBTYPE dbtypeDst,
  281. DBLENGTH & rcbDstLen )
  282. {
  283. SCODE sc = S_OK;
  284. DBTYPE dbtypeSrc;
  285. DBSTATUS DstStatus = DBSTATUS_S_OK;
  286. sc = _GetOLEDBType( vt, dbtypeSrc );
  287. if ( S_OK == sc )
  288. {
  289. if ( xDataConvert.IsNull( ) )
  290. {
  291. if ( !_GetIDataConvert( xDataConvert ) )
  292. sc = S_FALSE;
  293. }
  294. if ( S_OK == sc )
  295. {
  296. void * pbSrcBuf = _GetDataPointer();
  297. sc = xDataConvert->GetConversionSize( dbtypeSrc,
  298. dbtypeDst,
  299. 0,
  300. &rcbDstLen,
  301. pbSrcBuf );
  302. }
  303. }
  304. if ( S_OK != sc )
  305. {
  306. tbDebugOut(( DEB_ITRACE,
  307. "OLEDBConvert - GetConversionSize returned error 0x%x\n",
  308. sc ));
  309. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  310. }
  311. return DstStatus;
  312. }
  313. //+-------------------------------------------------------------------------
  314. //
  315. // Method: COLEDBVariant::_GetOLEDBType, private.
  316. //
  317. // Synopsis: Returns the OLEDB type equivalent of Variant type.
  318. //
  319. // Arguments: [vt] -- the source varaint type.
  320. // [dbtype] -- the equivalent oledb type.
  321. //
  322. // Returns: S_OK if equivalent OLE DB type exists,
  323. // else S_FALSE.
  324. //
  325. // Notes: Does not handle vectors
  326. //
  327. // History: 09 Jan 1998 VikasMan Created
  328. //
  329. //--------------------------------------------------------------------------
  330. inline SCODE COLEDBVariant::_GetOLEDBType( VARTYPE vt, DBTYPE& dbtype ) const
  331. {
  332. SCODE sc = S_OK;
  333. switch ( vt & ~VT_BYREF )
  334. {
  335. case VT_I1:
  336. case VT_UI1:
  337. case VT_I2:
  338. case VT_UI2:
  339. case VT_I4:
  340. case VT_UI4:
  341. case VT_I8:
  342. case VT_UI8:
  343. case VT_R4:
  344. case VT_R8:
  345. case VT_CY:
  346. case VT_DATE:
  347. case VT_BSTR:
  348. case VT_FILETIME: // WORKAROUND: Waiting on OLE DB Conv lib to handle this case - 01.12.98
  349. case VT_BOOL:
  350. case VT_ERROR:
  351. case VT_CLSID:
  352. case VT_VARIANT:
  353. case VT_DECIMAL:
  354. case VT_VECTOR | VT_I1:
  355. case VT_VECTOR | VT_UI1:
  356. case VT_VECTOR | VT_I2:
  357. case VT_VECTOR | VT_UI2:
  358. case VT_VECTOR | VT_I4:
  359. case VT_VECTOR | VT_UI4:
  360. case VT_VECTOR | VT_I8:
  361. case VT_VECTOR | VT_UI8:
  362. case VT_VECTOR | VT_R4:
  363. case VT_VECTOR | VT_R8:
  364. case VT_VECTOR | VT_CY:
  365. case VT_VECTOR | VT_DATE:
  366. case VT_VECTOR | VT_BSTR:
  367. case VT_VECTOR | VT_FILETIME: // WORKAROUND: Waiting on OLE DB Conv lib to handle this case - 01.12.98
  368. case VT_VECTOR | VT_BOOL:
  369. case VT_VECTOR | VT_ERROR:
  370. case VT_VECTOR | VT_CLSID:
  371. case VT_VECTOR | VT_VARIANT:
  372. case VT_ARRAY | VT_I1:
  373. case VT_ARRAY | VT_UI1:
  374. case VT_ARRAY | VT_I2:
  375. case VT_ARRAY | VT_UI2:
  376. case VT_ARRAY | VT_I4:
  377. case VT_ARRAY | VT_UI4:
  378. case VT_ARRAY | VT_I8:
  379. case VT_ARRAY | VT_UI8:
  380. case VT_ARRAY | VT_R4:
  381. case VT_ARRAY | VT_R8:
  382. case VT_ARRAY | VT_CY:
  383. case VT_ARRAY | VT_DATE:
  384. case VT_ARRAY | VT_BSTR:
  385. case VT_ARRAY | VT_BOOL:
  386. case VT_ARRAY | VT_VARIANT:
  387. case VT_ARRAY | VT_DECIMAL:
  388. // In all the above cases, the DBTYPE has same value as
  389. // VARIANT type
  390. case DBTYPE_NUMERIC:
  391. case DBTYPE_DBDATE:
  392. case DBTYPE_DBTIME:
  393. case DBTYPE_DBTIMESTAMP:
  394. case DBTYPE_HCHAPTER:
  395. case DBTYPE_BYTES:
  396. case DBTYPE_VARNUMERIC:
  397. // The above are OLEDB types only. So no conversion needed.
  398. dbtype = vt;
  399. break;
  400. case VT_LPSTR:
  401. case DBTYPE_STR:
  402. dbtype = DBTYPE_STR;
  403. break;
  404. case VT_LPWSTR:
  405. case DBTYPE_WSTR:
  406. dbtype = DBTYPE_WSTR;
  407. break;
  408. case VT_BLOB:
  409. dbtype = VT_VECTOR | VT_UI1;
  410. break;
  411. case VT_INT:
  412. dbtype = VT_I4;
  413. break;
  414. case VT_UINT:
  415. dbtype = VT_UI4;
  416. break;
  417. case VT_ARRAY | VT_INT:
  418. dbtype = VT_ARRAY | VT_I4;
  419. break;
  420. case VT_ARRAY | VT_UINT:
  421. dbtype = VT_ARRAY | VT_UI4;
  422. break;
  423. // SPECDEVIATION: What about VT_CF ??? (handled partially in base class)
  424. default:
  425. // default case: all types for which there is no equivalent
  426. // OLE DB type - VT_CF, VT_BLOBOBJECT,
  427. // VT_STREAM, VT_STREAMED_OBJECT, VT_STORAGE, VT_STORED_OBJECT,
  428. // VT_DISPATCH, VT_UNKNOWN,
  429. sc = S_FALSE;
  430. break;
  431. }
  432. return sc;
  433. }
  434. //+-------------------------------------------------------------------------
  435. //
  436. // Member: COLEDBVariant::_GetDataPointer, private
  437. //
  438. // Synopsis: Depending on the type of vt, returns the data pointer
  439. //
  440. // Arguments: -none-
  441. //
  442. // Returns: Returns the pointer to data in the PropVariant
  443. //
  444. // History: 09 Jan 1998 VikasMan Created
  445. //
  446. //--------------------------------------------------------------------------
  447. inline void* COLEDBVariant::_GetDataPointer() const
  448. {
  449. if (vt & VT_VECTOR)
  450. return (void*)&cal;
  451. if (vt & VT_ARRAY)
  452. return (void*) parray;
  453. void* pDataPtr = 0;
  454. switch ( vt )
  455. {
  456. case VT_LPSTR:
  457. case VT_LPWSTR:
  458. case VT_CLSID:
  459. case VT_CF:
  460. // all pointer values
  461. pDataPtr = (void*) pszVal;
  462. break;
  463. case VT_BSTR:
  464. // need address of bstr ptr
  465. pDataPtr = (void*) &bstrVal;
  466. break;
  467. case VT_BLOB:
  468. case VT_BLOB_OBJECT:
  469. pDataPtr = (void*) &blob;
  470. break;
  471. case VT_DECIMAL:
  472. pDataPtr = (void*) this;
  473. break;
  474. // cases which we do not handle
  475. case VT_EMPTY:
  476. case VT_NULL:
  477. case VT_ILLEGAL:
  478. case VT_STREAM:
  479. case VT_STREAMED_OBJECT:
  480. case VT_STORAGE:
  481. case VT_STORED_OBJECT:
  482. case VT_DISPATCH:
  483. case VT_VARIANT:
  484. case VT_UNKNOWN:
  485. case VT_VOID:
  486. pDataPtr = 0;
  487. break;
  488. // Rest of the stuff
  489. default:
  490. pDataPtr = (void*) &bVal;
  491. break;
  492. }
  493. return pDataPtr;
  494. }
  495. //+-------------------------------------------------------------------------
  496. //
  497. // Member: COLEDBVariant::_CopyToOAVariant, private
  498. //
  499. // Synopsis: Copy table data between a table variant structure and
  500. // an Ole automation variant. Automation variants have a
  501. // restricted set of usable types and vectors must be converted
  502. // to safearrays.
  503. //
  504. // Arguments: [pDest] -- pointer to destination variant
  505. // [rPool] -- pool to use for destination buffers
  506. //
  507. // Returns: status for copy
  508. //
  509. // History: 09 Jan 1998 VikasMan Created
  510. //
  511. //--------------------------------------------------------------------------
  512. DBSTATUS COLEDBVariant::_CopyToOAVariant( VARIANT * pDest,
  513. PVarAllocator & rPool) const
  514. {
  515. DBSTATUS DstStatus = DBSTATUS_S_OK;
  516. switch (vt)
  517. {
  518. case VT_LPSTR:
  519. case VT_LPWSTR:
  520. {
  521. DBLENGTH ulTemp;
  522. pDest->vt = VT_BSTR;
  523. DstStatus = _StoreString( (BYTE *)&(pDest->bstrVal),
  524. sizeof (BSTR),
  525. VT_BSTR,
  526. ulTemp,
  527. rPool);
  528. break;
  529. }
  530. case VT_I8:
  531. case VT_UI8:
  532. DstStatus = _StoreDecimal( &(pDest->decVal) );
  533. pDest->vt = VT_DECIMAL;
  534. break;
  535. case VT_I1:
  536. DstStatus = _StoreIntegerSignedToUnSigned( VT_UI1, &(pDest->bVal) );
  537. pDest->vt = VT_UI1;
  538. break;
  539. case VT_UI2:
  540. if (uiVal <= SHRT_MAX)
  541. {
  542. DstStatus = _StoreIntegerUnSignedToSigned( VT_I2, (BYTE*)&(pDest->iVal) );
  543. pDest->vt = VT_I2;
  544. }
  545. else
  546. {
  547. DstStatus = _StoreIntegerUnSignedToSigned( VT_I4, (BYTE*)&(pDest->lVal) );
  548. pDest->vt = VT_I4;
  549. }
  550. break;
  551. case VT_UI4:
  552. if (ulVal <= LONG_MAX)
  553. {
  554. DstStatus = _StoreIntegerUnSignedToSigned( VT_I4, (BYTE*)&(pDest->lVal) );
  555. pDest->vt = VT_I4;
  556. }
  557. else
  558. {
  559. DstStatus = _StoreDecimal( &(pDest->decVal) );
  560. pDest->vt = VT_DECIMAL;
  561. }
  562. break;
  563. case VT_FILETIME:
  564. DstStatus = _StoreDate( (BYTE*)&(pDest->date),
  565. sizeof pDest->date,
  566. VT_DATE );
  567. pDest->vt = VT_DATE;
  568. break;
  569. case (VT_VECTOR | VT_I2):
  570. case (VT_VECTOR | VT_I4):
  571. case (VT_VECTOR | VT_R4):
  572. case (VT_VECTOR | VT_R8):
  573. case (VT_VECTOR | VT_CY):
  574. case (VT_VECTOR | VT_DATE):
  575. case (VT_VECTOR | VT_ERROR):
  576. case (VT_VECTOR | VT_BOOL):
  577. case (VT_VECTOR | VT_UI1):
  578. case (VT_VECTOR | VT_DECIMAL):
  579. Win4Assert( IsSimpleOAType(vt & VT_TYPEMASK));
  580. Win4Assert( CanBeVectorType(vt & VT_TYPEMASK));
  581. DstStatus = _StoreSimpleTypeArray( &(pDest->parray));
  582. pDest->vt = (vt & VT_TYPEMASK) | VT_ARRAY;
  583. break;
  584. case (VT_VECTOR | VT_UI4): // could step thru to see if I4 is big enough
  585. case (VT_VECTOR | VT_I8):
  586. case (VT_VECTOR | VT_UI8):
  587. Win4Assert( !IsOAType(vt & VT_TYPEMASK));
  588. Win4Assert( CanBeVectorType(vt & VT_TYPEMASK));
  589. DstStatus = _StoreDecimalArray( &(pDest->parray));
  590. pDest->vt = VT_DECIMAL | VT_ARRAY;
  591. break;
  592. case (VT_VECTOR | VT_UI2): // could step thru to detect if I2 is big enough
  593. Win4Assert( !IsOAType(vt & VT_TYPEMASK));
  594. Win4Assert( CanBeVectorType(vt & VT_TYPEMASK));
  595. DstStatus = _StoreIntegerArray( VT_I4, &(pDest->parray));
  596. pDest->vt = VT_I4 | VT_ARRAY;
  597. break;
  598. case (VT_VECTOR | VT_I1): // should step thru to detect if UI1 is big enough
  599. Win4Assert( !IsOAType(vt & VT_TYPEMASK));
  600. Win4Assert( CanBeVectorType(vt & VT_TYPEMASK));
  601. DstStatus = _StoreIntegerArray( VT_UI1, &(pDest->parray));
  602. pDest->vt = VT_UI1 | VT_ARRAY;
  603. break;
  604. case (VT_VECTOR | VT_LPSTR): // byref/vector mutually exclusive
  605. Win4Assert( !IsOAType(vt & VT_TYPEMASK));
  606. Win4Assert( CanBeVectorType(vt & VT_TYPEMASK));
  607. DstStatus = _StoreLPSTRArray( &(pDest->parray), rPool );
  608. pDest->vt = VT_BSTR | VT_ARRAY;
  609. break;
  610. case (VT_VECTOR | VT_LPWSTR):
  611. Win4Assert( !IsOAType(vt & VT_TYPEMASK));
  612. Win4Assert( CanBeVectorType(vt & VT_TYPEMASK));
  613. DstStatus = _StoreLPWSTRArray( &(pDest->parray), rPool );
  614. pDest->vt = VT_BSTR | VT_ARRAY;
  615. break;
  616. case (VT_VECTOR | VT_BSTR):
  617. Win4Assert( IsOAType(vt & VT_TYPEMASK));
  618. Win4Assert( CanBeVectorType(vt & VT_TYPEMASK));
  619. DstStatus = _StoreBSTRArray( &(pDest->parray), rPool );
  620. pDest->vt = VT_BSTR | VT_ARRAY;
  621. break;
  622. case (VT_VECTOR | VT_VARIANT):
  623. Win4Assert( IsOAType(vt & VT_TYPEMASK));
  624. Win4Assert( CanBeVectorType(vt & VT_TYPEMASK));
  625. DstStatus = _StoreVariantArray( &(pDest->parray), rPool );
  626. pDest->vt = VT_VARIANT | VT_ARRAY;
  627. break;
  628. case (VT_VECTOR | VT_FILETIME):
  629. Win4Assert( !IsOAType(vt & VT_TYPEMASK));
  630. Win4Assert( CanBeVectorType(vt & VT_TYPEMASK));
  631. DstStatus = _StoreDateArray( &(pDest->parray) );
  632. pDest->vt = VT_DATE | VT_ARRAY;
  633. break;
  634. case VT_ARRAY | VT_I1:
  635. case VT_ARRAY | VT_UI1:
  636. case VT_ARRAY | VT_I2:
  637. case VT_ARRAY | VT_UI2:
  638. case VT_ARRAY | VT_I4:
  639. case VT_ARRAY | VT_INT:
  640. case VT_ARRAY | VT_UI4:
  641. case VT_ARRAY | VT_UINT:
  642. case VT_ARRAY | VT_ERROR:
  643. case VT_ARRAY | VT_I8:
  644. case VT_ARRAY | VT_UI8:
  645. case VT_ARRAY | VT_R4:
  646. case VT_ARRAY | VT_R8:
  647. case VT_ARRAY | VT_CY:
  648. case VT_ARRAY | VT_DATE:
  649. case VT_ARRAY | VT_BSTR:
  650. case VT_ARRAY | VT_BOOL:
  651. case VT_ARRAY | VT_VARIANT:
  652. case VT_ARRAY | VT_DECIMAL:
  653. {
  654. SAFEARRAY * psa = 0;
  655. SCODE sc = SafeArrayCopy( parray, &psa );
  656. Win4Assert( E_INVALIDARG != sc );
  657. Win4Assert( E_OUTOFMEMORY == sc || psa != 0 );
  658. if (S_OK != sc)
  659. {
  660. THROW(CException(E_OUTOFMEMORY));
  661. }
  662. else
  663. {
  664. pDest->vt = vt;
  665. pDest->parray = psa;
  666. }
  667. }
  668. break;
  669. case VT_CLSID: // no equivalent in OA variant
  670. case VT_CF: // no equivalent in OA variant
  671. default:
  672. Win4Assert( !(VT_ARRAY & vt) ); // should be handled elsewhere
  673. Win4Assert( !IsOAType(vt) ); // should be handled elsewhere
  674. Win4Assert(CanBeVectorType(vt & VT_TYPEMASK) || !(VT_VECTOR & vt));
  675. tbDebugOut(( DEB_WARN, "COLEDBVariant::CopyToOAVariant - bad variant type %d \n", vt ));
  676. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  677. }
  678. if ( !StatusSuccess(DstStatus) ||
  679. (DBSTATUS_S_ISNULL == DstStatus && pDest->vt != VT_NULL) )
  680. pDest->vt = VT_EMPTY;
  681. return DstStatus;
  682. }
  683. //+-------------------------------------------------------------------------
  684. //
  685. // Member: COLEDBVariant::_StoreSimpleTypeArray, private
  686. //
  687. // Synopsis: Copy vector of simple OA types to safearray of same type
  688. //
  689. // Arguments: [pbDstBuf] -- destination buffer
  690. //
  691. // Returns: status for copy
  692. //
  693. // Notes: None of the simple types require memory allocation.
  694. // Throws if safearray itself cannot be alloc'd
  695. //
  696. // History: 09 Apr 1997 EmilyB Created
  697. // 09 Jan 1998 VikasMan Moved from CTableVariant class
  698. // to here
  699. //
  700. //--------------------------------------------------------------------------
  701. DBSTATUS COLEDBVariant::_StoreSimpleTypeArray(SAFEARRAY ** pbDstBuf) const
  702. {
  703. if ( 0 == caul.cElems )
  704. return DBSTATUS_S_ISNULL;
  705. // CLEANCODE - add to PVarAllocator?
  706. SAFEARRAY *sa = SafeArrayCreateVector(vt & VT_TYPEMASK, 0, caul.cElems);
  707. if (0 == sa)
  708. THROW(CException(E_OUTOFMEMORY));
  709. XSafeArray xsa(sa);
  710. USHORT cbSize, cbAlign, rgFlags;
  711. VartypeInfo(vt & VT_TYPEMASK, cbSize, cbAlign, rgFlags);
  712. BYTE * pBase = (BYTE *)&(caul.pElems[0]);
  713. for (LONG lElem = 0; lElem < (LONG)(caul.cElems); lElem++)
  714. {
  715. SCODE sc = SafeArrayPutElement(xsa.Get(), &lElem, pBase + (cbSize * lElem));
  716. Win4Assert ( SUCCEEDED(sc) );
  717. }
  718. *pbDstBuf = xsa.Acquire();
  719. return DBSTATUS_S_OK;
  720. }
  721. //+-------------------------------------------------------------------------
  722. //
  723. // Member: COLEDBVariant::_StoreDecimalArray, private
  724. //
  725. // Synopsis: Copy vector to decimal safearray
  726. //
  727. // Arguments: [pbDstBuf] -- destination buffer
  728. //
  729. // Returns: status for copy
  730. //
  731. // Notes: Expects the 'this' data type to be VT_UI4|VT_VECTOR,
  732. // VT_I8|VT_VECTOR, or VT_UI8|VT_VECTOR.
  733. //
  734. // History: 09 Apr 1997 EmilyB Created
  735. // 09 Jan 1998 VikasMan Moved from CTableVariant class
  736. // to here
  737. //
  738. //--------------------------------------------------------------------------
  739. DBSTATUS COLEDBVariant::_StoreDecimalArray( SAFEARRAY ** pbDstBuf ) const
  740. {
  741. if ( 0 == caul.cElems )
  742. return DBSTATUS_S_ISNULL;
  743. DBSTATUS dbStatus = DBSTATUS_S_OK; // status of last conversion
  744. DBSTATUS dbStatusRet = DBSTATUS_S_OK; // error code of last conversion,
  745. // or if no errors, DBSTATUS_S code
  746. // of last item with any trouble converting.
  747. // CLEANCODE - add to PVarAllocator?
  748. SAFEARRAY * sa = SafeArrayCreateVector(VT_DECIMAL, 0, caul.cElems);
  749. if (0 == sa)
  750. THROW(CException(E_OUTOFMEMORY));
  751. XSafeArray xsa(sa);
  752. for (LONG lElem = 0; lElem < (LONG)caul.cElems && StatusSuccess(dbStatus); lElem++)
  753. {
  754. DECIMAL dec;
  755. dbStatus = _StoreDecimal( &dec, lElem);
  756. if (DBSTATUS_S_OK != dbStatus)
  757. dbStatusRet = dbStatus; // save last non-zero status
  758. SCODE sc = SafeArrayPutElement(xsa.Get(), &lElem, &dec);
  759. Win4Assert ( SUCCEEDED(sc) );
  760. }
  761. if (StatusSuccess(dbStatus))
  762. {
  763. *pbDstBuf = xsa.Acquire();
  764. }
  765. return dbStatusRet;
  766. }
  767. //+-------------------------------------------------------------------------
  768. //
  769. // Member: COLEDBVariant::_StoreIntegerArray, private
  770. //
  771. // Synopsis: Copy vector of integers to safearray of integers
  772. //
  773. // Arguments: [vtDst] -- destination safearray type
  774. // [pbDstBuf] -- destination buffer
  775. //
  776. // Returns: status for copy
  777. //
  778. // Notes: Expects the 'this' data type to be an int type | VT_VECTOR.
  779. //
  780. // History: 09 Apr 1997 EmilyB Created
  781. // 09 Jan 1998 VikasMan Moved from CTableVariant class
  782. // to here
  783. //
  784. //--------------------------------------------------------------------------
  785. DBSTATUS COLEDBVariant::_StoreIntegerArray(VARTYPE vtDst,
  786. SAFEARRAY ** pbDstBuf) const
  787. {
  788. if ( 0 == caul.cElems )
  789. return DBSTATUS_S_ISNULL;
  790. DBSTATUS dbStatus = DBSTATUS_S_OK;
  791. DBSTATUS dbStatusRet = DBSTATUS_S_OK; // error code of last conversion,
  792. // or if no errors, DBSTATUS_S code
  793. // of last item with any trouble converting.
  794. // CLEANCODE - add to PVarAllocator?
  795. SAFEARRAY * sa = SafeArrayCreateVector(vtDst, 0, caul.cElems);
  796. if (0 == sa)
  797. THROW(CException(E_OUTOFMEMORY));
  798. XSafeArray xsa(sa);
  799. for (LONG lElem = 0; lElem < (LONG)caul.cElems && StatusSuccess(dbStatus); lElem++)
  800. {
  801. LONGLONG iInt; // size of longest int - to use as buffer
  802. dbStatus = _StoreInteger( vtDst, (BYTE *)&iInt, lElem);
  803. if (DBSTATUS_S_OK != dbStatus)
  804. dbStatusRet = dbStatus; // save last non-zero status
  805. SCODE sc = SafeArrayPutElement(xsa.Get(), &lElem, &iInt);
  806. Win4Assert ( SUCCEEDED(sc) );
  807. }
  808. if (StatusSuccess(dbStatus))
  809. {
  810. *pbDstBuf = xsa.Acquire();
  811. }
  812. return dbStatusRet;
  813. }
  814. //+-------------------------------------------------------------------------
  815. //
  816. // Member: COLEDBVariant::_StoreLPSTRArray, private
  817. //
  818. // Synopsis: Copy LPSTR vector to safearray
  819. //
  820. // Arguments: [pbDstBuf] -- destination buffer
  821. // [rPool] -- pool to use for destination buffers
  822. //
  823. // Returns: status for copy
  824. //
  825. // History: 09 Apr 1997 EmilyB Created
  826. // 09 Jan 1998 VikasMan Moved from CTableVariant class
  827. // to here
  828. //
  829. //--------------------------------------------------------------------------
  830. DBSTATUS COLEDBVariant::_StoreLPSTRArray(
  831. SAFEARRAY ** pbDstBuf,
  832. PVarAllocator & rPool) const
  833. {
  834. if ( 0 == calpstr.cElems )
  835. return DBSTATUS_S_ISNULL;
  836. DBSTATUS dbStatus = DBSTATUS_S_OK;
  837. // CLEANCODE - add to PVarAllocator?
  838. SAFEARRAY * sa = SafeArrayCreateVector(VT_BSTR, 0, calpstr.cElems);
  839. if (0 == sa)
  840. THROW(CException(E_OUTOFMEMORY));
  841. XSafeArray xsa(sa);
  842. for (LONG lElem = 0; lElem < (LONG)(calpstr).cElems && StatusSuccess(dbStatus); lElem++)
  843. {
  844. int cwc = MultiByteToWideChar(ulCoercionCodePage,0,
  845. calpstr.pElems[lElem],-1,0,0);
  846. if (0 == cwc)
  847. {
  848. dbStatus = DBSTATUS_E_CANTCONVERTVALUE; // something odd...
  849. }
  850. else
  851. {
  852. XArray<WCHAR> wcsDest( cwc );
  853. MultiByteToWideChar(ulCoercionCodePage, 0,
  854. calpstr.pElems[lElem], -1, wcsDest.Get(), cwc);
  855. BSTR bstrDest = (BSTR) rPool.CopyBSTR((cwc-1)*sizeof (OLECHAR),
  856. wcsDest.Get());
  857. SCODE sc = SafeArrayPutElement(xsa.Get(), &lElem, (void *)rPool.PointerToOffset(bstrDest));
  858. rPool.FreeBSTR(bstrDest);
  859. if (E_OUTOFMEMORY == sc)
  860. THROW(CException(E_OUTOFMEMORY));
  861. Win4Assert ( SUCCEEDED(sc) );
  862. }
  863. }
  864. if (StatusSuccess(dbStatus))
  865. {
  866. *pbDstBuf = xsa.Acquire();
  867. }
  868. return dbStatus;
  869. }
  870. //+-------------------------------------------------------------------------
  871. //
  872. // Member: COLEDBVariant::_StoreLPWSTRArray, private
  873. //
  874. // Synopsis: Copy LPWSTR vector to safearray
  875. //
  876. // Arguments: [pbDstBuf] -- destination buffer
  877. // [rPool] -- pool to use for destination buffers
  878. //
  879. // Returns: status for copy
  880. //
  881. // History: 09 Apr 1997 EmilyB Created
  882. // 09 Jan 1998 VikasMan Moved from CTableVariant class
  883. // to here
  884. //
  885. //--------------------------------------------------------------------------
  886. DBSTATUS COLEDBVariant::_StoreLPWSTRArray(
  887. SAFEARRAY ** pbDstBuf,
  888. PVarAllocator & rPool) const
  889. {
  890. if ( 0 == calpwstr.cElems )
  891. return DBSTATUS_S_ISNULL;
  892. // CLEANCODE - add to PVarAllocator?
  893. SAFEARRAY * sa = SafeArrayCreateVector(VT_BSTR, 0, calpwstr.cElems);
  894. if (0 == sa)
  895. THROW(CException(E_OUTOFMEMORY));
  896. XSafeArray xsa(sa);
  897. for (LONG lElem = 0; lElem < (LONG)(calpwstr.cElems); lElem++)
  898. {
  899. BSTR bstrDest = (BSTR) rPool.CopyBSTR( wcslen(calpwstr.pElems[lElem]) * sizeof(WCHAR),
  900. calpwstr.pElems[lElem] );
  901. SCODE sc = SafeArrayPutElement(xsa.Get(), &lElem, (void *)rPool.PointerToOffset(bstrDest));
  902. rPool.FreeBSTR(bstrDest);
  903. if (E_OUTOFMEMORY == sc)
  904. THROW(CException(E_OUTOFMEMORY));
  905. Win4Assert ( SUCCEEDED(sc) );
  906. }
  907. *pbDstBuf = xsa.Acquire();
  908. return DBSTATUS_S_OK;
  909. }
  910. //+-------------------------------------------------------------------------
  911. //
  912. // Member: COLEDBVariant::_StoreBSTRArray, private
  913. //
  914. // Synopsis: Copy BSTR vector to safearray
  915. //
  916. // Arguments: [pbDstBuf] -- destination buffer
  917. // [rPool] -- pool to use for destination buffers
  918. //
  919. // Returns: status for copy
  920. //
  921. // Notes: Expects the 'this' data type to be VT_BSTR | VT_VECTOR.
  922. //
  923. // History: 09 Apr 1997 EmilyB Created
  924. // 09 Jan 1998 VikasMan Moved from CTableVariant class
  925. // to here
  926. //
  927. //--------------------------------------------------------------------------
  928. DBSTATUS COLEDBVariant::_StoreBSTRArray(
  929. SAFEARRAY ** pbDstBuf,
  930. PVarAllocator & rPool) const
  931. {
  932. if ( 0 == cabstr.cElems )
  933. return DBSTATUS_S_ISNULL;
  934. // CLEANCODE - add to PVarAllocator?
  935. SAFEARRAY * sa = SafeArrayCreateVector(VT_BSTR, 0, cabstr.cElems);
  936. if (0 == sa)
  937. THROW(CException(E_OUTOFMEMORY));
  938. XSafeArray xsa(sa);
  939. for (LONG lElem = 0; lElem < (LONG)cabstr.cElems; lElem++)
  940. {
  941. SCODE sc = SafeArrayPutElement(xsa.Get(), &lElem, cabstr.pElems[lElem]);
  942. if (E_OUTOFMEMORY == sc)
  943. THROW(CException(E_OUTOFMEMORY));
  944. Win4Assert ( SUCCEEDED(sc) );
  945. }
  946. *pbDstBuf = xsa.Acquire();
  947. return DBSTATUS_S_OK;
  948. }
  949. //+-------------------------------------------------------------------------
  950. //
  951. // Member: COLEDBVariant::_StoreVariantArray, private
  952. //
  953. // Synopsis: Copy variant vector to safearray
  954. //
  955. // Arguments: [pbDstBuf] -- destination buffer
  956. // [rPool] -- pool to use for destination buffers
  957. //
  958. // Returns: status for copy
  959. //
  960. // Notes: Expects the 'this' data type to be VT_VARIANT | VT_VECTOR.
  961. //
  962. // History: 09 Apr 1997 EmilyB Created
  963. // 09 Jan 1998 VikasMan Moved from CTableVariant class
  964. // to here
  965. //
  966. //--------------------------------------------------------------------------
  967. DBSTATUS COLEDBVariant::_StoreVariantArray(
  968. SAFEARRAY ** pbDstBuf,
  969. PVarAllocator & rPool) const
  970. {
  971. if ( 0 == capropvar.cElems )
  972. return DBSTATUS_S_ISNULL;
  973. DBSTATUS dbStatus = DBSTATUS_S_OK;
  974. DBSTATUS dbStatusRet = DBSTATUS_S_OK; // error code of last conversion,
  975. // or if no errors, DBSTATUS_S code
  976. // of last item with any trouble converting.
  977. Win4Assert(vt == (VT_VECTOR | VT_VARIANT));
  978. // CLEANCODE - add to PVarAllocator?
  979. SAFEARRAY * sa = SafeArrayCreateVector(VT_VARIANT, 0, capropvar.cElems);
  980. if (0 == sa)
  981. THROW(CException(E_OUTOFMEMORY));
  982. XSafeArray xsa(sa);
  983. for (LONG lElem = 0; lElem < (LONG)(capropvar.cElems) && StatusSuccess(dbStatus); lElem++)
  984. {
  985. COLEDBVariant tblVariant;
  986. if (IsOAType(capropvar.pElems[lElem].vt))
  987. {
  988. ((CTableVariant &)capropvar.pElems[lElem]).Copy(&tblVariant,
  989. rPool,
  990. (USHORT)((CTableVariant &)capropvar.pElems[lElem]).VarDataSize(),
  991. 0);
  992. }
  993. else // convert variant to an OA type
  994. {
  995. dbStatus = ((COLEDBVariant &)capropvar.pElems[lElem])._CopyToOAVariant( (VARIANT *)&tblVariant, rPool);
  996. if (DBSTATUS_S_OK != dbStatus)
  997. dbStatusRet = dbStatus; // save last non-zero status
  998. }
  999. SCODE sc = SafeArrayPutElement(xsa.Get(), &lElem, (PROPVARIANT *)&tblVariant);
  1000. if (E_OUTOFMEMORY == sc)
  1001. THROW(CException(E_OUTOFMEMORY));
  1002. Win4Assert ( SUCCEEDED(sc) );
  1003. }
  1004. *pbDstBuf = xsa.Acquire();
  1005. return dbStatusRet;
  1006. }
  1007. //+-------------------------------------------------------------------------
  1008. //
  1009. // Member: COLEDBVariant::_StoreDateArray, private
  1010. //
  1011. // Synopsis: Copy date vector to safearray of dates
  1012. //
  1013. // Arguments: [pbDstBuf] -- destination buffer
  1014. //
  1015. // Returns: status for copy
  1016. //
  1017. // Notes: Expects the 'this' data type to be VT_DATE | VT_VECTOR.
  1018. //
  1019. // History: 09 Apr 1997 EmilyB Created
  1020. // 09 Jan 1998 VikasMan Moved from CTableVariant class
  1021. // to here
  1022. //
  1023. //--------------------------------------------------------------------------
  1024. DBSTATUS COLEDBVariant::_StoreDateArray(SAFEARRAY ** pbDstBuf) const
  1025. {
  1026. if ( 0 == caul.cElems )
  1027. return DBSTATUS_S_ISNULL;
  1028. DBSTATUS dbStatus = DBSTATUS_S_OK;
  1029. DBSTATUS dbStatusRet = DBSTATUS_S_OK; // error code of last conversion,
  1030. // or if no errors, DBSTATUS_S code
  1031. // of last item with any trouble converting.
  1032. // CLEANCODE - add to PVarAllocator?
  1033. SAFEARRAY * sa = SafeArrayCreateVector(VT_DATE, 0, caul.cElems);
  1034. if (0 == sa)
  1035. THROW(CException(E_OUTOFMEMORY));
  1036. XSafeArray xsa(sa);
  1037. for (LONG lElem = 0; lElem < (LONG)(caul.cElems) && StatusSuccess(dbStatus); lElem++)
  1038. {
  1039. DATE date;
  1040. dbStatus = _StoreDate( (BYTE *)&date, sizeof(date), VT_DATE, lElem);
  1041. if (DBSTATUS_S_OK != dbStatus)
  1042. dbStatusRet = dbStatus; // save last non-zero status
  1043. SCODE sc = SafeArrayPutElement(xsa.Get(), &lElem, &date);
  1044. Win4Assert ( SUCCEEDED(sc) );
  1045. }
  1046. if (StatusSuccess(dbStatus))
  1047. {
  1048. *pbDstBuf = xsa.Acquire();
  1049. }
  1050. return dbStatusRet;
  1051. }
  1052. //+-------------------------------------------------------------------------
  1053. //
  1054. // Member: COLEDBVariant::_StoreDate, private
  1055. //
  1056. // Synopsis: Copy variant date/time data, coerce if possible
  1057. //
  1058. // Arguments: [pbDstBuf] -- destination buffer
  1059. // [cbDstBuf] -- size of destination buffer
  1060. // [vtDst] -- data type of the dest
  1061. // [lElem] -- element of vector to convert
  1062. //
  1063. // Returns: status for copy
  1064. //
  1065. // Notes: Expects the 'this' data type to be either VT_FILETIME or
  1066. // VT_DATE. Expects the vtDst to be VT_FILETIME, VT_DATE,
  1067. // DBTYPE_DBDATE, DBTYPE_DBTIME or DBTYPE_DBTIMESTAMP.
  1068. //
  1069. // History: 31 Jan 1997 AlanW Created
  1070. // 13 Jan 1998 VikasMan Moved from CTableVariant class
  1071. // to here
  1072. //
  1073. //--------------------------------------------------------------------------
  1074. DBSTATUS COLEDBVariant::_StoreDate(
  1075. BYTE * pbDstBuf,
  1076. DBLENGTH cbDstBuf,
  1077. VARTYPE vtDst,
  1078. LONG lElem) const
  1079. {
  1080. DBSTATUS DstStatus = DBSTATUS_S_OK;
  1081. SYSTEMTIME stUTC;
  1082. //
  1083. // Convert the input date into a common form: GMT SYSTEMTIME.
  1084. //
  1085. if (VT_DATE == vt)
  1086. {
  1087. if (! VariantTimeToSystemTime(date, &stUTC) )
  1088. return DBSTATUS_E_DATAOVERFLOW;
  1089. }
  1090. else if ((VT_DATE|VT_VECTOR)== vt)
  1091. {
  1092. if (! VariantTimeToSystemTime(cadate.pElems[lElem], &stUTC) )
  1093. return DBSTATUS_E_DATAOVERFLOW;
  1094. }
  1095. else if (VT_FILETIME == vt)
  1096. {
  1097. // do not do local time conversion
  1098. if (! FileTimeToSystemTime((LPFILETIME) &hVal.QuadPart, &stUTC) )
  1099. return DBSTATUS_E_DATAOVERFLOW;
  1100. }
  1101. else if ((VT_FILETIME|VT_VECTOR) == vt)
  1102. {
  1103. // do not do local time conversion
  1104. if (! FileTimeToSystemTime(&cafiletime.pElems[lElem], &stUTC) )
  1105. return DBSTATUS_E_DATAOVERFLOW;
  1106. }
  1107. else
  1108. return DBSTATUS_E_CANTCONVERTVALUE;
  1109. switch (vtDst)
  1110. {
  1111. case VT_DATE:
  1112. DATE dosDate;
  1113. if (! SystemTimeToVariantTime(&stUTC, &dosDate) )
  1114. return DBSTATUS_E_DATAOVERFLOW;
  1115. Win4Assert( cbDstBuf >= sizeof DATE );
  1116. RtlCopyMemory(pbDstBuf, &dosDate, sizeof DATE);
  1117. break;
  1118. case VT_FILETIME:
  1119. FILETIME ftUTC;
  1120. if (! SystemTimeToFileTime(&stUTC, &ftUTC) )
  1121. return DBSTATUS_E_DATAOVERFLOW;
  1122. Win4Assert( cbDstBuf >= sizeof FILETIME );
  1123. RtlCopyMemory(pbDstBuf, &ftUTC, sizeof FILETIME);
  1124. break;
  1125. case DBTYPE_DBTIMESTAMP:
  1126. {
  1127. // does not use local time
  1128. DBTIMESTAMP dbUTC;
  1129. dbUTC.year = stUTC.wYear;
  1130. dbUTC.month = stUTC.wMonth;
  1131. dbUTC.day = stUTC.wDay;
  1132. dbUTC.hour = stUTC.wHour;
  1133. dbUTC.minute = stUTC.wMinute;
  1134. dbUTC.second = stUTC.wSecond;
  1135. dbUTC.fraction = stUTC.wMilliseconds * 1000000;
  1136. Win4Assert( cbDstBuf >= sizeof dbUTC );
  1137. RtlCopyMemory(pbDstBuf, &dbUTC, sizeof dbUTC);
  1138. }
  1139. break;
  1140. case DBTYPE_DBDATE:
  1141. {
  1142. DBDATE dbUTC;
  1143. dbUTC.year = stUTC.wYear;
  1144. dbUTC.month = stUTC.wMonth;
  1145. dbUTC.day = stUTC.wDay;
  1146. Win4Assert( cbDstBuf >= sizeof dbUTC );
  1147. RtlCopyMemory(pbDstBuf, &dbUTC, sizeof dbUTC);
  1148. }
  1149. break;
  1150. case DBTYPE_DBTIME:
  1151. {
  1152. DBTIME dbUTC;
  1153. dbUTC.hour = stUTC.wHour;
  1154. dbUTC.minute = stUTC.wMinute;
  1155. dbUTC.second = stUTC.wSecond;
  1156. Win4Assert( cbDstBuf >= sizeof dbUTC );
  1157. RtlCopyMemory(pbDstBuf, &dbUTC, sizeof dbUTC);
  1158. }
  1159. break;
  1160. default:
  1161. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  1162. tbDebugOut(( DEB_WARN,
  1163. "_StoreDate - Unexpected dest storage type %4x\n",
  1164. vtDst));
  1165. break;
  1166. }
  1167. return DstStatus;
  1168. } //_StoreDate
  1169. //+---------------------------------------------------------------------------
  1170. //
  1171. // Member: COLEDBVariant::CanConvertType, static public
  1172. //
  1173. // Synopsis: Indicate whether a type conversion is valid. Uses the OLEDB
  1174. // Data Conversion Library.
  1175. //
  1176. // Arguments: [wFromType] -- source type
  1177. // [wToType] -- destination type
  1178. // [xDataConvert] -- OLEDB IDataConvert interface pointer
  1179. //
  1180. // Returns: TRUE if the conversion is available, FALSE otherwise.
  1181. //
  1182. // History: 13 Jan 98 VikasMan Created
  1183. //
  1184. //----------------------------------------------------------------------------
  1185. BOOL COLEDBVariant::CanConvertType(
  1186. DBTYPE wFromType,
  1187. DBTYPE wToType,
  1188. XInterface<IDataConvert>& xDataConvert)
  1189. {
  1190. if ( xDataConvert.IsNull( ) )
  1191. {
  1192. // use COLEDBVariant's helper function to get the IDataConvert ptr
  1193. if ( !_GetIDataConvert( xDataConvert ) )
  1194. {
  1195. // bail out
  1196. return FALSE;
  1197. }
  1198. }
  1199. SCODE sc = xDataConvert->CanConvert( wFromType, wToType );
  1200. if ( sc != S_OK && sc != S_FALSE )
  1201. {
  1202. QUIETTHROW(CException(sc)); // bad type
  1203. }
  1204. return ( sc == S_OK );
  1205. }
  1206. //+---------------------------------------------------------------------------
  1207. //
  1208. // Member: COLEDBVariant::_GetIDataConvert, static private
  1209. //
  1210. // Synopsis: Gets the IDataConvert interface
  1211. //
  1212. // Arguments: [xDataConvert] -- OLEDB IDataConvert interface pointer
  1213. //
  1214. // Returns: TRUE if the successful, else FALSE
  1215. //
  1216. // Notes: Make sure thet xDataConvert is null before calling this func.
  1217. //
  1218. // History: 13 Jan 98 VikasMan Created
  1219. //
  1220. //----------------------------------------------------------------------------
  1221. inline
  1222. BOOL COLEDBVariant::_GetIDataConvert( XInterface<IDataConvert>& xDataConvert )
  1223. {
  1224. Win4Assert( xDataConvert.IsNull( ) );
  1225. SCODE sc = CoCreateInstance( CLSID_OLEDB_CONVERSIONLIBRARY,
  1226. NULL,
  1227. CLSCTX_SERVER,
  1228. IID_IDataConvert,
  1229. xDataConvert.GetQIPointer( ) );
  1230. if ( FAILED(sc) )
  1231. {
  1232. // for some reason we could not get the IDataConvert interface
  1233. tbDebugOut(( DEB_ERROR,
  1234. "_GetIDataConvert - Couldn't get IDataConvert interface %x\n", sc ));
  1235. return FALSE;
  1236. }
  1237. // Set the OLEDB ver to 2.00
  1238. XInterface<IDCInfo> xIDCInfo;
  1239. DCINFO rgInfo[] = {{DCINFOTYPE_VERSION, {VT_UI4, 0, 0, 0, 0x0200}}};
  1240. sc = xDataConvert->QueryInterface( IID_IDCInfo, xIDCInfo.GetQIPointer( ) );
  1241. if ( SUCCEEDED(sc) )
  1242. {
  1243. sc = xIDCInfo->SetInfo( NUMELEM(rgInfo), rgInfo );
  1244. }
  1245. if ( FAILED(sc) )
  1246. {
  1247. tbDebugOut(( DEB_ERROR,
  1248. "_GetIDataConvert - Can't set OLEDB ver to 2.0. Error: 0x%x\n",
  1249. sc));
  1250. Win4Assert( ! "Failed to set OLEDB conversion library version!" );
  1251. xDataConvert.Free();
  1252. return FALSE;
  1253. }
  1254. return TRUE;
  1255. }