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.

1585 lines
44 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1998.
  5. //
  6. // File: StgVarA.cxx
  7. //
  8. // Contents: C++ wrapper for PROPVARIANT.
  9. //
  10. // History: 01-Aug-94 KyleP Created
  11. // 14-May-97 mohamedn allocate/deallocate SafeArrays (VT_ARRAY)
  12. //
  13. //--------------------------------------------------------------------------
  14. #include <pch.cxx>
  15. #pragma hdrstop
  16. #ifndef _NTDLLBUILD_
  17. #include <propset.h>
  18. #include <propvar.h>
  19. #include <pmalloc.hxx>
  20. CAllocStorageVariant::CAllocStorageVariant(
  21. BYTE *pb,
  22. ULONG cb,
  23. PMemoryAllocator &ma)
  24. {
  25. vt = VT_BLOB;
  26. if ( 0 == pb )
  27. {
  28. blob.cbSize = 0;
  29. blob.pBlobData = 0;
  30. }
  31. else
  32. {
  33. blob.cbSize = cb;
  34. blob.pBlobData = (BYTE *) ma.Allocate(cb);
  35. if (blob.pBlobData != NULL)
  36. {
  37. memcpy(blob.pBlobData, pb, cb);
  38. }
  39. }
  40. }
  41. CAllocStorageVariant::CAllocStorageVariant(
  42. char const *psz,
  43. PMemoryAllocator &ma)
  44. {
  45. vt = VT_LPSTR;
  46. if ( 0 == psz )
  47. {
  48. pszVal = 0;
  49. }
  50. else
  51. {
  52. int cb = strlen(psz) + 1;
  53. pszVal = (char *) ma.Allocate(cb);
  54. if (pszVal != NULL)
  55. {
  56. memcpy(pszVal, psz, cb);
  57. }
  58. }
  59. }
  60. CAllocStorageVariant::CAllocStorageVariant(
  61. WCHAR const *pwsz,
  62. PMemoryAllocator &ma)
  63. {
  64. vt = VT_LPWSTR;
  65. if ( 0 == pwsz )
  66. {
  67. pwszVal = 0;
  68. }
  69. else
  70. {
  71. int cb = (wcslen(pwsz) + 1) * sizeof(WCHAR);
  72. pwszVal = (WCHAR *) ma.Allocate(cb);
  73. if (pszVal != NULL)
  74. {
  75. memcpy(pwszVal, pwsz, cb);
  76. }
  77. }
  78. }
  79. CAllocStorageVariant::CAllocStorageVariant(
  80. CLSID const *pcid,
  81. PMemoryAllocator &ma)
  82. {
  83. vt = VT_CLSID;
  84. puuid = (CLSID *) ma.Allocate(sizeof(CLSID));
  85. if (puuid != NULL)
  86. {
  87. memcpy(puuid, pcid, sizeof(CLSID));
  88. }
  89. }
  90. CAllocStorageVariant::CAllocStorageVariant(
  91. VARENUM v,
  92. ULONG cElements,
  93. PMemoryAllocator &ma)
  94. {
  95. ULONG cbElement;
  96. BOOLEAN fZero = FALSE;
  97. // Ignore vector flag. This constructor is always for vectors only.
  98. vt = v | VT_VECTOR;
  99. switch (vt)
  100. {
  101. case VT_VECTOR | VT_I1:
  102. case VT_VECTOR | VT_UI1:
  103. AssertByteVector(cac); // VT_I1
  104. AssertByteVector(caub); // VT_UI1
  105. cbElement = sizeof(caub.pElems[0]);
  106. break;
  107. case VT_VECTOR | VT_I2:
  108. case VT_VECTOR | VT_UI2:
  109. case VT_VECTOR | VT_BOOL:
  110. AssertShortVector(cai); // VT_I2
  111. AssertShortVector(caui); // VT_UI2
  112. AssertShortVector(cabool); // VT_BOOL
  113. cbElement = sizeof(cai.pElems[0]);
  114. break;
  115. case VT_VECTOR | VT_I4:
  116. case VT_VECTOR | VT_UI4:
  117. case VT_VECTOR | VT_R4:
  118. case VT_VECTOR | VT_ERROR:
  119. AssertLongVector(cal); // VT_I4
  120. AssertLongVector(caul); // VT_UI4
  121. AssertLongVector(caflt); // VT_R4
  122. AssertLongVector(cascode); // VT_ERROR
  123. cbElement = sizeof(cal.pElems[0]);
  124. break;
  125. case VT_VECTOR | VT_I8:
  126. case VT_VECTOR | VT_UI8:
  127. case VT_VECTOR | VT_R8:
  128. case VT_VECTOR | VT_CY:
  129. case VT_VECTOR | VT_DATE:
  130. case VT_VECTOR | VT_FILETIME:
  131. AssertLongLongVector(cah); // VT_I8
  132. AssertLongLongVector(cauh); // VT_UI8
  133. AssertLongLongVector(cadbl); // VT_R8
  134. AssertLongLongVector(cacy); // VT_CY
  135. AssertLongLongVector(cadate); // VT_DATE
  136. AssertLongLongVector(cafiletime); // VT_FILETIME
  137. cbElement = sizeof(cah.pElems[0]);
  138. break;
  139. case VT_VECTOR | VT_CLSID:
  140. AssertVarVector(cauuid, sizeof(GUID));
  141. cbElement = sizeof(GUID);
  142. fZero = TRUE;
  143. break;
  144. case VT_VECTOR | VT_CF:
  145. AssertVarVector(caclipdata, sizeof(CLIPDATA)); // VT_CF
  146. cbElement = sizeof(CLIPDATA);
  147. fZero = TRUE;
  148. break;
  149. case VT_VECTOR | VT_BSTR:
  150. case VT_VECTOR | VT_LPSTR:
  151. case VT_VECTOR | VT_LPWSTR:
  152. AssertStringVector(calpwstr); // VT_LPWSTR
  153. AssertStringVector(cabstr); // VT_BSTR
  154. AssertStringVector(calpstr); // VT_LPSTR
  155. cbElement = sizeof(VOID *);
  156. fZero = TRUE;
  157. break;
  158. case VT_VECTOR | VT_VARIANT:
  159. AssertVarVector(capropvar, sizeof(PROPVARIANT)); // VT_VARIANT
  160. cbElement = sizeof(PROPVARIANT);
  161. ASSERT(VT_EMPTY == 0);
  162. fZero = TRUE;
  163. break;
  164. default:
  165. ASSERT(!"CAllocStorageVariant -- Invalid vector type");
  166. vt = VT_EMPTY;
  167. break;
  168. }
  169. if (vt != VT_EMPTY)
  170. {
  171. caub.cElems = 0;
  172. caub.pElems = (BYTE *) ma.Allocate(cElements * cbElement);
  173. if (caub.pElems != NULL)
  174. {
  175. if (fZero)
  176. {
  177. memset(caub.pElems, 0, cElements * cbElement);
  178. }
  179. caub.cElems = cElements;
  180. }
  181. }
  182. }
  183. #define POINTER_FIXUP(type, field) \
  184. field.pElems = (type *) ma.Allocate(field.cElems * sizeof(field.pElems[0]));\
  185. if (field.pElems != NULL) \
  186. { \
  187. memcpy( \
  188. field.pElems, \
  189. var.field.pElems, \
  190. field.cElems * sizeof(field.pElems[0])); \
  191. }
  192. CAllocStorageVariant::CAllocStorageVariant(
  193. PROPVARIANT& var,
  194. PMemoryAllocator &ma): CBaseStorageVariant(var)
  195. {
  196. BOOLEAN fNoMemory = FALSE;
  197. ULONG i;
  198. //
  199. // Fixup any pointers
  200. //
  201. switch (vt)
  202. {
  203. case VT_EMPTY:
  204. case VT_NULL:
  205. case VT_I1:
  206. case VT_UI1:
  207. case VT_I2:
  208. case VT_UI2:
  209. case VT_BOOL:
  210. case VT_I4:
  211. case VT_UI4:
  212. case VT_R4:
  213. case VT_ERROR:
  214. case VT_I8:
  215. case VT_UI8:
  216. case VT_R8:
  217. case VT_INT:
  218. case VT_UINT:
  219. case VT_DECIMAL:
  220. case VT_CY:
  221. case VT_DATE:
  222. case VT_FILETIME:
  223. break;
  224. case VT_CLSID:
  225. vt = VT_EMPTY;
  226. SetCLSID(var.puuid, ma);
  227. break;
  228. case VT_BLOB:
  229. case VT_BLOB_OBJECT:
  230. blob.pBlobData = (BYTE *) ma.Allocate(blob.cbSize);
  231. if (blob.pBlobData == NULL)
  232. {
  233. fNoMemory = TRUE;
  234. break;
  235. }
  236. memcpy(blob.pBlobData, var.blob.pBlobData, blob.cbSize);
  237. break;
  238. case VT_CF:
  239. pclipdata = (CLIPDATA *) ma.Allocate(sizeof(*pclipdata));
  240. if (pclipdata == NULL)
  241. {
  242. fNoMemory = TRUE;
  243. break;
  244. }
  245. *pclipdata = *var.pclipdata;
  246. pclipdata->pClipData = (BYTE *) ma.Allocate(CBPCLIPDATA(*pclipdata));
  247. if (pclipdata->pClipData == NULL)
  248. {
  249. fNoMemory = TRUE;
  250. break;
  251. }
  252. memcpy(pclipdata->pClipData, var.pclipdata->pClipData, CBPCLIPDATA(*pclipdata));
  253. break;
  254. case VT_STREAM:
  255. case VT_VERSIONED_STREAM:
  256. case VT_STREAMED_OBJECT:
  257. pStream->AddRef();
  258. break;
  259. case VT_STORAGE:
  260. case VT_STORED_OBJECT:
  261. pStorage->AddRef();
  262. break;
  263. case VT_BSTR:
  264. vt = VT_EMPTY;
  265. SetBSTR(var.bstrVal, ma);
  266. break;
  267. case VT_LPSTR:
  268. vt = VT_EMPTY;
  269. SetLPSTR(var.pszVal, ma);
  270. break;
  271. case VT_LPWSTR:
  272. vt = VT_EMPTY;
  273. SetLPWSTR(var.pwszVal, ma);
  274. break;
  275. case VT_VECTOR | VT_I1:
  276. case VT_VECTOR | VT_UI1:
  277. POINTER_FIXUP(BYTE, caub);
  278. break;
  279. case VT_VECTOR | VT_I2:
  280. case VT_VECTOR | VT_UI2:
  281. case VT_VECTOR | VT_BOOL:
  282. AssertShortVector(cai); // VT_I2
  283. AssertShortVector(caui); // VT_UI2
  284. AssertShortVector(cabool); // VT_BOOL
  285. POINTER_FIXUP(short, cai);
  286. break;
  287. case VT_VECTOR | VT_I4:
  288. case VT_VECTOR | VT_UI4:
  289. case VT_VECTOR | VT_R4:
  290. case VT_VECTOR | VT_ERROR:
  291. AssertLongVector(cal); // VT_I4
  292. AssertLongVector(caul); // VT_UI4
  293. AssertLongVector(caflt); // VT_R4
  294. AssertLongVector(cascode); // VT_ERROR
  295. POINTER_FIXUP(long, cal);
  296. break;
  297. case VT_VECTOR | VT_I8:
  298. case VT_VECTOR | VT_UI8:
  299. case VT_VECTOR | VT_R8:
  300. case VT_VECTOR | VT_CY:
  301. case VT_VECTOR | VT_DATE:
  302. case VT_VECTOR | VT_FILETIME:
  303. AssertLongLongVector(cah); // VT_I8
  304. AssertLongLongVector(cauh); // VT_UI8
  305. AssertLongLongVector(cadbl); // VT_R8
  306. AssertLongLongVector(cacy); // VT_CY
  307. AssertLongLongVector(cadate); // VT_DATE
  308. AssertLongLongVector(cafiletime); // VT_FILETIME
  309. POINTER_FIXUP(LARGE_INTEGER, cah);
  310. break;
  311. case VT_VECTOR | VT_CLSID:
  312. POINTER_FIXUP(CLSID, cauuid);
  313. break;
  314. case VT_VECTOR | VT_CF:
  315. {
  316. caclipdata.pElems = (CLIPDATA *)
  317. ma.Allocate(caclipdata.cElems * sizeof(caclipdata.pElems[0]));
  318. if (caclipdata.pElems == NULL)
  319. {
  320. fNoMemory = TRUE;
  321. break;
  322. }
  323. memset(
  324. caclipdata.pElems,
  325. 0,
  326. caclipdata.cElems * sizeof(caclipdata.pElems[0]));
  327. for (i = 0; i < caclipdata.cElems; i++)
  328. {
  329. caclipdata.pElems[i] = var.caclipdata.pElems[i];
  330. caclipdata.pElems[i].pClipData = (BYTE *)
  331. ma.Allocate(CBPCLIPDATA(caclipdata.pElems[i]));
  332. if (caclipdata.pElems[i].pClipData == NULL)
  333. {
  334. fNoMemory = TRUE;
  335. break;
  336. }
  337. memcpy(
  338. caclipdata.pElems[i].pClipData,
  339. var.caclipdata.pElems[i].pClipData,
  340. CBPCLIPDATA(caclipdata.pElems[i]));
  341. }
  342. break;
  343. }
  344. case VT_VECTOR | VT_BSTR:
  345. {
  346. cabstr.pElems = (BSTR *)
  347. ma.Allocate(cabstr.cElems * sizeof(cabstr.pElems[0]));
  348. if (cabstr.pElems == NULL)
  349. {
  350. fNoMemory = TRUE;
  351. break;
  352. }
  353. memset(cabstr.pElems, 0, cabstr.cElems * sizeof(cabstr.pElems[0]));
  354. for (i = 0; i < cabstr.cElems; i++)
  355. {
  356. cabstr.pElems[i] = SysAllocString(var.cabstr.pElems[i]);
  357. if (cabstr.pElems[i] == NULL)
  358. {
  359. fNoMemory = TRUE;
  360. break;
  361. }
  362. }
  363. break;
  364. }
  365. case VT_VECTOR | VT_LPSTR:
  366. {
  367. calpstr.pElems = (LPSTR *)
  368. ma.Allocate(calpstr.cElems * sizeof(calpstr.pElems[0]));
  369. if (calpstr.pElems == NULL)
  370. {
  371. fNoMemory = TRUE;
  372. break;
  373. }
  374. memset(calpstr.pElems, 0, calpstr.cElems * sizeof(calpstr.pElems[0]));
  375. for (i = 0; i < calpstr.cElems; i++)
  376. {
  377. unsigned cb = strlen(var.calpstr.pElems[i]) + 1;
  378. calpstr.pElems[i] = (char *) ma.Allocate(cb);
  379. if (calpstr.pElems[i] == NULL)
  380. {
  381. fNoMemory = TRUE;
  382. break;
  383. }
  384. memcpy(calpstr.pElems[i], var.calpstr.pElems[i], cb);
  385. }
  386. break;
  387. }
  388. case VT_VECTOR | VT_LPWSTR:
  389. {
  390. calpwstr.pElems = (LPWSTR *)
  391. ma.Allocate(calpwstr.cElems * sizeof(calpwstr.pElems[0]));
  392. if (calpwstr.pElems == NULL)
  393. {
  394. fNoMemory = TRUE;
  395. break;
  396. }
  397. memset(calpwstr.pElems, 0, calpwstr.cElems * sizeof(calpwstr.pElems[0]));
  398. for (i = 0; i < calpwstr.cElems; i++)
  399. {
  400. unsigned cb = (wcslen(var.calpwstr.pElems[i]) + 1) * sizeof(WCHAR);
  401. calpwstr.pElems[i] = (WCHAR *) ma.Allocate(cb);
  402. if (calpwstr.pElems[i] == NULL)
  403. {
  404. fNoMemory = TRUE;
  405. break;
  406. }
  407. memcpy(calpwstr.pElems[i], var.calpwstr.pElems[i], cb);
  408. }
  409. break;
  410. }
  411. case VT_VECTOR | VT_VARIANT:
  412. capropvar.pElems = (PROPVARIANT *)
  413. ma.Allocate(capropvar.cElems * sizeof(capropvar.pElems[0]));
  414. if (capropvar.pElems == NULL)
  415. {
  416. fNoMemory = TRUE;
  417. break;
  418. }
  419. ASSERT(VT_EMPTY == 0);
  420. memset(
  421. capropvar.pElems,
  422. 0,
  423. capropvar.cElems * sizeof(capropvar.pElems[0]));
  424. for (i = 0; i < capropvar.cElems; i++)
  425. {
  426. new (&capropvar.pElems[i]) CAllocStorageVariant(
  427. var.capropvar.pElems[i],
  428. ma);
  429. if (!((CAllocStorageVariant *) &capropvar.pElems[i])->IsValid())
  430. {
  431. fNoMemory = TRUE;
  432. break;
  433. }
  434. }
  435. break;
  436. case VT_ARRAY | VT_I4:
  437. case VT_ARRAY | VT_UI1:
  438. case VT_ARRAY | VT_I2:
  439. case VT_ARRAY | VT_R4:
  440. case VT_ARRAY | VT_R8:
  441. case VT_ARRAY | VT_BOOL:
  442. case VT_ARRAY | VT_ERROR:
  443. case VT_ARRAY | VT_CY:
  444. case VT_ARRAY | VT_DATE:
  445. case VT_ARRAY | VT_I1:
  446. case VT_ARRAY | VT_UI2:
  447. case VT_ARRAY | VT_UI4:
  448. case VT_ARRAY | VT_INT:
  449. case VT_ARRAY | VT_UINT:
  450. case VT_ARRAY | VT_DECIMAL:
  451. case VT_ARRAY | VT_BSTR:
  452. case VT_ARRAY | VT_VARIANT:
  453. {
  454. //
  455. // avoid double delete of the source variant
  456. //
  457. parray = 0;
  458. SAFEARRAY * pSaDst = 0;
  459. if ( FAILED( SafeArrayCopy( var.parray, &pSaDst ) ) )
  460. {
  461. fNoMemory = TRUE;
  462. break;
  463. }
  464. parray = pSaDst;
  465. }
  466. break;
  467. default:
  468. {
  469. Win4Assert( !"Unexpected vt type" );
  470. return;
  471. }
  472. }
  473. if (fNoMemory || !IsValid())
  474. {
  475. ResetType(ma);
  476. // We cannot raise in a non-unwindable constructor.
  477. // Just return a PROPVARIANT guaranteed to look invalid.
  478. vt = VT_LPSTR;
  479. pszVal = NULL;
  480. }
  481. }
  482. //+---------------------------------------------------------------------------
  483. //
  484. // Function: SaCreateAndCopy
  485. //
  486. // Synopsis: Creates a safearray & initializes it with source safearray.
  487. //
  488. // Arguments: [ma] - memory allocator to use
  489. // [psaSrc] - source safearry
  490. // [ppsaDst] - safearray to be created.
  491. //
  492. // Returns: TRUE - upon success
  493. // FALSE - upon failure
  494. //
  495. // History: 5-10-97 mohamedn created
  496. //
  497. //----------------------------------------------------------------------------
  498. BOOL SaCreateAndCopy( PMemoryAllocator &ma,
  499. SAFEARRAY * psaSrc,
  500. SAFEARRAY **ppsaDst )
  501. {
  502. ULONG cb = sizeof SAFEARRAY + ( ( 0 != psaSrc->cDims ?
  503. (psaSrc->cDims-1) : 0) * sizeof SAFEARRAYBOUND );
  504. Win4Assert( psaSrc->cDims > 0);
  505. SAFEARRAY * psaDst = (SAFEARRAY *) ma.Allocate( cb );
  506. if ( 0 == psaDst )
  507. {
  508. *ppsaDst = 0;
  509. return FALSE;
  510. }
  511. RtlCopyMemory(psaDst, psaSrc, cb);
  512. // reset fields and values
  513. psaDst->fFeatures &= ~( FADF_AUTO | FADF_STATIC );
  514. psaDst->cLocks = 1; // new safearray has lockcount of 1
  515. psaDst->pvData = 0;
  516. *ppsaDst = psaDst;
  517. return TRUE;
  518. } //SaCreateAndCopy
  519. //+---------------------------------------------------------------------------
  520. //
  521. // Function: SaCreateData
  522. //
  523. // Synopsis: Creates/initializes SafeArray's data area
  524. //
  525. // Arguments: [ma] - memory allocator to use
  526. // [vt] - variant type (VT_ARRAY assumed)
  527. // [saSrc] - source safearry
  528. // [saDst] - destination safearray.
  529. // [fUseAllocatorOnly] - if TRUE, BSTRs are allocated using [ma]
  530. //
  531. // Returns: TRUE - upon success
  532. // FALSE - upon failure
  533. //
  534. // History: 5-10-97 mohamedn created
  535. //
  536. //----------------------------------------------------------------------------
  537. BOOL SaCreateData(
  538. PVarAllocator & ma,
  539. VARTYPE vt,
  540. SAFEARRAY & saSrc,
  541. SAFEARRAY & saDst,
  542. BOOL fUseAllocatorOnly )
  543. {
  544. //
  545. // Find out how much memory is needed for the array and allocate it.
  546. //
  547. unsigned cDataElements = SaCountElements(saSrc);
  548. ULONG cb = cDataElements * saSrc.cbElements;
  549. void * pv = ma.Allocate( cb );
  550. if ( !pv )
  551. return FALSE;
  552. RtlZeroMemory( pv, cb );
  553. switch (vt)
  554. {
  555. case VT_I4:
  556. case VT_UI1:
  557. case VT_I2:
  558. case VT_R4:
  559. case VT_R8:
  560. case VT_BOOL:
  561. case VT_ERROR:
  562. case VT_CY:
  563. case VT_DATE:
  564. case VT_I1:
  565. case VT_UI2:
  566. case VT_UI4:
  567. case VT_INT:
  568. case VT_UINT:
  569. case VT_DECIMAL:
  570. {
  571. RtlCopyMemory( pv, saSrc.pvData, cb);
  572. saDst.pvData = pv;
  573. }
  574. break;
  575. case VT_BSTR:
  576. {
  577. BSTR *pBstrSrc = (BSTR *) saSrc.pvData;
  578. BSTR *pBstrDst = (BSTR *) pv;
  579. for ( unsigned i = 0; i < cDataElements; i++ )
  580. {
  581. Win4Assert( pBstrSrc[i] != 0 );
  582. Win4Assert( pBstrDst[i] == 0 );
  583. if ( fUseAllocatorOnly )
  584. {
  585. ULONG cbBstr = SysStringByteLen(pBstrSrc[i]) +
  586. sizeof (ULONG) +
  587. sizeof (WCHAR);
  588. void * pv = ma.Allocate( cbBstr );
  589. if ( 0 != pv )
  590. {
  591. BYTE * pbSrc = (BYTE *) pBstrSrc[i];
  592. pbSrc -= sizeof ULONG;
  593. RtlCopyMemory( pv, pbSrc, cbBstr);
  594. pBstrDst[i] = (BSTR) ( (BYTE *) pv + sizeof ULONG );
  595. pBstrDst[i] = (BSTR) ma.PointerToOffset( pBstrDst[i] );
  596. }
  597. }
  598. else
  599. {
  600. pBstrDst[i] = SysAllocString(pBstrSrc[i]);
  601. }
  602. if ( 0 == pBstrDst[i] )
  603. return FALSE;
  604. }
  605. saDst.pvData = pv;
  606. }
  607. break;
  608. case VT_VARIANT:
  609. {
  610. CAllocStorageVariant *pVarntSrc = (CAllocStorageVariant *)saSrc.pvData;
  611. CAllocStorageVariant *pVarntDst = (CAllocStorageVariant *)pv;
  612. for ( unsigned i = 0; i < cDataElements; i++ )
  613. {
  614. Win4Assert( pVarntDst[i].vt == 0 );
  615. if ( VT_BSTR == pVarntSrc[i].vt )
  616. {
  617. if ( fUseAllocatorOnly )
  618. {
  619. ULONG cbBstr = SysStringByteLen(pVarntSrc[i].bstrVal) +
  620. sizeof (ULONG) +
  621. sizeof (WCHAR);
  622. void * pv = ma.Allocate( cbBstr );
  623. if ( 0 != pv )
  624. {
  625. BYTE * pbSrc = (BYTE *) pVarntSrc[i].bstrVal;
  626. pbSrc -= sizeof ULONG;
  627. RtlCopyMemory( pv, pbSrc, cbBstr);
  628. pVarntDst[i].bstrVal = (BSTR) ((BYTE *) pv + sizeof ULONG);
  629. pVarntDst[i].bstrVal = (BSTR) ma.PointerToOffset( pVarntDst[i].bstrVal );
  630. }
  631. }
  632. else
  633. {
  634. pVarntDst[i].bstrVal = SysAllocString(pVarntSrc[i].bstrVal);
  635. }
  636. if ( 0 == pVarntDst[i].bstrVal )
  637. return FALSE;
  638. pVarntDst[i].vt = VT_BSTR;
  639. }
  640. else if ( 0 != (pVarntSrc[i].vt & VT_ARRAY) )
  641. {
  642. SAFEARRAY * pSaSrc = pVarntSrc[i].parray;
  643. SAFEARRAY * pSaDst = 0;
  644. if ( !SaCreateAndCopy( ma, pSaSrc, &pSaDst ) )
  645. return FALSE;
  646. if ( !SaCreateData( ma,
  647. pVarntSrc[i].vt & ~VT_ARRAY,
  648. *pSaSrc,
  649. *pSaDst,
  650. fUseAllocatorOnly ) )
  651. return FALSE;
  652. pVarntDst[i].parray = (SAFEARRAY *) ma.PointerToOffset( pSaDst );
  653. pVarntDst[i].vt = pVarntSrc[i].vt;
  654. }
  655. else
  656. {
  657. Win4Assert( pVarntSrc[i].vt != VT_VARIANT );
  658. Win4Assert( pVarntSrc[i].vt != VT_LPWSTR );
  659. Win4Assert( pVarntSrc[i].vt != VT_LPSTR );
  660. Win4Assert( pVarntSrc[i].vt != VT_CLSID );
  661. pVarntDst[i] = pVarntSrc[i];
  662. }
  663. }
  664. saDst.pvData = pv;
  665. }
  666. break;
  667. default:
  668. ciDebugOut(( DEB_ERROR, "Unexpected SafeArray type: vt=%x\n", vt ) );
  669. Win4Assert( !"Unexpected SafeArray Type" );
  670. return FALSE;
  671. }
  672. saDst.pvData = (void *) ma.PointerToOffset( saDst.pvData );
  673. return TRUE;
  674. } //SaCreateData
  675. //+---------------------------------------------------------------------------
  676. //
  677. // Function: SaComputeSize
  678. //
  679. // Synopsis: Computes the size of a safearray.
  680. //
  681. // Arguments: [vt] - variant type (VT_ARRAY assumed)
  682. // [saSrc] - source safearry
  683. //
  684. // Returns: ULONG - number of bytes of memory needed to store safearray
  685. //
  686. // History: 5-01-98 AlanW Created
  687. //
  688. //----------------------------------------------------------------------------
  689. ULONG SaComputeSize( VARTYPE vt,
  690. SAFEARRAY & saSrc )
  691. {
  692. //
  693. // get number of data elements in array and size of the header.
  694. //
  695. unsigned cDataElements = SaCountElements(saSrc);
  696. Win4Assert( 0 != saSrc.cDims );
  697. ULONG cb = sizeof (SAFEARRAY) +
  698. (saSrc.cDims-1) * sizeof (SAFEARRAYBOUND) +
  699. cDataElements * saSrc.cbElements;
  700. cb = AlignBlock( cb, sizeof LONGLONG );
  701. switch (vt)
  702. {
  703. case VT_I4:
  704. case VT_UI1:
  705. case VT_I2:
  706. case VT_R4:
  707. case VT_R8:
  708. case VT_BOOL:
  709. case VT_ERROR:
  710. case VT_CY:
  711. case VT_DATE:
  712. case VT_I1:
  713. case VT_UI2:
  714. case VT_UI4:
  715. case VT_INT:
  716. case VT_UINT:
  717. case VT_DECIMAL:
  718. break;
  719. case VT_BSTR:
  720. {
  721. BSTR *pBstrSrc = (BSTR *) saSrc.pvData;
  722. for ( unsigned i = 0; i < cDataElements; i++ )
  723. {
  724. Win4Assert( pBstrSrc[i] != 0 );
  725. cb += AlignBlock( SysStringByteLen(pBstrSrc[i]) +
  726. sizeof ULONG + sizeof WCHAR,
  727. sizeof LONGLONG );
  728. }
  729. }
  730. break;
  731. case VT_VARIANT:
  732. {
  733. CAllocStorageVariant *pVarnt = (CAllocStorageVariant *)saSrc.pvData;
  734. for ( unsigned i = 0; i < cDataElements; i++ )
  735. {
  736. if ( VT_BSTR == pVarnt[i].vt )
  737. {
  738. cb += AlignBlock( SysStringByteLen(pVarnt[i].bstrVal) +
  739. sizeof ULONG + sizeof WCHAR,
  740. sizeof LONGLONG );
  741. }
  742. else if ( 0 != (pVarnt[i].vt & VT_ARRAY) )
  743. {
  744. cb += AlignBlock( SaComputeSize( (pVarnt[i].vt & ~VT_ARRAY),
  745. *pVarnt[i].parray),
  746. sizeof LONGLONG );
  747. }
  748. else
  749. {
  750. Win4Assert( pVarnt[i].vt != VT_VARIANT );
  751. }
  752. }
  753. }
  754. break;
  755. default:
  756. ciDebugOut(( DEB_ERROR, "Unexpected SafeArray type: vt=%x\n", vt ) );
  757. Win4Assert( !"Unexpected SafeArray Type" );
  758. return 1;
  759. }
  760. return cb;
  761. }
  762. CAllocStorageVariant::~CAllocStorageVariant()
  763. {
  764. switch (vt)
  765. {
  766. case VT_EMPTY:
  767. case VT_NULL:
  768. case VT_I1:
  769. case VT_UI1:
  770. case VT_I2:
  771. case VT_UI2:
  772. case VT_BOOL:
  773. case VT_I4:
  774. case VT_UI4:
  775. case VT_R4:
  776. case VT_ERROR:
  777. case VT_I8:
  778. case VT_UI8:
  779. case VT_R8:
  780. case VT_INT:
  781. case VT_UINT:
  782. case VT_DECIMAL:
  783. case VT_CY:
  784. case VT_DATE:
  785. case VT_FILETIME:
  786. break;
  787. default:
  788. ciDebugOut(( DEB_ERROR, "~CAllocStorageVariant -- Memory Leak: vt=%x\n", vt ) );
  789. }
  790. }
  791. void
  792. CAllocStorageVariant::ResetType(PMemoryAllocator &ma)
  793. {
  794. // The most typical case
  795. if ( VT_EMPTY == vt )
  796. return;
  797. ULONG i;
  798. if ((vt & VT_BYREF) == 0)
  799. {
  800. switch (vt)
  801. {
  802. case VT_EMPTY:
  803. case VT_NULL:
  804. case VT_I1:
  805. case VT_UI1:
  806. case VT_I2:
  807. case VT_UI2:
  808. case VT_BOOL:
  809. case VT_I4:
  810. case VT_UI4:
  811. case VT_R4:
  812. case VT_ERROR:
  813. case VT_I8:
  814. case VT_UI8:
  815. case VT_R8:
  816. case VT_INT:
  817. case VT_UINT:
  818. case VT_DECIMAL:
  819. case VT_CY:
  820. case VT_DATE:
  821. case VT_FILETIME:
  822. break;
  823. case VT_CLSID:
  824. ma.Free(puuid);
  825. break;
  826. case VT_BLOB:
  827. case VT_BLOB_OBJECT:
  828. ma.Free(blob.pBlobData);
  829. break;
  830. case VT_CF:
  831. if (pclipdata != NULL)
  832. {
  833. ma.Free(pclipdata->pClipData);
  834. ma.Free(pclipdata);
  835. }
  836. break;
  837. case VT_STREAM:
  838. case VT_VERSIONED_STREAM:
  839. case VT_STREAMED_OBJECT:
  840. pStream->Release();
  841. break;
  842. case VT_STORAGE:
  843. case VT_STORED_OBJECT:
  844. pStorage->Release();
  845. break;
  846. case VT_BSTR:
  847. SysFreeString(bstrVal);
  848. break;
  849. case VT_LPSTR:
  850. case VT_LPWSTR:
  851. AssertStringField(pszVal); // VT_LPSTR
  852. AssertStringField(pwszVal); // VT_LPWSTR
  853. ma.Free(pwszVal);
  854. break;
  855. case VT_VECTOR | VT_I1:
  856. case VT_VECTOR | VT_UI1:
  857. case VT_VECTOR | VT_I2:
  858. case VT_VECTOR | VT_UI2:
  859. case VT_VECTOR | VT_BOOL:
  860. case VT_VECTOR | VT_I4:
  861. case VT_VECTOR | VT_UI4:
  862. case VT_VECTOR | VT_R4:
  863. case VT_VECTOR | VT_ERROR:
  864. case VT_VECTOR | VT_I8:
  865. case VT_VECTOR | VT_UI8:
  866. case VT_VECTOR | VT_R8:
  867. case VT_VECTOR | VT_CY:
  868. case VT_VECTOR | VT_DATE:
  869. case VT_VECTOR | VT_FILETIME:
  870. case VT_VECTOR | VT_CLSID:
  871. AssertByteVector(cac); // VT_I1
  872. AssertByteVector(caub); // VT_UI1
  873. AssertShortVector(cai); // VT_I2
  874. AssertShortVector(caui); // VT_UI2
  875. AssertShortVector(cabool); // VT_BOOL
  876. AssertLongVector(cal); // VT_I4
  877. AssertLongVector(caul); // VT_UI4
  878. AssertLongVector(caflt); // VT_R4
  879. AssertLongVector(cascode); // VT_ERROR
  880. AssertLongLongVector(cah); // VT_I8
  881. AssertLongLongVector(cauh); // VT_UI8
  882. AssertLongLongVector(cadbl); // VT_R8
  883. AssertLongLongVector(cacy); // VT_CY
  884. AssertLongLongVector(cadate); // VT_DATE
  885. AssertLongLongVector(cafiletime); // VT_FILETIME
  886. AssertVarVector(cauuid, sizeof(GUID)); // VT_CLSID
  887. ma.Free(cal.pElems);
  888. break;
  889. case VT_VECTOR | VT_CF:
  890. if (caclipdata.pElems != NULL)
  891. {
  892. for (i = 0; i < caclipdata.cElems; i++)
  893. {
  894. ma.Free(caclipdata.pElems[i].pClipData);
  895. }
  896. ma.Free(caclipdata.pElems);
  897. }
  898. break;
  899. case VT_VECTOR | VT_LPSTR:
  900. case VT_VECTOR | VT_LPWSTR:
  901. AssertStringVector(calpwstr); // VT_LPWSTR
  902. AssertStringVector(calpstr); // VT_LPSTR
  903. if (calpwstr.pElems != NULL)
  904. {
  905. for (i = 0; i < calpwstr.cElems; i++)
  906. {
  907. if (calpstr.pElems[i] != NULL) // don't free (NULL - cbbstr)
  908. {
  909. ma.Free((BYTE *) calpstr.pElems[i] );
  910. }
  911. }
  912. ma.Free(calpwstr.pElems);
  913. }
  914. break;
  915. case VT_VECTOR | VT_BSTR:
  916. AssertStringVector(cabstr); // VT_BSTR
  917. if (cabstr.pElems != NULL )
  918. {
  919. for (i = 0; i < cabstr.cElems; i++)
  920. {
  921. SysFreeString(cabstr.pElems[i]);
  922. }
  923. ma.Free(cabstr.pElems);
  924. }
  925. break;
  926. case VT_VECTOR | VT_VARIANT:
  927. if (capropvar.pElems != NULL)
  928. {
  929. for (i = 0; i < calpstr.cElems; i++)
  930. {
  931. ((CAllocStorageVariant *) &capropvar.pElems[i])->ResetType(ma);
  932. }
  933. ma.Free(capropvar.pElems);
  934. }
  935. break;
  936. case VT_ARRAY | VT_I4:
  937. case VT_ARRAY | VT_UI1:
  938. case VT_ARRAY | VT_I2:
  939. case VT_ARRAY | VT_R4:
  940. case VT_ARRAY | VT_R8:
  941. case VT_ARRAY | VT_BOOL:
  942. case VT_ARRAY | VT_ERROR:
  943. case VT_ARRAY | VT_CY:
  944. case VT_ARRAY | VT_DATE:
  945. case VT_ARRAY | VT_I1:
  946. case VT_ARRAY | VT_UI2:
  947. case VT_ARRAY | VT_UI4:
  948. case VT_ARRAY | VT_INT:
  949. case VT_ARRAY | VT_UINT:
  950. case VT_ARRAY | VT_DECIMAL:
  951. case VT_ARRAY | VT_BSTR:
  952. case VT_ARRAY | VT_VARIANT:
  953. {
  954. //
  955. // What should we do if the array is locked?
  956. // Perhaps just set cLocks to 0 so it can be freed.
  957. // Note that we never hit the assert below because
  958. // we deal with SafeArrays under our control so we
  959. // know they won't be locked.
  960. //
  961. if ( 0 != parray )
  962. {
  963. Win4Assert( 0 == parray->cLocks );
  964. HRESULT hr = SafeArrayDestroy( parray );
  965. Win4Assert( S_OK == hr );
  966. }
  967. break;
  968. }
  969. default:
  970. Win4Assert( !" Unexpected VT type" );
  971. }
  972. }
  973. vt = VT_EMPTY;
  974. }
  975. // Invalid variants have a pointer type but a NULL pointer.
  976. // Some are valid in this form in general, but not for many uses.
  977. BOOL
  978. CAllocStorageVariant::IsValid() const
  979. {
  980. ULONG i;
  981. if ((VT_VECTOR & vt) && cal.cElems != 0 && cal.pElems == NULL)
  982. {
  983. return(FALSE);
  984. }
  985. switch (vt)
  986. {
  987. case VT_EMPTY:
  988. case VT_NULL:
  989. case VT_I1:
  990. case VT_UI1:
  991. case VT_I2:
  992. case VT_UI2:
  993. case VT_BOOL:
  994. case VT_I4:
  995. case VT_UI4:
  996. case VT_R4:
  997. case VT_ERROR:
  998. case VT_I8:
  999. case VT_UI8:
  1000. case VT_INT:
  1001. case VT_UINT:
  1002. case VT_R8:
  1003. case VT_CY:
  1004. case VT_DATE:
  1005. case VT_FILETIME:
  1006. break;
  1007. case VT_DECIMAL:
  1008. return ( 0 == decVal.sign || DECIMAL_NEG == decVal.sign );
  1009. case VT_CLSID:
  1010. return(puuid != NULL);
  1011. case VT_BLOB:
  1012. case VT_BLOB_OBJECT:
  1013. return(blob.cbSize == 0 || blob.pBlobData != NULL);
  1014. case VT_CF:
  1015. return(pclipdata != NULL && pclipdata->pClipData != NULL);
  1016. case VT_STREAM:
  1017. case VT_VERSIONED_STREAM:
  1018. case VT_STREAMED_OBJECT:
  1019. return(pStream != NULL);
  1020. case VT_STORAGE:
  1021. case VT_STORED_OBJECT:
  1022. return(pStorage != NULL);
  1023. case VT_BSTR:
  1024. case VT_LPSTR:
  1025. case VT_LPWSTR:
  1026. AssertStringField(bstrVal); // VT_BSTR
  1027. AssertStringField(pszVal); // VT_LPSTR
  1028. AssertStringField(pwszVal); // VT_LPWSTR
  1029. return(pszVal != NULL);
  1030. case VT_VECTOR | VT_I1:
  1031. case VT_VECTOR | VT_UI1:
  1032. case VT_VECTOR | VT_I2:
  1033. case VT_VECTOR | VT_UI2:
  1034. case VT_VECTOR | VT_BOOL:
  1035. case VT_VECTOR | VT_I4:
  1036. case VT_VECTOR | VT_UI4:
  1037. case VT_VECTOR | VT_R4:
  1038. case VT_VECTOR | VT_ERROR:
  1039. case VT_VECTOR | VT_I8:
  1040. case VT_VECTOR | VT_UI8:
  1041. case VT_VECTOR | VT_R8:
  1042. case VT_VECTOR | VT_CY:
  1043. case VT_VECTOR | VT_DATE:
  1044. case VT_VECTOR | VT_FILETIME:
  1045. case VT_VECTOR | VT_CLSID:
  1046. AssertByteVector(cac); // VT_I1
  1047. AssertByteVector(caub); // VT_UI1
  1048. AssertShortVector(cai); // VT_I2
  1049. AssertShortVector(caui); // VT_UI2
  1050. AssertShortVector(cabool); // VT_BOOL
  1051. AssertLongVector(cal); // VT_I4
  1052. AssertLongVector(caul); // VT_UI4
  1053. AssertLongVector(caflt); // VT_R4
  1054. AssertLongVector(cascode); // VT_ERROR
  1055. AssertLongLongVector(cah); // VT_I8
  1056. AssertLongLongVector(cauh); // VT_UI8
  1057. AssertLongLongVector(cadbl); // VT_R8
  1058. AssertLongLongVector(cacy); // VT_CY
  1059. AssertLongLongVector(cadate); // VT_DATE
  1060. AssertLongLongVector(cafiletime); // VT_FILETIME
  1061. AssertVarVector(cauuid, sizeof(GUID)); // VT_CLSID
  1062. break;
  1063. case VT_VECTOR | VT_CF:
  1064. for (i = 0; i < caclipdata.cElems; i++)
  1065. {
  1066. if (caclipdata.pElems[i].pClipData == NULL)
  1067. {
  1068. return(FALSE);
  1069. }
  1070. }
  1071. case VT_VECTOR | VT_BSTR:
  1072. case VT_VECTOR | VT_LPSTR:
  1073. case VT_VECTOR | VT_LPWSTR:
  1074. AssertStringVector(calpwstr); // VT_LPWSTR
  1075. AssertStringVector(cabstr); // VT_BSTR
  1076. AssertStringVector(calpstr); // VT_LPSTR
  1077. for (i = 0; i < calpstr.cElems; i++)
  1078. {
  1079. if (calpstr.pElems[i] == NULL)
  1080. {
  1081. return(FALSE);
  1082. }
  1083. }
  1084. break;
  1085. case VT_VECTOR | VT_VARIANT:
  1086. for (i = 0; i < capropvar.cElems; i++)
  1087. {
  1088. if (!((CAllocStorageVariant *) &capropvar.pElems[i])->IsValid())
  1089. {
  1090. return(FALSE);
  1091. }
  1092. }
  1093. break;
  1094. case VT_ARRAY | VT_I4:
  1095. case VT_ARRAY | VT_UI1:
  1096. case VT_ARRAY | VT_I2:
  1097. case VT_ARRAY | VT_R4:
  1098. case VT_ARRAY | VT_R8:
  1099. case VT_ARRAY | VT_BOOL:
  1100. case VT_ARRAY | VT_ERROR:
  1101. case VT_ARRAY | VT_CY:
  1102. case VT_ARRAY | VT_DATE:
  1103. case VT_ARRAY | VT_I1:
  1104. case VT_ARRAY | VT_UI2:
  1105. case VT_ARRAY | VT_UI4:
  1106. case VT_ARRAY | VT_INT:
  1107. case VT_ARRAY | VT_UINT:
  1108. case VT_ARRAY | VT_BSTR:
  1109. case VT_ARRAY | VT_DECIMAL:
  1110. case VT_ARRAY | VT_VARIANT:
  1111. {
  1112. SAFEARRAY *pSa = parray;
  1113. if ( 0 == pSa )
  1114. return FALSE;
  1115. if ( !(pSa->cDims && pSa->pvData) )
  1116. return FALSE;
  1117. // validate all the bstrs are allocated
  1118. if ( ( VT_BSTR | VT_ARRAY ) == vt )
  1119. {
  1120. unsigned cDataElements = SaCountElements(*pSa);
  1121. BSTR *pBstr = (BSTR *)pSa->pvData;
  1122. for ( i = 0; i < cDataElements; i++ )
  1123. if ( 0 == pBstr[i] )
  1124. return FALSE;
  1125. }
  1126. if ( ( VT_VARIANT | VT_ARRAY ) == vt )
  1127. {
  1128. unsigned cDataElements = SaCountElements(*pSa);
  1129. CAllocStorageVariant *pVarnt = (CAllocStorageVariant *)pSa->pvData;
  1130. for ( i = 0; i < cDataElements; i++ )
  1131. if ( ! pVarnt[i].IsValid() )
  1132. return FALSE;
  1133. }
  1134. }
  1135. break;
  1136. case VT_BYREF | VT_I2:
  1137. case VT_BYREF | VT_I4:
  1138. case VT_BYREF | VT_R4:
  1139. case VT_BYREF | VT_R8:
  1140. case VT_BYREF | VT_CY:
  1141. case VT_BYREF | VT_DATE:
  1142. case VT_BYREF | VT_ERROR:
  1143. case VT_BYREF | VT_BOOL:
  1144. case VT_BYREF | VT_I1:
  1145. case VT_BYREF | VT_UI1:
  1146. case VT_BYREF | VT_UI2:
  1147. case VT_BYREF | VT_UI4:
  1148. case VT_BYREF | VT_INT:
  1149. case VT_BYREF | VT_UINT:
  1150. return (piVal != 0);
  1151. case VT_BYREF | VT_BSTR:
  1152. return ( pbstrVal != 0 && *pbstrVal != 0 );
  1153. case VT_BYREF | VT_DECIMAL:
  1154. return ( pdecVal != 0 &&
  1155. ( 0 == pdecVal->sign || DECIMAL_NEG == pdecVal->sign ) );
  1156. case VT_BYREF | VT_VARIANT:
  1157. return ( pvarVal != 0 && pvarVal->vt != (VT_BYREF|VT_VARIANT) &&
  1158. ((CAllocStorageVariant*)pvarVal)->IsValid() );
  1159. default:
  1160. ASSERT(!"CAllocStorageVariant::IsValid -- Invalid variant type");
  1161. return FALSE;
  1162. }
  1163. return TRUE;
  1164. }
  1165. CAllocStorageVariant::CAllocStorageVariant(
  1166. PDeSerStream& stm,
  1167. PMemoryAllocator &ma)
  1168. {
  1169. Unmarshall(stm, *((PROPVARIANT *)this), ma);
  1170. }
  1171. #define VECTOR_SET_BODY(type, vtype, val, aval) \
  1172. \
  1173. void CAllocStorageVariant::Set##vtype( \
  1174. type val, \
  1175. unsigned pos, \
  1176. PMemoryAllocator &ma) \
  1177. { \
  1178. if (vt != ( VT_##vtype | VT_VECTOR ) ) \
  1179. { \
  1180. ResetType(ma); \
  1181. new (this) CAllocStorageVariant(VT_##vtype, pos, ma); \
  1182. } \
  1183. \
  1184. if (pos >= cai.cElems) \
  1185. { \
  1186. type *pTemp = aval.pElems; \
  1187. aval.pElems = (type *) ma.Allocate( (pos+1) * sizeof(aval.pElems[0]));\
  1188. if (aval.pElems != NULL) \
  1189. { \
  1190. memcpy(aval.pElems, pTemp, aval.cElems * sizeof(aval.pElems[0])); \
  1191. memset( \
  1192. &aval.pElems[aval.cElems], \
  1193. 0, \
  1194. (( pos+1 ) - aval.cElems) * sizeof(aval.pElems[0])); \
  1195. aval.pElems[pos] = val; \
  1196. aval.cElems = pos+1; \
  1197. ma.Free(pTemp); \
  1198. } \
  1199. } \
  1200. else \
  1201. { \
  1202. aval.pElems[pos] = val; \
  1203. } \
  1204. }
  1205. #define VECTOR_GET_BODY(type, vtype, aval, nullval) \
  1206. \
  1207. type CAllocStorageVariant::Get##vtype(unsigned pos) const \
  1208. { \
  1209. if (vt == (VT_##vtype | VT_VECTOR) && pos < aval.cElems) \
  1210. { \
  1211. return(aval.pElems[pos]); \
  1212. } \
  1213. return(nullval); \
  1214. }
  1215. VECTOR_SET_BODY(CHAR, I1, i, cac)
  1216. VECTOR_GET_BODY(CHAR, I1, cac, 0)
  1217. VECTOR_SET_BODY(BYTE, UI1, ui, caub)
  1218. VECTOR_GET_BODY(BYTE, UI1, caub, 0)
  1219. VECTOR_SET_BODY(short, I2, i, cai)
  1220. VECTOR_GET_BODY(short, I2, cai, 0)
  1221. VECTOR_SET_BODY(USHORT, UI2, ui, caui)
  1222. VECTOR_GET_BODY(USHORT, UI2, caui, 0)
  1223. VECTOR_SET_BODY(long, I4, l, cal)
  1224. VECTOR_GET_BODY(long, I4, cal, 0)
  1225. VECTOR_SET_BODY(ULONG, UI4, ul, caul)
  1226. VECTOR_GET_BODY(ULONG, UI4, caul, 0)
  1227. VECTOR_SET_BODY(SCODE, ERROR, scode, cascode)
  1228. VECTOR_GET_BODY(SCODE, ERROR, cascode, 0)
  1229. static LARGE_INTEGER const liZero = { 0, 0 };
  1230. VECTOR_SET_BODY(LARGE_INTEGER, I8, li, cah)
  1231. VECTOR_GET_BODY(LARGE_INTEGER, I8, cah, liZero)
  1232. static ULARGE_INTEGER const uliZero = { 0, 0 };
  1233. VECTOR_SET_BODY(ULARGE_INTEGER, UI8, uli, cauh)
  1234. VECTOR_GET_BODY(ULARGE_INTEGER, UI8, cauh, uliZero)
  1235. VECTOR_SET_BODY(float, R4, f, caflt)
  1236. VECTOR_GET_BODY(float, R4, caflt, (float)0.0)
  1237. VECTOR_SET_BODY(double, R8, d, cadbl)
  1238. VECTOR_GET_BODY(double, R8, cadbl, 0.0)
  1239. VECTOR_SET_BODY(VARIANT_BOOL, BOOL, b, cabool)
  1240. VECTOR_GET_BODY(VARIANT_BOOL, BOOL, cabool, FALSE)
  1241. static CY const cyZero = { 0, 0 };
  1242. VECTOR_SET_BODY(CY, CY, cy, cacy)
  1243. VECTOR_GET_BODY(CY, CY, cacy, cyZero)
  1244. VECTOR_SET_BODY(DATE, DATE, d, cadate)
  1245. VECTOR_GET_BODY(DATE, DATE, cadate, 0.0)
  1246. BOOLEAN
  1247. CAllocStorageVariant::_AddStringToVector(
  1248. unsigned pos,
  1249. VOID *pv,
  1250. ULONG cb,
  1251. PMemoryAllocator &ma)
  1252. {
  1253. ASSERT(vt == (VT_VECTOR | VT_BSTR) ||
  1254. vt == (VT_VECTOR | VT_LPSTR) ||
  1255. vt == (VT_VECTOR | VT_LPWSTR));
  1256. ASSERT(calpstr.pElems != NULL);
  1257. if (pos >= calpstr.cElems)
  1258. {
  1259. char **ppsz = calpstr.pElems;
  1260. calpstr.pElems =
  1261. (char **) ma.Allocate((pos + 1) * sizeof(calpstr.pElems[0]));
  1262. if (calpstr.pElems == NULL)
  1263. {
  1264. calpstr.pElems = ppsz;
  1265. return(FALSE);
  1266. }
  1267. memcpy(calpstr.pElems, ppsz, calpstr.cElems * sizeof(calpstr.pElems[0]));
  1268. memset(
  1269. &calpstr.pElems[calpstr.cElems],
  1270. 0,
  1271. ((pos + 1) - calpstr.cElems) * sizeof(calpstr.pElems[0]));
  1272. calpstr.cElems = pos + 1;
  1273. ma.Free(ppsz);
  1274. }
  1275. if ( vt == (VT_VECTOR|VT_BSTR) )
  1276. {
  1277. BSTR bstrVal = SysAllocString( (OLECHAR *)pv );
  1278. if (bstrVal == NULL)
  1279. {
  1280. return (FALSE);
  1281. }
  1282. if ( cabstr.pElems[pos] != NULL )
  1283. {
  1284. SysFreeString(cabstr.pElems[pos]);
  1285. }
  1286. cabstr.pElems[pos] = bstrVal;
  1287. }
  1288. else
  1289. {
  1290. char *psz = (char *) ma.Allocate(cb);
  1291. if (psz == NULL)
  1292. {
  1293. return(FALSE);
  1294. }
  1295. memcpy(psz, pv, cb);
  1296. if (calpstr.pElems[pos] != NULL)
  1297. {
  1298. ma.Free(calpstr.pElems[pos]);
  1299. }
  1300. calpstr.pElems[pos] = psz;
  1301. }
  1302. return(TRUE);
  1303. }
  1304. void
  1305. CAllocStorageVariant::SetBSTR(BSTR b, PMemoryAllocator &ma)
  1306. {
  1307. ResetType(ma);
  1308. vt = VT_BSTR;
  1309. bstrVal = SysAllocString(b);
  1310. }
  1311. void
  1312. CAllocStorageVariant::SetBSTR(
  1313. BSTR b,
  1314. unsigned pos,
  1315. PMemoryAllocator &ma)
  1316. {
  1317. if (vt != (VT_VECTOR | VT_BSTR))
  1318. {
  1319. ResetType(ma);
  1320. new (this) CAllocStorageVariant(VT_BSTR, pos, ma);
  1321. }
  1322. _AddStringToVector(
  1323. pos,
  1324. b,
  1325. -1, // not used, pass an invalid value to detect failure.
  1326. ma);
  1327. }
  1328. void
  1329. CAllocStorageVariant::SetLPSTR(
  1330. char const *psz,
  1331. unsigned pos,
  1332. PMemoryAllocator &ma)
  1333. {
  1334. if (vt != (VT_VECTOR | VT_LPSTR))
  1335. {
  1336. ResetType(ma);
  1337. new (this) CAllocStorageVariant(VT_LPSTR, pos, ma);
  1338. }
  1339. _AddStringToVector(pos, (VOID *) psz, strlen(psz) + 1, ma);
  1340. }
  1341. void
  1342. CAllocStorageVariant::SetLPWSTR(
  1343. WCHAR const *pwsz,
  1344. unsigned pos,
  1345. PMemoryAllocator &ma)
  1346. {
  1347. if (vt != (VT_VECTOR | VT_LPWSTR))
  1348. {
  1349. ResetType(ma);
  1350. new (this) CAllocStorageVariant(VT_LPWSTR, pos, ma);
  1351. }
  1352. _AddStringToVector(
  1353. pos,
  1354. (VOID *) pwsz,
  1355. (wcslen(pwsz) + 1) * sizeof(WCHAR),
  1356. ma);
  1357. }
  1358. VECTOR_GET_BODY(char *, LPSTR, calpstr, 0);
  1359. VECTOR_GET_BODY(WCHAR *, LPWSTR, calpwstr, 0);
  1360. static FILETIME const fiZero = { 0, 0 };
  1361. VECTOR_SET_BODY(FILETIME, FILETIME, ft, cafiletime)
  1362. VECTOR_GET_BODY(FILETIME, FILETIME, cafiletime, fiZero)
  1363. static CLSID const guidZero =
  1364. {
  1365. 0x00000000,
  1366. 0x0000,
  1367. 0x0000,
  1368. { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
  1369. };
  1370. VECTOR_SET_BODY(CLSID, CLSID, c, cauuid)
  1371. VECTOR_GET_BODY(CLSID, CLSID, cauuid, guidZero)
  1372. #endif //ifndef _NTDLLBUILD_