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.

878 lines
20 KiB

  1. #include "pch.cxx"
  2. #include "CPropVar.hxx"
  3. #include "CHResult.hxx"
  4. #include <stdio.h>
  5. #include <tchar.h>
  6. // Declare this prototype here, for now. For non-Mac, the prototype
  7. // in "iofs.h" uses C decorations, but the definition in
  8. // ntpropb.cxx uses C++.
  9. #ifdef _MAC_NODOC
  10. EXTERN_C BOOLEAN
  11. #else
  12. BOOLEAN __declspec(dllimport) __stdcall
  13. #endif
  14. RtlCompareVariants(
  15. USHORT CodePage,
  16. PROPVARIANT const *pvar1,
  17. PROPVARIANT const *pvar2);
  18. /*
  19. CPropVariant::InitializeVector(
  20. VARENUM v,
  21. ULONG cElements)
  22. {
  23. ULONG cbElement;
  24. BOOLEAN fZero = FALSE;
  25. // Ignore vector flag. This constructor is always for vectors only.
  26. vt = v | VT_VECTOR;
  27. switch (vt)
  28. {
  29. case VT_VECTOR | VT_UI1:
  30. cbElement = sizeof(caub.pElems[0]);
  31. break;
  32. case VT_VECTOR | VT_I2:
  33. case VT_VECTOR | VT_UI2:
  34. case VT_VECTOR | VT_BOOL:
  35. cbElement = sizeof(cai.pElems[0]);
  36. break;
  37. case VT_VECTOR | VT_I4:
  38. case VT_VECTOR | VT_UI4:
  39. case VT_VECTOR | VT_R4:
  40. case VT_VECTOR | VT_ERROR:
  41. cbElement = sizeof(cal.pElems[0]);
  42. break;
  43. case VT_VECTOR | VT_I8:
  44. case VT_VECTOR | VT_UI8:
  45. case VT_VECTOR | VT_R8:
  46. case VT_VECTOR | VT_CY:
  47. case VT_VECTOR | VT_DATE:
  48. case VT_VECTOR | VT_FILETIME:
  49. cbElement = sizeof(cah.pElems[0]);
  50. break;
  51. case VT_VECTOR | VT_CLSID:
  52. cbElement = sizeof(GUID);
  53. fZero = TRUE;
  54. break;
  55. case VT_VECTOR | VT_CF:
  56. cbElement = sizeof(CLIPDATA);
  57. fZero = TRUE;
  58. break;
  59. case VT_VECTOR | VT_BSTR:
  60. case VT_VECTOR | VT_LPSTR:
  61. case VT_VECTOR | VT_LPWSTR:
  62. cbElement = sizeof(VOID *);
  63. fZero = TRUE;
  64. break;
  65. case VT_VECTOR | VT_VARIANT:
  66. cbElement = sizeof(PROPVARIANT);
  67. ASSERT(VT_EMPTY == 0);
  68. fZero = TRUE;
  69. break;
  70. default:
  71. ASSERT(!"CAllocStorageVariant -- Invalid vector type");
  72. vt = VT_EMPTY;
  73. break;
  74. }
  75. if (vt != VT_EMPTY)
  76. {
  77. caub.cElems = 0;
  78. caub.pElems = (BYTE *) CoTaskMemAlloc(cElements * cbElement);
  79. if (caub.pElems != NULL)
  80. {
  81. if (fZero)
  82. {
  83. memset(caub.pElems, 0, cElements * cbElement);
  84. }
  85. caub.cElems = cElements;
  86. }
  87. }
  88. }
  89. */
  90. VOID *
  91. CPropVariant::_AddStringToVector(
  92. unsigned pos,
  93. const VOID *pv,
  94. ULONG cb,
  95. VARTYPE vtNew )
  96. {
  97. vtNew |= VT_VECTOR;
  98. ASSERT(vtNew == (VT_VECTOR | VT_BSTR) ||
  99. vtNew == (VT_VECTOR | VT_LPSTR) ||
  100. vtNew == (VT_VECTOR | VT_LPWSTR) ||
  101. vtNew == (VT_VECTOR | VT_CF) );
  102. ASSERT(calpstr.pElems != NULL);
  103. if (pos >= calpstr.cElems)
  104. {
  105. char **ppsz = calpstr.pElems;
  106. calpstr.pElems =
  107. (char **) CoTaskMemAlloc((pos + 1) * sizeof(calpstr.pElems[0]));
  108. if (calpstr.pElems == NULL)
  109. {
  110. calpstr.pElems = ppsz;
  111. return(NULL);
  112. }
  113. if( NULL != ppsz )
  114. memcpy(calpstr.pElems, ppsz, calpstr.cElems * sizeof(calpstr.pElems[0]));
  115. memset(
  116. &calpstr.pElems[calpstr.cElems],
  117. 0,
  118. ((pos + 1) - calpstr.cElems) * sizeof(calpstr.pElems[0]));
  119. calpstr.cElems = pos + 1;
  120. CoTaskMemFree(ppsz);
  121. }
  122. LPSTR psz;
  123. if( (VT_VECTOR | VT_BSTR) == vtNew )
  124. {
  125. if( NULL == pv )
  126. {
  127. psz = NULL;
  128. }
  129. else
  130. {
  131. psz = (LPSTR) SysAllocString( (BSTR) pv );
  132. if (psz == NULL)
  133. {
  134. return(NULL);
  135. }
  136. }
  137. if (calpstr.pElems[pos] != NULL)
  138. {
  139. SysFreeString((BSTR) calpstr.pElems[pos]);
  140. }
  141. calpstr.pElems[pos] = psz;
  142. }
  143. else
  144. {
  145. if( NULL == pv )
  146. {
  147. psz = NULL;
  148. }
  149. else
  150. {
  151. psz = (LPSTR) CoTaskMemAlloc((VT_BSTR == (vtNew & ~VT_VECTOR) )
  152. ? cb + sizeof(ULONG)
  153. : cb );
  154. if (psz == NULL)
  155. {
  156. return(NULL);
  157. }
  158. memcpy(psz, pv, cb);
  159. }
  160. if (calpstr.pElems[pos] != NULL)
  161. {
  162. CoTaskMemFree(calpstr.pElems[pos]);
  163. }
  164. calpstr.pElems[pos] = psz;
  165. }
  166. return(calpstr.pElems[pos]);
  167. }
  168. VOID *
  169. CPropVariant::_AddScalerToVector(
  170. unsigned pos,
  171. const VOID *pv,
  172. ULONG cb)
  173. {
  174. ASSERT(calpstr.pElems != NULL);
  175. if (pos >= calpstr.cElems)
  176. {
  177. char **ppsz = calpstr.pElems;
  178. calpstr.pElems =
  179. (char **) CoTaskMemAlloc((pos + 1) * cb);
  180. if (calpstr.pElems == NULL)
  181. {
  182. calpstr.pElems = ppsz;
  183. return(NULL);
  184. }
  185. memset(
  186. calpstr.pElems,
  187. 0,
  188. ((pos + 1) - calpstr.cElems) * cb);
  189. if( NULL != ppsz )
  190. memcpy(calpstr.pElems, ppsz, calpstr.cElems * cb);
  191. calpstr.cElems = pos + 1;
  192. CoTaskMemFree(ppsz);
  193. }
  194. memcpy( (BYTE*)calpstr.pElems + pos*cb, pv, cb );
  195. return( (BYTE*)calpstr.pElems + pos*cb );
  196. }
  197. void
  198. CPropVariant::SetCF(
  199. const CLIPDATA *pclipdata,
  200. ULONG pos)
  201. {
  202. CLIPDATA *pclipdataNew;
  203. if (vt != (VT_VECTOR | VT_CF))
  204. {
  205. Clear();
  206. vt = VT_VECTOR | VT_CF;
  207. }
  208. pclipdataNew = (CLIPDATA*) _AddScalerToVector(pos, (VOID *) pclipdata, sizeof(CLIPDATA) );
  209. if( NULL != pclipdataNew
  210. &&
  211. NULL != pclipdata )
  212. {
  213. pclipdataNew->pClipData = (BYTE*) CoTaskMemAlloc( CBPCLIPDATA(*pclipdata) );
  214. if( NULL == pclipdataNew->pClipData )
  215. {
  216. ASSERT( !"Couldn't allocate pclipdataNew" );
  217. return;
  218. }
  219. else
  220. {
  221. pclipdataNew->cbSize = pclipdata->cbSize;
  222. pclipdataNew->ulClipFmt = pclipdata->ulClipFmt;
  223. memcpy( pclipdataNew->pClipData,
  224. pclipdata->pClipData,
  225. CBPCLIPDATA(*pclipdata) );
  226. return;
  227. }
  228. }
  229. }
  230. void
  231. CPropVariant::SetBSTR(
  232. const BSTR posz,
  233. ULONG pos)
  234. {
  235. ULONG cch;
  236. if( vt != (VT_BSTR | VT_VECTOR) ) Clear();
  237. if( NULL == posz )
  238. cch = 0;
  239. else
  240. cch = ocslen(posz) + 1;
  241. if (vt != (VT_VECTOR | VT_BSTR))
  242. Clear();
  243. _AddStringToVector(pos, (VOID *) posz,
  244. sizeof(OLECHAR) * cch, VT_BSTR );
  245. vt = VT_BSTR | VT_VECTOR;
  246. }
  247. CPropVariant & CPropVariant::operator =(PROPVARIANT &propvar)
  248. {
  249. if( INVALID_SUBSCRIPT == wReserved1 )
  250. {
  251. throw CHRESULT( (HRESULT) E_FAIL, OLESTR("Attempt to assign a singleton VT_VARIANT") );
  252. return (*this);
  253. }
  254. else
  255. {
  256. if( !(vt & VT_VECTOR)
  257. ||
  258. (vt & ~VT_VECTOR) != VT_VARIANT )
  259. {
  260. USHORT wReserved1Save = wReserved1;
  261. Clear();
  262. wReserved1 = wReserved1Save;
  263. }
  264. Set( VT_VARIANT | VT_VECTOR, (void*) &propvar, wReserved1 - 1 );
  265. wReserved1 = INVALID_SUBSCRIPT;
  266. return (*this);
  267. }
  268. }
  269. void
  270. CPropVariant::SetPROPVARIANT( PROPVARIANT &propvar, ULONG pos )
  271. {
  272. if( vt != (VT_VARIANT | VT_VECTOR) ) Clear();
  273. if (pos >= capropvar.cElems)
  274. {
  275. LPPROPVARIANT rgpropvar = capropvar.pElems;
  276. capropvar.pElems =
  277. (PROPVARIANT *) CoTaskMemAlloc((pos + 1) * sizeof(capropvar.pElems[0]));
  278. if (capropvar.pElems == NULL)
  279. {
  280. capropvar.pElems = rgpropvar;
  281. return;
  282. }
  283. if( NULL != rgpropvar )
  284. memcpy(capropvar.pElems, rgpropvar, capropvar.cElems * sizeof(capropvar.pElems[0]));
  285. memset(
  286. &capropvar.pElems[capropvar.cElems],
  287. 0,
  288. ((pos + 1) - capropvar.cElems) * sizeof(capropvar.pElems[0]));
  289. capropvar.cElems = pos + 1;
  290. CoTaskMemFree(rgpropvar);
  291. }
  292. PropVariantClear( &capropvar.pElems[pos] );
  293. PropVariantCopy( &capropvar.pElems[pos], &propvar );
  294. vt = VT_VARIANT | VT_VECTOR;
  295. return;
  296. }
  297. void
  298. CPropVariant::SetCF(const CLIPDATA *p)
  299. {
  300. Clear();
  301. if( NULL == p )
  302. return;
  303. pclipdata = (CLIPDATA*) CoTaskMemAlloc( sizeof(CLIPDATA) );
  304. if( NULL == pclipdata )
  305. {
  306. return;
  307. }
  308. pclipdata->cbSize = p->cbSize;
  309. pclipdata->ulClipFmt = p->ulClipFmt;
  310. pclipdata->pClipData = NULL;
  311. if( sizeof(pclipdata->ulClipFmt) > p->cbSize )
  312. {
  313. throw CHRESULT( (HRESULT) E_FAIL, OLESTR("Invalid input CLIPDATA*") );
  314. return;
  315. }
  316. if( NULL != p->pClipData )
  317. {
  318. pclipdata->pClipData = (BYTE*) CoTaskMemAlloc( pclipdata->cbSize
  319. - sizeof(pclipdata->ulClipFmt) );
  320. if( NULL == pclipdata->pClipData )
  321. return;
  322. memcpy( pclipdata->pClipData, p->pClipData, pclipdata->cbSize - sizeof(pclipdata->ulClipFmt) );
  323. }
  324. vt = VT_CF;
  325. }
  326. void
  327. CPropVariant::SetCLSID( const CLSID *pclsid )
  328. {
  329. Clear();
  330. puuid = (CLSID*) CoTaskMemAlloc( sizeof(CLSID) );
  331. if( NULL == puuid )
  332. throw CHRESULT( (HRESULT) E_OUTOFMEMORY, OLESTR("CPropVariant::SetCLSID couldn't alloc a new CLSID") );
  333. *puuid = *pclsid;
  334. vt = VT_CLSID;
  335. }
  336. void
  337. CPropVariant::SetCLSID(
  338. const CLSID *pclsid,
  339. unsigned pos)
  340. {
  341. CLSID *pclsidNew;
  342. if (vt != (VT_VECTOR | VT_CLSID))
  343. {
  344. Clear();
  345. vt = VT_VECTOR | VT_CLSID;
  346. }
  347. pclsidNew = (CLSID*) _AddScalerToVector(pos, (const VOID *) pclsid, sizeof(CLSID) );
  348. if( NULL != pclsidNew )
  349. {
  350. *pclsidNew = *pclsid;
  351. }
  352. }
  353. #define COMPARE_CHUNK_SIZE 4096
  354. //+----------------------------------------------------------------------------
  355. //
  356. // CPropVariant::Compare
  357. //
  358. // Compare two CPropVariants. This routine defers to the RtlCompareVariants
  359. // for most types. Types not supported by that routine are handled here.
  360. //
  361. //+----------------------------------------------------------------------------
  362. HRESULT
  363. CPropVariant::Compare( PROPVARIANT *ppropvar1, PROPVARIANT *ppropvar2 )
  364. {
  365. HRESULT hr = S_OK;
  366. VARTYPE vt1 = ppropvar1->vt;
  367. IStream *pStream1 = NULL, *pStream2 = NULL;
  368. BYTE *prgb1 = NULL, *prgb2 = NULL;
  369. CLargeInteger liCurrentSeek;
  370. switch( vt1 )
  371. {
  372. case VT_VERSIONED_STREAM:
  373. if( ppropvar1->pVersionedStream == NULL && ppropvar2->pVersionedStream == NULL )
  374. return( S_OK );
  375. else if( ppropvar1->pVersionedStream == NULL || ppropvar2->pVersionedStream == NULL )
  376. return( S_FALSE );
  377. else if( ppropvar1->pVersionedStream->guidVersion != ppropvar2->pVersionedStream->guidVersion )
  378. return( S_FALSE );
  379. pStream1 = ppropvar1->pVersionedStream->pStream;
  380. pStream2 = ppropvar2->pVersionedStream->pStream;
  381. // Fall through
  382. case VT_STREAM:
  383. case VT_STREAMED_OBJECT:
  384. {
  385. // Note: This comparisson effects the seek pointers, though
  386. // barring error they are restored on completion.
  387. STATSTG statstg1, statstg2;
  388. CULargeInteger uliSeek1, uliSeek2;
  389. if( NULL == pStream1 )
  390. {
  391. ASSERT( NULL == pStream2 );
  392. pStream1 = ppropvar1->pStream;
  393. pStream2 = ppropvar2->pStream;
  394. }
  395. if( ppropvar1->vt != ppropvar2->vt
  396. ||
  397. NULL == pStream1 && NULL != pStream2
  398. ||
  399. NULL != pStream1 && NULL == pStream2 )
  400. {
  401. return( S_FALSE );
  402. }
  403. hr = pStream1->Stat( &statstg1, STATFLAG_NONAME );
  404. if( FAILED(hr) ) goto Exit;
  405. hr = pStream2->Stat( &statstg2, STATFLAG_NONAME );
  406. if( FAILED(hr) ) goto Exit;
  407. if( CULargeInteger(statstg1.cbSize) != CULargeInteger(statstg2.cbSize) )
  408. return( S_FALSE );
  409. prgb1 = new BYTE[ COMPARE_CHUNK_SIZE ];
  410. if( NULL == prgb1 )
  411. {
  412. hr = E_OUTOFMEMORY;
  413. goto Exit;
  414. }
  415. prgb2 = new BYTE[ COMPARE_CHUNK_SIZE ];
  416. if( NULL == prgb2 )
  417. {
  418. hr = E_OUTOFMEMORY;
  419. goto Exit;
  420. }
  421. hr = pStream1->Seek( CLargeInteger(0), STREAM_SEEK_CUR, &uliSeek1 );
  422. if( FAILED(hr) ) goto Exit;
  423. hr = pStream2->Seek( CLargeInteger(0), STREAM_SEEK_CUR, &uliSeek2 );
  424. if( FAILED(hr) ) goto Exit;
  425. liCurrentSeek = CLargeInteger(0);
  426. CULargeInteger cbRemaining = statstg1.cbSize;
  427. while( cbRemaining > 0 )
  428. {
  429. ULONG cbRead1 = 0, cbRead2 = 0;
  430. hr = pStream1->Seek( liCurrentSeek, STREAM_SEEK_SET, NULL );
  431. if( FAILED(hr) ) goto Exit;
  432. hr = pStream1->Read( prgb1, COMPARE_CHUNK_SIZE, &cbRead1 );
  433. if( FAILED(hr) ) goto Exit;
  434. hr = pStream2->Seek( liCurrentSeek, STREAM_SEEK_SET, NULL );
  435. if( FAILED(hr) ) goto Exit;
  436. hr = pStream2->Read( prgb2, COMPARE_CHUNK_SIZE, &cbRead2 );
  437. if( FAILED(hr) ) goto Exit;
  438. if( cbRead1 != cbRead2 )
  439. {
  440. hr = STG_E_READFAULT;
  441. goto Exit;
  442. }
  443. if( memcmp( prgb1, prgb2, cbRead1 ) )
  444. {
  445. hr = S_FALSE;
  446. goto Exit;
  447. }
  448. liCurrentSeek += cbRead1;
  449. cbRemaining -= cbRead1;
  450. }
  451. hr = pStream1->Seek( static_cast<CLargeInteger>(uliSeek1), STREAM_SEEK_SET, NULL );
  452. if( FAILED(hr) ) goto Exit;
  453. hr = pStream2->Seek( static_cast<CLargeInteger>(uliSeek2), STREAM_SEEK_SET, NULL );
  454. if( FAILED(hr) ) goto Exit;
  455. hr = S_OK;
  456. goto Exit;
  457. }
  458. case VT_STORAGE:
  459. case VT_STORED_OBJECT:
  460. {
  461. if( ppropvar1->vt == ppropvar2->vt
  462. &&
  463. ( NULL == ppropvar1->vt
  464. &&
  465. NULL == ppropvar2->vt
  466. ||
  467. NULL != ppropvar1->vt
  468. &&
  469. NULL != ppropvar2->vt
  470. )
  471. )
  472. {
  473. return( S_OK );
  474. }
  475. else
  476. {
  477. return( S_FALSE );
  478. }
  479. }
  480. break;
  481. default:
  482. // For SafeArrays we just check the structure, not the data.
  483. if( VT_ARRAY & vt1 )
  484. {
  485. if( ppropvar1->vt != ppropvar2->vt
  486. ||
  487. ppropvar1->parray->cDims != ppropvar2->parray->cDims
  488. ||
  489. SafeArrayGetElemsize(ppropvar1->parray) != SafeArrayGetElemsize(ppropvar2->parray) )
  490. {
  491. return (HRESULT) S_FALSE;
  492. }
  493. else
  494. {
  495. return (HRESULT) S_OK;
  496. }
  497. }
  498. else if( PropTestCompareVariants( CP_ACP, // Ignored,
  499. ppropvar1,
  500. ppropvar2 ))
  501. {
  502. return( (HRESULT) S_OK );
  503. }
  504. else
  505. {
  506. return( (HRESULT) S_FALSE );
  507. }
  508. break;
  509. }
  510. Exit:
  511. if( NULL != prgb1 )
  512. delete[] prgb1;
  513. if( NULL != prgb2 )
  514. delete[] prgb2;
  515. return( hr );
  516. }
  517. void
  518. CPropVariant::Set( VARTYPE vtSet, void *pv, ULONG pos )
  519. {
  520. BOOL fVector = (vtSet & VT_VECTOR) ? TRUE : FALSE;
  521. switch( vtSet & ~VT_VECTOR )
  522. {
  523. case VT_I1:
  524. if( fVector )
  525. SetI1( *(CHAR*) pv, pos );
  526. else
  527. SetI1( *(CHAR*) pv );
  528. break;
  529. case VT_UI1:
  530. if( fVector )
  531. SetUI1( *(UCHAR*) pv, pos );
  532. else
  533. SetUI1( *(UCHAR*) pv );
  534. break;
  535. case VT_I2:
  536. if( fVector )
  537. SetI2( *(short*) pv, pos );
  538. else
  539. SetI2( *(short*) pv );
  540. break;
  541. case VT_UI2:
  542. if( fVector )
  543. SetUI2( *(USHORT*) pv, pos );
  544. else
  545. SetUI2( *(USHORT*) pv );
  546. break;
  547. case VT_BOOL:
  548. if( fVector )
  549. SetBOOL( *(VARIANT_BOOL*) pv, pos );
  550. else
  551. SetBOOL( *(VARIANT_BOOL*) pv );
  552. break;
  553. case VT_I4:
  554. if( fVector )
  555. SetI4( *(long*) pv, pos );
  556. else
  557. SetI4( *(long*) pv );
  558. break;
  559. case VT_UI4:
  560. if( fVector )
  561. SetUI4( *(ULONG*) pv, pos );
  562. else
  563. SetUI4( *(ULONG*) pv );
  564. break;
  565. case VT_R4:
  566. if( fVector )
  567. SetR4( *(float*) pv, pos );
  568. else
  569. SetR4( *(float*) pv );
  570. break;
  571. case VT_ERROR:
  572. if( fVector )
  573. SetERROR( *(SCODE*) pv, pos );
  574. else
  575. SetERROR( *(SCODE*) pv );
  576. break;
  577. case VT_I8:
  578. if( fVector )
  579. SetI8( *(LARGE_INTEGER*) pv, pos );
  580. else
  581. SetI8( *(LARGE_INTEGER*) pv );
  582. break;
  583. case VT_UI8:
  584. if( fVector )
  585. SetUI8( *(ULARGE_INTEGER*) pv, pos );
  586. else
  587. SetUI8( *(ULARGE_INTEGER*) pv );
  588. break;
  589. case VT_R8:
  590. if( fVector )
  591. SetR8( *(double*) pv, pos );
  592. else
  593. SetR8( *(double*) pv );
  594. break;
  595. case VT_CY:
  596. if( fVector )
  597. SetCY( *(CY*) pv, pos );
  598. else
  599. SetCY( *(CY*) pv );
  600. break;
  601. case VT_DATE:
  602. if( fVector )
  603. SetDATE( *(DATE*) pv, pos );
  604. else
  605. SetDATE( *(DATE*) pv );
  606. break;
  607. case VT_FILETIME:
  608. if( fVector )
  609. SetFILETIME( *(FILETIME*) pv, pos );
  610. else
  611. SetFILETIME( *(FILETIME*) pv );
  612. break;
  613. case VT_CLSID:
  614. if( fVector )
  615. SetCLSID( *(CLSID*) pv, pos );
  616. else
  617. SetCLSID( *(CLSID*) pv );
  618. break;
  619. case VT_BLOB:
  620. ASSERT( !fVector );
  621. SetBLOB( *(BLOB*) pv );
  622. break;
  623. case VT_CF:
  624. if( fVector )
  625. SetCF( *(CLIPDATA**) pv, pos );
  626. else
  627. SetCF( *(CLIPDATA**) pv );
  628. break;
  629. case VT_STREAM:
  630. ASSERT( !fVector );
  631. SetSTREAM( *(IStream**) pv );
  632. break;
  633. case VT_STORAGE:
  634. ASSERT( !fVector );
  635. SetSTORAGE( *(IStorage**) pv );
  636. break;
  637. case VT_BSTR:
  638. if( fVector )
  639. SetBSTR( *(BSTR*) pv, pos );
  640. else
  641. SetBSTR( *(BSTR*) pv );
  642. break;
  643. case VT_LPSTR:
  644. if( fVector )
  645. SetLPSTR( *(LPSTR*) pv, pos );
  646. else
  647. SetLPSTR( *(LPSTR*) pv );
  648. break;
  649. case VT_LPWSTR:
  650. if( fVector )
  651. SetLPWSTR( *(LPWSTR*) pv, pos );
  652. else
  653. SetLPWSTR( *(LPWSTR*) pv );
  654. break;
  655. case VT_VARIANT:
  656. if( !fVector )
  657. throw CHRESULT( E_FAIL, OLESTR("CPropVariant::Set - attempt to set a singleton VT_VARIANT") );
  658. SetPROPVARIANT( *(PROPVARIANT*) pv, pos );
  659. break;
  660. case VT_DECIMAL:
  661. ASSERT( !fVector );
  662. SetDECIMAL( *(DECIMAL*) pv );
  663. break;
  664. default:
  665. ASSERT(0);
  666. throw CHRESULT( (HRESULT) E_FAIL, OLESTR("CPropVariant::Set invalid type") );
  667. }
  668. return;
  669. }