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.

1160 lines
30 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1992.
  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. //--------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #include "debtrace.hxx"
  17. #include <propset.h>
  18. #include <propvar.h>
  19. // These optionally-compiled directives tell the compiler & debugger
  20. // where the real file, rather than the copy, is located.
  21. #ifdef _ORIG_FILE_LOCATION_
  22. #if __LINE__ != 25
  23. #error File heading has change size
  24. #else
  25. #line 29 "\\nt\\private\\dcomidl\\stgvarb.cxx"
  26. #endif
  27. #endif
  28. #if DBGPROP
  29. BOOLEAN
  30. IsUnicodeString(WCHAR const *pwszname, ULONG cb)
  31. {
  32. if (cb != 0)
  33. {
  34. for (ULONG i = 0; pwszname[i] != L'\0'; i++)
  35. {
  36. }
  37. // If cb isn't MAXULONG we verify that cb is at least as
  38. // big as the string. We can't check for equality, because
  39. // there are some property sets in which the length field
  40. // for a string may include several zero padding bytes.
  41. PROPASSERT(cb == MAXULONG || (i + 1) * sizeof(WCHAR) <= cb);
  42. }
  43. return(TRUE);
  44. }
  45. BOOLEAN
  46. IsAnsiString(CHAR const *pszname, ULONG cb)
  47. {
  48. if (cb != 0)
  49. {
  50. // If the string is NULL, then it's not not an Ansi string,
  51. // so we'll call it an Ansi string.
  52. if( NULL == pszname )
  53. return( TRUE );
  54. for (ULONG i = 0; pszname[i] != '\0'; i++)
  55. {
  56. }
  57. // If cb isn't MAXULONG we verify that cb is at least as
  58. // big as the string. We can't check for equality, because
  59. // there are some property sets in which the length field
  60. // for a string may include several zero padding bytes.
  61. PROPASSERT(cb == MAXULONG || i + 1 <= cb);
  62. }
  63. return(TRUE);
  64. }
  65. #endif
  66. //+-------------------------------------------------------------------
  67. // Member: CBaseStorageVariant::UnmarshalledSize, public
  68. //
  69. // Synopsis: Unmarshalls a PROPVARIANT value serialized in a PDeSerStream.
  70. //
  71. // Arguments: [stm] -- serialized stream
  72. // [cb] -- size of *additional* data goes here. Size of
  73. // base PROPVARIANT not included.
  74. //
  75. // Returns: one of the following NTSTATUS values
  76. // STATUS_SUCCESS -- the call was successful.
  77. // STATUS_INVALID_PARAMETER -- unsupported type for unmarshalling.
  78. //
  79. // Notes: The size is computed assuming 4-byte granular allocations.
  80. //
  81. //--------------------------------------------------------------------
  82. #if defined(WINNT) && !defined(IPROPERTY_DLL)
  83. #ifdef KERNEL
  84. NTSTATUS
  85. CBaseStorageVariant::UnmarshalledSize(
  86. PDeSerStream& stm,
  87. ULONG &cb)
  88. {
  89. NTSTATUS Status = STATUS_SUCCESS;
  90. ULONG cElems = 0;
  91. ULONG i;
  92. cb = 0;
  93. VARTYPE vt = (VARTYPE) stm.GetULong();
  94. switch (vt)
  95. {
  96. case VT_EMPTY:
  97. case VT_NULL:
  98. case VT_UI1:
  99. case VT_I2:
  100. case VT_UI2:
  101. case VT_BOOL:
  102. case VT_I4:
  103. case VT_UI4:
  104. case VT_R4:
  105. case VT_ERROR:
  106. case VT_I8:
  107. case VT_UI8:
  108. case VT_R8:
  109. case VT_CY:
  110. case VT_DATE:
  111. case VT_FILETIME:
  112. break;
  113. case VT_CLSID:
  114. cb = sizeof(GUID);
  115. break;
  116. case VT_BLOB:
  117. case VT_BLOB_OBJECT:
  118. cb = stm.GetULong();
  119. break;
  120. case VT_CF:
  121. cb = stm.GetULong() + sizeof(CLIPDATA);
  122. break;
  123. case VT_STREAM:
  124. case VT_STREAMED_OBJECT:
  125. PROPASSERT("Serialization of stream not yet supported!");
  126. Status = STATUS_INVALID_PARAMETER;
  127. break;
  128. case VT_STORAGE:
  129. case VT_STORED_OBJECT:
  130. PROPASSERT("Serialization of storage not yet supported!");
  131. Status = STATUS_INVALID_PARAMETER;
  132. break;
  133. case VT_BSTR:
  134. cb = sizeof(ULONG) + stm.GetULong();
  135. break;
  136. case VT_LPSTR:
  137. cb = stm.GetULong();
  138. break;
  139. case VT_LPWSTR:
  140. cb = stm.GetULong() * sizeof(WCHAR);
  141. break;
  142. case VT_VECTOR | VT_UI1:
  143. cb = stm.GetULong();
  144. break;
  145. case VT_VECTOR | VT_I2:
  146. case VT_VECTOR | VT_UI2:
  147. case VT_VECTOR | VT_BOOL:
  148. cb = stm.GetULong() * sizeof(SHORT);
  149. break;
  150. case VT_VECTOR | VT_I4:
  151. case VT_VECTOR | VT_UI4:
  152. case VT_VECTOR | VT_R4:
  153. case VT_VECTOR | VT_ERROR:
  154. cb = stm.GetULong() * sizeof(LONG);
  155. break;
  156. case VT_VECTOR | VT_I8:
  157. case VT_VECTOR | VT_UI8:
  158. case VT_VECTOR | VT_R8:
  159. case VT_VECTOR | VT_CY:
  160. case VT_VECTOR | VT_DATE:
  161. case VT_VECTOR | VT_FILETIME:
  162. cb = stm.GetULong() * sizeof(LARGE_INTEGER);
  163. break;
  164. case VT_VECTOR | VT_CLSID:
  165. cb = stm.GetULong() * sizeof(GUID);
  166. break;
  167. case VT_VECTOR | VT_CF:
  168. cElems = stm.GetULong();
  169. cb = cElems * sizeof(CLIPDATA);
  170. break;
  171. case VT_VECTOR | VT_BSTR:
  172. cElems = stm.GetULong();
  173. cb = cElems * (sizeof(ULONG) + sizeof(LPSTR));
  174. break;
  175. case VT_VECTOR | VT_LPSTR:
  176. cElems = stm.GetULong();
  177. cb = cElems * sizeof(LPSTR);
  178. break;
  179. case VT_VECTOR | VT_LPWSTR:
  180. cElems = stm.GetULong();
  181. cb = cElems * sizeof(LPWSTR);
  182. break;
  183. case VT_VECTOR | VT_VARIANT:
  184. cElems = stm.GetULong();
  185. cb = cElems * sizeof(PROPVARIANT);
  186. break;
  187. default:
  188. PROPASSERT(!"Invalid type for PROPVARIANT marshalling");
  189. Status = STATUS_INVALID_PARAMETER;
  190. break;
  191. }
  192. cb = (cb + 3) & ~3;
  193. if (cElems == 0 || Status != STATUS_SUCCESS)
  194. {
  195. return(Status);
  196. }
  197. // We have a variant with variable sized data which requires
  198. // further unmarshalling.
  199. switch(vt)
  200. {
  201. case VT_VECTOR | VT_CF:
  202. for (i = 0; i < cElems; i++)
  203. {
  204. ULONG len = (stm.GetULong() + 3) & ~3;
  205. cb += len;
  206. stm.SkipChar(sizeof(ULONG) + len);
  207. }
  208. break;
  209. case VT_VECTOR | VT_BSTR:
  210. case VT_VECTOR | VT_LPSTR:
  211. for (i = 0; i < cElems; i++)
  212. {
  213. ULONG len = (stm.GetULong() + 3) & ~3;
  214. cb += len;
  215. stm.SkipChar(len);
  216. }
  217. break;
  218. case VT_VECTOR | VT_LPWSTR:
  219. for (i = 0; i < cElems; i++)
  220. {
  221. ULONG len = (stm.GetULong() * sizeof(WCHAR) + 3) & ~3;
  222. cb += len;
  223. stm.SkipWChar(len / sizeof(WCHAR));
  224. }
  225. break;
  226. case VT_VECTOR | VT_VARIANT:
  227. for (i = 0; i < cElems; i++)
  228. {
  229. ULONG cbElem = 0;
  230. Status = CBaseStorageVariant::UnmarshalledSize(stm, cbElem);
  231. if (Status != STATUS_SUCCESS)
  232. {
  233. break;
  234. }
  235. cb += cbElem;
  236. }
  237. break;
  238. }
  239. return(Status);
  240. }
  241. #endif //ifdef KERNEL
  242. //+-------------------------------------------------------------------
  243. // Member: CBaseStorageVariant::Unmarshall, public
  244. //
  245. // Synopsis: Unmarshalls a PROPVARIANT value serialized in a PDeSerStream.
  246. //
  247. // Arguments: [stm] -- serialized stream
  248. // [var] -- unmarshalled PROPVARIANT instance
  249. // [MemAlloc] -- memory allocator for unmarshalling
  250. //
  251. // Returns: one of the following NTSTATUS values
  252. // STATUS_SUCCESS -- the call was successful.
  253. // STATUS_INSUFFICIENT_RESOURCES -- out of memory.
  254. // STATUS_INVALID_PARAMETER -- unsupported type for unmarshalling.
  255. //--------------------------------------------------------------------
  256. NTSTATUS
  257. CBaseStorageVariant::Unmarshall(
  258. PDeSerStream& stm,
  259. PROPVARIANT& var,
  260. PMemoryAllocator &MemAlloc)
  261. {
  262. #if DBG
  263. switch (stm.PeekULong())
  264. {
  265. case VT_EMPTY:
  266. case VT_NULL:
  267. case VT_UI1:
  268. case VT_I2:
  269. case VT_UI2:
  270. case VT_BOOL:
  271. case VT_I4:
  272. case VT_UI4:
  273. case VT_R4:
  274. case VT_ERROR:
  275. case VT_I8:
  276. case VT_UI8:
  277. case VT_R8:
  278. case VT_CY:
  279. case VT_DATE:
  280. case VT_FILETIME:
  281. case VT_CLSID:
  282. case VT_BLOB:
  283. case VT_BLOB_OBJECT:
  284. case VT_CF:
  285. case VT_STREAM:
  286. case VT_STREAMED_OBJECT:
  287. case VT_STORAGE:
  288. case VT_STORED_OBJECT:
  289. case VT_BSTR:
  290. case VT_LPSTR:
  291. case VT_LPWSTR:
  292. case VT_VECTOR | VT_UI1:
  293. case VT_VECTOR | VT_I2:
  294. case VT_VECTOR | VT_UI2:
  295. case VT_VECTOR | VT_BOOL:
  296. case VT_VECTOR | VT_I4:
  297. case VT_VECTOR | VT_UI4:
  298. case VT_VECTOR | VT_R4:
  299. case VT_VECTOR | VT_ERROR:
  300. case VT_VECTOR | VT_I8:
  301. case VT_VECTOR | VT_UI8:
  302. case VT_VECTOR | VT_R8:
  303. case VT_VECTOR | VT_CY:
  304. case VT_VECTOR | VT_DATE:
  305. case VT_VECTOR | VT_FILETIME:
  306. case VT_VECTOR | VT_CLSID:
  307. case VT_VECTOR | VT_CF:
  308. case VT_VECTOR | VT_BSTR:
  309. case VT_VECTOR | VT_LPSTR:
  310. case VT_VECTOR | VT_LPWSTR:
  311. case VT_VECTOR | VT_VARIANT:
  312. break;
  313. default:
  314. PROPASSERT(!"Invalid type (peek) for PROPVARIANT unmarshalling");
  315. break;
  316. }
  317. #endif
  318. NTSTATUS Status = STATUS_SUCCESS;
  319. ULONG cbAlloc = 0;
  320. VOID **ppv = NULL;
  321. BOOLEAN fZero = FALSE;
  322. // Zero the entire variant data structure before assembling it together.
  323. memset(&var, 0, sizeof(PROPVARIANT));
  324. var.vt = (VARTYPE) stm.GetULong();
  325. switch (var.vt)
  326. {
  327. case VT_EMPTY:
  328. case VT_NULL:
  329. break;
  330. case VT_UI1:
  331. var.bVal = stm.GetByte();
  332. break;
  333. case VT_I2:
  334. case VT_UI2:
  335. case VT_BOOL:
  336. var.iVal = stm.GetUShort();
  337. break;
  338. case VT_I4:
  339. case VT_UI4:
  340. case VT_R4:
  341. case VT_ERROR:
  342. var.lVal = stm.GetULong();
  343. break;
  344. case VT_I8:
  345. case VT_UI8:
  346. case VT_R8:
  347. case VT_CY:
  348. case VT_DATE:
  349. case VT_FILETIME:
  350. stm.GetBlob((BYTE *)&var.hVal, sizeof(LARGE_INTEGER));
  351. break;
  352. case VT_CLSID:
  353. cbAlloc = sizeof(GUID);
  354. ppv = (void **)&var.puuid;
  355. break;
  356. case VT_BLOB:
  357. case VT_BLOB_OBJECT:
  358. var.blob.cbSize = stm.GetULong();
  359. cbAlloc = var.blob.cbSize;
  360. ppv = (void **)&var.blob.pBlobData;
  361. break;
  362. case VT_CF:
  363. var.pclipdata = (CLIPDATA *) MemAlloc.Allocate(sizeof(*var.pclipdata));
  364. if (var.pclipdata == NULL)
  365. {
  366. Status = STATUS_INSUFFICIENT_RESOURCES;
  367. break;
  368. }
  369. var.pclipdata->cbSize = stm.GetULong();
  370. cbAlloc = CBPCLIPDATA(*var.pclipdata);
  371. var.pclipdata->ulClipFmt = stm.GetULong();
  372. ppv = (void **) &var.pclipdata->pClipData;
  373. break;
  374. case VT_STREAM:
  375. case VT_STREAMED_OBJECT:
  376. PROPASSERT("Serialization of stream not yet supported!");
  377. Status = STATUS_INVALID_PARAMETER;
  378. break;
  379. case VT_STORAGE:
  380. case VT_STORED_OBJECT:
  381. PROPASSERT("Serialization of storage not yet supported!");
  382. Status = STATUS_INVALID_PARAMETER;
  383. break;
  384. case VT_BSTR:
  385. cbAlloc = sizeof(ULONG) + stm.GetULong();
  386. ppv = (void **)&var.bstrVal;
  387. break;
  388. case VT_LPSTR:
  389. cbAlloc = stm.GetULong();
  390. ppv = (void **)&var.pszVal;
  391. break;
  392. case VT_LPWSTR:
  393. cbAlloc = stm.GetULong() * sizeof(WCHAR);
  394. ppv = (void **)&var.pwszVal;
  395. break;
  396. case VT_VECTOR | VT_UI1:
  397. var.caub.cElems = stm.GetULong();
  398. cbAlloc = var.caub.cElems * sizeof(BYTE);
  399. ppv = (void **)&var.caub.pElems;
  400. break;
  401. case VT_VECTOR | VT_I2:
  402. case VT_VECTOR | VT_UI2:
  403. case VT_VECTOR | VT_BOOL:
  404. var.cai.cElems = stm.GetULong();
  405. cbAlloc = var.cai.cElems * sizeof(SHORT);
  406. ppv = (void **)&var.cai.pElems;
  407. break;
  408. case VT_VECTOR | VT_I4:
  409. case VT_VECTOR | VT_UI4:
  410. case VT_VECTOR | VT_R4:
  411. case VT_VECTOR | VT_ERROR:
  412. var.cal.cElems = stm.GetULong();
  413. cbAlloc = var.cal.cElems * sizeof(LONG);
  414. ppv = (void **)&var.cal.pElems;
  415. break;
  416. case VT_VECTOR | VT_I8:
  417. case VT_VECTOR | VT_UI8:
  418. case VT_VECTOR | VT_R8:
  419. case VT_VECTOR | VT_CY:
  420. case VT_VECTOR | VT_DATE:
  421. case VT_VECTOR | VT_FILETIME:
  422. var.cah.cElems = stm.GetULong();
  423. cbAlloc = var.cah.cElems * sizeof(LARGE_INTEGER);
  424. ppv = (void **)&var.cah.pElems;
  425. break;
  426. case VT_VECTOR | VT_CLSID:
  427. var.cauuid.cElems = stm.GetULong();
  428. cbAlloc = var.cauuid.cElems * sizeof(GUID);
  429. ppv = (void **)&var.cauuid.pElems;
  430. break;
  431. case VT_VECTOR | VT_CF:
  432. var.caclipdata.cElems = stm.GetULong();
  433. cbAlloc = var.caclipdata.cElems * sizeof(CLIPDATA);
  434. ppv = (void **)&var.caclipdata.pElems;
  435. fZero = TRUE; // set all pClipData pointers to NULL
  436. break;
  437. case VT_VECTOR | VT_BSTR:
  438. var.cabstr.cElems = stm.GetULong();
  439. cbAlloc = var.cabstr.cElems * sizeof(BSTR);
  440. ppv = (void **)&var.cabstr.pElems;
  441. fZero = TRUE; // set all BSTR pointers to NULL
  442. break;
  443. case VT_VECTOR | VT_LPSTR:
  444. var.calpstr.cElems = stm.GetULong();
  445. cbAlloc = var.calpstr.cElems * sizeof(LPSTR);
  446. ppv = (void **)&var.calpstr.pElems;
  447. fZero = TRUE; // set all LPSTR pointers to NULL
  448. break;
  449. case VT_VECTOR | VT_LPWSTR:
  450. var.calpwstr.cElems = stm.GetULong();
  451. cbAlloc = var.calpwstr.cElems * sizeof(LPWSTR);
  452. ppv = (void **)&var.calpwstr.pElems;
  453. fZero = TRUE; // set all LPWSTR pointers to NULL
  454. break;
  455. case VT_VECTOR | VT_VARIANT:
  456. var.capropvar.cElems = stm.GetULong();
  457. cbAlloc = var.capropvar.cElems * sizeof(PROPVARIANT);
  458. ppv = (void **)&var.capropvar.pElems;
  459. fZero = TRUE; // set all vt pointers to VT_EMPTY
  460. PROPASSERT(VT_EMPTY == 0);
  461. break;
  462. default:
  463. PROPASSERT(!"Invalid type for PROPVARIANT unmarshalling");
  464. Status = STATUS_INVALID_PARAMETER;
  465. break;
  466. }
  467. if (cbAlloc == 0 || Status != STATUS_SUCCESS)
  468. {
  469. // No further work need be done. The Ummarshalling is complete,
  470. // i.e., fixed size variant or no variable length data.
  471. if (ppv != NULL)
  472. {
  473. *ppv = NULL;
  474. }
  475. return(Status);
  476. }
  477. // Allocate the desired amount of memory and continue unmarshalling
  478. // if allocation was successfull.
  479. ULONG i;
  480. PROPASSERT(ppv != NULL);
  481. *ppv = MemAlloc.Allocate(cbAlloc);
  482. if (*ppv == NULL)
  483. {
  484. return(STATUS_INSUFFICIENT_RESOURCES);
  485. }
  486. if (fZero)
  487. {
  488. memset(*ppv, 0, cbAlloc);
  489. }
  490. // We have a variant with variable sized data which requires
  491. // further unmarshalling.
  492. switch(var.vt)
  493. {
  494. case VT_CLSID:
  495. stm.GetBlob((BYTE *)var.puuid, sizeof(CLSID));
  496. break;
  497. case VT_BLOB:
  498. case VT_BLOB_OBJECT:
  499. stm.GetBlob(var.blob.pBlobData, var.blob.cbSize);
  500. break;
  501. case VT_CF:
  502. stm.GetBlob(var.pclipdata->pClipData, CBPCLIPDATA(*var.pclipdata));
  503. break;
  504. case VT_BSTR:
  505. cbAlloc -= sizeof(ULONG);
  506. *(ULONG *) var.bstrVal = cbAlloc - sizeof (OLECHAR);
  507. var.bstrVal = (BSTR) ((ULONG *) var.bstrVal + 1);
  508. stm.GetChar((char *) var.bstrVal, cbAlloc);
  509. break;
  510. case VT_LPSTR:
  511. stm.GetChar(var.pszVal, cbAlloc);
  512. break;
  513. case VT_LPWSTR:
  514. stm.GetWChar(var.pwszVal, cbAlloc / sizeof(WCHAR));
  515. break;
  516. case VT_VECTOR | VT_UI1:
  517. for (i = 0; i < var.caub.cElems; i++)
  518. {
  519. var.caub.pElems[i] = stm.GetByte();
  520. }
  521. break;
  522. case VT_VECTOR | VT_I2:
  523. case VT_VECTOR | VT_UI2:
  524. case VT_VECTOR | VT_BOOL:
  525. for (i = 0; i < var.cai.cElems; i++)
  526. {
  527. var.cai.pElems[i] = stm.GetUShort();
  528. }
  529. break;
  530. case VT_VECTOR | VT_I4:
  531. case VT_VECTOR | VT_UI4:
  532. case VT_VECTOR | VT_R4:
  533. case VT_VECTOR | VT_ERROR:
  534. for (i = 0; i < var.cal.cElems; i++)
  535. {
  536. var.cal.pElems[i] = stm.GetULong();
  537. }
  538. break;
  539. case VT_VECTOR | VT_I8:
  540. case VT_VECTOR | VT_UI8:
  541. case VT_VECTOR | VT_R8:
  542. case VT_VECTOR | VT_CY:
  543. case VT_VECTOR | VT_DATE:
  544. case VT_VECTOR | VT_FILETIME:
  545. for (i = 0; i < var.cah.cElems; i++)
  546. {
  547. stm.GetBlob((BYTE *)&var.cah.pElems[i], sizeof(LARGE_INTEGER));
  548. }
  549. break;
  550. case VT_VECTOR | VT_CLSID:
  551. for (i = 0; i < var.cauuid.cElems; i++)
  552. {
  553. stm.GetBlob((BYTE *)&var.cauuid.pElems[i], sizeof(CLSID));
  554. }
  555. break;
  556. case VT_VECTOR | VT_CF:
  557. for (i = 0; i < var.caclipdata.cElems; i++)
  558. {
  559. PROPASSERT(var.caclipdata.pElems[i].pClipData == NULL);
  560. var.caclipdata.pElems[i].cbSize = stm.GetULong();
  561. cbAlloc = CBPCLIPDATA(var.caclipdata.pElems[i]);
  562. var.caclipdata.pElems[i].ulClipFmt = stm.GetULong();
  563. if (cbAlloc == 0)
  564. {
  565. Status = STATUS_INVALID_PARAMETER;
  566. break;
  567. }
  568. var.caclipdata.pElems[i].pClipData =
  569. (BYTE *) MemAlloc.Allocate(cbAlloc);
  570. if (var.caclipdata.pElems[i].pClipData == NULL)
  571. {
  572. Status = STATUS_INSUFFICIENT_RESOURCES;
  573. break;
  574. }
  575. stm.GetBlob(var.caclipdata.pElems[i].pClipData, cbAlloc);
  576. }
  577. break;
  578. case VT_VECTOR | VT_BSTR:
  579. for (i = 0; i < var.cabstr.cElems; i++)
  580. {
  581. PROPASSERT(var.cabstr.pElems[i] == NULL);
  582. cbAlloc = stm.GetULong();
  583. if (cbAlloc == 0)
  584. {
  585. Status = STATUS_INVALID_PARAMETER;
  586. break;
  587. }
  588. var.cabstr.pElems[i] =
  589. (BSTR) MemAlloc.Allocate(sizeof(ULONG) + cbAlloc);
  590. if (var.cabstr.pElems[i] == NULL)
  591. {
  592. Status = STATUS_INSUFFICIENT_RESOURCES;
  593. break;
  594. }
  595. *(ULONG *) var.cabstr.pElems[i] = cbAlloc - sizeof (OLECHAR);
  596. var.cabstr.pElems[i] = (BSTR) ((ULONG *) var.cabstr.pElems[i] + 1);
  597. stm.GetChar((char *) var.cabstr.pElems[i], cbAlloc);
  598. }
  599. break;
  600. case VT_VECTOR | VT_LPSTR:
  601. for (i = 0; i < var.calpstr.cElems; i++)
  602. {
  603. PROPASSERT(var.calpstr.pElems[i] == NULL);
  604. cbAlloc = stm.GetULong();
  605. if (cbAlloc == 0)
  606. {
  607. Status = STATUS_INVALID_PARAMETER;
  608. break;
  609. }
  610. var.calpstr.pElems[i] = (LPSTR) MemAlloc.Allocate(cbAlloc);
  611. if (var.calpstr.pElems[i] == NULL)
  612. {
  613. Status = STATUS_INSUFFICIENT_RESOURCES;
  614. break;
  615. }
  616. stm.GetChar(var.calpstr.pElems[i], cbAlloc);
  617. }
  618. break;
  619. case VT_VECTOR | VT_LPWSTR:
  620. for (i = 0; i < var.calpwstr.cElems; i++)
  621. {
  622. PROPASSERT(var.calpwstr.pElems[i] == NULL);
  623. cbAlloc = stm.GetULong(); // actually, a count of WCHARs
  624. if (cbAlloc == 0)
  625. {
  626. Status = STATUS_INVALID_PARAMETER;
  627. break;
  628. }
  629. var.calpwstr.pElems[i] = (WCHAR *) MemAlloc.Allocate(cbAlloc * sizeof(WCHAR));
  630. if (var.calpwstr.pElems[i] == NULL)
  631. {
  632. Status = STATUS_INSUFFICIENT_RESOURCES;
  633. break;
  634. }
  635. stm.GetWChar(var.calpwstr.pElems[i], cbAlloc);
  636. }
  637. break;
  638. case VT_VECTOR | VT_VARIANT:
  639. for (i = 0; i < var.capropvar.cElems; i++)
  640. {
  641. PROPASSERT(var.capropvar.pElems[i].vt == VT_EMPTY);
  642. Status = CBaseStorageVariant::Unmarshall(
  643. stm,
  644. var.capropvar.pElems[i],
  645. MemAlloc);
  646. if (Status != STATUS_SUCCESS)
  647. {
  648. break;
  649. }
  650. }
  651. break;
  652. }
  653. return(Status);
  654. }
  655. #ifdef ENABLE_MARSHAL_VARIANT
  656. inline void
  657. _Marshall_VT_CF(CLIPDATA *pclipdata, PSerStream &stm)
  658. {
  659. CLIPDATA clipdata;
  660. clipdata.cbSize = 0;
  661. clipdata.ulClipFmt = 0;
  662. if (pclipdata != NULL)
  663. {
  664. clipdata.cbSize = pclipdata->cbSize;
  665. clipdata.ulClipFmt = pclipdata->ulClipFmt;
  666. if (pclipdata->pClipData == NULL)
  667. {
  668. clipdata.cbSize = 0;
  669. }
  670. }
  671. stm.PutULong(clipdata.cbSize);
  672. stm.PutULong(clipdata.ulClipFmt);
  673. if (clipdata.cbSize)
  674. {
  675. stm.PutBlob((BYTE *) pclipdata->pClipData, CBPCLIPDATA(clipdata));
  676. }
  677. }
  678. #endif //ifdef ENABLE_MARSHAL_VARIANT
  679. #ifdef ENABLE_MARSHAL_VARIANT
  680. inline void
  681. _Marshall_VT_BSTR(BSTR bstrVal, PSerStream &stm)
  682. {
  683. if (bstrVal != NULL)
  684. {
  685. ULONG cc = BSTRLEN(bstrVal) + sizeof (OLECHAR);
  686. stm.PutULong(cc);
  687. stm.PutChar((char *) bstrVal, cc);
  688. }
  689. else
  690. {
  691. stm.PutULong(0);
  692. }
  693. }
  694. #endif //ifdef ENABLE_MARSHAL_VARIANT
  695. #ifdef ENABLE_MARSHAL_VARIANT
  696. inline void
  697. _Marshall_VT_LPSTR(CHAR *pszVal, PSerStream &stm)
  698. {
  699. if (pszVal != NULL)
  700. {
  701. // Include NULL because OLE 2.0 spec says so.
  702. ULONG cc = strlen(pszVal) + 1;
  703. stm.PutULong(cc);
  704. stm.PutChar(pszVal, cc);
  705. PROPASSERT(IsAnsiString(pszVal, cc));
  706. }
  707. else
  708. {
  709. stm.PutULong(0);
  710. }
  711. }
  712. #endif //ifdef ENABLE_MARSHAL_VARIANT
  713. #ifdef ENABLE_MARSHAL_VARIANT
  714. inline void
  715. _Marshall_VT_LPWSTR(LPWSTR pwszVal, PSerStream &stm)
  716. {
  717. if (pwszVal != NULL)
  718. {
  719. // Include NULL because OLE 2.0 spec says so.
  720. ULONG cc = Prop_wcslen(pwszVal) + 1;
  721. PROPASSERT(IsUnicodeString(pwszVal, cc * sizeof(WCHAR)));
  722. stm.PutULong(cc);
  723. stm.PutWChar(pwszVal, cc);
  724. }
  725. else
  726. {
  727. stm.PutULong(0);
  728. }
  729. }
  730. #endif //ifdef ENABLE_MARSHAL_VARIANT
  731. #ifdef ENABLE_MARSHAL_VARIANT
  732. void
  733. CBaseStorageVariant::Marshall(PSerStream & stm) const
  734. {
  735. ULONG i;
  736. stm.PutULong(vt);
  737. switch (vt)
  738. {
  739. case VT_EMPTY:
  740. case VT_NULL:
  741. break;
  742. case VT_UI1:
  743. stm.PutByte(bVal);
  744. break;
  745. case VT_I2:
  746. case VT_UI2:
  747. case VT_BOOL:
  748. stm.PutUShort(iVal);
  749. break;
  750. case VT_I4:
  751. case VT_UI4:
  752. case VT_R4:
  753. case VT_ERROR:
  754. stm.PutULong(lVal);
  755. break;
  756. case VT_I8:
  757. case VT_UI8:
  758. case VT_R8:
  759. case VT_CY:
  760. case VT_DATE:
  761. case VT_FILETIME:
  762. stm.PutBlob((BYTE *) &hVal, sizeof(hVal));
  763. break;
  764. case VT_CLSID:
  765. stm.PutBlob((BYTE *)puuid, sizeof(CLSID));
  766. break;
  767. case VT_BLOB:
  768. case VT_BLOB_OBJECT:
  769. stm.PutULong(blob.cbSize);
  770. stm.PutBlob(blob.pBlobData, blob.cbSize);
  771. break;
  772. case VT_CF:
  773. _Marshall_VT_CF(pclipdata, stm);
  774. break;
  775. case VT_STREAM:
  776. case VT_STREAMED_OBJECT:
  777. PROPASSERT("Serialization of stream not yet supported!");
  778. break;
  779. case VT_STORAGE:
  780. case VT_STORED_OBJECT:
  781. PROPASSERT("Serialization of storage not yet supported!");
  782. break;
  783. case VT_BSTR:
  784. _Marshall_VT_BSTR(bstrVal, stm);
  785. break;
  786. case VT_LPSTR:
  787. _Marshall_VT_LPSTR(pszVal, stm);
  788. break;
  789. case VT_LPWSTR:
  790. _Marshall_VT_LPWSTR(pwszVal, stm);
  791. break;
  792. case VT_VECTOR | VT_UI1:
  793. stm.PutULong(caub.cElems);
  794. for (i = 0; i < caub.cElems; i++)
  795. {
  796. stm.PutByte(caub.pElems[i]);
  797. }
  798. break;
  799. case VT_VECTOR | VT_I2:
  800. case VT_VECTOR | VT_UI2:
  801. case VT_VECTOR | VT_BOOL:
  802. stm.PutULong(cai.cElems);
  803. for (i = 0; i < cai.cElems; i++)
  804. {
  805. stm.PutUShort(cai.pElems[i]);
  806. }
  807. break;
  808. case VT_VECTOR | VT_I4:
  809. case VT_VECTOR | VT_UI4:
  810. case VT_VECTOR | VT_R4:
  811. case VT_VECTOR | VT_ERROR:
  812. stm.PutULong(cal.cElems);
  813. for (i = 0; i < cal.cElems; i++)
  814. {
  815. stm.PutULong(cal.pElems[i]);
  816. }
  817. break;
  818. case VT_VECTOR | VT_I8:
  819. case VT_VECTOR | VT_UI8:
  820. case VT_VECTOR | VT_R8:
  821. case VT_VECTOR | VT_CY:
  822. case VT_VECTOR | VT_DATE:
  823. case VT_VECTOR | VT_FILETIME:
  824. stm.PutULong(cah.cElems);
  825. for (i = 0; i < cah.cElems; i++)
  826. {
  827. stm.PutBlob((BYTE *) &cah.pElems[i], sizeof(LARGE_INTEGER));
  828. }
  829. break;
  830. case VT_VECTOR | VT_CLSID:
  831. stm.PutULong(cauuid.cElems);
  832. for (i = 0; i < cauuid.cElems; i++)
  833. {
  834. stm.PutBlob((BYTE *)&cauuid.pElems[i], sizeof(CLSID));
  835. }
  836. break;
  837. case VT_VECTOR | VT_CF:
  838. stm.PutULong(caclipdata.cElems);
  839. for (i = 0; i < caclipdata.cElems; i++)
  840. {
  841. _Marshall_VT_CF(&caclipdata.pElems[i], stm);
  842. }
  843. break;
  844. break;
  845. case VT_VECTOR | VT_BSTR:
  846. stm.PutULong(cabstr.cElems);
  847. for (i = 0; i < cabstr.cElems; i++)
  848. {
  849. _Marshall_VT_BSTR(cabstr.pElems[i], stm);
  850. }
  851. break;
  852. case VT_VECTOR | VT_LPSTR:
  853. stm.PutULong(calpstr.cElems);
  854. for (i = 0; i < calpstr.cElems; i++)
  855. {
  856. _Marshall_VT_LPSTR(calpstr.pElems[i], stm);
  857. }
  858. break;
  859. case VT_VECTOR | VT_LPWSTR:
  860. stm.PutULong(calpwstr.cElems);
  861. for (i = 0; i < calpwstr.cElems; i++)
  862. {
  863. _Marshall_VT_LPWSTR(calpwstr.pElems[i], stm);
  864. }
  865. break;
  866. case VT_VECTOR | VT_VARIANT:
  867. stm.PutULong(capropvar.cElems);
  868. for (i = 0; i < capropvar.cElems; i++)
  869. {
  870. ((CBaseStorageVariant *) &capropvar.pElems[i])->Marshall(stm);
  871. }
  872. break;
  873. default:
  874. PROPASSERT(!"Invalid type for PROPVARIANT marshalling");
  875. break;
  876. }
  877. }
  878. #endif //ifdef ENABLE_MARSHAL_VARIANT
  879. #ifdef OLDSUMCATAPI
  880. void
  881. MarshallVariant(PSerStream &stm, PROPVARIANT &stgvar)
  882. {
  883. CBaseStorageVariant *pstgvar = (CBaseStorageVariant *)&stgvar;
  884. pstgvar->Marshall(stm);
  885. }
  886. #endif //ifdef OLDSUMCATAPI
  887. #ifdef ENABLE_DISPLAY_VARIANT
  888. VOID
  889. CBaseStorageVariant::DisplayVariant(
  890. ULONG ulLevel,
  891. USHORT CodePage) const
  892. {
  893. char *psz;
  894. switch (vt)
  895. {
  896. case VT_ILLEGAL: psz = "ILLEGAL"; goto EmptyType;
  897. case VT_EMPTY: psz = "EMPTY"; goto EmptyType;
  898. case VT_NULL: psz = "NULL"; goto EmptyType;
  899. BlobType:
  900. EmptyType:
  901. DEBTRACE((DBGFLAG "%s", psz));
  902. break;
  903. case VT_UI1:
  904. AssertByteField(bVal); // VT_UI1
  905. DEBTRACE((DBGFLAG "UI1=%hx", bVal));
  906. break;
  907. case VT_I2: psz = "I2"; goto ShortType;
  908. case VT_UI2: psz = "UI2"; goto ShortType;
  909. ShortType:
  910. AssertShortField(iVal); // VT_I2
  911. AssertShortField(uiVal); // VT_UI2
  912. DEBTRACE((DBGFLAG "%s=%hx", psz, iVal));
  913. break;
  914. case VT_BOOL:
  915. switch (boolVal)
  916. {
  917. case VARIANT_TRUE:
  918. DEBTRACE((DBGFLAG "BOOL=TRUE"));
  919. break;
  920. case FALSE:
  921. DEBTRACE((DBGFLAG "BOOL=FALSE"));
  922. break;
  923. default:
  924. DEBTRACE((DBGFLAG "BOOL=%hx???", boolVal));
  925. break;
  926. }
  927. break;
  928. case VT_I4: psz = "I4"; goto LongType;
  929. case VT_UI4: psz = "UI4"; goto LongType;
  930. case VT_R4: psz = "R4"; goto LongType;
  931. case VT_ERROR: psz = "ERROR"; goto LongType;
  932. LongType:
  933. AssertLongField(lVal); // VT_I4
  934. AssertLongField(ulVal); // VT_UI4
  935. AssertLongField(fltVal); // VT_R4
  936. AssertLongField(scode); // VT_ERROR
  937. DEBTRACE((DBGFLAG "%s=%x", psz, lVal));
  938. break;
  939. case VT_I8: psz = "I8"; goto LongLongType;
  940. case VT_UI8: psz = "UI8"; goto LongLongType;
  941. case VT_R8: psz = "R8"; goto LongLongType;
  942. case VT_CY: psz = "CY"; goto LongLongType;
  943. case VT_DATE: psz = "DATE"; goto LongLongType;
  944. case VT_FILETIME: psz = "FILETIME"; goto LongLongType;
  945. LongLongType:
  946. AssertLongLongField(hVal); // VT_I8
  947. AssertLongLongField(uhVal); // VT_UI8
  948. AssertLongLongField(dblVal); // VT_R8
  949. AssertLongLongField(cyVal); // VT_CY
  950. AssertLongLongField(date); // VT_DATE
  951. AssertLongLongField(filetime); // VT_FILETIME
  952. DEBTRACE((DBGFLAG "%s=%x:%x", psz, hVal.HighPart, hVal.LowPart));
  953. break;
  954. case VT_CLSID: psz = "CLSID"; goto EmptyType;
  955. case VT_BLOB: psz = "BLOB"; goto BlobType;
  956. case VT_BLOB_OBJECT: psz = "BLOB_OBJECT"; goto BlobType;
  957. case VT_CF: psz = "CF"; goto BlobType;
  958. case VT_STREAM: psz = "STREAM"; goto TestUnicode;
  959. case VT_STREAMED_OBJECT: psz = "STREAMED_OBJECT"; goto TestUnicode;
  960. case VT_STORAGE: psz = "STORAGE"; goto TestUnicode;
  961. case VT_STORED_OBJECT: psz = "STORED_OBJECT"; goto TestUnicode;
  962. case VT_LPSTR: psz = "LPSTR"; goto TestUnicode;
  963. TestUnicode:
  964. AssertStringField(pszVal); // VT_STREAM, VT_STREAMED_OBJECT
  965. AssertStringField(pszVal); // VT_STORAGE, VT_STORED_OBJECT
  966. AssertStringField(pszVal); // VT_LPSTR
  967. DEBTRACE((
  968. DBGFLAG
  969. CodePage == CP_WINUNICODE? "%s=L'%ws'" : "%s='%s'",
  970. psz,
  971. pszVal));
  972. break;
  973. case VT_BSTR: psz = "BSTR"; goto PrintUnicode;
  974. case VT_LPWSTR: psz = "LPWSTR"; goto PrintUnicode;
  975. PrintUnicode:
  976. AssertStringField(pwszVal); // VT_LPWSTR
  977. AssertStringField(bstrVal); // VT_BSTR
  978. DEBTRACE((DBGFLAG "%s=L'%ws'", psz, pwszVal));
  979. break;
  980. default:
  981. if (vt & VT_VECTOR)
  982. {
  983. DEBTRACE((DBGFLAG "UNPRINTABLE VECTOR TYPE=%x(%u)", vt, vt));
  984. }
  985. else
  986. {
  987. DEBTRACE((DBGFLAG "UNKNOWN TYPE=%x(%u)", vt, vt));
  988. }
  989. break;
  990. }
  991. }
  992. #endif //ifdef ENABLE_DISPLAY_VARIANT
  993. #endif //ifdef WINNT