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.

1450 lines
40 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. SAFEARRAY * psaDest;
  374. HRESULT hr = SafeArrayAllocDescriptorEx( var.vt & (~VT_ARRAY),
  375. cDims,
  376. &psaDest );
  377. if ( FAILED( hr ) )
  378. return hr;
  379. var.parray = psaDest;
  380. psaDest->fFeatures = stm.GetUShort();
  381. psaDest->cbElements= stm.GetULong();
  382. // Override what was written to support Win64 interop
  383. if ( (VT_ARRAY | VT_BSTR) == var.vt )
  384. psaDest->cbElements = sizeof(void *);
  385. else if ( (VT_ARRAY | VT_VARIANT) == var.vt )
  386. psaDest->cbElements = sizeof PROPVARIANT;
  387. psaDest->cLocks = 0; // no one has this locked, and if it's
  388. // locked, it can't be freed
  389. for ( unsigned i = 0; i < cDims; i++ )
  390. {
  391. psaDest->rgsabound[i].cElements = stm.GetULong();
  392. psaDest->rgsabound[i].lLbound = stm.GetLong();
  393. }
  394. ppv = (void **) &(psaDest->pvData);
  395. fZero = TRUE; // set all vt pointers to VT_EMPTY
  396. break;
  397. }
  398. default:
  399. PROPASSERT(!"Invalid type for PROPVARIANT unmarshalling");
  400. Status = STATUS_INVALID_PARAMETER;
  401. break;
  402. }
  403. if ( FAILED( Status ) )
  404. return Status;
  405. if ( ( 0 == ( var.vt & VT_ARRAY ) ) &&
  406. ( cbAlloc == 0 || Status != STATUS_SUCCESS ) )
  407. {
  408. // No further work need be done. The Ummarshalling is complete,
  409. // i.e., fixed size variant or no variable length data.
  410. if (ppv != NULL)
  411. *ppv = NULL;
  412. return(Status);
  413. }
  414. // Guard against attack
  415. if ( cbAlloc >= 65536 )
  416. return E_INVALIDARG;
  417. // Allocate the desired amount of memory and continue unmarshalling
  418. // if allocation was successfull.
  419. PROPASSERT(ppv != NULL);
  420. if ( var.vt == VT_BSTR )
  421. {
  422. *ppv = (void *)SysAllocStringLen(NULL, (cbAlloc - sizeof(OLECHAR))/sizeof(OLECHAR) );
  423. }
  424. else if ( 0 != ( VT_ARRAY & var.vt ) )
  425. {
  426. HRESULT hr = SafeArrayAllocData( var.parray );
  427. if ( FAILED( hr ) )
  428. return hr;
  429. Win4Assert( 0 != *ppv );
  430. }
  431. else
  432. {
  433. *ppv = MemAlloc.Allocate(cbAlloc);
  434. }
  435. if (0 == *ppv )
  436. return STATUS_INSUFFICIENT_RESOURCES;
  437. if (fZero)
  438. RtlZeroMemory(*ppv, cbAlloc);
  439. ULONG i;
  440. // We have a variant with variable sized data which requires
  441. // further unmarshalling.
  442. switch(var.vt)
  443. {
  444. case VT_CLSID:
  445. stm.GetBlob((BYTE *)var.puuid, sizeof(CLSID));
  446. break;
  447. case VT_BLOB:
  448. case VT_BLOB_OBJECT:
  449. stm.GetBlob(var.blob.pBlobData, var.blob.cbSize);
  450. break;
  451. case VT_CF:
  452. stm.GetBlob(var.pclipdata->pClipData, CBPCLIPDATA(*var.pclipdata));
  453. break;
  454. case VT_BSTR:
  455. stm.GetChar((char *) var.bstrVal, cbAlloc );
  456. break;
  457. case VT_LPSTR:
  458. stm.GetChar(var.pszVal, cbAlloc);
  459. break;
  460. case VT_LPWSTR:
  461. stm.GetWChar(var.pwszVal, cbAlloc / sizeof(WCHAR));
  462. break;
  463. case VT_VECTOR | VT_I1:
  464. case VT_VECTOR | VT_UI1:
  465. for (i = 0; i < var.caub.cElems; i++)
  466. {
  467. var.caub.pElems[i] = stm.GetByte();
  468. }
  469. break;
  470. case VT_VECTOR | VT_I2:
  471. case VT_VECTOR | VT_UI2:
  472. case VT_VECTOR | VT_BOOL:
  473. for (i = 0; i < var.cai.cElems; i++)
  474. {
  475. var.cai.pElems[i] = stm.GetUShort();
  476. }
  477. break;
  478. case VT_VECTOR | VT_I4:
  479. case VT_VECTOR | VT_UI4:
  480. case VT_VECTOR | VT_R4:
  481. case VT_VECTOR | VT_ERROR:
  482. for (i = 0; i < var.cal.cElems; i++)
  483. {
  484. var.cal.pElems[i] = stm.GetULong();
  485. }
  486. break;
  487. case VT_VECTOR | VT_I8:
  488. case VT_VECTOR | VT_UI8:
  489. case VT_VECTOR | VT_R8:
  490. case VT_VECTOR | VT_CY:
  491. case VT_VECTOR | VT_DATE:
  492. case VT_VECTOR | VT_FILETIME:
  493. for (i = 0; i < var.cah.cElems; i++)
  494. {
  495. stm.GetBlob((BYTE *)&var.cah.pElems[i], sizeof(LARGE_INTEGER));
  496. }
  497. break;
  498. case VT_VECTOR | VT_CLSID:
  499. for (i = 0; i < var.cauuid.cElems; i++)
  500. {
  501. stm.GetBlob((BYTE *)&var.cauuid.pElems[i], sizeof(CLSID));
  502. }
  503. break;
  504. case VT_VECTOR | VT_CF:
  505. for (i = 0; i < var.caclipdata.cElems; i++)
  506. {
  507. PROPASSERT(var.caclipdata.pElems[i].pClipData == NULL);
  508. var.caclipdata.pElems[i].cbSize = stm.GetULong();
  509. cbAlloc = CBPCLIPDATA(var.caclipdata.pElems[i]);
  510. var.caclipdata.pElems[i].ulClipFmt = stm.GetULong();
  511. if (cbAlloc == 0)
  512. {
  513. Status = STATUS_INVALID_PARAMETER;
  514. break;
  515. }
  516. var.caclipdata.pElems[i].pClipData =
  517. (BYTE *) MemAlloc.Allocate(cbAlloc);
  518. if (var.caclipdata.pElems[i].pClipData == NULL)
  519. {
  520. Status = STATUS_INSUFFICIENT_RESOURCES;
  521. break;
  522. }
  523. stm.GetBlob(var.caclipdata.pElems[i].pClipData, cbAlloc);
  524. }
  525. break;
  526. case VT_VECTOR | VT_BSTR:
  527. for (i = 0; i < var.cabstr.cElems; i++)
  528. {
  529. PROPASSERT(var.cabstr.pElems[i] == NULL);
  530. cbAlloc = stm.GetULong();
  531. // guard against attack
  532. if ( cbAlloc == 0 || cbAlloc >= 65536 )
  533. {
  534. Status = STATUS_INVALID_PARAMETER;
  535. break;
  536. }
  537. // cbAlloc includes sizeof(OLECHAR)
  538. var.cabstr.pElems[i] = SysAllocStringLen(NULL, (cbAlloc - sizeof(OLECHAR)) / sizeof(OLECHAR) );
  539. if (var.cabstr.pElems[i] == NULL)
  540. {
  541. Status = STATUS_INSUFFICIENT_RESOURCES;
  542. break;
  543. }
  544. stm.GetChar((char *) var.cabstr.pElems[i], cbAlloc);
  545. }
  546. break;
  547. case VT_VECTOR | VT_LPSTR:
  548. for (i = 0; i < var.calpstr.cElems; i++)
  549. {
  550. PROPASSERT(var.calpstr.pElems[i] == NULL);
  551. cbAlloc = stm.GetULong();
  552. // guard against attack
  553. if ( cbAlloc == 0 || cbAlloc >= 65536 )
  554. {
  555. Status = STATUS_INVALID_PARAMETER;
  556. break;
  557. }
  558. var.calpstr.pElems[i] = (LPSTR) MemAlloc.Allocate(cbAlloc);
  559. if (var.calpstr.pElems[i] == NULL)
  560. {
  561. Status = STATUS_INSUFFICIENT_RESOURCES;
  562. break;
  563. }
  564. stm.GetChar(var.calpstr.pElems[i], cbAlloc);
  565. }
  566. break;
  567. case VT_VECTOR | VT_LPWSTR:
  568. for (i = 0; i < var.calpwstr.cElems; i++)
  569. {
  570. PROPASSERT(var.calpwstr.pElems[i] == NULL);
  571. cbAlloc = stm.GetULong(); // actually, a count of WCHARs
  572. // guard against attack
  573. if ( cbAlloc == 0 || cbAlloc >= 65536 )
  574. {
  575. Status = STATUS_INVALID_PARAMETER;
  576. break;
  577. }
  578. var.calpwstr.pElems[i] = (WCHAR *) MemAlloc.Allocate(cbAlloc * sizeof(WCHAR));
  579. if (var.calpwstr.pElems[i] == NULL)
  580. {
  581. Status = STATUS_INSUFFICIENT_RESOURCES;
  582. break;
  583. }
  584. stm.GetWChar(var.calpwstr.pElems[i], cbAlloc);
  585. }
  586. break;
  587. case VT_VECTOR | VT_VARIANT:
  588. for (i = 0; i < var.capropvar.cElems; i++)
  589. {
  590. PROPASSERT(var.capropvar.pElems[i].vt == VT_EMPTY);
  591. Status = CBaseStorageVariant::Unmarshall(
  592. stm,
  593. var.capropvar.pElems[i],
  594. MemAlloc);
  595. if (Status != STATUS_SUCCESS)
  596. {
  597. break;
  598. }
  599. }
  600. break;
  601. case VT_ARRAY | VT_I4:
  602. case VT_ARRAY | VT_UI1:
  603. case VT_ARRAY | VT_I2:
  604. case VT_ARRAY | VT_R4:
  605. case VT_ARRAY | VT_R8:
  606. case VT_ARRAY | VT_BOOL:
  607. case VT_ARRAY | VT_ERROR:
  608. case VT_ARRAY | VT_CY:
  609. case VT_ARRAY | VT_DATE:
  610. case VT_ARRAY | VT_I1:
  611. case VT_ARRAY | VT_UI2:
  612. case VT_ARRAY | VT_UI4:
  613. case VT_ARRAY | VT_INT:
  614. case VT_ARRAY | VT_UINT:
  615. case VT_ARRAY | VT_DECIMAL:
  616. case VT_ARRAY | VT_BSTR:
  617. case VT_ARRAY | VT_VARIANT:
  618. {
  619. SAFEARRAY *pSaDest = var.parray;
  620. unsigned cDataElements = 1;
  621. //
  622. // get total # of data elements to be unmarshalled.
  623. //
  624. for ( i = 0; i < pSaDest->cDims; i++)
  625. {
  626. cDataElements *= pSaDest->rgsabound[i].cElements;
  627. }
  628. //
  629. // unmarshall data elements
  630. //
  631. switch (var.vt)
  632. {
  633. case VT_ARRAY | VT_I1:
  634. case VT_ARRAY | VT_UI1:
  635. {
  636. BYTE * pByte = (BYTE *)pSaDest->pvData;
  637. for ( i = 0; i < cDataElements ; i++ )
  638. pByte[i] = stm.GetByte();
  639. }
  640. break;
  641. case VT_ARRAY | VT_I2:
  642. case VT_ARRAY | VT_UI2:
  643. case VT_ARRAY | VT_BOOL:
  644. {
  645. Win4Assert( sizeof VARIANT_BOOL == sizeof USHORT );
  646. USHORT * pUShort = (USHORT *)pSaDest->pvData;
  647. for ( i = 0; i < cDataElements ; i++ )
  648. pUShort[i] = stm.GetUShort();
  649. }
  650. break;
  651. case VT_ARRAY | VT_I4:
  652. case VT_ARRAY | VT_UI4:
  653. case VT_ARRAY | VT_INT:
  654. case VT_ARRAY | VT_UINT:
  655. case VT_ARRAY | VT_R4:
  656. case VT_ARRAY | VT_ERROR:
  657. {
  658. Win4Assert( sizeof(ULONG) == sizeof (INT) );
  659. Win4Assert( sizeof(ULONG) == sizeof (UINT) );
  660. Win4Assert( sizeof(ULONG) == sizeof (SCODE) ); // VT_ERROR
  661. ULONG * pULong = (ULONG *)pSaDest->pvData;
  662. for ( i = 0; i < cDataElements; i++ )
  663. {
  664. pULong[i] = stm.GetULong();
  665. }
  666. }
  667. break;
  668. case VT_ARRAY | VT_R8:
  669. case VT_ARRAY | VT_CY:
  670. case VT_ARRAY | VT_DATE:
  671. {
  672. Win4Assert( sizeof (LARGE_INTEGER) == sizeof (CY) );
  673. Win4Assert( sizeof (LARGE_INTEGER) == sizeof (DATE));
  674. Win4Assert( sizeof (LARGE_INTEGER) == sizeof (double));
  675. LARGE_INTEGER * pLargInt = (LARGE_INTEGER *)pSaDest->pvData;
  676. for ( i = 0; i < cDataElements ; i++ )
  677. {
  678. stm.GetBlob( (BYTE *) &pLargInt[i], sizeof(LARGE_INTEGER) );
  679. }
  680. }
  681. break;
  682. case VT_ARRAY | VT_DECIMAL:
  683. {
  684. Win4Assert( sizeof (DECIMAL) == pSaDest->cbElements );
  685. DECIMAL * pDecVal = (DECIMAL *)pSaDest->pvData;
  686. for ( i = 0; i < cDataElements ; i++ )
  687. {
  688. stm.GetBlob( (BYTE *) &pDecVal[i], sizeof(DECIMAL) );
  689. }
  690. }
  691. break;
  692. case VT_ARRAY|VT_BSTR:
  693. {
  694. BSTR *pBstrDest = (BSTR *) pSaDest->pvData;
  695. for ( i = 0; i < cDataElements; i++ )
  696. {
  697. PROPASSERT( pBstrDest[i] == NULL );
  698. cbAlloc = stm.GetULong(); // actually, a count of WCHARs + NULL terminator
  699. if ( cbAlloc == 0 || cbAlloc >= 65536 )
  700. {
  701. Status = STATUS_INVALID_PARAMETER;
  702. break;
  703. }
  704. // cbAlloc already contains sizeof(OLECHAR), ie null terminator.
  705. pBstrDest[i] = (BSTR) SysAllocStringLen(NULL, (cbAlloc - sizeof(OLECHAR)) / sizeof(OLECHAR) );
  706. if ( !pBstrDest[i] )
  707. {
  708. Status = STATUS_INSUFFICIENT_RESOURCES;
  709. break;
  710. }
  711. stm.GetChar( (char *) pBstrDest[i], cbAlloc );
  712. }
  713. }
  714. break;
  715. case VT_ARRAY | VT_VARIANT:
  716. {
  717. Win4Assert( sizeof (PROPVARIANT) == pSaDest->cbElements );
  718. PROPVARIANT *pVarDest = (PROPVARIANT *) pSaDest->pvData;
  719. for (i = 0; i < cDataElements; i++)
  720. {
  721. PROPASSERT(pVarDest[i].vt == VT_EMPTY);
  722. Status = CBaseStorageVariant::Unmarshall(
  723. stm,
  724. pVarDest[i],
  725. MemAlloc);
  726. if (Status != STATUS_SUCCESS)
  727. {
  728. break;
  729. }
  730. }
  731. }
  732. break;
  733. default:
  734. Win4Assert( !"Unexpected SAFEARRAY type" );
  735. }
  736. }
  737. break;
  738. default:
  739. PROPASSERT(!"Invalid type (peek) for PROPVARIANT unmarshalling");
  740. break;
  741. }
  742. return(Status);
  743. }
  744. #ifdef ENABLE_MARSHAL_VARIANT
  745. inline void
  746. _Marshall_VT_CF(CLIPDATA *pclipdata, PSerStream &stm)
  747. {
  748. CLIPDATA clipdata;
  749. clipdata.cbSize = 0;
  750. clipdata.ulClipFmt = 0;
  751. if (pclipdata != NULL)
  752. {
  753. clipdata.cbSize = pclipdata->cbSize;
  754. clipdata.ulClipFmt = pclipdata->ulClipFmt;
  755. if (pclipdata->pClipData == NULL)
  756. {
  757. clipdata.cbSize = 0;
  758. }
  759. }
  760. stm.PutULong(clipdata.cbSize);
  761. stm.PutULong(clipdata.ulClipFmt);
  762. if (clipdata.cbSize)
  763. {
  764. stm.PutBlob((BYTE *) pclipdata->pClipData, CBPCLIPDATA(clipdata));
  765. }
  766. }
  767. #endif //ifdef ENABLE_MARSHAL_VARIANT
  768. #ifdef ENABLE_MARSHAL_VARIANT
  769. inline void
  770. _Marshall_VT_BSTR(BSTR bstrVal, PSerStream &stm)
  771. {
  772. if (bstrVal != NULL)
  773. {
  774. ULONG cc = BSTRLEN(bstrVal) + sizeof(OLECHAR);
  775. stm.PutULong(cc);
  776. stm.PutChar((char *) bstrVal, cc);
  777. }
  778. else
  779. {
  780. stm.PutULong(0);
  781. }
  782. }
  783. #endif //ifdef ENABLE_MARSHAL_VARIANT
  784. #ifdef ENABLE_MARSHAL_VARIANT
  785. inline void
  786. _Marshall_VT_LPSTR(CHAR *pszVal, PSerStream &stm)
  787. {
  788. if (pszVal != NULL)
  789. {
  790. // Include NULL because OLE 2.0 spec says so.
  791. ULONG cc = strlen(pszVal) + 1;
  792. stm.PutULong(cc);
  793. stm.PutChar(pszVal, cc);
  794. PROPASSERT(IsAnsiString(pszVal, cc));
  795. }
  796. else
  797. {
  798. stm.PutULong(0);
  799. }
  800. }
  801. #endif //ifdef ENABLE_MARSHAL_VARIANT
  802. #ifdef ENABLE_MARSHAL_VARIANT
  803. inline void
  804. _Marshall_VT_LPWSTR(LPWSTR pwszVal, PSerStream &stm)
  805. {
  806. if (pwszVal != NULL)
  807. {
  808. // Include NULL because OLE 2.0 spec says so.
  809. ULONG cc = Prop_wcslen(pwszVal) + 1;
  810. PROPASSERT(IsUnicodeString(pwszVal, cc * sizeof(WCHAR)));
  811. stm.PutULong(cc);
  812. stm.PutWChar(pwszVal, cc);
  813. }
  814. else
  815. {
  816. stm.PutULong(0);
  817. }
  818. }
  819. #endif //ifdef ENABLE_MARSHAL_VARIANT
  820. #ifdef ENABLE_MARSHAL_VARIANT
  821. void
  822. CBaseStorageVariant::Marshall(PSerStream & stm) const
  823. {
  824. ULONG i;
  825. if ((VT_BYREF|VT_VARIANT) == vt)
  826. {
  827. PROPASSERT(pvarVal->vt != (VT_BYREF|VT_VARIANT));
  828. ((CBaseStorageVariant*)pvarVal)->Marshall(stm);
  829. return;
  830. }
  831. stm.PutULong(vt & ~VT_BYREF);
  832. switch (vt)
  833. {
  834. case VT_EMPTY:
  835. case VT_NULL:
  836. break;
  837. case VT_I1:
  838. case VT_UI1:
  839. stm.PutByte(bVal);
  840. break;
  841. case VT_I2:
  842. case VT_UI2:
  843. case VT_BOOL:
  844. stm.PutUShort(iVal);
  845. break;
  846. case VT_I4:
  847. case VT_UI4:
  848. case VT_R4:
  849. case VT_INT:
  850. case VT_UINT:
  851. case VT_ERROR:
  852. stm.PutULong(lVal);
  853. break;
  854. case VT_I8:
  855. case VT_UI8:
  856. case VT_R8:
  857. case VT_CY:
  858. case VT_DATE:
  859. case VT_FILETIME:
  860. stm.PutBlob((BYTE *) &hVal, sizeof(hVal));
  861. break;
  862. case VT_DECIMAL:
  863. stm.PutBlob((BYTE *) &decVal, sizeof(DECIMAL));
  864. break;
  865. case VT_CLSID:
  866. stm.PutBlob((BYTE *)puuid, sizeof(CLSID));
  867. break;
  868. case VT_BLOB:
  869. case VT_BLOB_OBJECT:
  870. stm.PutULong(blob.cbSize);
  871. stm.PutBlob(blob.pBlobData, blob.cbSize);
  872. break;
  873. case VT_CF:
  874. _Marshall_VT_CF(pclipdata, stm);
  875. break;
  876. case VT_STREAM:
  877. case VT_VERSIONED_STREAM:
  878. case VT_STREAMED_OBJECT:
  879. case VT_STORAGE:
  880. case VT_STORED_OBJECT:
  881. // NTRAID#DB-NTBUG9-84615-2000/07/31-dlee Some VT types not supported by Indexing Service
  882. break;
  883. case VT_BSTR:
  884. _Marshall_VT_BSTR(bstrVal, stm);
  885. break;
  886. case VT_LPSTR:
  887. _Marshall_VT_LPSTR(pszVal, stm);
  888. break;
  889. case VT_LPWSTR:
  890. _Marshall_VT_LPWSTR(pwszVal, stm);
  891. break;
  892. case VT_VECTOR | VT_I1:
  893. case VT_VECTOR | VT_UI1:
  894. stm.PutULong(caub.cElems);
  895. for (i = 0; i < caub.cElems; i++)
  896. {
  897. stm.PutByte(caub.pElems[i]);
  898. }
  899. break;
  900. case VT_VECTOR | VT_I2:
  901. case VT_VECTOR | VT_UI2:
  902. case VT_VECTOR | VT_BOOL:
  903. stm.PutULong(cai.cElems);
  904. for (i = 0; i < cai.cElems; i++)
  905. {
  906. stm.PutUShort(cai.pElems[i]);
  907. }
  908. break;
  909. case VT_VECTOR | VT_I4:
  910. case VT_VECTOR | VT_UI4:
  911. case VT_VECTOR | VT_R4:
  912. case VT_VECTOR | VT_ERROR:
  913. stm.PutULong(cal.cElems);
  914. for (i = 0; i < cal.cElems; i++)
  915. {
  916. stm.PutULong(cal.pElems[i]);
  917. }
  918. break;
  919. case VT_VECTOR | VT_I8:
  920. case VT_VECTOR | VT_UI8:
  921. case VT_VECTOR | VT_R8:
  922. case VT_VECTOR | VT_CY:
  923. case VT_VECTOR | VT_DATE:
  924. case VT_VECTOR | VT_FILETIME:
  925. stm.PutULong(cah.cElems);
  926. for (i = 0; i < cah.cElems; i++)
  927. {
  928. stm.PutBlob((BYTE *) &cah.pElems[i], sizeof(LARGE_INTEGER));
  929. }
  930. break;
  931. case VT_VECTOR | VT_CLSID:
  932. stm.PutULong(cauuid.cElems);
  933. for (i = 0; i < cauuid.cElems; i++)
  934. {
  935. stm.PutBlob((BYTE *)&cauuid.pElems[i], sizeof(CLSID));
  936. }
  937. break;
  938. case VT_VECTOR | VT_CF:
  939. stm.PutULong(caclipdata.cElems);
  940. for (i = 0; i < caclipdata.cElems; i++)
  941. {
  942. _Marshall_VT_CF(&caclipdata.pElems[i], stm);
  943. }
  944. break;
  945. break;
  946. case VT_VECTOR | VT_BSTR:
  947. stm.PutULong(cabstr.cElems);
  948. for (i = 0; i < cabstr.cElems; i++)
  949. {
  950. _Marshall_VT_BSTR(cabstr.pElems[i], stm);
  951. }
  952. break;
  953. case VT_VECTOR | VT_LPSTR:
  954. stm.PutULong(calpstr.cElems);
  955. for (i = 0; i < calpstr.cElems; i++)
  956. {
  957. _Marshall_VT_LPSTR(calpstr.pElems[i], stm);
  958. }
  959. break;
  960. case VT_VECTOR | VT_LPWSTR:
  961. stm.PutULong(calpwstr.cElems);
  962. for (i = 0; i < calpwstr.cElems; i++)
  963. {
  964. _Marshall_VT_LPWSTR(calpwstr.pElems[i], stm);
  965. }
  966. break;
  967. case VT_VECTOR | VT_VARIANT:
  968. stm.PutULong(capropvar.cElems);
  969. for (i = 0; i < capropvar.cElems; i++)
  970. {
  971. ((CBaseStorageVariant &) capropvar.pElems[i]).Marshall(stm);
  972. }
  973. break;
  974. case VT_ARRAY | VT_I4:
  975. case VT_ARRAY | VT_UI1:
  976. case VT_ARRAY | VT_I2:
  977. case VT_ARRAY | VT_R4:
  978. case VT_ARRAY | VT_R8:
  979. case VT_ARRAY | VT_BOOL:
  980. case VT_ARRAY | VT_ERROR:
  981. case VT_ARRAY | VT_CY:
  982. case VT_ARRAY | VT_DATE:
  983. case VT_ARRAY | VT_I1:
  984. case VT_ARRAY | VT_UI2:
  985. case VT_ARRAY | VT_UI4:
  986. case VT_ARRAY | VT_INT:
  987. case VT_ARRAY | VT_UINT:
  988. case VT_ARRAY | VT_BSTR:
  989. case VT_ARRAY | VT_DECIMAL:
  990. case VT_ARRAY | VT_VARIANT:
  991. {
  992. SAFEARRAY *pSa = parray;
  993. unsigned cDataElements = 1;
  994. stm.PutUShort(pSa->cDims);
  995. stm.PutUShort(pSa->fFeatures);
  996. stm.PutULong(pSa->cbElements);
  997. // don't marshall cLocks member, set to 1 upon unmarshalling
  998. //
  999. // marshall rgsabound
  1000. //
  1001. for ( i = 0; i < pSa->cDims; i++ )
  1002. {
  1003. stm.PutULong(pSa->rgsabound[i].cElements);
  1004. stm.PutLong(pSa->rgsabound[i].lLbound);
  1005. cDataElements *= pSa->rgsabound[i].cElements;
  1006. }
  1007. //
  1008. // marshall pvData
  1009. //
  1010. switch ( vt )
  1011. {
  1012. case VT_ARRAY | VT_I1:
  1013. case VT_ARRAY | VT_UI1:
  1014. {
  1015. BYTE * pByte = (BYTE *)pSa->pvData;
  1016. for ( i = 0; i < cDataElements ; i++ )
  1017. stm.PutByte(pByte[i]);
  1018. }
  1019. break;
  1020. case VT_ARRAY | VT_I2:
  1021. case VT_ARRAY | VT_UI2:
  1022. case VT_ARRAY | VT_BOOL:
  1023. {
  1024. Win4Assert( sizeof VARIANT_BOOL == sizeof USHORT );
  1025. USHORT * pUShort = (USHORT *)pSa->pvData;
  1026. for ( i = 0; i < cDataElements ; i++ )
  1027. stm.PutUShort(pUShort[i]);
  1028. }
  1029. break;
  1030. case VT_ARRAY | VT_I4:
  1031. case VT_ARRAY | VT_UI4:
  1032. case VT_ARRAY | VT_INT:
  1033. case VT_ARRAY | VT_UINT:
  1034. case VT_ARRAY | VT_R4:
  1035. case VT_ARRAY | VT_ERROR:
  1036. {
  1037. Win4Assert( sizeof(ULONG) == sizeof (INT) );
  1038. Win4Assert( sizeof(ULONG) == sizeof (UINT) );
  1039. Win4Assert( sizeof(ULONG) == sizeof (SCODE) ); // VT_ERROR
  1040. ULONG * pULong = (ULONG *)pSa->pvData;
  1041. for ( i = 0; i < cDataElements ; i++ )
  1042. stm.PutULong(pULong[i]);
  1043. }
  1044. break;
  1045. case VT_ARRAY | VT_R8:
  1046. case VT_ARRAY | VT_CY:
  1047. case VT_ARRAY | VT_DATE:
  1048. {
  1049. Win4Assert( sizeof (LARGE_INTEGER) == sizeof (CY) );
  1050. Win4Assert( sizeof (LARGE_INTEGER) == sizeof (DATE));
  1051. Win4Assert( sizeof (LARGE_INTEGER) == sizeof (double));
  1052. LARGE_INTEGER * pLargInt = (LARGE_INTEGER *)pSa->pvData;
  1053. for ( i = 0; i < cDataElements ; i++ )
  1054. stm.PutBlob( (BYTE *) &pLargInt[i], sizeof(LARGE_INTEGER) );
  1055. }
  1056. break;
  1057. case VT_ARRAY | VT_DECIMAL:
  1058. {
  1059. Win4Assert( sizeof (DECIMAL) == pSa->cbElements );
  1060. DECIMAL * pDecVal = (DECIMAL *)pSa->pvData;
  1061. for ( i = 0; i < cDataElements ; i++ )
  1062. stm.PutBlob( (BYTE *) &pDecVal[i], sizeof(DECIMAL) );
  1063. }
  1064. break;
  1065. case VT_ARRAY | VT_BSTR:
  1066. {
  1067. for ( i = 0 ; i < cDataElements; i++ )
  1068. _Marshall_VT_BSTR( ((BSTR *)pSa->pvData)[i], stm );
  1069. }
  1070. break;
  1071. case VT_ARRAY | VT_VARIANT:
  1072. {
  1073. PROPVARIANT *pVarnt = (PROPVARIANT *) pSa->pvData;
  1074. for ( i = 0 ; i < cDataElements; i++ )
  1075. ((CBaseStorageVariant &) pVarnt[i]).Marshall(stm);
  1076. }
  1077. break;
  1078. default:
  1079. Win4Assert( !"Invalid SAFEARRAY type" );
  1080. }
  1081. }
  1082. break;
  1083. case VT_BYREF | VT_I1:
  1084. case VT_BYREF | VT_UI1:
  1085. stm.PutByte(*pbVal);
  1086. break;
  1087. case VT_BYREF | VT_I2:
  1088. case VT_BYREF | VT_UI2:
  1089. case VT_BYREF | VT_BOOL:
  1090. stm.PutUShort(*piVal);
  1091. break;
  1092. case VT_BYREF | VT_I4:
  1093. case VT_BYREF | VT_UI4:
  1094. case VT_BYREF | VT_INT:
  1095. case VT_BYREF | VT_UINT:
  1096. case VT_BYREF | VT_R4:
  1097. case VT_BYREF | VT_ERROR:
  1098. stm.PutULong(*plVal);
  1099. break;
  1100. case VT_BYREF | VT_R8:
  1101. case VT_BYREF | VT_CY:
  1102. case VT_BYREF | VT_DATE:
  1103. stm.PutBlob((BYTE *) pdblVal, sizeof(double));
  1104. break;
  1105. case VT_BYREF | VT_DECIMAL:
  1106. stm.PutBlob((BYTE *) pdecVal, sizeof(DECIMAL));
  1107. break;
  1108. case VT_BYREF | VT_BSTR:
  1109. _Marshall_VT_BSTR( *pbstrVal, stm );
  1110. break;
  1111. default:
  1112. PROPASSERT(!"Invalid type for PROPVARIANT marshalling");
  1113. break;
  1114. }
  1115. }
  1116. #endif //ifdef ENABLE_MARSHAL_VARIANT
  1117. #ifdef OLDSUMCATAPI
  1118. void
  1119. MarshallVariant(PSerStream &stm, PROPVARIANT &stgvar)
  1120. {
  1121. CBaseStorageVariant *pstgvar = (CBaseStorageVariant *)&stgvar;
  1122. pstgvar->Marshall(stm);
  1123. }
  1124. #endif //ifdef OLDSUMCATAPI
  1125. #ifdef ENABLE_DISPLAY_VARIANT
  1126. VOID
  1127. CBaseStorageVariant::DisplayVariant(
  1128. ULONG ulLevel,
  1129. USHORT CodePage) const
  1130. {
  1131. char *psz;
  1132. switch (vt)
  1133. {
  1134. case VT_ILLEGAL: psz = "ILLEGAL"; goto EmptyType;
  1135. case VT_EMPTY: psz = "EMPTY"; goto EmptyType;
  1136. case VT_NULL: psz = "NULL"; goto EmptyType;
  1137. BlobType:
  1138. EmptyType:
  1139. DEBTRACE((DBGFLAG "%s", psz));
  1140. break;
  1141. case VT_UI1:
  1142. AssertByteField(bVal); // VT_UI1
  1143. DEBTRACE((DBGFLAG "UI1=%hx", bVal));
  1144. break;
  1145. case VT_I2: psz = "I2"; goto ShortType;
  1146. case VT_UI2: psz = "UI2"; goto ShortType;
  1147. ShortType:
  1148. AssertShortField(iVal); // VT_I2
  1149. AssertShortField(uiVal); // VT_UI2
  1150. DEBTRACE((DBGFLAG "%s=%hx", psz, iVal));
  1151. break;
  1152. case VT_BOOL:
  1153. switch (boolVal)
  1154. {
  1155. case VARIANT_TRUE:
  1156. DEBTRACE((DBGFLAG "BOOL=TRUE"));
  1157. break;
  1158. case FALSE:
  1159. DEBTRACE((DBGFLAG "BOOL=FALSE"));
  1160. break;
  1161. default:
  1162. DEBTRACE((DBGFLAG "BOOL=%hx???", boolVal));
  1163. break;
  1164. }
  1165. break;
  1166. case VT_I4: psz = "I4"; goto LongType;
  1167. case VT_UI4: psz = "UI4"; goto LongType;
  1168. case VT_R4: psz = "R4"; goto LongType;
  1169. case VT_ERROR: psz = "ERROR"; goto LongType;
  1170. LongType:
  1171. AssertLongField(lVal); // VT_I4
  1172. AssertLongField(ulVal); // VT_UI4
  1173. AssertLongField(fltVal); // VT_R4
  1174. AssertLongField(scode); // VT_ERROR
  1175. DEBTRACE((DBGFLAG "%s=%x", psz, lVal));
  1176. break;
  1177. case VT_I8: psz = "I8"; goto LongLongType;
  1178. case VT_UI8: psz = "UI8"; goto LongLongType;
  1179. case VT_R8: psz = "R8"; goto LongLongType;
  1180. case VT_CY: psz = "CY"; goto LongLongType;
  1181. case VT_DATE: psz = "DATE"; goto LongLongType;
  1182. case VT_FILETIME: psz = "FILETIME"; goto LongLongType;
  1183. LongLongType:
  1184. AssertLongLongField(hVal); // VT_I8
  1185. AssertLongLongField(uhVal); // VT_UI8
  1186. AssertLongLongField(dblVal); // VT_R8
  1187. AssertLongLongField(cyVal); // VT_CY
  1188. AssertLongLongField(date); // VT_DATE
  1189. AssertLongLongField(filetime); // VT_FILETIME
  1190. DEBTRACE((DBGFLAG "%s=%x:%x", psz, hVal.HighPart, hVal.LowPart));
  1191. break;
  1192. case VT_CLSID: psz = "CLSID"; goto EmptyType;
  1193. case VT_BLOB: psz = "BLOB"; goto BlobType;
  1194. case VT_BLOB_OBJECT: psz = "BLOB_OBJECT"; goto BlobType;
  1195. case VT_CF: psz = "CF"; goto BlobType;
  1196. case VT_STREAM: psz = "STREAM"; goto TestUnicode;
  1197. case VT_STREAMED_OBJECT: psz = "STREAMED_OBJECT"; goto TestUnicode;
  1198. case VT_STORAGE: psz = "STORAGE"; goto TestUnicode;
  1199. case VT_STORED_OBJECT: psz = "STORED_OBJECT"; goto TestUnicode;
  1200. case VT_VERSIONED_STREAM: psz = "VERSIONED_STREAM"; goto TestUnicode;
  1201. case VT_LPSTR: psz = "LPSTR"; goto TestUnicode;
  1202. TestUnicode:
  1203. AssertStringField(pszVal); // VT_STREAM, VT_STREAMED_OBJECT
  1204. AssertStringField(pszVal); // VT_STORAGE, VT_STORED_OBJECT
  1205. AssertStringField(pszVal); // VT_LPSTR
  1206. DEBTRACE((
  1207. DBGFLAG
  1208. CodePage == CP_WINUNICODE? "%s=L'%ws'" : "%s='%s'",
  1209. psz,
  1210. pszVal));
  1211. break;
  1212. case VT_BSTR: psz = "BSTR"; goto PrintUnicode;
  1213. case VT_LPWSTR: psz = "LPWSTR"; goto PrintUnicode;
  1214. PrintUnicode:
  1215. AssertStringField(pwszVal); // VT_LPWSTR
  1216. AssertStringField(bstrVal); // VT_BSTR
  1217. DEBTRACE((DBGFLAG "%s=L'%ws'", psz, pwszVal));
  1218. break;
  1219. default:
  1220. if (vt & VT_VECTOR)
  1221. {
  1222. DEBTRACE((DBGFLAG "UNPRINTABLE VECTOR TYPE=%x(%u)", vt, vt));
  1223. }
  1224. else
  1225. {
  1226. DEBTRACE((DBGFLAG "UNKNOWN TYPE=%x(%u)", vt, vt));
  1227. }
  1228. break;
  1229. }
  1230. }
  1231. #endif //ifdef ENABLE_DISPLAY_VARIANT
  1232. #endif //ifdef WINNT