Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1035 lines
32 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 1999
  5. //
  6. // File: tblvarnt.hxx
  7. //
  8. // Contents: Helper class for PROPVARIANTs in tables
  9. //
  10. // Classes: CTableVariant - PROPVARIANT wrapper; adds useful methods
  11. //
  12. // History: 28 Jan 1994 AlanW Created
  13. //
  14. //--------------------------------------------------------------------------
  15. #pragma once
  16. #include <tblalloc.hxx>
  17. // A few useful defines and inline funcs.
  18. #define BSTRLEN(bstrVal) *((ULONG *) bstrVal - 1)
  19. inline BOOL IsLPWSTR(VARTYPE vt) { return VT_LPWSTR == vt;}
  20. inline BOOL IsLPSTR(VARTYPE vt) { return VT_LPSTR == vt;}
  21. inline BOOL IsVector(VARTYPE vt) { return 0 != ( vt & VT_VECTOR );}
  22. inline BOOL IsArray(VARTYPE vt) { return 0 != ( vt & VT_ARRAY );}
  23. inline BOOL IsVectorOrArray(VARTYPE vt)
  24. {
  25. return 0 != ( vt & (VT_VECTOR | VT_ARRAY));
  26. }
  27. inline BOOL StatusSuccess(DBSTATUS status)
  28. {
  29. return (status == DBSTATUS_S_OK ||
  30. status == DBSTATUS_S_ISNULL ||
  31. status == DBSTATUS_S_TRUNCATED ||
  32. status == DBSTATUS_S_DEFAULT);
  33. }
  34. //+-------------------------------------------------------------------------
  35. //
  36. // Class: CTableVariant
  37. //
  38. // Purpose: Wraps PROPVARIANT struct, adding useful methods.
  39. //
  40. // Interface:
  41. //
  42. // Notes: Because the underlying base data *is* a variant, this
  43. // class cannot have any non-static members (including
  44. // a vtable).
  45. //
  46. // This class now deals only with PROPVARIANT. If conversion
  47. // to other OLE-DB types or Automation variant types is needed,
  48. // use COLEDBVaraint class (which derives from this class).
  49. //
  50. // The class is also used to extend the PROPVARIANT for use
  51. // internally in tables. For internal storage, the
  52. // PROPVARIANT.reserved2 field is used to store the total
  53. // size of variable data pointed to by the variant.
  54. // Also, the pointers within internal variants may
  55. // be offsets to storage. There are three cases of
  56. // the way offsets may be stored.
  57. //
  58. // The pointer inside the internal variant structure
  59. // itself (to a vector, string, blob or UUID) is an
  60. // offset based from the variable data allocator used
  61. // to allocate the space.
  62. //
  63. // For vectors which contain pointers (e.g., vectors of
  64. // strings), the pointers are stored as offsets based from
  65. // the vector's address.
  66. //
  67. // For vectors of variants, the above two rules apply to
  68. // each embedded variant. The rules apply recursively to
  69. // embedded variants which are vectors of variant.
  70. //
  71. // Use of these rules permits the variable data of a variant
  72. // to be treated as a unit and to be block copied from place
  73. // to place without affecting the internally stored offsets.
  74. //
  75. // History: 21 Mar 1994 AlanW Created
  76. // 09 Jan 1998 VikasMan Mofified the class to deal ONLY
  77. // with PROPVARIANTs. Moved rest of
  78. // the functionality in the
  79. // COLEDBVaraiant class
  80. // 01 Sep 1999 KLam Reinstated FixDataPointers used
  81. // for Win64 Clients -> Win32 Servers
  82. // 04 Nov 1999 KLam Added VarDataSize32
  83. // for Win64 Servers -> Win32 Clients
  84. //
  85. //--------------------------------------------------------------------------
  86. class CTableVariant: public tagPROPVARIANT {
  87. public:
  88. //
  89. // varntData is indexed by variant type, and gives the width,
  90. // alignment constraints and other information for a scalar
  91. // variant type.
  92. //
  93. struct VARNT_DATA {
  94. USHORT width; // width in bytes of data
  95. USHORT alignment; // required alignment of data
  96. USHORT flags; // flags about variants
  97. };
  98. static const VARNT_DATA varntData[], varntExtData[];
  99. static const unsigned cVarntData, cVarntExtData;
  100. #ifdef _WIN64
  101. static const VARNT_DATA varntData32[], varntExtData32[];
  102. #endif
  103. enum varntDataFlags {
  104. CanBeVector = 1, // vector forms are permitted
  105. ByRef = 2, // variant data has pointer to real data
  106. CntRef = 4, // variant data has count followed by pointer
  107. StoreDirect = 8, // variant form is indirect, store as fixed
  108. MultiSize = 0x10, // used for chapters and bookmarks, for data
  109. // like UI1 that is inline in client output
  110. SimpleType = 0x20, // simple inline datatype, like VT_I4
  111. OAType = 0x40, // valid type for automation VARIANT
  112. };
  113. static BOOL IsSimpleType( VARTYPE vtype )
  114. {
  115. const VARNT_DATA & rvarInfo = _FindVarType( vtype );
  116. return ( 0 != ( rvarInfo.flags & SimpleType ) );
  117. }
  118. static BOOL IsSimpleOAType( VARTYPE vtype )
  119. {
  120. const VARNT_DATA & rvarInfo = _FindVarType( vtype );
  121. return ( (SimpleType|OAType) == ( rvarInfo.flags & (SimpleType|OAType ) ) );
  122. }
  123. static BOOL CanBeVectorType( VARTYPE vtype )
  124. {
  125. const VARNT_DATA & rvarInfo = _FindVarType( vtype );
  126. return ( 0 != ( rvarInfo.flags & CanBeVector ) );
  127. }
  128. // NOTE: in NT5, VARIANT can include additional types. This operates on
  129. // the traditional types so old clients can understand the variants
  130. // we produce.
  131. static BOOL IsOAType( VARTYPE vtype )
  132. {
  133. const VARNT_DATA & rvarInfo = _FindVarType( vtype );
  134. return ( 0 != ( rvarInfo.flags & OAType ) );
  135. }
  136. static BOOL IsByRef( VARTYPE vtype )
  137. {
  138. const VARNT_DATA & rvarInfo = _FindVarType( vtype );
  139. return ( 0 != ( rvarInfo.flags & ByRef ) );
  140. }
  141. //
  142. // Return information about a variant's base type
  143. //
  144. static void VartypeInfo(VARTYPE vtype, USHORT& rcbWidth,
  145. USHORT& rcbAlign, USHORT& rgfFlags) {
  146. const VARNT_DATA& rvarInfo = _FindVarType(vtype);
  147. rcbWidth = rvarInfo.width;
  148. rcbAlign = rvarInfo.alignment;
  149. rgfFlags = rvarInfo.flags;
  150. if (vtype & VT_VECTOR) {
  151. rgfFlags |= CntRef;
  152. }
  153. return;
  154. }
  155. //
  156. // Check if a type is stored in-line in a table row.
  157. //
  158. static BOOL TableIsStoredInline( USHORT fFlags, VARTYPE vtype )
  159. {
  160. if (vtype & (VT_ARRAY | VT_VECTOR | VT_BYREF) ||
  161. vtype == VT_VARIANT ||
  162. (fFlags & (CntRef | ByRef) && ! (fFlags & StoreDirect)))
  163. return FALSE;
  164. return TRUE;
  165. }
  166. static void Free(BYTE * pbData,
  167. VARTYPE vtData,
  168. PVarAllocator & rPool);
  169. //
  170. // Return TRUE iff the variant's type is valid for a property.
  171. //
  172. BOOL IsValidType(void) const
  173. {
  174. // NOTE: we don't expect VT_BYREF in our stored variants
  175. if ( (vt & ~(VT_TYPEMASK | VT_VECTOR | VT_ARRAY)) != 0 ||
  176. (vt & (VT_VECTOR | VT_ARRAY)) == (VT_VECTOR | VT_ARRAY) )
  177. return FALSE;
  178. const VARNT_DATA& rvarInfo = _FindVarType(vt);
  179. if (vt & VT_VECTOR)
  180. return ((rvarInfo.flags & CanBeVector) == CanBeVector);
  181. if (vt & VT_ARRAY)
  182. return ((rvarInfo.flags & (OAType|CanBeVector)) != 0);
  183. return rvarInfo.width != 0;
  184. }
  185. //
  186. // Return TRUE iff the variant contains a pointer at offset 8
  187. //
  188. BOOL VariantPointerInFirstWord (void) const
  189. {
  190. return ( (vt & (VT_ARRAY | VT_BYREF)) != 0 ||
  191. ( (vt & VT_VECTOR) == 0 &&
  192. (_FindVarType(vt).flags & ByRef) == ByRef) );
  193. // return ((vt == VT_CLSID) ||
  194. // (vt == VT_LPWSTR) ||
  195. // (vt == VT_LPSTR) ||
  196. // (vt == VT_BSTR) ||
  197. // (vt == VT_CF) ||
  198. // (vt == VT_STREAM) ||
  199. // (vt == VT_STREAMED_OBJECT) ||
  200. // (vt == VT_STORAGE) ||
  201. // (vt == VT_STORED_OBJECT));
  202. }
  203. //
  204. // Return TRUE iff the variant contains a pointer at offset 0xC
  205. //
  206. BOOL VariantPointerInSecondWord (void) const
  207. {
  208. return ( (vt & VT_VECTOR) == VT_VECTOR ||
  209. ( (vt & (VT_ARRAY | VT_BYREF)) == 0 &&
  210. (_FindVarType(vt).flags & CntRef) == CntRef) );
  211. }
  212. //
  213. // Copy data stored outside the variant structure itself
  214. //
  215. void Copy( CTableVariant* pvarntDest,
  216. PVarAllocator &rVarAllocator,
  217. USHORT cbDest,
  218. BYTE* pbBias = 0) const;
  219. void OffsetsToPointers(PVarAllocator &rPool)
  220. {
  221. if ( VariantPointerInFirstWord() )
  222. pszVal = (LPSTR) rPool.OffsetToPointer((ULONG_PTR) pszVal);
  223. else if ( VariantPointerInSecondWord() )
  224. blob.pBlobData = (BYTE *) rPool.OffsetToPointer((ULONG_PTR) blob.pBlobData);
  225. }
  226. DBSTATUS CopyOrCoerce( BYTE * pbDest,
  227. DBLENGTH cbDest,
  228. VARTYPE vtDest,
  229. DBLENGTH & rcbDstLen,
  230. PVarAllocator & rVarAllocator) const;
  231. //
  232. // Compute variable data size
  233. //
  234. ULONG VarDataSize (void) const;
  235. #ifdef _WIN64
  236. //
  237. // Convert offsets to pointers in variable data (32server->64client)
  238. //
  239. void FixDataPointers( BYTE* pbBias, CFixedVarAllocator *pAlloc );
  240. //
  241. // Compute variable data size for 32 bit
  242. //
  243. ULONG VarDataSize32 ( BYTE *pbBase,
  244. ULONG_PTR ulpOffset ) const;
  245. //
  246. // Compute the size of a safearray for 32 bit
  247. //
  248. static ULONG SaComputeSize32 ( VARTYPE vt,
  249. SAFEARRAY & saSrc,
  250. BYTE *pbBase,
  251. ULONG_PTR ulpOffset );
  252. //
  253. // Return information about a variant's base type
  254. //
  255. static void VartypeInfo32( VARTYPE vtype, USHORT& rcbWidth,
  256. USHORT& rcbAlign, USHORT& rgfFlags) {
  257. const VARNT_DATA& rvarInfo = _FindVarType32(vtype);
  258. rcbWidth = rvarInfo.width;
  259. rcbAlign = rvarInfo.alignment;
  260. rgfFlags = rvarInfo.flags;
  261. if (vtype & VT_VECTOR) {
  262. rgfFlags |= CntRef;
  263. }
  264. return;
  265. }
  266. #endif
  267. //
  268. // Initialize a variant from base parts
  269. //
  270. void Init( VARTYPE vt,
  271. BYTE* pbData = 0,
  272. ULONG cbData = 0);
  273. protected:
  274. enum { ulCoercionCodePage = CP_ACP };
  275. DBSTATUS _StoreString(BYTE * pbDstBuf,
  276. DBLENGTH cbDstBuf,
  277. VARTYPE vtDst,
  278. DBLENGTH & rcbDstLen,
  279. PVarAllocator & rPool) const;
  280. DBSTATUS _StoreDecimal(DECIMAL * pDecimal,
  281. LONG lElem = 0) const;
  282. DBSTATUS _StoreInteger(VARTYPE vtDst,
  283. BYTE * pbDstBuf,
  284. LONG lElem = 0) const;
  285. DBSTATUS _StoreIntegerUnSignedToSigned( VARTYPE vtDst,
  286. BYTE * pbDstBuf,
  287. LONG lElem = 0) const;
  288. DBSTATUS _StoreIntegerSignedToSigned( VARTYPE vtDst,
  289. BYTE * pbDstBuf,
  290. LONG lElem = 0) const;
  291. DBSTATUS _StoreIntegerUnSignedToUnSigned(VARTYPE vtDst,
  292. BYTE * pbDstBuf,
  293. LONG lElem = 0) const;
  294. DBSTATUS _StoreIntegerSignedToUnSigned( VARTYPE vtDst,
  295. BYTE * pbDstBuf,
  296. LONG lElem = 0) const;
  297. private:
  298. void SetDataSize (ULONG cbVarData);
  299. void ResetDataSize ();
  300. VOID * CopyData( PVarAllocator &rVarAllocator,
  301. USHORT cbDest,
  302. BYTE* pbBias = 0) const;
  303. static const USHORT _wInternalSig;
  304. inline BOOL _IsInternalVariant( void ) const;
  305. static inline const VARNT_DATA& _FindVarType( VARTYPE vt );
  306. #ifdef _WIN64
  307. static inline const VARNT_DATA& _FindVarType32( VARTYPE vt );
  308. #endif
  309. DBSTATUS _GetUL8Value(ULONGLONG * ul8Value, LONG lElem = 0L) const;
  310. DBSTATUS _GetL8Value(LONGLONG * l8Value, LONG lElem = 0L ) const;
  311. };
  312. const USHORT minExtVariantType = 128;
  313. #ifdef _WIN64
  314. //+-------------------------------------------------------------------------
  315. //
  316. // Method: CTableVariant::_FindVarType32, inline private
  317. //
  318. // Synopsis: Return a 32 bit description of a variant given its type
  319. //
  320. // Arguments: [vt] - the variant type to be looked up
  321. //
  322. // Returns: VARNT_DATA& - a reference to the variant type information
  323. //
  324. //--------------------------------------------------------------------------
  325. inline const CTableVariant::VARNT_DATA& CTableVariant::_FindVarType32(
  326. VARTYPE vtype
  327. ) {
  328. USHORT vtBase = vtype & VT_TYPEMASK;
  329. if (vtBase < cVarntData)
  330. {
  331. return varntData32[vtBase];
  332. }
  333. else if (vtBase >= minExtVariantType &&
  334. vtBase < minExtVariantType + cVarntExtData)
  335. {
  336. return varntExtData32[ vtBase - minExtVariantType ];
  337. }
  338. else
  339. {
  340. return varntData32[0]; // return ref. to VT_EMPTY info
  341. }
  342. }
  343. #endif // _WIN64
  344. //+-------------------------------------------------------------------------
  345. //
  346. // Method: CTableVariant::_FindVarType, inline private
  347. //
  348. // Synopsis: Return a description of a variant given its type
  349. //
  350. // Arguments: [vt] - the variant type to be looked up
  351. //
  352. // Returns: VARNT_DATA& - a reference to the variant type information
  353. //
  354. //--------------------------------------------------------------------------
  355. inline const CTableVariant::VARNT_DATA& CTableVariant::_FindVarType(
  356. VARTYPE vtype
  357. ) {
  358. USHORT vtBase = vtype & VT_TYPEMASK;
  359. if (vtBase < cVarntData)
  360. {
  361. return varntData[vtBase];
  362. }
  363. else if (vtBase >= minExtVariantType &&
  364. vtBase < minExtVariantType + cVarntExtData)
  365. {
  366. return varntExtData[ vtBase - minExtVariantType ];
  367. }
  368. else
  369. {
  370. return varntData[0]; // return ref. to VT_EMPTY info
  371. }
  372. }
  373. //+-------------------------------------------------------------------------
  374. //
  375. // Method: CTableVariant::_IsInternalVariant, inline private
  376. //
  377. // Synopsis: Return whether the variant is an internal form with
  378. // pointers stored as offsets and variable data embedded.
  379. //
  380. // Arguments: -None-
  381. //
  382. // Returns: BOOL - TRUE if the variant is in internal form.
  383. //
  384. //--------------------------------------------------------------------------
  385. inline BOOL CTableVariant::_IsInternalVariant(
  386. void
  387. ) const {
  388. return (wReserved1 == _wInternalSig &&
  389. wReserved3 == _wInternalSig &&
  390. VT_DECIMAL != vt);
  391. }
  392. //+-------------------------------------------------------------------------
  393. //
  394. // Method: CTableVariant::SetDataSize, public
  395. //
  396. // Synopsis: Set variable data size for an internal variant
  397. //
  398. // Arguments: [cbVarData] - length of variable data associated with
  399. // the variant.
  400. //
  401. // Returns: -Nothing-
  402. //
  403. // Notes: For variants which are stored internally in the table,
  404. // the size is computed once and stored in the wReserved2
  405. // field of the variant structure.
  406. //
  407. //--------------------------------------------------------------------------
  408. inline void CTableVariant::SetDataSize (ULONG cbVarData)
  409. {
  410. Win4Assert(cbVarData <= USHRT_MAX);
  411. if (vt != VT_DECIMAL) // this uses the reserved fields
  412. {
  413. wReserved2 = (USHORT)cbVarData;
  414. //
  415. // Put a signature value in the variant to distinguish internal
  416. // vs. external variants.
  417. //
  418. wReserved1 = wReserved3 = _wInternalSig;
  419. }
  420. }
  421. inline void CTableVariant::ResetDataSize ()
  422. {
  423. if (vt != VT_DECIMAL)
  424. wReserved1 = wReserved2 = wReserved3 = 0;
  425. }
  426. //+-------------------------------------------------------------------------
  427. //
  428. // Member: CTableVariant::_StoreDecimal, private
  429. //
  430. // Synopsis: Copy variant integer data, coercing to VT_DECIMAL
  431. //
  432. // Arguments: [pDec] -- destination buffer
  433. // [lElem] -- element of vector to convert
  434. //
  435. // Returns: status for copy
  436. //
  437. // History: 25 Nov 1996 AlanW Created
  438. //
  439. //--------------------------------------------------------------------------
  440. inline DBSTATUS CTableVariant::_StoreDecimal( DECIMAL * pDec,
  441. LONG lElem ) const
  442. {
  443. ULONGLONG ul8Value = 0;
  444. Win4Assert( (vt & VT_TYPEMASK) != VT_DECIMAL );
  445. DBSTATUS DstStatus = _GetUL8Value (&ul8Value, lElem);
  446. if (DBSTATUS_S_OK == DstStatus)
  447. {
  448. pDec->scale = 0;
  449. pDec->sign = 0;
  450. pDec->Hi32 = 0;
  451. pDec->Lo64 = ul8Value;
  452. }
  453. else if ( DBSTATUS_E_CANTCONVERTVALUE == DstStatus )
  454. {
  455. LONGLONG l8Value;
  456. DstStatus = _GetL8Value (&l8Value, lElem);
  457. if (DBSTATUS_S_OK == DstStatus)
  458. {
  459. pDec->scale = 0;
  460. pDec->Hi32 = 0;
  461. if ( l8Value < 0 )
  462. {
  463. pDec->sign = DECIMAL_NEG;
  464. pDec->Lo64 = -l8Value;
  465. }
  466. else
  467. {
  468. pDec->sign = 0;
  469. pDec->Lo64 = l8Value;
  470. }
  471. }
  472. }
  473. return DstStatus;
  474. } //_StoreDecimal
  475. //+-------------------------------------------------------------------------
  476. //
  477. // Member: CTableVariant::_StoreIntegerUnSignedToSigned, private
  478. //
  479. // Synopsis: Copy variant integer data, coerce if possible
  480. //
  481. // Arguments: [vtDst] -- type of the destination
  482. // [pbDstBuf] -- destination buffer
  483. // [lElem] -- element of vector to convert
  484. //
  485. // Returns: status for copy
  486. //
  487. // History: 24 Jul 1995 dlee Created
  488. //
  489. //--------------------------------------------------------------------------
  490. inline DBSTATUS CTableVariant::_StoreIntegerUnSignedToSigned(
  491. VARTYPE vtDst,
  492. BYTE * pbDstBuf,
  493. LONG lElem ) const
  494. {
  495. ULONGLONG ul8Value = 0;
  496. DBSTATUS DstStatus = _GetUL8Value(&ul8Value, lElem);
  497. // Store the ULONGLONG assuming alignment verified at accessor creation
  498. if (DBSTATUS_S_OK == DstStatus)
  499. {
  500. switch ( vtDst )
  501. {
  502. case VT_I1 :
  503. * (signed char *) pbDstBuf = (signed char) ul8Value;
  504. if ( ul8Value > SCHAR_MAX )
  505. DstStatus = DBSTATUS_E_DATAOVERFLOW;
  506. break;
  507. case VT_I2 :
  508. * (short *) pbDstBuf = (short) ul8Value;
  509. if ( ul8Value > SHRT_MAX )
  510. DstStatus = DBSTATUS_E_DATAOVERFLOW;
  511. break;
  512. case VT_I4 :
  513. case VT_INT :
  514. * (long *) pbDstBuf = (long) ul8Value;
  515. if ( ul8Value > LONG_MAX )
  516. DstStatus = DBSTATUS_E_DATAOVERFLOW;
  517. break;
  518. case VT_I8 :
  519. * (LONGLONG *) pbDstBuf = (LONGLONG) ul8Value;
  520. if ( ul8Value > _I64_MAX )
  521. DstStatus = DBSTATUS_E_DATAOVERFLOW;
  522. break;
  523. default:
  524. //tbDebugOut(( DEB_WARN, "US bad dst type %4x\n", vtDst ));
  525. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  526. break;
  527. }
  528. }
  529. return DstStatus;
  530. } //_StoreIntegerUnSignedToSigned
  531. //+-------------------------------------------------------------------------
  532. //
  533. // Member: CTableVariant::_StoreIntegerUnSignedToUnSigned, private
  534. //
  535. // Synopsis: Copy variant integer data, coerce if possible
  536. //
  537. // Arguments: [vtDst] -- type of the destination
  538. // [pbDstBuf] -- destination buffer
  539. // [lElem] -- element of vector to convert
  540. //
  541. // Returns: status for copy
  542. //
  543. // History: 24 Jul 1995 dlee Created
  544. //
  545. //--------------------------------------------------------------------------
  546. inline DBSTATUS CTableVariant::_StoreIntegerUnSignedToUnSigned(
  547. VARTYPE vtDst,
  548. BYTE * pbDstBuf,
  549. LONG lElem ) const
  550. {
  551. ULONGLONG ul8Value;
  552. DBSTATUS DstStatus = _GetUL8Value(&ul8Value, lElem);
  553. // Store the ULONGLONG assuming alignment verified at accessor creation
  554. if (DBSTATUS_S_OK == DstStatus)
  555. {
  556. switch ( vtDst )
  557. {
  558. case VT_UI1 :
  559. * (unsigned char *) pbDstBuf = (char) ul8Value;
  560. if ( ul8Value > UCHAR_MAX )
  561. DstStatus = DBSTATUS_E_DATAOVERFLOW;
  562. break;
  563. case VT_UI2 :
  564. * (unsigned short *) pbDstBuf = (unsigned short) ul8Value;
  565. if ( ul8Value > USHRT_MAX )
  566. DstStatus = DBSTATUS_E_DATAOVERFLOW;
  567. break;
  568. case VT_UI4 :
  569. case VT_UINT :
  570. * (unsigned long *) pbDstBuf = (unsigned long) ul8Value;
  571. if ( ul8Value > ULONG_MAX )
  572. DstStatus = DBSTATUS_E_DATAOVERFLOW;
  573. break;
  574. case VT_UI8 :
  575. * (ULONGLONG *) pbDstBuf = ul8Value;
  576. break;
  577. default:
  578. //tbDebugOut(( DEB_WARN, "UU bad dst type %4x\n", vtDst ));
  579. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  580. break;
  581. }
  582. }
  583. return DstStatus;
  584. } //_StoreIntegerUnSignedToUnSigned
  585. //+-------------------------------------------------------------------------
  586. //
  587. // Member: CTableVariant::_StoreIntegerSignedToUnSigned, private
  588. //
  589. // Synopsis: Copy variant integer data, coerce if possible
  590. //
  591. // Arguments: [vtDst] -- type of the destination
  592. // [pbDstBuf] -- destination buffer
  593. // [lElem] -- element of vector to convert
  594. //
  595. // Returns: status for copy
  596. //
  597. // History: 24 Jul 1995 dlee Created
  598. //
  599. //--------------------------------------------------------------------------
  600. inline DBSTATUS CTableVariant::_StoreIntegerSignedToUnSigned(
  601. VARTYPE vtDst,
  602. BYTE * pbDstBuf,
  603. LONG lElem ) const
  604. {
  605. LONGLONG l8Value;
  606. DBSTATUS DstStatus = _GetL8Value( &l8Value, lElem ) ;
  607. // Store the LONGLONG assuming alignment verified at accessor creation
  608. if (DBSTATUS_S_OK == DstStatus)
  609. {
  610. if ( l8Value < 0 )
  611. DstStatus = DBSTATUS_E_SIGNMISMATCH;
  612. else
  613. {
  614. switch ( vtDst )
  615. {
  616. case VT_UI1 :
  617. * (unsigned char *) pbDstBuf = (unsigned char) l8Value;
  618. if ( l8Value > UCHAR_MAX )
  619. DstStatus = DBSTATUS_E_DATAOVERFLOW;
  620. break;
  621. case VT_UI2 :
  622. * (unsigned short *) pbDstBuf = (unsigned short) l8Value;
  623. if ( l8Value > USHRT_MAX )
  624. DstStatus = DBSTATUS_E_DATAOVERFLOW;
  625. break;
  626. case VT_UI4 :
  627. case VT_UINT :
  628. * (unsigned long *) pbDstBuf = (unsigned long) l8Value;
  629. if ( l8Value > ULONG_MAX )
  630. DstStatus = DBSTATUS_E_DATAOVERFLOW;
  631. break;
  632. case VT_UI8 :
  633. * (ULONGLONG *) pbDstBuf = (ULONGLONG) l8Value;
  634. break;
  635. default:
  636. //tbDebugOut(( DEB_WARN, "SU bad dst type %4x\n", vtDst ));
  637. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  638. break;
  639. }
  640. }
  641. }
  642. return DstStatus;
  643. } //_StoreIntegerSignedToUnSigned
  644. //+-------------------------------------------------------------------------
  645. //
  646. // Member: CTableVariant::_StoreIntegerSignedToSigned, private
  647. //
  648. // Synopsis: Copy variant integer data, coerce if possible
  649. //
  650. // Arguments: [vtDst] -- type of the destination
  651. // [pbDstBuf] -- destination buffer
  652. // [lElem] -- element of vector to convert
  653. //
  654. // Returns: status for copy
  655. //
  656. // History: 24 Jul 1995 dlee Created
  657. //
  658. //--------------------------------------------------------------------------
  659. inline DBSTATUS CTableVariant::_StoreIntegerSignedToSigned(
  660. VARTYPE vtDst,
  661. BYTE * pbDstBuf,
  662. LONG lElem ) const
  663. {
  664. LONGLONG l8Value = 0;
  665. DBSTATUS DstStatus = _GetL8Value ( &l8Value, lElem );
  666. // Store the ULONGLONG assuming alignment verified at accessor creation
  667. if (DBSTATUS_S_OK == DstStatus)
  668. {
  669. switch ( vtDst )
  670. {
  671. case VT_I1 :
  672. * (signed char *) pbDstBuf = (signed char) l8Value;
  673. if (l8Value < SCHAR_MIN || l8Value > SCHAR_MAX)
  674. DstStatus = DBSTATUS_E_DATAOVERFLOW;
  675. break;
  676. case VT_I2 :
  677. * (short *) pbDstBuf = (short) l8Value;
  678. if (l8Value < SHRT_MIN || l8Value > SHRT_MAX)
  679. DstStatus = DBSTATUS_E_DATAOVERFLOW;
  680. break;
  681. case VT_I4 :
  682. * (long *) pbDstBuf = (long) l8Value;
  683. if (l8Value < LONG_MIN || l8Value > LONG_MAX)
  684. DstStatus = DBSTATUS_E_DATAOVERFLOW;
  685. break;
  686. case VT_I8 :
  687. * (LONGLONG *) pbDstBuf = l8Value;
  688. break;
  689. default:
  690. //tbDebugOut(( DEB_WARN, "SS bad dst type %4x\n", vtDst ));
  691. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  692. break;
  693. }
  694. }
  695. return DstStatus;
  696. } //_StoreIntegerSignedToSigned
  697. //+-------------------------------------------------------------------------
  698. //
  699. // Member: CTableVariant::_StoreInteger, private
  700. //
  701. // Synopsis: Copy variant integer data, coerce if possible
  702. //
  703. // Arguments: [vtDst] -- type of the destination
  704. // [pbDstBuf] -- destination buffer
  705. // [lElem] -- element of vector to convert
  706. //
  707. // Returns: status for copy
  708. //
  709. // History: 24 Jul 1995 dlee Rewrote to support unsigned values
  710. //
  711. //--------------------------------------------------------------------------
  712. inline BOOL isSignedInteger( VARTYPE vt )
  713. {
  714. return ( VT_I1 == vt ||
  715. VT_I2 == vt ||
  716. VT_I4 == vt ||
  717. VT_INT == vt ||
  718. VT_I8 == vt ||
  719. VT_BOOL == vt );
  720. } //isSignedInteger
  721. inline DBSTATUS CTableVariant::_StoreInteger(
  722. VARTYPE vtDst,
  723. BYTE * pbDstBuf,
  724. LONG lElem ) const
  725. {
  726. // vt is the type of the source of the data
  727. Win4Assert( vt == VT_I1 ||
  728. vt == VT_UI1 ||
  729. vt == VT_I2 ||
  730. vt == VT_UI2 ||
  731. vt == VT_I4 ||
  732. vt == VT_UI4 ||
  733. vt == VT_I8 ||
  734. vt == VT_UI8 ||
  735. vt == VT_INT ||
  736. vt == VT_UINT ||
  737. vt == VT_BOOL ||
  738. vt == VT_ERROR ||
  739. vt == VT_HRESULT ||
  740. vt == VT_FILETIME ||
  741. vt == VT_EMPTY || // empty if object is deleted
  742. vt == (VT_I1 | VT_VECTOR) ||
  743. vt == (VT_UI1 | VT_VECTOR) ||
  744. vt == (VT_I2 | VT_VECTOR) ||
  745. vt == (VT_UI2 | VT_VECTOR) ||
  746. vt == (VT_I4 | VT_VECTOR) ||
  747. vt == (VT_UI4 | VT_VECTOR) ||
  748. vt == (VT_I8 | VT_VECTOR) ||
  749. vt == (VT_UI8 | VT_VECTOR) ||
  750. vt == (VT_BOOL | VT_VECTOR) ||
  751. vt == (VT_ERROR | VT_VECTOR) ||
  752. vt == (VT_FILETIME | VT_VECTOR));
  753. BOOL fSrcSigned = isSignedInteger( vt & VT_TYPEMASK );
  754. BOOL fDstSigned = isSignedInteger( vtDst );
  755. if ( fSrcSigned && fDstSigned )
  756. return _StoreIntegerSignedToSigned( vtDst, pbDstBuf, lElem );
  757. else if ( fSrcSigned && !fDstSigned )
  758. return _StoreIntegerSignedToUnSigned( vtDst, pbDstBuf, lElem );
  759. else if ( !fSrcSigned && fDstSigned )
  760. return _StoreIntegerUnSignedToSigned( vtDst, pbDstBuf, lElem );
  761. else
  762. return _StoreIntegerUnSignedToUnSigned( vtDst, pbDstBuf, lElem );
  763. } //_StoreInteger
  764. //+-------------------------------------------------------------------------
  765. //
  766. // Method: CTableVariant::_GetL8Value, private
  767. //
  768. // Synopsis: Converts the variant value to a LONGLONG
  769. //
  770. // Arguments: [*l8Value] - LONGLONG value on return
  771. // [lElem] - for vector variants, the element whose value is
  772. // to be converted
  773. //
  774. // Returns: DBSTATUS
  775. //
  776. //--------------------------------------------------------------------------
  777. inline DBSTATUS CTableVariant::_GetL8Value(LONGLONG * l8Value, LONG lElem ) const
  778. {
  779. *l8Value = 0;
  780. DBSTATUS DstStatus = DBSTATUS_S_OK;
  781. Win4Assert((lElem == 0) || (vt & DBTYPE_VECTOR));
  782. switch ( vt ) // type of the source
  783. {
  784. case VT_I1:
  785. *l8Value = (CHAR)bVal;
  786. break;
  787. case VT_I2:
  788. case VT_BOOL:
  789. *l8Value = iVal;
  790. break;
  791. case VT_I4:
  792. case VT_INT :
  793. *l8Value = lVal;
  794. break;
  795. case VT_I8:
  796. *l8Value = hVal.QuadPart;
  797. break;
  798. case VT_EMPTY:
  799. case VT_NULL :
  800. DstStatus = DBSTATUS_S_ISNULL;
  801. break;
  802. case VT_I1 | VT_VECTOR: // no i1 vector struct definition use UI1 and cast
  803. *l8Value = (CHAR)caub.pElems[lElem];
  804. break;
  805. case VT_I2 | VT_VECTOR:
  806. *l8Value = cai.pElems[lElem];
  807. break;
  808. case VT_I4 | VT_VECTOR:
  809. *l8Value = cal.pElems[lElem];
  810. break;
  811. case VT_I8 | VT_VECTOR:
  812. *l8Value = cah.pElems[lElem].QuadPart;
  813. break;
  814. default:
  815. //tbDebugOut(( DEB_WARN, "_GetL8Value bad src type %4x\n", vt ));
  816. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  817. break;
  818. }
  819. return DstStatus;
  820. }
  821. //+-------------------------------------------------------------------------
  822. //
  823. // Method: CTableVariant::_GetUL8Value, private
  824. //
  825. // Synopsis: Converts the variant value to a ULONGLONG
  826. //
  827. // Arguments: [*ul8Value] - ULONGLONG value on return
  828. // [lElem] - for vector variants, the element whose value is
  829. // to be converted
  830. //
  831. // Returns: DBSTATUS
  832. //
  833. //--------------------------------------------------------------------------
  834. inline DBSTATUS CTableVariant::_GetUL8Value(ULONGLONG * ul8Value, LONG lElem ) const
  835. {
  836. *ul8Value = 0;
  837. DBSTATUS DstStatus = DBSTATUS_S_OK;
  838. Win4Assert((lElem == 0) || (vt & DBTYPE_VECTOR));
  839. switch ( vt ) // type of the source
  840. {
  841. case VT_UI1:
  842. *ul8Value = bVal;
  843. break;
  844. case VT_UI2:
  845. *ul8Value = uiVal;
  846. break;
  847. case VT_UI4:
  848. case VT_UINT :
  849. case VT_ERROR :
  850. case VT_HRESULT :
  851. *ul8Value = ulVal;
  852. break;
  853. case VT_UI8:
  854. case VT_FILETIME :
  855. *ul8Value = uhVal.QuadPart;
  856. break;
  857. case VT_EMPTY:
  858. case VT_NULL :
  859. DstStatus = DBSTATUS_S_ISNULL;
  860. break;
  861. case VT_UI1 | VT_VECTOR:
  862. *ul8Value = caub.pElems[lElem];
  863. break;
  864. case VT_UI2 | VT_VECTOR:
  865. *ul8Value = caui.pElems[lElem];
  866. break;
  867. case VT_BOOL | VT_VECTOR :
  868. *ul8Value = cabool.pElems[lElem];
  869. break;
  870. case VT_UI4 | VT_VECTOR:
  871. *ul8Value = caul.pElems[lElem];
  872. break;
  873. case VT_ERROR | VT_VECTOR:
  874. *ul8Value = cascode.pElems[lElem];
  875. break;
  876. case VT_UI8 | VT_VECTOR:
  877. *ul8Value = cauh.pElems[lElem].QuadPart;
  878. break;
  879. case VT_FILETIME | VT_VECTOR:
  880. *ul8Value = ((ULARGE_INTEGER *)(&cafiletime.pElems[lElem]))->QuadPart;
  881. break;
  882. default:
  883. //tbDebugOut(( DEB_WARN, "_GetUL8Value bad src type %4x\n", vt ));
  884. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  885. break;
  886. }
  887. return DstStatus;
  888. }