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.

2014 lines
70 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 2000.
  5. //
  6. // File: tblvarnt.cxx
  7. //
  8. // Contents: Class to aid in dealing with PROPVARIANTs in the result table.
  9. //
  10. // Classes: VARNT_DATA - size and allignment constraints of variant types
  11. // CTableVariant - Wrapper around PROPVARIANT
  12. //
  13. // History: 25 Jan 1994 AlanW Created
  14. //
  15. //--------------------------------------------------------------------------
  16. #include "pch.cxx"
  17. #pragma hdrstop
  18. #include <bigtable.hxx>
  19. #include <tblvarnt.hxx>
  20. #include <pmalloc.hxx>
  21. #include "tabledbg.hxx"
  22. //--------------------------------------------------------------------------
  23. //
  24. // The following structure gives the size and allignment requirements
  25. // to store a bare variant type (without the variant overhead) in window
  26. // row data. For variable length data, information about the location
  27. // of pointers in the structure is given.
  28. //
  29. // Flags information is given as follows:
  30. // 01 (CanBeVector) - base type can be in a vector
  31. // 02 (ByRef) - includes pointer in first word of data part
  32. // 04 (CntRef) - includes pointer in second word of data part
  33. // 08 (StoreDirect) - variant form includes pointer; store direct in table
  34. // 10 (MultiSize) - for data like BYTES that is inline in client output
  35. // 20 (SimpleType) - simple inline datatype, like VT_I4
  36. // 40 (OAType) - valid in OLE Automation variants (older style)
  37. //
  38. // NOTE: This table includes all valid types in PROPVARIANT;
  39. // it is not limited to types in OLE-DB's appendix A.
  40. // NOTE: Some types are listed in wtypes.h as being valid in automation
  41. // variants, but we can't mark them as OAType until the language
  42. // interpreters catch up and recognize those types.
  43. //
  44. //--------------------------------------------------------------------------
  45. const CTableVariant::VARNT_DATA CTableVariant::varntData [] = {
  46. // DBTYPE_VECTOR 0x1000
  47. // DBTYPE_BYREF 0x4000
  48. /* 0 0 VT_EMPTY */ { 0, 0, SimpleType|OAType},
  49. /* 1 1 VT_NULL */ { 0, 0, SimpleType},
  50. /* 2 2 VT_I2 */ { sizeof (short), sizeof (short), CanBeVector|SimpleType|OAType},
  51. /* 3 3 VT_I4 */ { sizeof (long), sizeof (long), CanBeVector|SimpleType|OAType},
  52. /* 4 4 VT_R4 */ { sizeof (float), sizeof (float), CanBeVector|SimpleType|OAType},
  53. /* 5 5 VT_R8 */ { sizeof (double), sizeof (double), CanBeVector|SimpleType|OAType},
  54. /* 6 6 VT_CY */ { sizeof (CY), sizeof (CY), CanBeVector|SimpleType|OAType},
  55. /* 7 7 VT_DATE */ { sizeof (DATE), sizeof (DATE), CanBeVector|SimpleType|OAType},
  56. /* 8 8 VT_BSTR */ { sizeof (void*), sizeof (void*), CanBeVector|ByRef|OAType},
  57. /* 9 9 VT_DISPATCH*/ { sizeof (void *), sizeof (void *), 0},
  58. /* a 10 VT_ERROR */ { sizeof(SCODE), sizeof(SCODE), CanBeVector|SimpleType|OAType},
  59. /* b 11 VT_BOOL */ { sizeof (VARIANT_BOOL), sizeof (VARIANT_BOOL), CanBeVector|SimpleType|OAType},
  60. /* c 12 VT_VARIANT */ { sizeof (PROPVARIANT), sizeof (double), ByRef|StoreDirect|CanBeVector|OAType},
  61. /* d 13 VT_UNKNOWN */ { sizeof (void *), sizeof (void *), 0},
  62. /* e 14 VT_DECIMAL */ { sizeof (DECIMAL), sizeof (LARGE_INTEGER), SimpleType|OAType},
  63. /* f 15 */ { 0, 0, 0},
  64. /* 10 16 VT_I1 */ { sizeof(char), sizeof(char), CanBeVector|SimpleType},
  65. /* 11 17 VT_UI1 */ { sizeof(UCHAR), sizeof(UCHAR), CanBeVector|SimpleType|OAType},
  66. /* 12 18 VT_UI2 */ { sizeof(unsigned short), sizeof(unsigned short), CanBeVector|SimpleType},
  67. /* 13 19 VT_UI4 */ { sizeof(unsigned long), sizeof(unsigned long), CanBeVector|SimpleType},
  68. /* 14 20 VT_I8 */ { sizeof (LARGE_INTEGER), sizeof (LARGE_INTEGER), CanBeVector|SimpleType},
  69. /* 15 21 VT_UI8 */ { sizeof (LARGE_INTEGER), sizeof (LARGE_INTEGER), CanBeVector|SimpleType},
  70. /* 16 22 VT_INT */ { sizeof (INT), sizeof (INT), SimpleType},
  71. /* 17 23 VT_UINT */ { sizeof (UINT), sizeof (UINT), SimpleType},
  72. // Codes 24-29 are valid for typelibs only
  73. /* 18 24 */ { 0, 0, 0},
  74. {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, // 25-29, unused
  75. /* 1e 30 VT_LPSTR */ { sizeof (LPSTR), sizeof (LPSTR), CanBeVector|ByRef},
  76. /* 1f 31 VT_LPWSTR */ { sizeof (LPWSTR), sizeof (LPWSTR), CanBeVector|ByRef},
  77. /* 20 32 */ { 0, 0, 0},
  78. /* 21 33 */ { 0, 0, 0},
  79. /* 22 34 */ { 0, 0, 0},
  80. /* 23 35 */ { 0, 0, 0},
  81. /* 24 36 VT_RECORD? */ { 0, 0, 0}, // SPECDEVIATION - what is it?
  82. {0,0,0}, {0,0,0}, {0,0,0}, // 37-39, unused
  83. {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, // 40-44, unused
  84. {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, // 45-49, unused
  85. {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, // 50-54, unused
  86. {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, // 55-59, unused
  87. /* 3c 60 */ { 0, 0, 0},
  88. /* 3d 61 */ { 0, 0, 0},
  89. /* 3e 62 */ { 0, 0, 0},
  90. /* 3f 63 */ { 0, 0, 0},
  91. /* 40 64 VT_FILETIME*/ { sizeof (FILETIME), sizeof (FILETIME), CanBeVector|SimpleType},
  92. /* 41 65 VT_BLOB */ { sizeof (BLOB), sizeof (void*), CntRef},
  93. // Can these really occur in properties??? varnt.idl says they
  94. // are interface pointers
  95. /* 42 66 VT_STREAM */ { sizeof (LPWSTR), sizeof (LPWSTR), ByRef},
  96. /* 43 67 VT_STORAGE */ { sizeof (LPWSTR), sizeof (LPWSTR), ByRef},
  97. // NOTE: object-valued properties must be retrieved as Entry IDs
  98. // (workid, propid)
  99. // Can these really occur in properties??? varnt.idl says they
  100. // are interface pointers. Even if so, is the definition
  101. // below appropriate?
  102. /* 44 68 VT_STREAMED_OBJECT */ { 2*sizeof (ULONG), sizeof (ULONG), 0},
  103. /* 45 69 VT_STORED_OBJECT */ { 2*sizeof (ULONG), sizeof (ULONG), 0},
  104. /* 46 70 VT_BLOB_OBJECT */ { 2*sizeof (ULONG), sizeof (ULONG), 0},
  105. /* 47 71 VT_CF */ { sizeof (CLIPDATA*), sizeof (CLIPDATA*), CanBeVector|ByRef},
  106. /* 48 72 VT_CLSID */ { sizeof (GUID), sizeof DWORD, StoreDirect|ByRef|CanBeVector},
  107. };
  108. const unsigned CTableVariant::cVarntData = sizeof CTableVariant::varntData /
  109. sizeof CTableVariant::varntData[0];
  110. //--------------------------------------------------------------------------
  111. //
  112. // This table is like the table above, but is for DBVARIANT extensions,
  113. // i.e., those whose variant type values are 128 and above.
  114. //
  115. //--------------------------------------------------------------------------
  116. const CTableVariant::VARNT_DATA CTableVariant::varntExtData [] = {
  117. //
  118. // Additional type definitions above those in PROPVARIANT.
  119. // Some cannot be used for variant binding.
  120. //
  121. { 0, sizeof BYTE, MultiSize}, // DBTYPE_BYTES = x80 128,
  122. { 0, sizeof CHAR, MultiSize}, // DBTYPE_STR = x81 129,
  123. { 0, sizeof WCHAR, MultiSize}, // DBTYPE_WSTR = x82 130,
  124. { sizeof LONGLONG, sizeof LONGLONG, 0}, // DBTYPE_NUMERIC = x83 131,
  125. { 0, 0, 0}, // DBTYPE_UDT = x84 132,
  126. { sizeof DBDATE, sizeof USHORT, 0}, // DBTYPE_DBDATE = x85 133,
  127. { sizeof DBTIME, sizeof USHORT, 0}, // DBTYPE_DBTIME = x86 134,
  128. { sizeof DBTIMESTAMP, sizeof ULONG, 0}, // DBTYPE_DBTIMESTAMP= x87 135,
  129. { sizeof HCHAPTER, sizeof ULONG, 0}, // DBTYPE_HCHAPTER = x88 136,
  130. { 0, 0, 0}, // was DBTYPE_DBFILETIME
  131. { sizeof PROPVARIANT, sizeof(double), 0}, // DBTYPE_PROPVARIANT = X8a 138,
  132. { sizeof DB_VARNUMERIC, sizeof BYTE, 0}, // DBTYPE_VARNUMERIC = x8b 139,
  133. };
  134. const unsigned CTableVariant::cVarntExtData =
  135. sizeof CTableVariant::varntExtData / sizeof CTableVariant::varntExtData[0];
  136. #ifdef _WIN64
  137. //
  138. // VARIANT DATA for Win32 clients on a Win64 server
  139. // Pointer references must be 32 bits in length (sizeof ULONG)
  140. // See '+' for changed entries
  141. //
  142. const CTableVariant::VARNT_DATA CTableVariant::varntData32 [] = {
  143. // DBTYPE_VECTOR 0x1000
  144. // DBTYPE_BYREF 0x4000
  145. /* 0 0 VT_EMPTY */ { 0, 0, SimpleType|OAType},
  146. /* 1 1 VT_NULL */ { 0, 0, SimpleType},
  147. /* 2 2 VT_I2 */ { sizeof (short), sizeof (short), CanBeVector|SimpleType|OAType},
  148. /* 3 3 VT_I4 */ { sizeof (long), sizeof (long), CanBeVector|SimpleType|OAType},
  149. /* 4 4 VT_R4 */ { sizeof (float), sizeof (float), CanBeVector|SimpleType|OAType},
  150. /* 5 5 VT_R8 */ { sizeof (double), sizeof (double), CanBeVector|SimpleType|OAType},
  151. /* 6 6 VT_CY */ { sizeof (CY), sizeof (CY), CanBeVector|SimpleType|OAType},
  152. /* 7 7 VT_DATE */ { sizeof (DATE), sizeof (DATE), CanBeVector|SimpleType|OAType},
  153. /*+8 8 VT_BSTR */ { sizeof (ULONG), sizeof (ULONG), CanBeVector|ByRef|OAType},
  154. /*+9 9 VT_DISPATCH*/ { sizeof (ULONG), sizeof (ULONG), 0},
  155. /* a 10 VT_ERROR */ { sizeof (SCODE), sizeof(SCODE), CanBeVector|SimpleType|OAType},
  156. /* b 11 VT_BOOL */ { sizeof (VARIANT_BOOL), sizeof (VARIANT_BOOL), CanBeVector|SimpleType|OAType},
  157. /*+c 12 VT_VARIANT */ { sizeof (PROPVARIANT32), sizeof (double), ByRef|StoreDirect|CanBeVector|OAType},
  158. /* d 13 VT_UNKNOWN */ { sizeof (ULONG), sizeof (ULONG), 0},
  159. /* e 14 VT_DECIMAL */ { sizeof (DECIMAL), sizeof (LARGE_INTEGER), SimpleType|OAType},
  160. /* f 15 */ { 0, 0, 0},
  161. /* 10 16 VT_I1 */ { sizeof(char), sizeof(char), CanBeVector|SimpleType},
  162. /* 11 17 VT_UI1 */ { sizeof(UCHAR), sizeof(UCHAR), CanBeVector|SimpleType|OAType},
  163. /* 12 18 VT_UI2 */ { sizeof(unsigned short), sizeof(unsigned short), CanBeVector|SimpleType},
  164. /* 13 19 VT_UI4 */ { sizeof(unsigned long), sizeof(unsigned long), CanBeVector|SimpleType},
  165. /* 14 20 VT_I8 */ { sizeof (LARGE_INTEGER), sizeof (LARGE_INTEGER), CanBeVector|SimpleType},
  166. /* 15 21 VT_UI8 */ { sizeof (LARGE_INTEGER), sizeof (LARGE_INTEGER), CanBeVector|SimpleType},
  167. /* 16 22 VT_INT */ { sizeof (INT), sizeof (INT), SimpleType},
  168. /* 17 23 VT_UINT */ { sizeof (UINT), sizeof (UINT), SimpleType},
  169. // Codes 24-29 are valid for typelibs only
  170. /* 18 24 */ { 0, 0, 0},
  171. {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, // 25-29, unused
  172. /*+1e 30 VT_LPSTR */ { sizeof (ULONG), sizeof (ULONG), CanBeVector|ByRef},
  173. /* 1f 31 VT_LPWSTR */ { sizeof (ULONG), sizeof (ULONG), CanBeVector|ByRef},
  174. /* 20 32 */ { 0, 0, 0},
  175. /* 21 33 */ { 0, 0, 0},
  176. /* 22 34 */ { 0, 0, 0},
  177. /* 23 35 */ { 0, 0, 0},
  178. /* 24 36 VT_RECORD? */ { 0, 0, 0}, // SPECDEVIATION - what is it?
  179. {0,0,0}, {0,0,0}, {0,0,0}, // 37-39, unused
  180. {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, // 40-44, unused
  181. {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, // 45-49, unused
  182. {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, // 50-54, unused
  183. {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, {0,0,0}, // 55-59, unused
  184. /* 3c 60 */ { 0, 0, 0},
  185. /* 3d 61 */ { 0, 0, 0},
  186. /* 3e 62 */ { 0, 0, 0},
  187. /* 3f 63 */ { 0, 0, 0},
  188. /* 40 64 VT_FILETIME*/ { sizeof (FILETIME), sizeof (FILETIME), CanBeVector|SimpleType},
  189. /*+41 65 VT_BLOB */ { sizeof (BLOB32), sizeof (ULONG), CntRef},
  190. // Can these really occur in properties??? varnt.idl says they
  191. // are interface pointers
  192. /*+42 66 VT_STREAM */ { sizeof (ULONG), sizeof (ULONG), ByRef},
  193. /*+43 67 VT_STORAGE */ { sizeof (ULONG), sizeof (ULONG), ByRef},
  194. // NOTE: object-valued properties must be retrieved as Entry IDs
  195. // (workid, propid)
  196. // Can these really occur in properties??? varnt.idl says they
  197. // are interface pointers. Even if so, is the definition
  198. // below appropriate?
  199. /* 44 68 VT_STREAMED_OBJECT */ { 2*sizeof (ULONG), sizeof (ULONG), 0},
  200. /* 45 69 VT_STORED_OBJECT */ { 2*sizeof (ULONG), sizeof (ULONG), 0},
  201. /* 46 70 VT_BLOB_OBJECT */ { 2*sizeof (ULONG), sizeof (ULONG), 0},
  202. /*+47 71 VT_CF */ { sizeof (ULONG), sizeof (ULONG), CanBeVector|ByRef},
  203. /* 48 72 VT_CLSID */ { sizeof (GUID), sizeof DWORD, StoreDirect|ByRef|CanBeVector},
  204. };
  205. //--------------------------------------------------------------------------
  206. //
  207. // This table is like the table above, but is for DBVARIANT extensions,
  208. // i.e., those whose variant type values are 128 and above.
  209. //
  210. // This one is also for 64 bit servers talking to 32 bit clients
  211. //--------------------------------------------------------------------------
  212. const CTableVariant::VARNT_DATA CTableVariant::varntExtData32 [] = {
  213. //
  214. // Additional type definitions above those in PROPVARIANT.
  215. // Some cannot be used for variant binding.
  216. //
  217. { 0, sizeof BYTE, MultiSize}, // DBTYPE_BYTES = x80 128,
  218. { 0, sizeof CHAR, MultiSize}, // DBTYPE_STR = x81 129,
  219. { 0, sizeof WCHAR, MultiSize}, // DBTYPE_WSTR = x82 130,
  220. { sizeof LONGLONG, sizeof LONGLONG, 0}, // DBTYPE_NUMERIC = x83 131,
  221. { 0, 0, 0}, // DBTYPE_UDT = x84 132,
  222. { sizeof DBDATE, sizeof USHORT, 0}, // DBTYPE_DBDATE = x85 133,
  223. { sizeof DBTIME, sizeof USHORT, 0}, // DBTYPE_DBTIME = x86 134,
  224. { sizeof DBTIMESTAMP, sizeof ULONG, 0}, // DBTYPE_DBTIMESTAMP= x87 135,
  225. { sizeof ULONG, sizeof ULONG, 0}, // DBTYPE_HCHAPTER = x88 136,
  226. { 0, 0, 0}, // was DBTYPE_DBFILETIME
  227. { sizeof PROPVARIANT32, sizeof(double), 0}, // DBTYPE_PROPVARIANT = X8a 138,
  228. { sizeof DB_VARNUMERIC, sizeof BYTE, 0}, // DBTYPE_VARNUMERIC = x8b 139,
  229. };
  230. #endif // _WIN64
  231. //
  232. // Variant helper methods
  233. //
  234. //+-------------------------------------------------------------------------
  235. //
  236. // Method: CTableVariant::Copy, public
  237. // CTableVariant::CopyData, private
  238. //
  239. // Synopsis: Copy the data of a variant. One method copies the variant
  240. // and its data, the other copies the variant only.
  241. //
  242. // Arguments: [pvarntDest] - pointer to destination variant (Copy method only)
  243. // [rVarAllocator] - pointer to variable allocator for dest. data
  244. // [cbDest] - expected size in bytes of variable data
  245. // [pbBias] - base address of variable data if offset stored in
  246. // variant
  247. //
  248. // Returns: VOID* - the address to which the data was copied
  249. //
  250. // Notes: If the variant is an internal form, double indirect
  251. // data will use offsets, not pointers. The input
  252. // variant from external callers will generally have
  253. // pointers, not offsets even for internal form variants.
  254. //
  255. //--------------------------------------------------------------------------
  256. void CTableVariant::Copy(
  257. CTableVariant *pvarntDest,
  258. PVarAllocator &rVarAllocator,
  259. USHORT cbDest,
  260. BYTE* pbBias) const
  261. {
  262. // Copy into a temp variant so if copy fails the output variant
  263. // isn't affected. Clients don't always check return codes.
  264. CTableVariant tmp = *this;
  265. BOOL fBased = rVarAllocator.IsBasedMemory();
  266. if ( fBased )
  267. {
  268. tmp.SetDataSize((USHORT) cbDest);
  269. }
  270. else
  271. {
  272. tmp.ResetDataSize( );
  273. }
  274. if (cbDest != 0)
  275. {
  276. BYTE* pbDest = (BYTE *) CopyData(rVarAllocator, cbDest, pbBias);
  277. if ( fBased )
  278. pbDest = (BYTE*) rVarAllocator.PointerToOffset(pbDest);
  279. if ( tmp.VariantPointerInFirstWord() )
  280. {
  281. tmp.pszVal = (LPSTR)pbDest;
  282. }
  283. else
  284. {
  285. Win4Assert( tmp.VariantPointerInSecondWord() );
  286. tmp.blob.pBlobData = pbDest;
  287. }
  288. }
  289. *pvarntDest = tmp;
  290. }
  291. VOID* CTableVariant::CopyData(
  292. PVarAllocator &rVarAllocator,
  293. USHORT cbDest, BYTE* pbBias ) const
  294. {
  295. BYTE* pbSrc = VariantPointerInFirstWord() ?
  296. (BYTE*)pszVal : blob.pBlobData;
  297. pbSrc += (ULONG_PTR)pbBias;
  298. Win4Assert( cbDest != 0 );
  299. // optimize this most typical path
  300. if ( VT_LPWSTR == vt )
  301. {
  302. return (BYTE*) rVarAllocator.CopyTo( cbDest, pbSrc );
  303. }
  304. if (vt == VT_BSTR)
  305. {
  306. // Need to allow for byte count before the string
  307. return rVarAllocator.CopyBSTR(cbDest -
  308. (sizeof (DWORD) + sizeof (OLECHAR)),
  309. (WCHAR *)pbSrc );
  310. }
  311. //
  312. // Determine if offsets or pointers are used in the source data. If
  313. // offsets are used, and offsets will be used in the destination, the
  314. // data can simply be block copied. Otherwise, vectors of strings and
  315. // vectors of variants must have pointers translated to offsets or
  316. // vice-versa.
  317. //
  318. if ( _IsInternalVariant() && rVarAllocator.IsBasedMemory() )
  319. {
  320. Win4Assert( vt != VT_VARIANT && vt != VT_BSTR );
  321. //
  322. // We're copying with offsets to a destination with offsets.
  323. // Just copy.
  324. //
  325. return rVarAllocator.CopyTo(cbDest, pbSrc);
  326. }
  327. BYTE* pbDest = 0;
  328. switch (vt)
  329. {
  330. case VT_LPSTR:
  331. case VT_CLSID:
  332. case VT_BLOB:
  333. case VT_VECTOR | VT_I2:
  334. case VT_VECTOR | VT_I4:
  335. case VT_VECTOR | VT_R4:
  336. case VT_VECTOR | VT_R8:
  337. case VT_VECTOR | VT_CY:
  338. case VT_VECTOR | VT_DATE:
  339. case VT_VECTOR | VT_ERROR:
  340. case VT_VECTOR | VT_BOOL:
  341. case VT_VECTOR | VT_I1:
  342. case VT_VECTOR | VT_UI1:
  343. case VT_VECTOR | VT_UI2:
  344. case VT_VECTOR | VT_UI4:
  345. case VT_VECTOR | VT_I8:
  346. case VT_VECTOR | VT_UI8:
  347. case VT_VECTOR | VT_FILETIME:
  348. case VT_VECTOR | VT_CLSID:
  349. //
  350. // There are no embedded pointers. Just copy.
  351. //
  352. pbDest = (BYTE*) rVarAllocator.CopyTo(cbDest, pbSrc);
  353. break;
  354. case VT_VECTOR | VT_BSTR:
  355. pbDest = (BYTE*) rVarAllocator.Allocate( calpstr.cElems * sizeof (BSTR) );
  356. if (pbDest != 0)
  357. {
  358. BSTR* paStr = (BSTR*) pbDest;
  359. CABSTR caStr = cabstr;
  360. caStr.pElems = (BSTR*)pbSrc;
  361. for (unsigned i = 0; i < caStr.cElems; i++)
  362. {
  363. pbSrc = pbBias + (ULONG_PTR) caStr.pElems[i];
  364. ULONG cb = BSTRLEN((BSTR)pbSrc);
  365. BYTE *pbTmp = (BYTE *) rVarAllocator.PointerToOffset(
  366. rVarAllocator.CopyBSTR(cb, (WCHAR*)pbSrc));
  367. paStr[i] = (BSTR) pbTmp;
  368. }
  369. }
  370. break;
  371. case VT_VECTOR | VT_LPWSTR:
  372. case VT_VECTOR | VT_LPSTR:
  373. pbDest = (BYTE*) rVarAllocator.Allocate( calpstr.cElems * sizeof (LPSTR) );
  374. if (pbDest != 0)
  375. {
  376. LPSTR* paStr = (LPSTR*) pbDest;
  377. CALPSTR caStr = calpstr;
  378. caStr.pElems = (LPSTR*)pbSrc;
  379. for (unsigned i = 0; i < caStr.cElems; i++)
  380. {
  381. ULONG cb;
  382. pbSrc = pbBias + (ULONG_PTR) caStr.pElems[i];
  383. if ( ( VT_LPWSTR | VT_VECTOR ) == vt )
  384. cb = (wcslen((LPWSTR)pbSrc) + 1) * sizeof (WCHAR);
  385. else
  386. cb = (strlen((LPSTR)pbSrc) + 1) * sizeof (CHAR);
  387. paStr[i] = (LPSTR) rVarAllocator.PointerToOffset(
  388. rVarAllocator.CopyTo(cb, pbSrc));
  389. }
  390. }
  391. break;
  392. case VT_CF:
  393. {
  394. pbDest = (BYTE *) rVarAllocator.Allocate( sizeof CLIPDATA );
  395. CLIPDATA *pClipData = (CLIPDATA *) pbDest;
  396. pClipData->cbSize = pclipdata->cbSize;
  397. pClipData->ulClipFmt = pclipdata->ulClipFmt;
  398. ULONG cbData = CBPCLIPDATA( *pclipdata );
  399. pClipData->pClipData = 0;
  400. pClipData->pClipData = (BYTE *) rVarAllocator.Allocate( cbData );
  401. RtlCopyMemory( pClipData->pClipData, pclipdata->pClipData, cbData );
  402. pClipData->pClipData = (BYTE *) rVarAllocator.PointerToOffset( pClipData->pClipData );
  403. }
  404. break;
  405. case VT_VECTOR | VT_CF:
  406. {
  407. // allocate the array of pointers to clip format elements
  408. ULONG cbArray = caclipdata.cElems * sizeof caclipdata.pElems[0];
  409. pbDest = (BYTE *) rVarAllocator.Allocate( cbArray );
  410. if ( 0 != pbDest )
  411. {
  412. CLIPDATA * aData = (CLIPDATA *) pbDest;
  413. RtlZeroMemory( aData, cbArray );
  414. for ( unsigned i = 0; i < caclipdata.cElems; i++ )
  415. {
  416. aData[i].cbSize = caclipdata.pElems[i].cbSize;
  417. aData[i].ulClipFmt = caclipdata.pElems[i].ulClipFmt;
  418. ULONG cbData = CBPCLIPDATA( caclipdata.pElems[ i ] );
  419. aData[i].pClipData = (BYTE *) rVarAllocator.Allocate( cbData );
  420. RtlCopyMemory( aData[i].pClipData,
  421. caclipdata.pElems[i].pClipData,
  422. cbData );
  423. aData[i].pClipData = (BYTE *) rVarAllocator.PointerToOffset( aData[i].pClipData );
  424. }
  425. }
  426. }
  427. break;
  428. case VT_VECTOR | VT_VARIANT:
  429. //
  430. // Copy vector of variant. Recurses for any element of the
  431. // vector that has variable data. Special handling is needed
  432. // for the case of pVarAllocator being a size allocator, which
  433. // is indicated by an allocation return being zero (the allocators
  434. // throw an exception if out of memory).
  435. //
  436. pbDest = (BYTE*) rVarAllocator.Allocate( capropvar.cElems *
  437. sizeof CTableVariant );
  438. if (pbDest != 0)
  439. {
  440. CTableVariant* paVarnt = (CTableVariant*) pbDest;
  441. CTableVariant* paSrcVarnt = (CTableVariant*)
  442. (pbBias + (ULONG_PTR) capropvar.pElems);
  443. for (unsigned i = 0; i < capropvar.cElems; i++)
  444. {
  445. ULONG cbVarData = paSrcVarnt->VarDataSize();
  446. Win4Assert( cbVarData <= USHRT_MAX );
  447. paSrcVarnt->Copy(paVarnt, rVarAllocator, (USHORT)cbVarData,
  448. _IsInternalVariant() ? (BYTE *)paSrcVarnt : 0);
  449. paSrcVarnt++;
  450. }
  451. }
  452. break;
  453. case VT_ARRAY | VT_I2:
  454. case VT_ARRAY | VT_I4:
  455. case VT_ARRAY | VT_R4:
  456. case VT_ARRAY | VT_R8:
  457. case VT_ARRAY | VT_CY:
  458. case VT_ARRAY | VT_DATE:
  459. case VT_ARRAY | VT_BSTR:
  460. case VT_ARRAY | VT_ERROR:
  461. case VT_ARRAY | VT_BOOL:
  462. case VT_ARRAY | VT_VARIANT:
  463. case VT_ARRAY | VT_DECIMAL:
  464. case VT_ARRAY | VT_I1:
  465. case VT_ARRAY | VT_UI1:
  466. case VT_ARRAY | VT_UI2:
  467. case VT_ARRAY | VT_UI4:
  468. case VT_ARRAY | VT_INT:
  469. case VT_ARRAY | VT_UINT:
  470. {
  471. SAFEARRAY * pSaSrc = parray;
  472. SAFEARRAY * pSaDest = 0;
  473. if ( SaCreateAndCopy( rVarAllocator, pSaSrc, &pSaDest ) &&
  474. 0 != pSaDest )
  475. SaCreateData( rVarAllocator,
  476. vt & ~VT_ARRAY,
  477. *pSaSrc,
  478. *pSaDest,
  479. TRUE );
  480. pbDest = (BYTE*)pSaDest;
  481. }
  482. break;
  483. default:
  484. tbDebugOut(( DEB_WARN, "Unsupported variant type %4x\n", (int) vt ));
  485. Win4Assert(! "Unsupported variant type in CTableVariant::CopyData");
  486. }
  487. //
  488. // NOTE: pbDest can be null if the allocator we were passed is a
  489. // size allocator.
  490. //
  491. //Win4Assert(pbDest != 0);
  492. return pbDest;
  493. }
  494. #ifdef _WIN64
  495. //+-------------------------------------------------------------------------
  496. //
  497. // Method: CTableVariant::FixDataPointers, public
  498. //
  499. // Synopsis: Adjust offsets to be pointers for variable data
  500. //
  501. // Arguments: [pbBias] - adjustment base for variable data pointer
  502. // [pArrayAlloc] - Pointer to an allocator
  503. //
  504. // Returns: -Nothing-
  505. //
  506. // History: 22 Sep 1999 KLam Reinstated and added code
  507. //
  508. // Notes: This routine can be recursive when operating on variants
  509. // which contain vectors of variants. As a side-effect, the
  510. // signature which indicates an internal form of variant is
  511. // cleared.
  512. //
  513. // This routine is only be used for communication between a 32
  514. // bit server and 64 bit client. So the pointers found in the
  515. // rows are always 32 bits. Note the casting.
  516. // Arrays of of pointers are stored in the pArrayAlloc buffer.
  517. //
  518. //--------------------------------------------------------------------------
  519. void CTableVariant::FixDataPointers(BYTE* pbBias, CFixedVarAllocator *pArrayAlloc)
  520. {
  521. PROPVARIANT32 *pThis32 = (PROPVARIANT32 *)this;
  522. USHORT flags = _FindVarType( pThis32->vt ).flags;
  523. BOOL fVectorOrArray = ( 0 != ( (VT_ARRAY|VT_VECTOR) & pThis32->vt ) );
  524. USHORT vtBase = pThis32->vt & VT_TYPEMASK;
  525. BOOL fSafeArray = ( (0 != ( VT_ARRAY & pThis32->vt )) || (VT_SAFEARRAY == vtBase) );
  526. // If a simple type and not a vector, just return
  527. tbDebugOut(( DEB_TRACE, "CTableVariant::FixDataPointers [this:0x%I64x] (Bias: 0x%I64x) pThis32->vt:0x%x\n",
  528. this, pbBias, vt ));
  529. if ( ( 0 != ( flags & SimpleType ) ) &&
  530. ( ! fVectorOrArray ) )
  531. return;
  532. Win4Assert( _IsInternalVariant() );
  533. // Clear internal reserved fields
  534. ResetDataSize();
  535. BYTE* pbVarData;
  536. if ( ( ! fVectorOrArray ) &&
  537. ( 0 != ( flags & ByRef ) ) )
  538. {
  539. pszVal = (LPSTR) ( pbBias + pThis32->p );
  540. tbDebugOut(( DEB_TRACE, "CTableVariant::FixDataPointers setting string to 0x%I64x\n", pszVal ));
  541. return;
  542. }
  543. else if ( fSafeArray )
  544. {
  545. pbVarData = pbVal = pbBias + pThis32->p;
  546. tbDebugOut(( DEB_TRACE, "CTableVariant::FixDataPointers setting SafeArray to 0x%I64x\n", pszVal ));
  547. }
  548. else
  549. {
  550. Win4Assert( VariantPointerInSecondWord() );
  551. blob.pBlobData = pbVarData = pbBias + pThis32->blob.pBlob;
  552. blob.cbSize = pThis32->blob.cbSize;
  553. tbDebugOut(( DEB_TRACE, "CTableVariant::FixDataPointers setting value to 0x%I64x\n", pbVarData ));
  554. }
  555. //
  556. // Adjust offsets to pointers in vectors with pointers
  557. //
  558. if (vt == (VT_LPWSTR|VT_VECTOR) ||
  559. vt == (VT_LPSTR|VT_VECTOR) ||
  560. vt == (VT_BSTR|VT_VECTOR))
  561. {
  562. LPSTR * paNewArray = (LPSTR *)pArrayAlloc->Allocate( calpstr.cElems * (sizeof (void *)) );
  563. ULONG * puStr = (ULONG *) pbVarData;
  564. for (unsigned i = 0; i < calpstr.cElems; i++)
  565. paNewArray[i] = (LPSTR) (puStr[i] + pbBias);
  566. // Point to the new bigger array
  567. blob.pBlobData = pbVarData = (BYTE *)paNewArray;
  568. tbDebugOut(( DEB_TRACE, "CTableVariant::FixDataPointers setting vector to 0x%I64x\n", paNewArray ));
  569. }
  570. // VECTOR of VARIANTS aren't currently supported
  571. // This branch is untested
  572. else if (vt == (VT_VARIANT|VT_VECTOR))
  573. {
  574. CTableVariant* pVarnt = (CTableVariant*) pbVarData;
  575. tbDebugOut(( DEB_TRACE, "CTableVariant::FixDataPointers recursively setting variant vector!\n" ));
  576. for (unsigned i = 0; i < capropvar.cElems; i++)
  577. {
  578. pVarnt->FixDataPointers(pbBias, pArrayAlloc);
  579. pVarnt++;
  580. }
  581. }
  582. else if ( fSafeArray )
  583. {
  584. SAFEARRAY32 *pSafeArray32 = (SAFEARRAY32 *) pbVarData;
  585. // Get the size of the safearray
  586. unsigned cbSASize = sizeof (SAFEARRAY) + ( (pSafeArray32->cDims - 1 ) * sizeof (SAFEARRAYBOUND) );
  587. // Allocate a new SAFEARRAY for WIN64
  588. SAFEARRAY *pSafeArray = (SAFEARRAY *)pArrayAlloc->Allocate( cbSASize );
  589. // Copy the SAFEARRAY
  590. tbDebugOut(( DEB_TRACE,
  591. "CTableVariant::FixDataPointers SafeArray32\n\tcDims:%d fFeatures:0x%x cbElements:%d cLocks:%d pvData:0x%I64x\n",
  592. pSafeArray32->cDims, pSafeArray32->fFeatures, pSafeArray32->cbElements, pSafeArray32->cLocks, pSafeArray32->pvData ));
  593. pSafeArray->cDims = pSafeArray32->cDims;
  594. pSafeArray->fFeatures = pSafeArray32->fFeatures;
  595. pSafeArray->cbElements = pSafeArray32->cbElements;
  596. pSafeArray->cLocks = pSafeArray32->cLocks;
  597. pSafeArray->pvData = pSafeArray32->pvData + pbBias;
  598. memcpy ( pSafeArray->rgsabound, pSafeArray32->rgsabound, pSafeArray32->cDims * sizeof (SAFEARRAYBOUND) );
  599. tbDebugOut(( DEB_TRACE,
  600. "CTableVariant::FixDataPointers SafeArray\n\tcDims:%d fFeatures:0x%x cbElements:%d cLocks:%d pvData:0x%I64x\n",
  601. pSafeArray->cDims, pSafeArray->fFeatures, pSafeArray->cbElements, pSafeArray->cLocks, pSafeArray->pvData ));
  602. // Point the table variant at it
  603. parray = pSafeArray;
  604. tbDebugOut(( DEB_TRACE,
  605. "CTableVariant::FixDataPointers setting safearray to 0x%I64x with array at 0x%I64x\n",
  606. pSafeArray, pSafeArray->pvData ));
  607. // Safearray of BSTR
  608. if ( VT_BSTR == vtBase )
  609. {
  610. // Pointing to an array of pointers so adjust the size
  611. pSafeArray->cbElements = sizeof (void *);
  612. // Get the number of elements in the safe array
  613. unsigned cBstrElements = pSafeArray->rgsabound[0].cElements;
  614. for ( unsigned j = 1; j < pSafeArray->cDims; j++ )
  615. cBstrElements *= pSafeArray->rgsabound[j].cElements;
  616. unsigned cbBstrElements = cBstrElements * sizeof (void *);
  617. ULONG_PTR *apStrings = (ULONG_PTR *) pArrayAlloc->Allocate ( cbBstrElements );
  618. ULONG *pulBstr = (ULONG *) pSafeArray->pvData;
  619. for ( j = 0; j < cBstrElements; j++ )
  620. apStrings[j] = (ULONG_PTR) (pulBstr[j] + pbBias);
  621. pSafeArray->pvData = apStrings;
  622. tbDebugOut(( DEB_TRACE,
  623. "CTableVariant::FixDataPointers setting safearray BSTRs to 0x%I64x\n",
  624. apStrings ));
  625. }
  626. else if ( VT_VARIANT == vtBase )
  627. {
  628. // Pointing to an array of variants so adjust its size
  629. pSafeArray->cbElements = sizeof ( PROPVARIANT );
  630. // Get the number of elements in the safe array
  631. unsigned cVarElements = pSafeArray->rgsabound[0].cElements;
  632. for ( unsigned k = 1; k < pSafeArray->cDims; k++ )
  633. cVarElements *= pSafeArray->rgsabound[k].cElements;
  634. unsigned cbVarElements = cVarElements * sizeof (PROPVARIANT);
  635. PROPVARIANT *apVar = (PROPVARIANT *) pArrayAlloc->Allocate ( cbVarElements );
  636. PROPVARIANT32 *pVar32 = (PROPVARIANT32 *) pSafeArray->pvData;
  637. CTableVariant *ptv;
  638. for ( k = 0; k < cVarElements; k++ )
  639. {
  640. apVar[k].vt = pVar32[k].vt;
  641. apVar[k].wReserved1 = _wInternalSig;
  642. apVar[k].wReserved2 = pVar32[k].wReserved2;
  643. apVar[k].wReserved3 = _wInternalSig;
  644. apVar[k].blob.cbSize = pVar32[k].blob.cbSize;
  645. ULONG ulBlob = pVar32[k].blob.pBlob;
  646. apVar[k].blob.pBlobData = (BYTE *) UlongToPtr( ulBlob ) ;
  647. ptv = (CTableVariant *)&apVar[k];
  648. ptv->FixDataPointers ( pbBias, pArrayAlloc );
  649. }
  650. pSafeArray->pvData = apVar;
  651. tbDebugOut(( DEB_TRACE,
  652. "CTableVariant::FixDataPointers setting safearray BSTRs to 0x%I64x\n",
  653. apVar ));
  654. }
  655. }
  656. } //FixDataPointers
  657. //+-------------------------------------------------------------------------
  658. //
  659. // Method: CTableVariant::VarDataSize32, public
  660. //
  661. // Synopsis: Compute variable data size of a 64 bit variant for a Win32
  662. // machine
  663. //
  664. // Arguments: [pbBase] - Buffer containing variant data
  665. // [ulpOffset] - Offset of buffer on the client
  666. //
  667. // Returns: ULONG - size in bytes of data which is outside the
  668. // variant structure itself
  669. //
  670. // Notes: For variants which are stored internally in the table,
  671. // the size is computed once and stored in the wReserved2
  672. // field of the variant structure.
  673. //
  674. // This function must be called **BEFORE** 32 pointer fixing
  675. //
  676. // History: 11-04-99 KLam Created for Win64
  677. // 12-Feb-2000 KLam Vector string pointers not rebased
  678. // BSTRs not multiplied by sizeof (OLECHAR)
  679. //
  680. //--------------------------------------------------------------------------
  681. ULONG CTableVariant::VarDataSize32 ( BYTE *pbBase,
  682. ULONG_PTR ulpOffset ) const
  683. {
  684. if ( VT_LPWSTR == vt )
  685. {
  686. LPWSTR lpwstrRef = (LPWSTR)( ((UINT_PTR)pwszVal - ulpOffset ) + pbBase );
  687. return ( wcslen( lpwstrRef ) + 1 ) * sizeof (WCHAR);
  688. }
  689. if ( IsSimpleType( vt ) )
  690. {
  691. if ( 0 == ( ( VT_ARRAY | VT_VECTOR ) & vt ) )
  692. {
  693. return 0;
  694. }
  695. else if ( vt & VT_VECTOR )
  696. {
  697. USHORT cbSize, cbAllign, rgFlags;
  698. VartypeInfo32( vt, cbSize, cbAllign, rgFlags );
  699. return cbSize * cai.cElems;
  700. }
  701. }
  702. Win4Assert( 0 == ( vt & VT_BYREF ) );
  703. switch (vt)
  704. {
  705. case VT_LPSTR:
  706. {
  707. LPSTR lpstrRef = (LPSTR)( ((UINT_PTR)pszVal - ulpOffset ) + pbBase );
  708. return strlen(lpstrRef) + 1;
  709. }
  710. case VT_BLOB:
  711. return blob.cbSize;
  712. case VT_BSTR:
  713. {
  714. BSTR bstrRef = (BSTR)( ((UINT_PTR)bstrVal - ulpOffset ) + pbBase );
  715. tbDebugOut(( DEB_TRACE,
  716. "VarDataSize32 sizing BSTR at bstrRef: 0x%I64x with size %d\n",
  717. bstrRef, BSTRLEN(bstrRef) ));
  718. Win4Assert(bstrRef[ BSTRLEN(bstrRef) / sizeof (OLECHAR) ] == OLESTR('\0'));
  719. return ( BSTRLEN(bstrRef) * sizeof (OLECHAR) )
  720. + sizeof (DWORD) + sizeof (OLECHAR);
  721. }
  722. case VT_BSTR | VT_VECTOR:
  723. {
  724. ULONG cbTotal = sizeof (PTR32) * cabstr.cElems;
  725. BSTR * abstrRef = (BSTR *)( ((UINT_PTR)cabstr.pElems - ulpOffset ) + pbBase );
  726. tbDebugOut(( DEB_TRACE,
  727. "VarDataSize32 sizing %d BSTR(s) vector at abstrRef: 0x%I64x \n",
  728. cabstr.cElems, abstrRef ));
  729. for (unsigned i=0; i < cabstr.cElems; i++)
  730. {
  731. BSTR bstrFixed = (BSTR)((((UINT_PTR)(abstrRef[i])) - ulpOffset ) + pbBase);
  732. cbTotal += ( BSTRLEN( bstrFixed ) * sizeof (OLECHAR) ) +
  733. sizeof (DWORD) + sizeof (OLECHAR);
  734. }
  735. return cbTotal;
  736. }
  737. case VT_LPSTR | VT_VECTOR:
  738. {
  739. ULONG cbTotal = sizeof (PTR32) * calpstr.cElems;
  740. LPSTR * alpstrRef = (LPSTR *)( ((UINT_PTR)calpstr.pElems - ulpOffset ) + pbBase );
  741. for (unsigned i=0; i < calpstr.cElems; i++)
  742. {
  743. LPSTR lpstrFixed = (LPSTR)(( ((UINT_PTR)(alpstrRef[i])) - ulpOffset ) + pbBase);
  744. cbTotal += strlen( lpstrFixed ) + 1;
  745. }
  746. return cbTotal;
  747. }
  748. case VT_LPWSTR | VT_VECTOR:
  749. {
  750. ULONG cbTotal = sizeof(PTR32) * calpwstr.cElems;
  751. LPWSTR * alpwstr = (LPWSTR *)( ((UINT_PTR)calpwstr.pElems - ulpOffset ) + pbBase );
  752. for (unsigned i=0; i < calpwstr.cElems; i++)
  753. {
  754. LPWSTR lpwstrFixed = (LPWSTR)(( ((UINT_PTR)(alpwstr[i])) - ulpOffset ) + pbBase);
  755. cbTotal += (wcslen( lpwstrFixed ) + 1) * sizeof (WCHAR);
  756. }
  757. return cbTotal;
  758. }
  759. case VT_VARIANT | VT_VECTOR:
  760. {
  761. ULONG cbTotal = sizeof PROPVARIANT32 * capropvar.cElems;
  762. CTableVariant * atv = (CTableVariant *)( ((UINT_PTR)capropvar.pElems - ulpOffset ) + pbBase );
  763. for (unsigned i=0; i < capropvar.cElems; i++)
  764. cbTotal += atv[i].VarDataSize();
  765. return cbTotal;
  766. }
  767. case VT_CLSID :
  768. {
  769. return sizeof CLSID;
  770. }
  771. case VT_CLSID | VT_VECTOR :
  772. {
  773. return sizeof CLSID * cai.cElems;
  774. }
  775. case VT_CF :
  776. {
  777. if ( 0 != pclipdata )
  778. {
  779. CLIPDATA * pclipRef = (CLIPDATA *)( ((UINT_PTR)pclipdata - ulpOffset ) + pbBase );
  780. return sizeof CLIPDATA32 + CBPCLIPDATA( *pclipRef );
  781. }
  782. else
  783. return 0;
  784. }
  785. case VT_CF | VT_VECTOR :
  786. {
  787. ULONG cb = sizeof CLIPDATA32 * caclipdata.cElems;
  788. CLIPDATA * aclipRef = (CLIPDATA *)( ((UINT_PTR)(caclipdata.pElems) - ulpOffset ) + pbBase );
  789. for ( ULONG i = 0; i < caclipdata.cElems; i++ )
  790. cb += CBPCLIPDATA( aclipRef[i] );
  791. return cb;
  792. }
  793. case VT_ARRAY | VT_I4:
  794. case VT_ARRAY | VT_UI1:
  795. case VT_ARRAY | VT_I2:
  796. case VT_ARRAY | VT_R4:
  797. case VT_ARRAY | VT_R8:
  798. case VT_ARRAY | VT_BOOL:
  799. case VT_ARRAY | VT_ERROR:
  800. case VT_ARRAY | VT_CY:
  801. case VT_ARRAY | VT_DATE:
  802. case VT_ARRAY | VT_I1:
  803. case VT_ARRAY | VT_UI2:
  804. case VT_ARRAY | VT_UI4:
  805. case VT_ARRAY | VT_INT:
  806. case VT_ARRAY | VT_UINT:
  807. case VT_ARRAY | VT_DECIMAL:
  808. case VT_ARRAY | VT_BSTR:
  809. case VT_ARRAY | VT_VARIANT:
  810. {
  811. LPSAFEARRAY psaRef = (LPSAFEARRAY)( ((UINT_PTR)parray - ulpOffset ) + pbBase );
  812. return SaComputeSize32( vt & ~VT_ARRAY, *psaRef, pbBase, ulpOffset );
  813. }
  814. case VT_EMPTY :
  815. return 0;
  816. default:
  817. tbDebugOut(( DEB_WARN, "Unsupported variant type %4x\n", (int) vt ));
  818. Win4Assert(! "Unsupported variant type in CTableVariant::VarDataSize");
  819. return 0;
  820. }
  821. } // VarDataSize32
  822. //+---------------------------------------------------------------------------
  823. //
  824. // Function: CTableVariant::SaComputeSize32, public static
  825. //
  826. // Synopsis: Computes the size of a safearray for a 32 bit machine.
  827. //
  828. // Arguments: [vt] - variant type (VT_ARRAY assumed)
  829. // [saSrc] - 64 bit source safearry
  830. // [pbBase] - Buffer containing variant data
  831. // [ulpOffset] - Offset of buffer on the client
  832. //
  833. // Returns: ULONG - number of bytes of memory needed to store safearray
  834. //
  835. // History: 5-01-98 AlanW Created
  836. // 11-4-99 KLam Adjusted for 32bit array on 64bit machine
  837. //
  838. //----------------------------------------------------------------------------
  839. ULONG CTableVariant::SaComputeSize32( VARTYPE vt,
  840. SAFEARRAY & saSrc,
  841. BYTE *pbBase,
  842. ULONG_PTR ulpOffset )
  843. {
  844. //
  845. // get number of data elements in array and size of the header.
  846. //
  847. unsigned cDataElements = 1;
  848. for ( unsigned i = 0; i < saSrc.cDims; i++ )
  849. // This array is in place so no pointer fixing is necessary
  850. cDataElements *= saSrc.rgsabound[i].cElements;
  851. Win4Assert( 0 != saSrc.cDims );
  852. ULONG cb = sizeof (SAFEARRAY32) +
  853. (saSrc.cDims-1) * sizeof (SAFEARRAYBOUND) +
  854. cDataElements * saSrc.cbElements;
  855. cb = AlignBlock( cb, sizeof LONGLONG );
  856. switch (vt)
  857. {
  858. case VT_I4:
  859. case VT_UI1:
  860. case VT_I2:
  861. case VT_R4:
  862. case VT_R8:
  863. case VT_BOOL:
  864. case VT_ERROR:
  865. case VT_CY:
  866. case VT_DATE:
  867. case VT_I1:
  868. case VT_UI2:
  869. case VT_UI4:
  870. case VT_INT:
  871. case VT_UINT:
  872. case VT_DECIMAL:
  873. break;
  874. case VT_BSTR:
  875. {
  876. BSTR *pBstrSrc = (BSTR *)( ( ((UINT_PTR)saSrc.pvData) - ulpOffset ) + pbBase );
  877. for ( unsigned i = 0; i < cDataElements; i++ )
  878. {
  879. Win4Assert( pBstrSrc[i] != 0 );
  880. BSTR bstrRef = (BSTR) ( ( ( (UINT_PTR) (pBstrSrc[i]) ) - ulpOffset ) + pbBase );
  881. tbDebugOut(( DEB_TRACE,
  882. "Sizing Array of BSTR: 0x%I64x BSTR[%d]: %xI64x (size: %d)\n",
  883. pBstrSrc, bstrRef, BSTRLEN(bstrRef) ));
  884. cb += AlignBlock( SysStringByteLen(bstrRef) +
  885. sizeof ULONG + sizeof WCHAR,
  886. sizeof LONGLONG );
  887. }
  888. }
  889. break;
  890. case VT_VARIANT:
  891. {
  892. CAllocStorageVariant *pVarnt = (CAllocStorageVariant *)( ((UINT_PTR)saSrc.pvData - ulpOffset ) + pbBase );
  893. for ( unsigned i = 0; i < cDataElements; i++ )
  894. {
  895. if ( VT_BSTR == pVarnt[i].vt )
  896. {
  897. BSTR bstrRef = (BSTR)( ((UINT_PTR)pVarnt[i].bstrVal - ulpOffset ) + pbBase );
  898. cb += AlignBlock( SysStringByteLen( bstrRef ) +
  899. sizeof ULONG + sizeof WCHAR,
  900. sizeof LONGLONG );
  901. }
  902. else if ( 0 != (pVarnt[i].vt & VT_ARRAY) )
  903. {
  904. LPSAFEARRAY psaRef = (LPSAFEARRAY)( ((UINT_PTR)pVarnt[i].parray - ulpOffset ) + pbBase );
  905. cb += AlignBlock( SaComputeSize32( (pVarnt[i].vt & ~VT_ARRAY),
  906. *psaRef,
  907. pbBase,
  908. ulpOffset ),
  909. sizeof LONGLONG );
  910. }
  911. else
  912. {
  913. Win4Assert( pVarnt[i].vt != VT_VARIANT );
  914. }
  915. }
  916. }
  917. break;
  918. default:
  919. ciDebugOut(( DEB_ERROR, "Unexpected SafeArray type: vt=%x\n", vt ) );
  920. Win4Assert( !"Unexpected SafeArray Type" );
  921. return 1;
  922. }
  923. return cb;
  924. } // SaComputeSize32
  925. #endif // _WIN64
  926. //+-------------------------------------------------------------------------
  927. //
  928. // Method: CTableVariant::VarDataSize, public
  929. //
  930. // Synopsis: Compute variable data size for a variant
  931. //
  932. // Arguments: - none -
  933. //
  934. // Returns: ULONG - size in bytes of data which is outside the
  935. // variant structure itself
  936. //
  937. // Notes: For variants which are stored internally in the table,
  938. // the size is computed once and stored in the wReserved2
  939. // field of the variant structure.
  940. //
  941. //--------------------------------------------------------------------------
  942. ULONG CTableVariant::VarDataSize (void) const
  943. {
  944. // short-circuit this common path: VT_LPWSTR
  945. if ( VT_LPWSTR == vt )
  946. return ( wcslen( pwszVal ) + 1 ) * sizeof (WCHAR);
  947. if ( IsSimpleType( vt ) )
  948. {
  949. if ( 0 == ( ( VT_ARRAY | VT_VECTOR ) & vt ) )
  950. {
  951. return 0;
  952. }
  953. else if ( vt & VT_VECTOR )
  954. {
  955. USHORT cbSize, cbAllign, rgFlags;
  956. VartypeInfo( vt, cbSize, cbAllign, rgFlags );
  957. return cbSize * cai.cElems;
  958. }
  959. }
  960. Win4Assert( 0 == ( vt & VT_BYREF ) );
  961. switch (vt)
  962. {
  963. case VT_LPSTR:
  964. return strlen(pszVal) + 1;
  965. case VT_BLOB:
  966. return blob.cbSize;
  967. case VT_BSTR:
  968. Win4Assert(bstrVal[ BSTRLEN(bstrVal) / sizeof (OLECHAR) ] == OLESTR('\0'));
  969. return BSTRLEN(bstrVal) + sizeof (DWORD) + sizeof (OLECHAR);
  970. case VT_BSTR | VT_VECTOR:
  971. {
  972. ULONG cbTotal = sizeof (void *) * cabstr.cElems;
  973. for (unsigned i=0; i<cabstr.cElems; i++)
  974. cbTotal += BSTRLEN(cabstr.pElems[i]) +
  975. sizeof (DWORD) + sizeof (OLECHAR);
  976. return cbTotal;
  977. }
  978. case VT_LPSTR | VT_VECTOR:
  979. {
  980. ULONG cbTotal = sizeof (void *) * calpstr.cElems;
  981. for (unsigned i=0; i<calpstr.cElems; i++)
  982. cbTotal += strlen(calpstr.pElems[i]) + 1;
  983. return cbTotal;
  984. }
  985. case VT_LPWSTR | VT_VECTOR:
  986. {
  987. ULONG cbTotal = sizeof( void * ) * calpwstr.cElems;
  988. for (unsigned i=0; i<calpwstr.cElems; i++)
  989. cbTotal += (wcslen(calpwstr.pElems[i]) + 1) * sizeof (WCHAR);
  990. return cbTotal;
  991. }
  992. case VT_VARIANT | VT_VECTOR:
  993. {
  994. ULONG cbTotal = sizeof PROPVARIANT * capropvar.cElems;
  995. for (unsigned i=0; i<capropvar.cElems; i++)
  996. cbTotal += ((CTableVariant &)capropvar.pElems[i]).VarDataSize();
  997. return cbTotal;
  998. }
  999. case VT_CLSID :
  1000. {
  1001. return sizeof CLSID;
  1002. }
  1003. case VT_CLSID | VT_VECTOR :
  1004. {
  1005. return sizeof CLSID * cai.cElems;
  1006. }
  1007. case VT_CF :
  1008. {
  1009. if ( 0 != pclipdata )
  1010. return sizeof CLIPDATA + CBPCLIPDATA( *pclipdata );
  1011. else
  1012. return 0;
  1013. }
  1014. case VT_CF | VT_VECTOR :
  1015. {
  1016. ULONG cb = sizeof CLIPDATA * caclipdata.cElems;
  1017. for ( ULONG i = 0; i < caclipdata.cElems; i++ )
  1018. cb += CBPCLIPDATA( caclipdata.pElems[i] );
  1019. return cb;
  1020. }
  1021. case VT_ARRAY | VT_I4:
  1022. case VT_ARRAY | VT_UI1:
  1023. case VT_ARRAY | VT_I2:
  1024. case VT_ARRAY | VT_R4:
  1025. case VT_ARRAY | VT_R8:
  1026. case VT_ARRAY | VT_BOOL:
  1027. case VT_ARRAY | VT_ERROR:
  1028. case VT_ARRAY | VT_CY:
  1029. case VT_ARRAY | VT_DATE:
  1030. case VT_ARRAY | VT_I1:
  1031. case VT_ARRAY | VT_UI2:
  1032. case VT_ARRAY | VT_UI4:
  1033. case VT_ARRAY | VT_INT:
  1034. case VT_ARRAY | VT_UINT:
  1035. case VT_ARRAY | VT_DECIMAL:
  1036. case VT_ARRAY | VT_BSTR:
  1037. case VT_ARRAY | VT_VARIANT:
  1038. return SaComputeSize( vt & ~VT_ARRAY, *parray);
  1039. case VT_EMPTY :
  1040. return 0;
  1041. default:
  1042. tbDebugOut(( DEB_WARN, "Unsupported variant type %4x\n", (int) vt ));
  1043. Win4Assert(! "Unsupported variant type in CTableVariant::VarDataSize");
  1044. return 0;
  1045. }
  1046. }
  1047. const USHORT CTableVariant::_wInternalSig = 0x3210;
  1048. //+-------------------------------------------------------------------------
  1049. //
  1050. // Method: CTableVariant::Init, public
  1051. //
  1052. // Synopsis: Fills in a variant with new data
  1053. //
  1054. // Arguments: [vtIn] -- the data type of the new variant
  1055. // [pbData] -- pointer to source of data
  1056. // [cbData] -- size in bytes of data at pbData
  1057. //
  1058. // Returns: -Nothing-
  1059. //
  1060. // Notes: The variant is reused. The caller is responsible
  1061. // for freeing any memory from the previous contents
  1062. // of the variant prior to calling Init.
  1063. //
  1064. // If pbData is NULL and cbData is zero, only the
  1065. // variant type is filled in.
  1066. //
  1067. //--------------------------------------------------------------------------
  1068. void CTableVariant::Init(
  1069. VARTYPE vtIn,
  1070. BYTE* pbData,
  1071. ULONG cbData)
  1072. {
  1073. // Clean out the entire variant
  1074. RtlZeroMemory(this, sizeof CTableVariant);
  1075. vt = vtIn; // default; minor exceptions below
  1076. if (pbData == 0 && cbData == 0)
  1077. return;
  1078. if ( VT_VARIANT == vtIn )
  1079. {
  1080. tbDebugOut(( DEB_ITRACE, "CTableVariant::Init from vt_variant\n" ));
  1081. * this = * ((CTableVariant *) pbData);
  1082. }
  1083. else if (vtIn & VT_VECTOR)
  1084. {
  1085. Win4Assert( cbData == sizeof (CAI) );
  1086. RtlCopyMemory((BYTE *)&cai, pbData, sizeof (CAI));
  1087. }
  1088. else if ( IsSimpleType( vtIn ) )
  1089. {
  1090. RtlCopyMemory( (BYTE *)&iVal, pbData, cbData );
  1091. }
  1092. else
  1093. {
  1094. switch (vtIn)
  1095. {
  1096. case VT_CLSID:
  1097. Win4Assert(cbData == sizeof (GUID));
  1098. puuid = (GUID *)pbData;
  1099. break;
  1100. case VT_BSTR:
  1101. case VT_LPSTR:
  1102. case VT_LPWSTR:
  1103. Win4Assert(cbData == sizeof (LPSTR));
  1104. pszVal = *(LPSTR *)pbData;
  1105. break;
  1106. case VT_BLOB:
  1107. Win4Assert(cbData == sizeof (BLOB));
  1108. blob = *(BLOB *)pbData;
  1109. break;
  1110. default:
  1111. tbDebugOut(( DEB_WARN, "Unsupported variant type %4x\n", (int) vtIn ));
  1112. Win4Assert(! "unsupported variant type in CTableVariant::Init");
  1113. }
  1114. }
  1115. } //Init
  1116. //+-------------------------------------------------------------------------
  1117. //
  1118. // Member: CTableVariant::_StoreString, private
  1119. //
  1120. // Synopsis: Copy variant string data, coerce if possible
  1121. //
  1122. // Arguments: [pbDstBuf] -- destination buffer
  1123. // [cbDstBuf] -- size of destination buffer
  1124. // [vtDst] -- data type of the dest
  1125. // [rcbDstLen] -- on return, length of destination data
  1126. // [rPool] -- to use for destination byref allocations
  1127. //
  1128. // Returns: status for copy
  1129. // Notes: Expects the 'this' data type to be either VT_LPSTR,
  1130. // VT_LPWSTR or VT_BSTR.
  1131. //
  1132. //--------------------------------------------------------------------------
  1133. DBSTATUS CTableVariant::_StoreString( BYTE * pbDstBuf,
  1134. DBLENGTH cbDstBuf,
  1135. VARTYPE vtDst,
  1136. DBLENGTH & rcbDstLen,
  1137. PVarAllocator & rPool) const
  1138. {
  1139. DBSTATUS DstStatus = DBSTATUS_S_OK;
  1140. ULONG cbSrc = (vt == VT_BSTR) ? BSTRLEN(bstrVal) + sizeof (OLECHAR) :
  1141. VarDataSize();
  1142. // if both are VT_LPWSTR or
  1143. // both are VT_LPSTR or
  1144. // dst is byref wstr and source is VT_LPWSTR or
  1145. // dst is byref str and source is VT_LPSTR
  1146. if ( ( (vtDst == vt) &&
  1147. (IsLPWSTR(vtDst))) ||
  1148. ( (vtDst == vt) &&
  1149. (IsLPSTR(vtDst)) ) ||
  1150. ( (vtDst == (DBTYPE_BYREF | DBTYPE_WSTR) ) &&
  1151. (IsLPWSTR(vt) || vt == VT_BSTR) ) ||
  1152. ( (vtDst == (DBTYPE_BYREF | DBTYPE_STR) ) &&
  1153. (IsLPSTR(vt)) ) )
  1154. {
  1155. Win4Assert ((vtDst & VT_VECTOR) == 0 &&
  1156. cbDstBuf == sizeof LPWSTR);
  1157. BYTE* pbDest = (BYTE *) rPool.CopyTo(cbSrc,(BYTE *) pszVal);
  1158. // ADO gives us 1 byte aligned buffers sometimes. Sigh.
  1159. // Happens for vt_lpwstr => dbtype_byref|dbtype_wstr
  1160. // Win4Assert( 0 == ( (ULONG_PTR) pbDstBuf % sizeof(ULONG_PTR) ) );
  1161. *(ULONG_PTR UNALIGNED *) pbDstBuf = rPool.PointerToOffset(pbDest);
  1162. rcbDstLen = (vtDst == VT_BSTR) ? sizeof (BSTR) :
  1163. (vtDst == VT_LPWSTR || vtDst == (DBTYPE_BYREF|DBTYPE_WSTR)) ?
  1164. cbSrc - sizeof (WCHAR) : cbSrc - sizeof (char);
  1165. }
  1166. else if (((vtDst == DBTYPE_WSTR) &&
  1167. (IsLPWSTR(vt) || vt == VT_BSTR)) ||
  1168. ((vtDst == DBTYPE_STR) &&
  1169. (IsLPSTR(vt))))
  1170. {
  1171. // In-line, compatible data types
  1172. if (cbDstBuf >= cbSrc)
  1173. {
  1174. RtlCopyMemory(pbDstBuf, pszVal, cbSrc);
  1175. rcbDstLen = cbSrc - ((vtDst == DBTYPE_WSTR) ?
  1176. sizeof (WCHAR) : sizeof (char));
  1177. }
  1178. else
  1179. {
  1180. RtlCopyMemory(pbDstBuf, pszVal, cbDstBuf);
  1181. DstStatus = DBSTATUS_S_TRUNCATED;
  1182. rcbDstLen = cbDstBuf;
  1183. }
  1184. }
  1185. else if ((vtDst == DBTYPE_STR) && (IsLPWSTR(vt) || vt == VT_BSTR))
  1186. {
  1187. // if they want fancy composed chars, they can bind to the
  1188. // proper data type and do the coercion themselves.
  1189. int cb = WideCharToMultiByte(ulCoercionCodePage,0,pwszVal,-1,
  1190. 0,0,0,0);
  1191. if (0 == cb)
  1192. DstStatus = DBSTATUS_E_CANTCONVERTVALUE; // something odd...
  1193. else
  1194. {
  1195. if (cb > (int) cbDstBuf)
  1196. {
  1197. DstStatus = DBSTATUS_S_TRUNCATED;
  1198. rcbDstLen = cbDstBuf;
  1199. }
  1200. else
  1201. rcbDstLen = cb - sizeof (char);
  1202. WideCharToMultiByte(ulCoercionCodePage,0,pwszVal,-1,
  1203. (char *) pbDstBuf,(ULONG) cbDstBuf,0,0);
  1204. }
  1205. }
  1206. else if ((vtDst == DBTYPE_WSTR) && (IsLPSTR(vt)))
  1207. {
  1208. // if they want fancy composed chars, they can bind to the
  1209. // proper data type and do the coercion themselves.
  1210. int cwcDst = (int) ( cbDstBuf / sizeof WCHAR );
  1211. int cwc = MultiByteToWideChar(ulCoercionCodePage,0,
  1212. pszVal,-1,0,0);
  1213. if (0 == cwc)
  1214. DstStatus = DBSTATUS_E_CANTCONVERTVALUE; // something odd...
  1215. else
  1216. {
  1217. if (cwc > cwcDst)
  1218. {
  1219. DstStatus = DBSTATUS_S_TRUNCATED;
  1220. rcbDstLen = (cwcDst) * sizeof (WCHAR);
  1221. }
  1222. else
  1223. rcbDstLen = (cwc-1) * sizeof (WCHAR);
  1224. MultiByteToWideChar(ulCoercionCodePage,0,
  1225. pszVal,-1,(WCHAR *) pbDstBuf,cwcDst);
  1226. }
  1227. }
  1228. else if (vtDst == VT_BSTR)
  1229. {
  1230. Win4Assert(vt != VT_BSTR && vt != DBTYPE_STR && vt != DBTYPE_WSTR);
  1231. rcbDstLen = sizeof (BSTR);
  1232. if (IsLPWSTR(vt))
  1233. {
  1234. BSTR bstrDest = (BSTR) rPool.CopyBSTR( cbSrc - sizeof (OLECHAR),
  1235. pwszVal );
  1236. *(ULONG_PTR*) pbDstBuf = rPool.PointerToOffset(bstrDest);
  1237. }
  1238. else
  1239. {
  1240. Win4Assert(IsLPSTR(vt));
  1241. int cwc = MultiByteToWideChar(ulCoercionCodePage,0,
  1242. pszVal,-1,0,0);
  1243. if (0 == cwc)
  1244. {
  1245. DstStatus = DBSTATUS_E_CANTCONVERTVALUE; // something odd...
  1246. *(BSTR*) pbDstBuf = 0;
  1247. rcbDstLen = 0;
  1248. }
  1249. else
  1250. {
  1251. XArray<WCHAR> wcsDest( cwc );
  1252. MultiByteToWideChar(ulCoercionCodePage, 0,
  1253. pszVal, -1, wcsDest.Get(), cwc);
  1254. BSTR bstrDest = (BSTR) rPool.CopyBSTR((cwc-1)*sizeof (OLECHAR),
  1255. wcsDest.Get());
  1256. *(ULONG_PTR*) pbDstBuf = rPool.PointerToOffset(bstrDest);
  1257. }
  1258. }
  1259. }
  1260. else
  1261. {
  1262. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  1263. rcbDstLen = 0;
  1264. }
  1265. return DstStatus;
  1266. } //_StoreString
  1267. //+-------------------------------------------------------------------------
  1268. //
  1269. // Member: CTableVariant::CopyOrCoerce, public
  1270. //
  1271. // Synopsis: Copy table data between a variant structure and
  1272. // a fixed width field. This is used both for copying
  1273. // data into a window, and out to an output destination.
  1274. //
  1275. // Arguments: [pbDstBuf] -- pointer to area to be filled in
  1276. // [cbDstBuf] -- size in bytes of storage area
  1277. // [vtDst] -- VARTYPE of the destination
  1278. // [rcbDstLen] -- on return, length of destination data
  1279. // [rPool] -- pool to use for destination buffers
  1280. //
  1281. // Returns: status for copy
  1282. //
  1283. // Notes: This function(and class) now deals only with PROPVARIANTs.
  1284. // If conversion is needed for OLE-DB/Automation types, use the
  1285. // COLEDBVariant class.
  1286. // The [rcbDstLen] is computed according to OLE-DB's (somewhat
  1287. // arbitrary) rules.
  1288. //
  1289. // History: 09 Jan 1998 VikasMan Modified the function to deal ONLY
  1290. // with PROPVARIANTs
  1291. //
  1292. //--------------------------------------------------------------------------
  1293. DBSTATUS CTableVariant::CopyOrCoerce(
  1294. BYTE * pbDstBuf,
  1295. DBLENGTH cbDstBuf,
  1296. VARTYPE vtDst,
  1297. DBLENGTH & rcbDstLen,
  1298. PVarAllocator & rPool) const
  1299. {
  1300. DBSTATUS DstStatus = DBSTATUS_S_OK;
  1301. Win4Assert( (vt & VT_BYREF) == 0 );
  1302. if ( ( vtDst == vt ) && IsSimpleType( vt ) && ! IsVectorOrArray( vt ) )
  1303. {
  1304. if (vt == VT_DECIMAL)
  1305. {
  1306. Win4Assert( cbDstBuf == sizeof (DECIMAL) );
  1307. RtlCopyMemory(pbDstBuf, this, cbDstBuf);
  1308. }
  1309. else
  1310. {
  1311. Win4Assert( cbDstBuf &&
  1312. cbDstBuf <= sizeof (LONGLONG) );
  1313. RtlCopyMemory(pbDstBuf, &iVal, cbDstBuf);
  1314. }
  1315. rcbDstLen = cbDstBuf;
  1316. }
  1317. else if ( VT_VARIANT == vtDst )
  1318. {
  1319. Win4Assert(cbDstBuf == sizeof PROPVARIANT);
  1320. Copy( (CTableVariant*) pbDstBuf, rPool, (USHORT) VarDataSize() );
  1321. if ( VT_EMPTY == vt )
  1322. DstStatus = DBSTATUS_S_ISNULL;
  1323. rcbDstLen = sizeof (PROPVARIANT);
  1324. }
  1325. else if ( VT_EMPTY == vt )
  1326. {
  1327. RtlZeroMemory( pbDstBuf, cbDstBuf );
  1328. DstStatus = DBSTATUS_S_ISNULL;
  1329. rcbDstLen = 0;
  1330. }
  1331. else if ( ( IsLPWSTR( vtDst ) ) || ( IsLPSTR( vtDst ) ) )
  1332. {
  1333. if ( VT_LPSTR == vt || VT_LPWSTR == vt || VT_BSTR == vt )
  1334. {
  1335. DstStatus = _StoreString( pbDstBuf,
  1336. cbDstBuf,
  1337. vtDst,
  1338. rcbDstLen,
  1339. rPool );
  1340. }
  1341. else
  1342. {
  1343. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  1344. rcbDstLen = 0;
  1345. }
  1346. }
  1347. else if ( vtDst == vt )
  1348. {
  1349. if ( VT_CLSID == vtDst )
  1350. {
  1351. // UUID is the one case of a fixed size indirect
  1352. // reference in DBVARIANT.
  1353. Win4Assert(cbDstBuf == sizeof GUID );
  1354. RtlCopyMemory(pbDstBuf,puuid,sizeof GUID);
  1355. rcbDstLen = sizeof (GUID);
  1356. }
  1357. else
  1358. {
  1359. // Must be a vector or a blob or a bstr
  1360. unsigned cbSrcVar = VarDataSize();
  1361. Win4Assert(vtDst == VT_BSTR ||
  1362. ((vtDst & VT_VECTOR) != 0 &&
  1363. vtDst != (VT_VARIANT|VT_VECTOR) &&
  1364. vtDst != (VT_LPWSTR|VT_VECTOR) &&
  1365. vtDst != (VT_LPSTR|VT_VECTOR)));
  1366. BYTE* pTmpBuf = (BYTE *) CopyData(rPool,(USHORT) cbSrcVar);
  1367. if (VariantPointerInFirstWord()) // BSTR case
  1368. {
  1369. Win4Assert(cbDstBuf == sizeof (BYTE *));
  1370. *(ULONG_PTR *) pbDstBuf = rPool.PointerToOffset(pTmpBuf);
  1371. rcbDstLen = sizeof (BSTR);
  1372. }
  1373. else
  1374. {
  1375. Win4Assert(VariantPointerInSecondWord() &&
  1376. (cbDstBuf == sizeof (BLOB) ||
  1377. cbDstBuf == sizeof (DBVECTOR)));
  1378. if (vtDst == VT_BLOB)
  1379. {
  1380. ((BLOB *) pbDstBuf)->pBlobData = (BYTE *) rPool.PointerToOffset(pTmpBuf);
  1381. ((BLOB *) pbDstBuf)->cbSize = blob.cbSize;
  1382. rcbDstLen = sizeof (BLOB);
  1383. }
  1384. else
  1385. {
  1386. ((DBVECTOR *) pbDstBuf)->ptr = (BYTE *) rPool.PointerToOffset(pTmpBuf);
  1387. ((DBVECTOR *) pbDstBuf)->size =cai.cElems;
  1388. rcbDstLen = 0;
  1389. }
  1390. }
  1391. }
  1392. }
  1393. else
  1394. {
  1395. // Coercion required. Only a very limited set of coercions
  1396. // are done. These are between various types of integers,
  1397. // and between two types of strings (both direct and by reference).
  1398. switch (vtDst)
  1399. {
  1400. case VT_LPWSTR:
  1401. case VT_LPSTR:
  1402. case VT_BSTR:
  1403. case (DBTYPE_STR | DBTYPE_BYREF):
  1404. case (DBTYPE_WSTR | DBTYPE_BYREF):
  1405. case DBTYPE_STR:
  1406. case DBTYPE_WSTR:
  1407. // case DBTYPE_BYTES:
  1408. if ( VT_LPSTR == vt || VT_LPWSTR == vt || VT_BSTR == vt )
  1409. {
  1410. DstStatus = _StoreString(pbDstBuf,
  1411. cbDstBuf,
  1412. vtDst,
  1413. rcbDstLen,
  1414. rPool);
  1415. }
  1416. else
  1417. {
  1418. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  1419. }
  1420. break;
  1421. case VT_R4:
  1422. if (VT_R8 == vt)
  1423. {
  1424. if (dblVal > FLT_MAX ||
  1425. dblVal < FLT_MIN)
  1426. DstStatus = DBSTATUS_S_TRUNCATED;
  1427. * (float *) pbDstBuf = (float) dblVal;
  1428. rcbDstLen = sizeof (float);
  1429. }
  1430. else
  1431. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  1432. break;
  1433. case VT_R8:
  1434. // since DATE is stored as a double, someone may want
  1435. // this odd coercion.
  1436. if (VT_R4 == vt)
  1437. * (double *) pbDstBuf = (double) fltVal;
  1438. if (VT_DATE == vt)
  1439. * (double *) pbDstBuf = (double) date;
  1440. else
  1441. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  1442. rcbDstLen = sizeof (double);
  1443. break;
  1444. case VT_HRESULT:
  1445. case VT_ERROR:
  1446. // allow coercions from some 4-byte quantities
  1447. if (VT_ERROR == vt || VT_HRESULT == vt ||
  1448. VT_I4 == vt || VT_UI4 == vt)
  1449. * (ULONG *) pbDstBuf = lVal;
  1450. else
  1451. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  1452. rcbDstLen = sizeof (SCODE);
  1453. break;
  1454. case VT_CY:
  1455. // allow coercions from I8 and UI8
  1456. if (VT_I8 == vt || VT_UI8 == vt)
  1457. * (LONGLONG *) pbDstBuf = hVal.QuadPart;
  1458. else
  1459. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  1460. rcbDstLen = sizeof (LONGLONG);
  1461. break;
  1462. case VT_I1:
  1463. case VT_UI1:
  1464. case VT_I2:
  1465. case VT_UI2:
  1466. case VT_I4:
  1467. case VT_UI4:
  1468. case VT_BOOL:
  1469. case VT_I8:
  1470. case VT_UI8:
  1471. if ( vt == VT_I1 ||
  1472. vt == VT_UI1 ||
  1473. vt == VT_I2 ||
  1474. vt == VT_UI2 ||
  1475. vt == VT_I4 ||
  1476. vt == VT_UI4 ||
  1477. vt == VT_I8 ||
  1478. vt == VT_UI8 ||
  1479. vt == VT_BOOL ||
  1480. vt == VT_ERROR ||
  1481. vt == VT_HRESULT ||
  1482. vt == VT_FILETIME ||
  1483. vt == VT_EMPTY ) // empty if object is deleted
  1484. {
  1485. DstStatus = _StoreInteger( vtDst, pbDstBuf );
  1486. if (DstStatus != DBSTATUS_E_CANTCONVERTVALUE)
  1487. rcbDstLen = cbDstBuf;
  1488. #if DBG
  1489. USHORT cbSize, cbAllign, rgFlags;
  1490. VartypeInfo( vtDst, cbSize, cbAllign, rgFlags );
  1491. // this fires for all conversions to VT_BOOL
  1492. // Win4Assert( rcbDstLen == cbSize );
  1493. Win4Assert( DstStatus != DBSTATUS_S_TRUNCATED );
  1494. #endif // DBG
  1495. }
  1496. else
  1497. {
  1498. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  1499. }
  1500. break;
  1501. case VT_CLSID:
  1502. // VT_CLSID is given with VT_BYREF in the row buffer
  1503. if (vt == (VT_CLSID | VT_BYREF))
  1504. RtlCopyMemory(pbDstBuf,puuid,sizeof (GUID *));
  1505. else
  1506. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  1507. break;
  1508. case VT_DATE:
  1509. case VT_FILETIME:
  1510. case DBTYPE_DBDATE:
  1511. case DBTYPE_DBTIME:
  1512. case DBTYPE_DBTIMESTAMP:
  1513. // CTableVariant class does not handle date conversions any longer.
  1514. // These get handled by its derived class - COLEDBVariant now
  1515. tbDebugOut(( DEB_IWARN,
  1516. "CTableVariant does not handle date conversions.\n" ));
  1517. //Win4Assert( !"Invalid switch case in CopyOrCoerce!" );
  1518. // FALL through
  1519. default:
  1520. DstStatus = DBSTATUS_E_CANTCONVERTVALUE;
  1521. tbDebugOut(( DEB_ITRACE,
  1522. "Unexpected dest storage type %4x\n"
  1523. "\tsource storage type %4x\n",
  1524. vtDst, vt));
  1525. break;
  1526. }
  1527. }
  1528. if (DstStatus == DBSTATUS_E_CANTCONVERTVALUE)
  1529. rcbDstLen = 0;
  1530. Win4Assert( rcbDstLen < 0x01000000 );
  1531. return DstStatus;
  1532. } //CopyOrCoerce
  1533. //+-------------------------------------------------------------------------
  1534. //
  1535. // Member: CTableVariant::Free, public, static
  1536. //
  1537. // Synopsis: Frees data associated with a variant or a variant type
  1538. //
  1539. // Arguments: [pbData] -- pointer to area to be freed
  1540. // [vtData] -- VARTYPE of the data
  1541. // [rPool] -- pool to free from if necessary
  1542. //
  1543. // History: 18 Jan 1995 dlee Created
  1544. //
  1545. //--------------------------------------------------------------------------
  1546. void CTableVariant::Free(
  1547. BYTE * pbData,
  1548. VARTYPE vtData,
  1549. PVarAllocator & rPool)
  1550. {
  1551. switch ( vtData )
  1552. {
  1553. case DBTYPE_BYREF|DBTYPE_PROPVARIANT:
  1554. Win4Assert( !"DBTYPE_BYREF|DBTYPE_PROPVARIANT free" );
  1555. {
  1556. CTableVariant *pvar = *((CTableVariant **) pbData);
  1557. Free( (BYTE *) & ( pvar->lVal ), pvar->vt, rPool );
  1558. break;
  1559. }
  1560. case VT_VARIANT :
  1561. {
  1562. CTableVariant *pvar = (CTableVariant *) pbData;
  1563. Free( (BYTE *) & ( pvar->lVal ), pvar->vt, rPool );
  1564. break;
  1565. }
  1566. case VT_EMPTY:
  1567. case VT_NULL:
  1568. case VT_I1:
  1569. case VT_I2:
  1570. case VT_I4:
  1571. case VT_I8:
  1572. case VT_UI1:
  1573. case VT_UI2:
  1574. case VT_UI4:
  1575. case VT_UI8:
  1576. case VT_INT:
  1577. case VT_UINT:
  1578. case VT_R4:
  1579. case VT_R8:
  1580. case VT_BOOL:
  1581. case VT_CY:
  1582. case VT_DATE:
  1583. case VT_DECIMAL:
  1584. case VT_FILETIME:
  1585. case VT_ERROR:
  1586. case DBTYPE_WSTR:
  1587. case DBTYPE_STR:
  1588. case DBTYPE_HCHAPTER:
  1589. break;
  1590. case VT_BSTR:
  1591. {
  1592. BSTR * pBstr = (BSTR *) pbData;
  1593. rPool.FreeBSTR( *pBstr );
  1594. break;
  1595. }
  1596. case VT_LPWSTR:
  1597. case VT_LPSTR:
  1598. case DBTYPE_STR | DBTYPE_BYREF:
  1599. case DBTYPE_WSTR | DBTYPE_BYREF:
  1600. case VT_CLSID:
  1601. {
  1602. rPool.Free( * (LPWSTR *) pbData );
  1603. break;
  1604. }
  1605. case VT_BLOB:
  1606. {
  1607. BLOB * p = (BLOB *) pbData;
  1608. if ( 0 != p->cbSize )
  1609. rPool.Free( p->pBlobData );
  1610. break;
  1611. }
  1612. case (VT_VECTOR | VT_I1):
  1613. case (VT_VECTOR | VT_I2):
  1614. case (VT_VECTOR | VT_I4):
  1615. case (VT_VECTOR | VT_I8):
  1616. case (VT_VECTOR | VT_UI1):
  1617. case (VT_VECTOR | VT_UI2):
  1618. case (VT_VECTOR | VT_UI4):
  1619. case (VT_VECTOR | VT_UI8):
  1620. case (VT_VECTOR | VT_R4):
  1621. case (VT_VECTOR | VT_R8):
  1622. case (VT_VECTOR | VT_BOOL):
  1623. case (VT_VECTOR | VT_CY):
  1624. case (VT_VECTOR | VT_DATE):
  1625. case (VT_VECTOR | VT_FILETIME):
  1626. case (VT_VECTOR | VT_CLSID):
  1627. {
  1628. CAUL * p = (CAUL *) pbData;
  1629. tbDebugOut(( DEB_ITRACE, "calling free on vector type %x, # %x, pb %x\n",
  1630. vtData, p->cElems, p->pElems ));
  1631. if ( 0 != p->cElems )
  1632. rPool.Free( p->pElems );
  1633. break;
  1634. }
  1635. case (VT_VECTOR | VT_LPSTR):
  1636. case (VT_VECTOR | VT_LPWSTR):
  1637. case (VT_VECTOR | DBTYPE_STR | DBTYPE_BYREF): // SPECDEVIATION vector/byref mutually exclusive
  1638. case (VT_VECTOR | DBTYPE_WSTR | DBTYPE_BYREF):
  1639. {
  1640. CALPWSTR * p = (CALPWSTR *) pbData;
  1641. if ( 0 != p->cElems )
  1642. {
  1643. for ( unsigned x = 0; x < p->cElems; x++ )
  1644. rPool.Free( p->pElems[ x ] );
  1645. rPool.Free( p->pElems );
  1646. }
  1647. break;
  1648. }
  1649. case (VT_VECTOR | VT_BSTR):
  1650. {
  1651. CABSTR * p = (CABSTR *) pbData;
  1652. if ( 0 != p->cElems )
  1653. {
  1654. for ( unsigned x = 0; x < p->cElems; x++ )
  1655. rPool.FreeBSTR( p->pElems[ x ] );
  1656. rPool.Free( p->pElems );
  1657. }
  1658. break;
  1659. }
  1660. case (VT_VECTOR | VT_VARIANT):
  1661. {
  1662. CAPROPVARIANT * p = (CAPROPVARIANT *) pbData;
  1663. if ( 0 != p->cElems )
  1664. {
  1665. for ( unsigned x = 0; x < p->cElems; x++ )
  1666. Free( (BYTE *) & (p->pElems[ x ]), VT_VARIANT, rPool );
  1667. rPool.Free( p->pElems );
  1668. }
  1669. break;
  1670. }
  1671. case VT_ARRAY|VT_I1:
  1672. case VT_ARRAY|VT_I2:
  1673. case VT_ARRAY|VT_I4:
  1674. case VT_ARRAY|VT_I8:
  1675. case VT_ARRAY|VT_UI1:
  1676. case VT_ARRAY|VT_UI2:
  1677. case VT_ARRAY|VT_UI4:
  1678. case VT_ARRAY|VT_UI8:
  1679. case VT_ARRAY|VT_INT:
  1680. case VT_ARRAY|VT_UINT:
  1681. case VT_ARRAY|VT_R4:
  1682. case VT_ARRAY|VT_R8:
  1683. case VT_ARRAY|VT_BOOL:
  1684. case VT_ARRAY|VT_CY:
  1685. case VT_ARRAY|VT_DATE:
  1686. case VT_ARRAY|VT_DECIMAL:
  1687. {
  1688. SAFEARRAY * p = *(SAFEARRAY **)pbData;
  1689. tbDebugOut(( DEB_ITRACE, "calling free on array type %x, # %x, pb %x\n",
  1690. vtData, p, p->pvData ));
  1691. rPool.Free( p->pvData );
  1692. rPool.Free( p );
  1693. break;
  1694. }
  1695. case VT_ARRAY|VT_BSTR:
  1696. {
  1697. SAFEARRAY * p = *(SAFEARRAY **)pbData;
  1698. tbDebugOut(( DEB_ITRACE, "calling free on array type %x, # %x, pb %x\n",
  1699. vtData, p, p->pvData ));
  1700. ULONG cElements = SaCountElements(*p);
  1701. BSTR *apBstr = (BSTR *)p->pvData;
  1702. for (unsigned x = 0; x < cElements; x++)
  1703. {
  1704. rPool.FreeBSTR( apBstr[ x ] );
  1705. }
  1706. rPool.Free( apBstr );
  1707. rPool.Free( p );
  1708. break;
  1709. }
  1710. case VT_ARRAY|VT_VARIANT:
  1711. {
  1712. SAFEARRAY * p = *(SAFEARRAY **)pbData;
  1713. tbDebugOut(( DEB_ITRACE, "calling free on array type %x, # %x, pb %x\n",
  1714. vtData, p, p->pvData ));
  1715. ULONG cElements = SaCountElements(*p);
  1716. VARIANT *apVarnt = (VARIANT *)p->pvData;
  1717. for (unsigned x = 0; x < cElements; x++)
  1718. {
  1719. Free( (BYTE *) & (apVarnt[ x ]), VT_VARIANT, rPool );
  1720. }
  1721. rPool.Free( apVarnt );
  1722. rPool.Free( p );
  1723. break;
  1724. }
  1725. case VT_CF:
  1726. {
  1727. CLIPDATA * * ppClipData = (CLIPDATA **) pbData;
  1728. if ( 0 != ppClipData )
  1729. {
  1730. rPool.Free( (*ppClipData)->pClipData );
  1731. rPool.Free( *ppClipData );
  1732. }
  1733. break;
  1734. }
  1735. case (VT_VECTOR | VT_CF):
  1736. {
  1737. CACLIPDATA * p = (CACLIPDATA *) pbData;
  1738. if ( 0 != p )
  1739. {
  1740. for ( ULONG i = 0; i < p->cElems; i++ )
  1741. rPool.Free( p->pElems[i].pClipData );
  1742. rPool.Free( p->pElems );
  1743. }
  1744. break;
  1745. }
  1746. default:
  1747. {
  1748. tbDebugOut(( DEB_WARN, "tblvarnt free of unknown type %x\n",
  1749. vtData ));
  1750. break;
  1751. }
  1752. }
  1753. } //Free