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

1518 lines
43 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 2000.
  5. //
  6. // File: StgVarB.cxx
  7. //
  8. // Contents: C++ Base wrapper for PROPVARIANT.
  9. //
  10. // History: 01-Aug-94 KyleP Created
  11. // 31-Jul-96 MikeHill - Relaxed assert in IsUnicodeString.
  12. // - Allow NULL strings.
  13. // 14-May-97 mohamedn - Allow marshalling of VT_ARRAY
  14. // 28 Apr 98 AlanW - Added all permitted VARIANT types
  15. //
  16. //--------------------------------------------------------------------------
  17. #include <pch.cxx>
  18. #pragma hdrstop
  19. #include <propset.h>
  20. #include <propvar.h>
  21. #include "debtrace.hxx"
  22. #undef PROPASSERT
  23. #define PROPASSERT Win4Assert
  24. #if DBGPROP
  25. BOOLEAN
  26. IsUnicodeString(WCHAR const *pwszname, ULONG cb)
  27. {
  28. if (cb != 0)
  29. {
  30. ULONG i, cchDoubleAnsi, cchNull;
  31. cchNull = cchDoubleAnsi = 0;
  32. for (i = 0; pwszname[i] != L'\0'; i++)
  33. {
  34. if ((char) pwszname[i] == '\0' || (char) (pwszname[i] >> 8) == '\0')
  35. {
  36. cchNull++;
  37. if (i > 8 && cchDoubleAnsi > (3*i)/4)
  38. {
  39. return(TRUE);
  40. }
  41. }
  42. else
  43. if (isprint((char) pwszname[i]) && isprint((char) (pwszname[i] >> 8)))
  44. {
  45. cchDoubleAnsi++;
  46. }
  47. }
  48. // If cb isn't MAXULONG we verify that cb is at least as
  49. // big as the string. We can't check for equality, because
  50. // there are some property sets in which the length field
  51. // for a string may include several zero padding bytes.
  52. PROPASSERT(cb == MAXULONG || (i + 1) * sizeof(WCHAR) <= cb);
  53. }
  54. return(TRUE);
  55. }
  56. BOOLEAN
  57. IsAnsiString(CHAR const *pszname, ULONG cb)
  58. {
  59. if (cb != 0)
  60. {
  61. ULONG i;
  62. // If the string is NULL, then it's not not an Ansi string,
  63. // so we'll call it an Ansi string.
  64. if( NULL == pszname )
  65. return( TRUE );
  66. for (i = 0; pszname[i] != '\0'; i++)
  67. {
  68. }
  69. if (i == 1 && isprint(pszname[0]) &&
  70. ((ULONG_PTR) &pszname[8] & 0xfff) == ((ULONG_PTR) pszname & 0xfff) &&
  71. isprint(pszname[2]) && pszname[3] == '\0' &&
  72. isprint(pszname[4]) && pszname[5] == '\0' &&
  73. isprint(pszname[6]) && pszname[7] == '\0')
  74. {
  75. PROPASSERT(!"IsAnsiString: Suspicious string: looks like Unicode");
  76. return(FALSE);
  77. }
  78. // If cb isn't MAXULONG we verify that cb is at least as
  79. // big as the string. We can't check for equality, because
  80. // there are some property sets in which the length field
  81. // for a string may include several zero padding bytes.
  82. PROPASSERT(cb == MAXULONG || i + 1 <= cb);
  83. }
  84. return(TRUE);
  85. }
  86. #endif
  87. //+-------------------------------------------------------------------
  88. // Member: CBaseStorageVariant::UnmarshalledSize, public
  89. //
  90. // Synopsis: Unmarshalls a PROPVARIANT value serialized in a PDeSerStream.
  91. //
  92. // Arguments: [stm] -- serialized stream
  93. // [cb] -- size of *additional* data goes here. Size of
  94. // base PROPVARIANT not included.
  95. //
  96. // Returns: one of the following NTSTATUS values
  97. // STATUS_SUCCESS -- the call was successful.
  98. // STATUS_INVALID_PARAMETER -- unsupported type for unmarshalling.
  99. //
  100. // Notes: The size is computed assuming 4-byte granular allocations.
  101. //
  102. //--------------------------------------------------------------------
  103. #if defined(WINNT) && !defined(IPROPERTY_DLL)
  104. //+-------------------------------------------------------------------
  105. // Member: CBaseStorageVariant::Unmarshall, public
  106. //
  107. // Synopsis: Unmarshalls a PROPVARIANT value serialized in a PDeSerStream.
  108. //
  109. // Arguments: [stm] -- serialized stream
  110. // [var] -- unmarshalled PROPVARIANT instance
  111. // [MemAlloc] -- memory allocator for unmarshalling
  112. //
  113. // Returns: one of the following NTSTATUS values
  114. // STATUS_SUCCESS -- the call was successful.
  115. // STATUS_INSUFFICIENT_RESOURCES -- out of memory.
  116. // STATUS_INVALID_PARAMETER -- unsupported type for unmarshalling.
  117. //
  118. //--------------------------------------------------------------------
  119. NTSTATUS
  120. CBaseStorageVariant::Unmarshall(
  121. PDeSerStream& stm,
  122. PROPVARIANT& var,
  123. PMemoryAllocator &MemAlloc)
  124. {
  125. #if DBG
  126. switch (stm.PeekULong())
  127. {
  128. case VT_EMPTY:
  129. case VT_NULL:
  130. case VT_I1:
  131. case VT_UI1:
  132. case VT_I2:
  133. case VT_UI2:
  134. case VT_BOOL:
  135. case VT_I4:
  136. case VT_UI4:
  137. case VT_R4:
  138. case VT_ERROR:
  139. case VT_I8:
  140. case VT_UI8:
  141. case VT_R8:
  142. case VT_INT:
  143. case VT_UINT:
  144. case VT_DECIMAL:
  145. case VT_CY:
  146. case VT_DATE:
  147. case VT_FILETIME:
  148. case VT_CLSID:
  149. case VT_BLOB:
  150. case VT_BLOB_OBJECT:
  151. case VT_CF:
  152. case VT_STREAM:
  153. case VT_STREAMED_OBJECT:
  154. case VT_STORAGE:
  155. case VT_STORED_OBJECT:
  156. case VT_VERSIONED_STREAM:
  157. case VT_BSTR:
  158. case VT_LPSTR:
  159. case VT_LPWSTR:
  160. case VT_VECTOR | VT_I1:
  161. case VT_VECTOR | VT_UI1:
  162. case VT_VECTOR | VT_I2:
  163. case VT_VECTOR | VT_UI2:
  164. case VT_VECTOR | VT_BOOL:
  165. case VT_VECTOR | VT_I4:
  166. case VT_VECTOR | VT_UI4:
  167. case VT_VECTOR | VT_R4:
  168. case VT_VECTOR | VT_ERROR:
  169. case VT_VECTOR | VT_I8:
  170. case VT_VECTOR | VT_UI8:
  171. case VT_VECTOR | VT_R8:
  172. case VT_VECTOR | VT_CY:
  173. case VT_VECTOR | VT_DATE:
  174. case VT_VECTOR | VT_FILETIME:
  175. case VT_VECTOR | VT_CLSID:
  176. case VT_VECTOR | VT_CF:
  177. case VT_VECTOR | VT_BSTR:
  178. case VT_VECTOR | VT_LPSTR:
  179. case VT_VECTOR | VT_LPWSTR:
  180. case VT_VECTOR | VT_VARIANT:
  181. case VT_ARRAY | VT_I4:
  182. case VT_ARRAY | VT_UI1:
  183. case VT_ARRAY | VT_I2:
  184. case VT_ARRAY | VT_R4:
  185. case VT_ARRAY | VT_R8:
  186. case VT_ARRAY | VT_BOOL:
  187. case VT_ARRAY | VT_ERROR:
  188. case VT_ARRAY | VT_CY:
  189. case VT_ARRAY | VT_DATE:
  190. case VT_ARRAY | VT_I1:
  191. case VT_ARRAY | VT_UI2:
  192. case VT_ARRAY | VT_UI4:
  193. case VT_ARRAY | VT_INT:
  194. case VT_ARRAY | VT_UINT:
  195. case VT_ARRAY | VT_BSTR:
  196. case VT_ARRAY | VT_DECIMAL:
  197. case VT_ARRAY | VT_VARIANT:
  198. break;
  199. default:
  200. PROPASSERT(!"Invalid type (peek) for PROPVARIANT unmarshalling");
  201. break;
  202. }
  203. #endif
  204. NTSTATUS Status = STATUS_SUCCESS;
  205. ULONG cbAlloc = 0;
  206. VOID **ppv = NULL;
  207. BOOLEAN fZero = FALSE;
  208. // Zero the entire variant data structure before assembling it together.
  209. RtlZeroMemory(&var, sizeof(PROPVARIANT));
  210. var.vt = (VARTYPE) stm.GetULong();
  211. switch (var.vt)
  212. {
  213. case VT_EMPTY:
  214. case VT_NULL:
  215. break;
  216. case VT_I1:
  217. case VT_UI1:
  218. var.bVal = stm.GetByte();
  219. break;
  220. case VT_I2:
  221. case VT_UI2:
  222. case VT_BOOL:
  223. var.iVal = stm.GetUShort();
  224. break;
  225. case VT_I4:
  226. case VT_UI4:
  227. case VT_R4:
  228. case VT_ERROR:
  229. case VT_INT:
  230. case VT_UINT:
  231. var.lVal = stm.GetULong();
  232. break;
  233. case VT_I8:
  234. case VT_UI8:
  235. case VT_R8:
  236. case VT_CY:
  237. case VT_DATE:
  238. case VT_FILETIME:
  239. stm.GetBlob((BYTE *)&var.hVal, sizeof(LARGE_INTEGER));
  240. break;
  241. case VT_DECIMAL:
  242. stm.GetBlob((BYTE *)&var, sizeof(DECIMAL));
  243. var.vt = VT_DECIMAL;
  244. break;
  245. case VT_CLSID:
  246. cbAlloc = sizeof(GUID);
  247. ppv = (void **)&var.puuid;
  248. break;
  249. case VT_BLOB:
  250. case VT_BLOB_OBJECT:
  251. var.blob.cbSize = stm.GetULong();
  252. cbAlloc = var.blob.cbSize;
  253. ppv = (void **)&var.blob.pBlobData;
  254. break;
  255. case VT_CF:
  256. var.pclipdata = (CLIPDATA *) MemAlloc.Allocate(sizeof(*var.pclipdata));
  257. if (var.pclipdata == NULL)
  258. {
  259. Status = STATUS_INSUFFICIENT_RESOURCES;
  260. break;
  261. }
  262. var.pclipdata->cbSize = stm.GetULong();
  263. cbAlloc = CBPCLIPDATA(*var.pclipdata);
  264. var.pclipdata->ulClipFmt = stm.GetULong();
  265. ppv = (void **) &var.pclipdata->pClipData;
  266. break;
  267. case VT_STREAM:
  268. case VT_STREAMED_OBJECT:
  269. case VT_STORAGE:
  270. case VT_STORED_OBJECT:
  271. case VT_VERSIONED_STREAM:
  272. // NTRAID#DB-NTBUG9-84615-2000/07/31-dlee Some VT types not supported by Indexing Service
  273. var.vt = VT_EMPTY;
  274. break;
  275. case VT_BSTR:
  276. cbAlloc = stm.GetULong();
  277. ppv = (void **)&var.bstrVal;
  278. break;
  279. case VT_LPSTR:
  280. cbAlloc = stm.GetULong();
  281. ppv = (void **)&var.pszVal;
  282. break;
  283. case VT_LPWSTR:
  284. cbAlloc = stm.GetULong() * sizeof(WCHAR);
  285. ppv = (void **)&var.pwszVal;
  286. break;
  287. case VT_VECTOR | VT_I1:
  288. case VT_VECTOR | VT_UI1:
  289. var.caub.cElems = stm.GetULong();
  290. cbAlloc = var.caub.cElems * sizeof(BYTE);
  291. ppv = (void **)&var.caub.pElems;
  292. break;
  293. case VT_VECTOR | VT_I2:
  294. case VT_VECTOR | VT_UI2:
  295. case VT_VECTOR | VT_BOOL:
  296. var.cai.cElems = stm.GetULong();
  297. cbAlloc = var.cai.cElems * sizeof(SHORT);
  298. ppv = (void **)&var.cai.pElems;
  299. break;
  300. case VT_VECTOR | VT_I4:
  301. case VT_VECTOR | VT_UI4:
  302. case VT_VECTOR | VT_R4:
  303. case VT_VECTOR | VT_ERROR:
  304. var.cal.cElems = stm.GetULong();
  305. cbAlloc = var.cal.cElems * sizeof(LONG);
  306. ppv = (void **)&var.cal.pElems;
  307. break;
  308. case VT_VECTOR | VT_I8:
  309. case VT_VECTOR | VT_UI8:
  310. case VT_VECTOR | VT_R8:
  311. case VT_VECTOR | VT_CY:
  312. case VT_VECTOR | VT_DATE:
  313. case VT_VECTOR | VT_FILETIME:
  314. var.cah.cElems = stm.GetULong();
  315. cbAlloc = var.cah.cElems * sizeof(LARGE_INTEGER);
  316. ppv = (void **)&var.cah.pElems;
  317. break;
  318. case VT_VECTOR | VT_CLSID:
  319. var.cauuid.cElems = stm.GetULong();
  320. cbAlloc = var.cauuid.cElems * sizeof(GUID);
  321. ppv = (void **)&var.cauuid.pElems;
  322. break;
  323. case VT_VECTOR | VT_CF:
  324. var.caclipdata.cElems = stm.GetULong();
  325. cbAlloc = var.caclipdata.cElems * sizeof(CLIPDATA);
  326. ppv = (void **)&var.caclipdata.pElems;
  327. fZero = TRUE; // set all pClipData pointers to NULL
  328. break;
  329. case VT_VECTOR | VT_BSTR:
  330. var.cabstr.cElems = stm.GetULong();
  331. cbAlloc = var.cabstr.cElems * sizeof(BSTR);
  332. ppv = (void **)&var.cabstr.pElems;
  333. fZero = TRUE; // set all BSTR pointers to NULL
  334. break;
  335. case VT_VECTOR | VT_LPSTR:
  336. var.calpstr.cElems = stm.GetULong();
  337. cbAlloc = var.calpstr.cElems * sizeof(LPSTR);
  338. ppv = (void **)&var.calpstr.pElems;
  339. fZero = TRUE; // set all LPSTR pointers to NULL
  340. break;
  341. case VT_VECTOR | VT_LPWSTR:
  342. var.calpwstr.cElems = stm.GetULong();
  343. cbAlloc = var.calpwstr.cElems * sizeof(LPWSTR);
  344. ppv = (void **)&var.calpwstr.pElems;
  345. fZero = TRUE; // set all LPWSTR pointers to NULL
  346. break;
  347. case VT_VECTOR | VT_VARIANT:
  348. var.capropvar.cElems = stm.GetULong();
  349. cbAlloc = var.capropvar.cElems * sizeof(PROPVARIANT);
  350. ppv = (void **)&var.capropvar.pElems;
  351. fZero = TRUE; // set all vt pointers to VT_EMPTY
  352. PROPASSERT(VT_EMPTY == 0);
  353. break;
  354. case VT_ARRAY | VT_I4:
  355. case VT_ARRAY | VT_UI1:
  356. case VT_ARRAY | VT_I2:
  357. case VT_ARRAY | VT_R4:
  358. case VT_ARRAY | VT_R8:
  359. case VT_ARRAY | VT_BOOL:
  360. case VT_ARRAY | VT_ERROR:
  361. case VT_ARRAY | VT_CY:
  362. case VT_ARRAY | VT_DATE:
  363. case VT_ARRAY | VT_I1:
  364. case VT_ARRAY | VT_UI2:
  365. case VT_ARRAY | VT_UI4:
  366. case VT_ARRAY | VT_INT:
  367. case VT_ARRAY | VT_UINT:
  368. case VT_ARRAY | VT_BSTR:
  369. case VT_ARRAY | VT_DECIMAL:
  370. case VT_ARRAY | VT_VARIANT:
  371. {
  372. unsigned short cDims = stm.GetUShort();
  373. // Guard against attack
  374. if ( cDims >= 50 )
  375. return E_INVALIDARG;
  376. USHORT fFeatures = stm.GetUShort();
  377. ULONG cbElements = stm.GetULong();
  378. if ( cbElements > 64 )
  379. return E_INVALIDARG;
  380. if ( 0 != ( FADF_RESERVED & fFeatures ) )
  381. return E_INVALIDARG;
  382. SAFEARRAY * psaDest;
  383. HRESULT hr = SafeArrayAllocDescriptorEx( var.vt & (~VT_ARRAY),
  384. cDims,
  385. &psaDest );
  386. if ( FAILED( hr ) )
  387. return hr;
  388. psaDest->pvData = 0;
  389. // Figure out features on our own -- it could be hacked.
  390. fFeatures = 0;
  391. // Ignore the cbElements in the stream -- it could be hacked.
  392. switch ( var.vt )
  393. {
  394. case VT_ARRAY | VT_UI1:
  395. case VT_ARRAY | VT_I1:
  396. cbElements = sizeof( BYTE );
  397. break;
  398. case VT_ARRAY | VT_BOOL:
  399. case VT_ARRAY | VT_I2:
  400. case VT_ARRAY | VT_UI2:
  401. cbElements = sizeof( SHORT );
  402. break;
  403. case VT_ARRAY | VT_ERROR:
  404. case VT_ARRAY | VT_R4:
  405. case VT_ARRAY | VT_I4:
  406. case VT_ARRAY | VT_UI4:
  407. case VT_ARRAY | VT_INT:
  408. case VT_ARRAY | VT_UINT:
  409. cbElements = sizeof( ULONG );
  410. break;
  411. case VT_ARRAY | VT_CY:
  412. case VT_ARRAY | VT_DATE:
  413. case VT_ARRAY | VT_R8:
  414. cbElements = sizeof( double );
  415. break;
  416. case VT_ARRAY | VT_BSTR:
  417. cbElements = sizeof( void * );
  418. fFeatures |= FADF_BSTR;
  419. break;
  420. case VT_ARRAY | VT_DECIMAL:
  421. cbElements = sizeof DECIMAL;
  422. break;
  423. case VT_ARRAY | VT_VARIANT:
  424. cbElements = sizeof PROPVARIANT;
  425. fFeatures |= FADF_VARIANT;
  426. break;
  427. default:
  428. Win4Assert( !"impossible" );
  429. break;
  430. }
  431. psaDest->fFeatures = fFeatures;
  432. psaDest->cbElements = cbElements;
  433. psaDest->cLocks = 0; // no one has this locked, and if it's
  434. // locked, it can't be freed
  435. for ( unsigned i = 0; i < cDims; i++ )
  436. {
  437. ULONG cElem = stm.GetULong();
  438. // Guard against attack
  439. if ( cElem >= 65536 )
  440. {
  441. SafeArrayDestroyDescriptor( psaDest );
  442. RtlZeroMemory( &var, sizeof PROPVARIANT );
  443. return E_INVALIDARG;
  444. }
  445. psaDest->rgsabound[i].cElements = cElem;
  446. psaDest->rgsabound[i].lLbound = stm.GetLong();
  447. }
  448. var.parray = psaDest;
  449. ppv = (void **) &(psaDest->pvData);
  450. break;
  451. }
  452. default:
  453. PROPASSERT(!"Invalid type for PROPVARIANT unmarshalling");
  454. Status = STATUS_INVALID_PARAMETER;
  455. break;
  456. }
  457. if ( FAILED( Status ) )
  458. return Status;
  459. if ( ( 0 == ( var.vt & VT_ARRAY ) ) &&
  460. ( cbAlloc == 0 || Status != STATUS_SUCCESS ) )
  461. {
  462. // No further work need be done. The Ummarshalling is complete,
  463. // i.e., fixed size variant or no variable length data.
  464. if (ppv != NULL)
  465. *ppv = NULL;
  466. return(Status);
  467. }
  468. // Guard against attack
  469. if ( cbAlloc >= 65536 )
  470. return E_INVALIDARG;
  471. // Allocate the desired amount of memory and continue unmarshalling
  472. // if allocation was successfull.
  473. PROPASSERT(ppv != NULL);
  474. if ( var.vt == VT_BSTR )
  475. {
  476. *ppv = (void *)SysAllocStringLen(NULL, (cbAlloc - sizeof(OLECHAR))/sizeof(OLECHAR) );
  477. }
  478. else if ( 0 != ( VT_ARRAY & var.vt ) )
  479. {
  480. HRESULT hr = SafeArrayAllocData( var.parray );
  481. if ( FAILED( hr ) )
  482. {
  483. SafeArrayDestroyDescriptor( var.parray );
  484. RtlZeroMemory( &var, sizeof PROPVARIANT );
  485. return hr;
  486. }
  487. Win4Assert( 0 != *ppv );
  488. }
  489. else
  490. {
  491. *ppv = MemAlloc.Allocate(cbAlloc);
  492. }
  493. if (0 == *ppv )
  494. return STATUS_INSUFFICIENT_RESOURCES;
  495. if (fZero)
  496. RtlZeroMemory( *ppv, cbAlloc );
  497. ULONG i;
  498. // We have a variant with variable sized data which requires
  499. // further unmarshalling.
  500. switch(var.vt)
  501. {
  502. case VT_CLSID:
  503. stm.GetBlob((BYTE *)var.puuid, sizeof(CLSID));
  504. break;
  505. case VT_BLOB:
  506. case VT_BLOB_OBJECT:
  507. stm.GetBlob(var.blob.pBlobData, var.blob.cbSize);
  508. break;
  509. case VT_CF:
  510. stm.GetBlob(var.pclipdata->pClipData, CBPCLIPDATA(*var.pclipdata));
  511. break;
  512. case VT_BSTR:
  513. stm.GetChar((char *) var.bstrVal, cbAlloc );
  514. break;
  515. case VT_LPSTR:
  516. stm.GetChar(var.pszVal, cbAlloc);
  517. break;
  518. case VT_LPWSTR:
  519. stm.GetWChar(var.pwszVal, cbAlloc / sizeof(WCHAR));
  520. break;
  521. case VT_VECTOR | VT_I1:
  522. case VT_VECTOR | VT_UI1:
  523. for (i = 0; i < var.caub.cElems; i++)
  524. {
  525. var.caub.pElems[i] = stm.GetByte();
  526. }
  527. break;
  528. case VT_VECTOR | VT_I2:
  529. case VT_VECTOR | VT_UI2:
  530. case VT_VECTOR | VT_BOOL:
  531. for (i = 0; i < var.cai.cElems; i++)
  532. {
  533. var.cai.pElems[i] = stm.GetUShort();
  534. }
  535. break;
  536. case VT_VECTOR | VT_I4:
  537. case VT_VECTOR | VT_UI4:
  538. case VT_VECTOR | VT_R4:
  539. case VT_VECTOR | VT_ERROR:
  540. for (i = 0; i < var.cal.cElems; i++)
  541. {
  542. var.cal.pElems[i] = stm.GetULong();
  543. }
  544. break;
  545. case VT_VECTOR | VT_I8:
  546. case VT_VECTOR | VT_UI8:
  547. case VT_VECTOR | VT_R8:
  548. case VT_VECTOR | VT_CY:
  549. case VT_VECTOR | VT_DATE:
  550. case VT_VECTOR | VT_FILETIME:
  551. for (i = 0; i < var.cah.cElems; i++)
  552. {
  553. stm.GetBlob((BYTE *)&var.cah.pElems[i], sizeof(LARGE_INTEGER));
  554. }
  555. break;
  556. case VT_VECTOR | VT_CLSID:
  557. for (i = 0; i < var.cauuid.cElems; i++)
  558. {
  559. stm.GetBlob((BYTE *)&var.cauuid.pElems[i], sizeof(CLSID));
  560. }
  561. break;
  562. case VT_VECTOR | VT_CF:
  563. for (i = 0; i < var.caclipdata.cElems; i++)
  564. {
  565. PROPASSERT(var.caclipdata.pElems[i].pClipData == NULL);
  566. var.caclipdata.pElems[i].cbSize = stm.GetULong();
  567. cbAlloc = CBPCLIPDATA(var.caclipdata.pElems[i]);
  568. var.caclipdata.pElems[i].ulClipFmt = stm.GetULong();
  569. if (cbAlloc == 0)
  570. {
  571. Status = STATUS_INVALID_PARAMETER;
  572. break;
  573. }
  574. var.caclipdata.pElems[i].pClipData =
  575. (BYTE *) MemAlloc.Allocate(cbAlloc);
  576. if (var.caclipdata.pElems[i].pClipData == NULL)
  577. {
  578. Status = STATUS_INSUFFICIENT_RESOURCES;
  579. break;
  580. }
  581. stm.GetBlob(var.caclipdata.pElems[i].pClipData, cbAlloc);
  582. }
  583. break;
  584. case VT_VECTOR | VT_BSTR:
  585. for (i = 0; i < var.cabstr.cElems; i++)
  586. {
  587. PROPASSERT(var.cabstr.pElems[i] == NULL);
  588. cbAlloc = stm.GetULong();
  589. // guard against attack
  590. if ( cbAlloc == 0 || cbAlloc >= 65536 )
  591. {
  592. Status = STATUS_INVALID_PARAMETER;
  593. break;
  594. }
  595. // cbAlloc includes sizeof(OLECHAR)
  596. var.cabstr.pElems[i] = SysAllocStringLen(NULL, (cbAlloc - sizeof(OLECHAR)) / sizeof(OLECHAR) );
  597. if (var.cabstr.pElems[i] == NULL)
  598. {
  599. Status = STATUS_INSUFFICIENT_RESOURCES;
  600. break;
  601. }
  602. stm.GetChar((char *) var.cabstr.pElems[i], cbAlloc);
  603. }
  604. break;
  605. case VT_VECTOR | VT_LPSTR:
  606. for (i = 0; i < var.calpstr.cElems; i++)
  607. {
  608. PROPASSERT(var.calpstr.pElems[i] == NULL);
  609. cbAlloc = stm.GetULong();
  610. // guard against attack
  611. if ( cbAlloc == 0 || cbAlloc >= 65536 )
  612. {
  613. Status = STATUS_INVALID_PARAMETER;
  614. break;
  615. }
  616. var.calpstr.pElems[i] = (LPSTR) MemAlloc.Allocate(cbAlloc);
  617. if (var.calpstr.pElems[i] == NULL)
  618. {
  619. Status = STATUS_INSUFFICIENT_RESOURCES;
  620. break;
  621. }
  622. stm.GetChar(var.calpstr.pElems[i], cbAlloc);
  623. }
  624. break;
  625. case VT_VECTOR | VT_LPWSTR:
  626. for (i = 0; i < var.calpwstr.cElems; i++)
  627. {
  628. PROPASSERT(var.calpwstr.pElems[i] == NULL);
  629. cbAlloc = stm.GetULong(); // actually, a count of WCHARs
  630. // guard against attack
  631. if ( cbAlloc == 0 || cbAlloc >= 65536 )
  632. {
  633. Status = STATUS_INVALID_PARAMETER;
  634. break;
  635. }
  636. var.calpwstr.pElems[i] = (WCHAR *) MemAlloc.Allocate(cbAlloc * sizeof(WCHAR));
  637. if (var.calpwstr.pElems[i] == NULL)
  638. {
  639. Status = STATUS_INSUFFICIENT_RESOURCES;
  640. break;
  641. }
  642. stm.GetWChar(var.calpwstr.pElems[i], cbAlloc);
  643. }
  644. break;
  645. case VT_VECTOR | VT_VARIANT:
  646. for (i = 0; i < var.capropvar.cElems; i++)
  647. {
  648. PROPASSERT(var.capropvar.pElems[i].vt == VT_EMPTY);
  649. Status = CBaseStorageVariant::Unmarshall(
  650. stm,
  651. var.capropvar.pElems[i],
  652. MemAlloc);
  653. if (Status != STATUS_SUCCESS)
  654. {
  655. break;
  656. }
  657. }
  658. break;
  659. case VT_ARRAY | VT_I4:
  660. case VT_ARRAY | VT_UI1:
  661. case VT_ARRAY | VT_I2:
  662. case VT_ARRAY | VT_R4:
  663. case VT_ARRAY | VT_R8:
  664. case VT_ARRAY | VT_BOOL:
  665. case VT_ARRAY | VT_ERROR:
  666. case VT_ARRAY | VT_CY:
  667. case VT_ARRAY | VT_DATE:
  668. case VT_ARRAY | VT_I1:
  669. case VT_ARRAY | VT_UI2:
  670. case VT_ARRAY | VT_UI4:
  671. case VT_ARRAY | VT_INT:
  672. case VT_ARRAY | VT_UINT:
  673. case VT_ARRAY | VT_DECIMAL:
  674. case VT_ARRAY | VT_BSTR:
  675. case VT_ARRAY | VT_VARIANT:
  676. {
  677. SAFEARRAY *pSaDest = var.parray;
  678. unsigned cDataElements = 1;
  679. //
  680. // get total # of data elements to be unmarshalled.
  681. //
  682. for ( i = 0; i < pSaDest->cDims; i++)
  683. {
  684. cDataElements *= pSaDest->rgsabound[i].cElements;
  685. }
  686. //
  687. // unmarshall data elements
  688. //
  689. switch (var.vt)
  690. {
  691. case VT_ARRAY | VT_I1:
  692. case VT_ARRAY | VT_UI1:
  693. {
  694. BYTE * pByte = (BYTE *)pSaDest->pvData;
  695. for ( i = 0; i < cDataElements ; i++ )
  696. pByte[i] = stm.GetByte();
  697. }
  698. break;
  699. case VT_ARRAY | VT_I2:
  700. case VT_ARRAY | VT_UI2:
  701. case VT_ARRAY | VT_BOOL:
  702. {
  703. Win4Assert( sizeof VARIANT_BOOL == sizeof USHORT );
  704. USHORT * pUShort = (USHORT *)pSaDest->pvData;
  705. for ( i = 0; i < cDataElements ; i++ )
  706. pUShort[i] = stm.GetUShort();
  707. }
  708. break;
  709. case VT_ARRAY | VT_I4:
  710. case VT_ARRAY | VT_UI4:
  711. case VT_ARRAY | VT_INT:
  712. case VT_ARRAY | VT_UINT:
  713. case VT_ARRAY | VT_R4:
  714. case VT_ARRAY | VT_ERROR:
  715. {
  716. Win4Assert( sizeof(ULONG) == sizeof (INT) );
  717. Win4Assert( sizeof(ULONG) == sizeof (UINT) );
  718. Win4Assert( sizeof(ULONG) == sizeof (SCODE) ); // VT_ERROR
  719. ULONG * pULong = (ULONG *)pSaDest->pvData;
  720. for ( unsigned i = 0; i < cDataElements; i++ )
  721. {
  722. pULong[i] = stm.GetULong();
  723. }
  724. }
  725. break;
  726. case VT_ARRAY | VT_R8:
  727. case VT_ARRAY | VT_CY:
  728. case VT_ARRAY | VT_DATE:
  729. {
  730. Win4Assert( sizeof (LARGE_INTEGER) == sizeof (CY) );
  731. Win4Assert( sizeof (LARGE_INTEGER) == sizeof (DATE));
  732. Win4Assert( sizeof (LARGE_INTEGER) == sizeof (double));
  733. LARGE_INTEGER * pLargInt = (LARGE_INTEGER *)pSaDest->pvData;
  734. for ( i = 0; i < cDataElements ; i++ )
  735. {
  736. stm.GetBlob( (BYTE *) &pLargInt[i], sizeof(LARGE_INTEGER) );
  737. }
  738. }
  739. break;
  740. case VT_ARRAY | VT_DECIMAL:
  741. {
  742. Win4Assert( sizeof (DECIMAL) == pSaDest->cbElements );
  743. DECIMAL * pDecVal = (DECIMAL *)pSaDest->pvData;
  744. for ( i = 0; i < cDataElements ; i++ )
  745. {
  746. stm.GetBlob( (BYTE *) &pDecVal[i], sizeof(DECIMAL) );
  747. }
  748. }
  749. break;
  750. case VT_ARRAY|VT_BSTR:
  751. {
  752. BSTR *pBstrDest = (BSTR *) pSaDest->pvData;
  753. for ( i = 0; i < cDataElements; i++ )
  754. {
  755. PROPASSERT( pBstrDest[i] == NULL );
  756. cbAlloc = stm.GetULong(); // actually, a count of WCHARs + NULL terminator
  757. if ( cbAlloc == 0 || cbAlloc >= 65536 )
  758. {
  759. Status = STATUS_INVALID_PARAMETER;
  760. break;
  761. }
  762. // cbAlloc already contains sizeof(OLECHAR), ie null terminator.
  763. pBstrDest[i] = (BSTR) SysAllocStringLen(NULL, (cbAlloc - sizeof(OLECHAR)) / sizeof(OLECHAR) );
  764. if ( !pBstrDest[i] )
  765. {
  766. Status = STATUS_INSUFFICIENT_RESOURCES;
  767. break;
  768. }
  769. stm.GetChar( (char *) pBstrDest[i], cbAlloc );
  770. }
  771. }
  772. break;
  773. case VT_ARRAY | VT_VARIANT:
  774. {
  775. Win4Assert( sizeof (PROPVARIANT) == pSaDest->cbElements );
  776. PROPVARIANT *pVarDest = (PROPVARIANT *) pSaDest->pvData;
  777. for (i = 0; i < cDataElements; i++)
  778. {
  779. PROPASSERT(pVarDest[i].vt == VT_EMPTY);
  780. Status = CBaseStorageVariant::Unmarshall(
  781. stm,
  782. pVarDest[i],
  783. MemAlloc);
  784. if (Status != STATUS_SUCCESS)
  785. {
  786. break;
  787. }
  788. }
  789. }
  790. break;
  791. default:
  792. Win4Assert( !"Unexpected SAFEARRAY type" );
  793. }
  794. }
  795. break;
  796. default:
  797. PROPASSERT(!"Invalid type (peek) for PROPVARIANT unmarshalling");
  798. break;
  799. }
  800. return(Status);
  801. }
  802. #ifdef ENABLE_MARSHAL_VARIANT
  803. inline void
  804. _Marshall_VT_CF(CLIPDATA *pclipdata, PSerStream &stm)
  805. {
  806. CLIPDATA clipdata;
  807. clipdata.cbSize = 0;
  808. clipdata.ulClipFmt = 0;
  809. if (pclipdata != NULL)
  810. {
  811. clipdata.cbSize = pclipdata->cbSize;
  812. clipdata.ulClipFmt = pclipdata->ulClipFmt;
  813. if (pclipdata->pClipData == NULL)
  814. {
  815. clipdata.cbSize = 0;
  816. }
  817. }
  818. stm.PutULong(clipdata.cbSize);
  819. stm.PutULong(clipdata.ulClipFmt);
  820. if (clipdata.cbSize)
  821. {
  822. stm.PutBlob((BYTE *) pclipdata->pClipData, CBPCLIPDATA(clipdata));
  823. }
  824. }
  825. #endif //ifdef ENABLE_MARSHAL_VARIANT
  826. #ifdef ENABLE_MARSHAL_VARIANT
  827. inline void
  828. _Marshall_VT_BSTR(BSTR bstrVal, PSerStream &stm)
  829. {
  830. if (bstrVal != NULL)
  831. {
  832. ULONG cc = BSTRLEN(bstrVal) + sizeof(OLECHAR);
  833. stm.PutULong(cc);
  834. stm.PutChar((char *) bstrVal, cc);
  835. }
  836. else
  837. {
  838. stm.PutULong(0);
  839. }
  840. }
  841. #endif //ifdef ENABLE_MARSHAL_VARIANT
  842. #ifdef ENABLE_MARSHAL_VARIANT
  843. inline void
  844. _Marshall_VT_LPSTR(CHAR *pszVal, PSerStream &stm)
  845. {
  846. if (pszVal != NULL)
  847. {
  848. // Include NULL because OLE 2.0 spec says so.
  849. ULONG cc = strlen(pszVal) + 1;
  850. stm.PutULong(cc);
  851. stm.PutChar(pszVal, cc);
  852. PROPASSERT(IsAnsiString(pszVal, cc));
  853. }
  854. else
  855. {
  856. stm.PutULong(0);
  857. }
  858. }
  859. #endif //ifdef ENABLE_MARSHAL_VARIANT
  860. #ifdef ENABLE_MARSHAL_VARIANT
  861. inline void
  862. _Marshall_VT_LPWSTR(LPWSTR pwszVal, PSerStream &stm)
  863. {
  864. if (pwszVal != NULL)
  865. {
  866. // Include NULL because OLE 2.0 spec says so.
  867. ULONG cc = Prop_wcslen(pwszVal) + 1;
  868. PROPASSERT(IsUnicodeString(pwszVal, cc * sizeof(WCHAR)));
  869. stm.PutULong(cc);
  870. stm.PutWChar(pwszVal, cc);
  871. }
  872. else
  873. {
  874. stm.PutULong(0);
  875. }
  876. }
  877. #endif //ifdef ENABLE_MARSHAL_VARIANT
  878. #ifdef ENABLE_MARSHAL_VARIANT
  879. void
  880. CBaseStorageVariant::Marshall(PSerStream & stm) const
  881. {
  882. ULONG i;
  883. if ((VT_BYREF|VT_VARIANT) == vt)
  884. {
  885. PROPASSERT(pvarVal->vt != (VT_BYREF|VT_VARIANT));
  886. ((CBaseStorageVariant*)pvarVal)->Marshall(stm);
  887. return;
  888. }
  889. stm.PutULong(vt & ~VT_BYREF);
  890. switch (vt)
  891. {
  892. case VT_EMPTY:
  893. case VT_NULL:
  894. break;
  895. case VT_I1:
  896. case VT_UI1:
  897. stm.PutByte(bVal);
  898. break;
  899. case VT_I2:
  900. case VT_UI2:
  901. case VT_BOOL:
  902. stm.PutUShort(iVal);
  903. break;
  904. case VT_I4:
  905. case VT_UI4:
  906. case VT_R4:
  907. case VT_INT:
  908. case VT_UINT:
  909. case VT_ERROR:
  910. stm.PutULong(lVal);
  911. break;
  912. case VT_I8:
  913. case VT_UI8:
  914. case VT_R8:
  915. case VT_CY:
  916. case VT_DATE:
  917. case VT_FILETIME:
  918. stm.PutBlob((BYTE *) &hVal, sizeof(hVal));
  919. break;
  920. case VT_DECIMAL:
  921. stm.PutBlob((BYTE *) &decVal, sizeof(DECIMAL));
  922. break;
  923. case VT_CLSID:
  924. stm.PutBlob((BYTE *)puuid, sizeof(CLSID));
  925. break;
  926. case VT_BLOB:
  927. case VT_BLOB_OBJECT:
  928. stm.PutULong(blob.cbSize);
  929. stm.PutBlob(blob.pBlobData, blob.cbSize);
  930. break;
  931. case VT_CF:
  932. _Marshall_VT_CF(pclipdata, stm);
  933. break;
  934. case VT_STREAM:
  935. case VT_VERSIONED_STREAM:
  936. case VT_STREAMED_OBJECT:
  937. case VT_STORAGE:
  938. case VT_STORED_OBJECT:
  939. // NTRAID#DB-NTBUG9-84615-2000/07/31-dlee Some VT types not supported by Indexing Service
  940. break;
  941. case VT_BSTR:
  942. _Marshall_VT_BSTR(bstrVal, stm);
  943. break;
  944. case VT_LPSTR:
  945. _Marshall_VT_LPSTR(pszVal, stm);
  946. break;
  947. case VT_LPWSTR:
  948. _Marshall_VT_LPWSTR(pwszVal, stm);
  949. break;
  950. case VT_VECTOR | VT_I1:
  951. case VT_VECTOR | VT_UI1:
  952. stm.PutULong(caub.cElems);
  953. for (i = 0; i < caub.cElems; i++)
  954. {
  955. stm.PutByte(caub.pElems[i]);
  956. }
  957. break;
  958. case VT_VECTOR | VT_I2:
  959. case VT_VECTOR | VT_UI2:
  960. case VT_VECTOR | VT_BOOL:
  961. stm.PutULong(cai.cElems);
  962. for (i = 0; i < cai.cElems; i++)
  963. {
  964. stm.PutUShort(cai.pElems[i]);
  965. }
  966. break;
  967. case VT_VECTOR | VT_I4:
  968. case VT_VECTOR | VT_UI4:
  969. case VT_VECTOR | VT_R4:
  970. case VT_VECTOR | VT_ERROR:
  971. stm.PutULong(cal.cElems);
  972. for (i = 0; i < cal.cElems; i++)
  973. {
  974. stm.PutULong(cal.pElems[i]);
  975. }
  976. break;
  977. case VT_VECTOR | VT_I8:
  978. case VT_VECTOR | VT_UI8:
  979. case VT_VECTOR | VT_R8:
  980. case VT_VECTOR | VT_CY:
  981. case VT_VECTOR | VT_DATE:
  982. case VT_VECTOR | VT_FILETIME:
  983. stm.PutULong(cah.cElems);
  984. for (i = 0; i < cah.cElems; i++)
  985. {
  986. stm.PutBlob((BYTE *) &cah.pElems[i], sizeof(LARGE_INTEGER));
  987. }
  988. break;
  989. case VT_VECTOR | VT_CLSID:
  990. stm.PutULong(cauuid.cElems);
  991. for (i = 0; i < cauuid.cElems; i++)
  992. {
  993. stm.PutBlob((BYTE *)&cauuid.pElems[i], sizeof(CLSID));
  994. }
  995. break;
  996. case VT_VECTOR | VT_CF:
  997. stm.PutULong(caclipdata.cElems);
  998. for (i = 0; i < caclipdata.cElems; i++)
  999. {
  1000. _Marshall_VT_CF(&caclipdata.pElems[i], stm);
  1001. }
  1002. break;
  1003. break;
  1004. case VT_VECTOR | VT_BSTR:
  1005. stm.PutULong(cabstr.cElems);
  1006. for (i = 0; i < cabstr.cElems; i++)
  1007. {
  1008. _Marshall_VT_BSTR(cabstr.pElems[i], stm);
  1009. }
  1010. break;
  1011. case VT_VECTOR | VT_LPSTR:
  1012. stm.PutULong(calpstr.cElems);
  1013. for (i = 0; i < calpstr.cElems; i++)
  1014. {
  1015. _Marshall_VT_LPSTR(calpstr.pElems[i], stm);
  1016. }
  1017. break;
  1018. case VT_VECTOR | VT_LPWSTR:
  1019. stm.PutULong(calpwstr.cElems);
  1020. for (i = 0; i < calpwstr.cElems; i++)
  1021. {
  1022. _Marshall_VT_LPWSTR(calpwstr.pElems[i], stm);
  1023. }
  1024. break;
  1025. case VT_VECTOR | VT_VARIANT:
  1026. stm.PutULong(capropvar.cElems);
  1027. for (i = 0; i < capropvar.cElems; i++)
  1028. {
  1029. ((CBaseStorageVariant &) capropvar.pElems[i]).Marshall(stm);
  1030. }
  1031. break;
  1032. case VT_ARRAY | VT_I4:
  1033. case VT_ARRAY | VT_UI1:
  1034. case VT_ARRAY | VT_I2:
  1035. case VT_ARRAY | VT_R4:
  1036. case VT_ARRAY | VT_R8:
  1037. case VT_ARRAY | VT_BOOL:
  1038. case VT_ARRAY | VT_ERROR:
  1039. case VT_ARRAY | VT_CY:
  1040. case VT_ARRAY | VT_DATE:
  1041. case VT_ARRAY | VT_I1:
  1042. case VT_ARRAY | VT_UI2:
  1043. case VT_ARRAY | VT_UI4:
  1044. case VT_ARRAY | VT_INT:
  1045. case VT_ARRAY | VT_UINT:
  1046. case VT_ARRAY | VT_BSTR:
  1047. case VT_ARRAY | VT_DECIMAL:
  1048. case VT_ARRAY | VT_VARIANT:
  1049. {
  1050. SAFEARRAY *pSa = parray;
  1051. unsigned cDataElements = 1;
  1052. stm.PutUShort(pSa->cDims);
  1053. stm.PutUShort(pSa->fFeatures);
  1054. stm.PutULong(pSa->cbElements);
  1055. // don't marshall cLocks member, set to 1 upon unmarshalling
  1056. //
  1057. // marshall rgsabound
  1058. //
  1059. for ( i = 0; i < pSa->cDims; i++ )
  1060. {
  1061. stm.PutULong(pSa->rgsabound[i].cElements);
  1062. stm.PutLong(pSa->rgsabound[i].lLbound);
  1063. cDataElements *= pSa->rgsabound[i].cElements;
  1064. }
  1065. //
  1066. // marshall pvData
  1067. //
  1068. switch ( vt )
  1069. {
  1070. case VT_ARRAY | VT_I1:
  1071. case VT_ARRAY | VT_UI1:
  1072. {
  1073. BYTE * pByte = (BYTE *)pSa->pvData;
  1074. for ( i = 0; i < cDataElements ; i++ )
  1075. stm.PutByte(pByte[i]);
  1076. }
  1077. break;
  1078. case VT_ARRAY | VT_I2:
  1079. case VT_ARRAY | VT_UI2:
  1080. case VT_ARRAY | VT_BOOL:
  1081. {
  1082. Win4Assert( sizeof VARIANT_BOOL == sizeof USHORT );
  1083. USHORT * pUShort = (USHORT *)pSa->pvData;
  1084. for ( i = 0; i < cDataElements ; i++ )
  1085. stm.PutUShort(pUShort[i]);
  1086. }
  1087. break;
  1088. case VT_ARRAY | VT_I4:
  1089. case VT_ARRAY | VT_UI4:
  1090. case VT_ARRAY | VT_INT:
  1091. case VT_ARRAY | VT_UINT:
  1092. case VT_ARRAY | VT_R4:
  1093. case VT_ARRAY | VT_ERROR:
  1094. {
  1095. Win4Assert( sizeof(ULONG) == sizeof (INT) );
  1096. Win4Assert( sizeof(ULONG) == sizeof (UINT) );
  1097. Win4Assert( sizeof(ULONG) == sizeof (SCODE) ); // VT_ERROR
  1098. ULONG * pULong = (ULONG *)pSa->pvData;
  1099. for ( i = 0; i < cDataElements ; i++ )
  1100. stm.PutULong(pULong[i]);
  1101. }
  1102. break;
  1103. case VT_ARRAY | VT_R8:
  1104. case VT_ARRAY | VT_CY:
  1105. case VT_ARRAY | VT_DATE:
  1106. {
  1107. Win4Assert( sizeof (LARGE_INTEGER) == sizeof (CY) );
  1108. Win4Assert( sizeof (LARGE_INTEGER) == sizeof (DATE));
  1109. Win4Assert( sizeof (LARGE_INTEGER) == sizeof (double));
  1110. LARGE_INTEGER * pLargInt = (LARGE_INTEGER *)pSa->pvData;
  1111. for ( i = 0; i < cDataElements ; i++ )
  1112. stm.PutBlob( (BYTE *) &pLargInt[i], sizeof(LARGE_INTEGER) );
  1113. }
  1114. break;
  1115. case VT_ARRAY | VT_DECIMAL:
  1116. {
  1117. Win4Assert( sizeof (DECIMAL) == pSa->cbElements );
  1118. DECIMAL * pDecVal = (DECIMAL *)pSa->pvData;
  1119. for ( i = 0; i < cDataElements ; i++ )
  1120. stm.PutBlob( (BYTE *) &pDecVal[i], sizeof(DECIMAL) );
  1121. }
  1122. break;
  1123. case VT_ARRAY | VT_BSTR:
  1124. {
  1125. for ( i = 0 ; i < cDataElements; i++ )
  1126. _Marshall_VT_BSTR( ((BSTR *)pSa->pvData)[i], stm );
  1127. }
  1128. break;
  1129. case VT_ARRAY | VT_VARIANT:
  1130. {
  1131. PROPVARIANT *pVarnt = (PROPVARIANT *) pSa->pvData;
  1132. for ( i = 0 ; i < cDataElements; i++ )
  1133. ((CBaseStorageVariant &) pVarnt[i]).Marshall(stm);
  1134. }
  1135. break;
  1136. default:
  1137. Win4Assert( !"Invalid SAFEARRAY type" );
  1138. }
  1139. }
  1140. break;
  1141. case VT_BYREF | VT_I1:
  1142. case VT_BYREF | VT_UI1:
  1143. stm.PutByte(*pbVal);
  1144. break;
  1145. case VT_BYREF | VT_I2:
  1146. case VT_BYREF | VT_UI2:
  1147. case VT_BYREF | VT_BOOL:
  1148. stm.PutUShort(*piVal);
  1149. break;
  1150. case VT_BYREF | VT_I4:
  1151. case VT_BYREF | VT_UI4:
  1152. case VT_BYREF | VT_INT:
  1153. case VT_BYREF | VT_UINT:
  1154. case VT_BYREF | VT_R4:
  1155. case VT_BYREF | VT_ERROR:
  1156. stm.PutULong(*plVal);
  1157. break;
  1158. case VT_BYREF | VT_R8:
  1159. case VT_BYREF | VT_CY:
  1160. case VT_BYREF | VT_DATE:
  1161. stm.PutBlob((BYTE *) pdblVal, sizeof(double));
  1162. break;
  1163. case VT_BYREF | VT_DECIMAL:
  1164. stm.PutBlob((BYTE *) pdecVal, sizeof(DECIMAL));
  1165. break;
  1166. case VT_BYREF | VT_BSTR:
  1167. _Marshall_VT_BSTR( *pbstrVal, stm );
  1168. break;
  1169. default:
  1170. PROPASSERT(!"Invalid type for PROPVARIANT marshalling");
  1171. break;
  1172. }
  1173. }
  1174. #endif //ifdef ENABLE_MARSHAL_VARIANT
  1175. #ifdef OLDSUMCATAPI
  1176. void
  1177. MarshallVariant(PSerStream &stm, PROPVARIANT &stgvar)
  1178. {
  1179. CBaseStorageVariant *pstgvar = (CBaseStorageVariant *)&stgvar;
  1180. pstgvar->Marshall(stm);
  1181. }
  1182. #endif //ifdef OLDSUMCATAPI
  1183. #ifdef ENABLE_DISPLAY_VARIANT
  1184. VOID
  1185. CBaseStorageVariant::DisplayVariant(
  1186. ULONG ulLevel,
  1187. USHORT CodePage) const
  1188. {
  1189. char *psz;
  1190. switch (vt)
  1191. {
  1192. case VT_ILLEGAL: psz = "ILLEGAL"; goto EmptyType;
  1193. case VT_EMPTY: psz = "EMPTY"; goto EmptyType;
  1194. case VT_NULL: psz = "NULL"; goto EmptyType;
  1195. BlobType:
  1196. EmptyType:
  1197. DEBTRACE((DBGFLAG "%s", psz));
  1198. break;
  1199. case VT_UI1:
  1200. AssertByteField(bVal); // VT_UI1
  1201. DEBTRACE((DBGFLAG "UI1=%hx", bVal));
  1202. break;
  1203. case VT_I2: psz = "I2"; goto ShortType;
  1204. case VT_UI2: psz = "UI2"; goto ShortType;
  1205. ShortType:
  1206. AssertShortField(iVal); // VT_I2
  1207. AssertShortField(uiVal); // VT_UI2
  1208. DEBTRACE((DBGFLAG "%s=%hx", psz, iVal));
  1209. break;
  1210. case VT_BOOL:
  1211. switch (boolVal)
  1212. {
  1213. case VARIANT_TRUE:
  1214. DEBTRACE((DBGFLAG "BOOL=TRUE"));
  1215. break;
  1216. case FALSE:
  1217. DEBTRACE((DBGFLAG "BOOL=FALSE"));
  1218. break;
  1219. default:
  1220. DEBTRACE((DBGFLAG "BOOL=%hx???", boolVal));
  1221. break;
  1222. }
  1223. break;
  1224. case VT_I4: psz = "I4"; goto LongType;
  1225. case VT_UI4: psz = "UI4"; goto LongType;
  1226. case VT_R4: psz = "R4"; goto LongType;
  1227. case VT_ERROR: psz = "ERROR"; goto LongType;
  1228. LongType:
  1229. AssertLongField(lVal); // VT_I4
  1230. AssertLongField(ulVal); // VT_UI4
  1231. AssertLongField(fltVal); // VT_R4
  1232. AssertLongField(scode); // VT_ERROR
  1233. DEBTRACE((DBGFLAG "%s=%x", psz, lVal));
  1234. break;
  1235. case VT_I8: psz = "I8"; goto LongLongType;
  1236. case VT_UI8: psz = "UI8"; goto LongLongType;
  1237. case VT_R8: psz = "R8"; goto LongLongType;
  1238. case VT_CY: psz = "CY"; goto LongLongType;
  1239. case VT_DATE: psz = "DATE"; goto LongLongType;
  1240. case VT_FILETIME: psz = "FILETIME"; goto LongLongType;
  1241. LongLongType:
  1242. AssertLongLongField(hVal); // VT_I8
  1243. AssertLongLongField(uhVal); // VT_UI8
  1244. AssertLongLongField(dblVal); // VT_R8
  1245. AssertLongLongField(cyVal); // VT_CY
  1246. AssertLongLongField(date); // VT_DATE
  1247. AssertLongLongField(filetime); // VT_FILETIME
  1248. DEBTRACE((DBGFLAG "%s=%x:%x", psz, hVal.HighPart, hVal.LowPart));
  1249. break;
  1250. case VT_CLSID: psz = "CLSID"; goto EmptyType;
  1251. case VT_BLOB: psz = "BLOB"; goto BlobType;
  1252. case VT_BLOB_OBJECT: psz = "BLOB_OBJECT"; goto BlobType;
  1253. case VT_CF: psz = "CF"; goto BlobType;
  1254. case VT_STREAM: psz = "STREAM"; goto TestUnicode;
  1255. case VT_STREAMED_OBJECT: psz = "STREAMED_OBJECT"; goto TestUnicode;
  1256. case VT_STORAGE: psz = "STORAGE"; goto TestUnicode;
  1257. case VT_STORED_OBJECT: psz = "STORED_OBJECT"; goto TestUnicode;
  1258. case VT_VERSIONED_STREAM: psz = "VERSIONED_STREAM"; goto TestUnicode;
  1259. case VT_LPSTR: psz = "LPSTR"; goto TestUnicode;
  1260. TestUnicode:
  1261. AssertStringField(pszVal); // VT_STREAM, VT_STREAMED_OBJECT
  1262. AssertStringField(pszVal); // VT_STORAGE, VT_STORED_OBJECT
  1263. AssertStringField(pszVal); // VT_LPSTR
  1264. DEBTRACE((
  1265. DBGFLAG
  1266. CodePage == CP_WINUNICODE? "%s=L'%ws'" : "%s='%s'",
  1267. psz,
  1268. pszVal));
  1269. break;
  1270. case VT_BSTR: psz = "BSTR"; goto PrintUnicode;
  1271. case VT_LPWSTR: psz = "LPWSTR"; goto PrintUnicode;
  1272. PrintUnicode:
  1273. AssertStringField(pwszVal); // VT_LPWSTR
  1274. AssertStringField(bstrVal); // VT_BSTR
  1275. DEBTRACE((DBGFLAG "%s=L'%ws'", psz, pwszVal));
  1276. break;
  1277. default:
  1278. if (vt & VT_VECTOR)
  1279. {
  1280. DEBTRACE((DBGFLAG "UNPRINTABLE VECTOR TYPE=%x(%u)", vt, vt));
  1281. }
  1282. else
  1283. {
  1284. DEBTRACE((DBGFLAG "UNKNOWN TYPE=%x(%u)", vt, vt));
  1285. }
  1286. break;
  1287. }
  1288. }
  1289. #endif //ifdef ENABLE_DISPLAY_VARIANT
  1290. #endif //ifdef WINNT