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.

1482 lines
47 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1993.
  5. //
  6. // File: utils.cxx
  7. //
  8. // Contents: Utility classes/functions for property implementation.
  9. //
  10. // Classes: CPropSetName -- wraps buffer and conversion of fmtids
  11. // CStackBuffer -- utility class that allows a small number
  12. // of items be on stack, but more be on heap.
  13. //
  14. // Functions: PropVariantClear
  15. // FreePropVariantArray
  16. // AllocAndCopy
  17. // PropVariantCopy
  18. //
  19. // History: 1-Mar-95 BillMo Created.
  20. // 22-Feb-96 MikeHill Removed an over-active assert.
  21. // 22-May-96 MikeHill Handle "unmappable character" in
  22. // NtStatusToScode.
  23. // 12-Jun-96 MikeHill - Added PropSysAllocString and PropSysFreeString.
  24. // - Added VT_I1 support (under ifdef)
  25. // - Fix PropVarCopy where the input VT_CF
  26. // has a zero size but a non-NULL pClipData.
  27. // 29-Jul-96 MikeHill - PropSet names: WCHAR => OLECHAR
  28. // - Bug in PropVarCopy of 0-length VT_BLOB
  29. // - Support VT_BSTR_BLOB types (used in IProp.dll)
  30. // 10-Mar-98 MikeHIll Support Variant types in PropVariantCopy/Clear
  31. // 06-May-98 MikeHill - Use CoTaskMem rather than new/delete.
  32. // - Removed unused PropSysAlloc/FreeString.
  33. // - Support VT_VECTOR|VT_I1.
  34. // - Removed UnicodeCallouts support.
  35. // - Use oleaut32.dll wrappers, don't call directly.
  36. // 5/18/98 MikeHill
  37. // - Moved IsOriginalPropVariantType from utils.hxx.
  38. // - Added IsVariantType.
  39. //
  40. // Notes:
  41. //
  42. // Codework:
  43. //
  44. //--------------------------------------------------------------------------
  45. #include <pch.cxx>
  46. #include <privoa.h> // Private OleAut32 wrappers
  47. #ifdef _MAC_NODOC
  48. ASSERTDATA // File-specific data for FnAssert
  49. #endif
  50. //+-------------------------------------------------------------------
  51. //
  52. // Member: CPropSetName::CPropSetName
  53. //
  54. // Synopsis: Initialize internal buffer with converted FMTID
  55. //
  56. // Arguments: [rfmtid] -- FMTID to convert
  57. //
  58. //--------------------------------------------------------------------
  59. CPropSetName::CPropSetName(REFFMTID rfmtid)
  60. {
  61. PrGuidToPropertySetName(&rfmtid, _oszName);
  62. }
  63. //+-------------------------------------------------------------------
  64. //
  65. // Member: CStackBuffer::Init
  66. //
  67. // Synopsis: Determine whether the class derived from this one
  68. // needs to have additional buffer allocated on the
  69. // heap and allocate it if neccessary. Otherwise, if
  70. // there is space, use the internal buffer in the
  71. // derived class.
  72. //
  73. // Arguments: [cElements] -- the number of elements required.
  74. //
  75. // Returns: S_OK if buffer available
  76. // STG_E_INSUFFICIENTMEMORY if stack buffer was not
  77. // big enough AND heap allocation failed.
  78. //
  79. // Notes: To be called directly by client after the derived
  80. // classes constructor initialized CStackBuffer.
  81. //
  82. //--------------------------------------------------------------------
  83. HRESULT CStackBuffer::Init(ULONG cElements)
  84. {
  85. if (cElements > _cElements)
  86. {
  87. _pbHeapBuf = reinterpret_cast<BYTE*>( CoTaskMemAlloc( cElements * _cbElement ));
  88. if (_pbHeapBuf == NULL)
  89. {
  90. return(STG_E_INSUFFICIENTMEMORY);
  91. }
  92. _cElements = cElements;
  93. }
  94. memset( _pbHeapBuf, 0, _cElements * _cbElement );
  95. return(S_OK);
  96. }
  97. //+-------------------------------------------------------------------------
  98. //
  99. // Function: PropVariantClear
  100. //
  101. // Synopsis: Deallocates the members of the PROPVARIANT that require
  102. // deallocation.
  103. //
  104. // Arguments: [pvarg] - variant to clear
  105. //
  106. // Returns: S_OK if successful,
  107. // STG_E_INVALIDPARAMETER if any part of the variant has
  108. // an unknown vt type. (In this case, ALL the elements
  109. // that can be freed, will be freed.)
  110. //
  111. // Modifies: [pvarg] - the variant is left with vt = VT_EMPTY
  112. //
  113. //--------------------------------------------------------------------------
  114. STDAPI PropVariantClear(PROPVARIANT *pvarg)
  115. {
  116. ULONG l;
  117. HRESULT hr = S_OK;
  118. // Is there really anything to clear?
  119. if (pvarg == NULL)
  120. return(hr);
  121. // Validate the input
  122. VDATEPTROUT( pvarg, PROPVARIANT );
  123. switch (pvarg->vt)
  124. {
  125. case VT_EMPTY:
  126. case VT_NULL:
  127. case VT_ILLEGAL:
  128. case VT_I1:
  129. case VT_UI1:
  130. case VT_I2:
  131. case VT_UI2:
  132. case VT_I4:
  133. case VT_UI4:
  134. case VT_I8:
  135. case VT_UI8:
  136. case VT_R4:
  137. case VT_R8:
  138. case VT_CY:
  139. case VT_DATE:
  140. break;
  141. case VT_BSTR:
  142. if (pvarg->bstrVal != NULL)
  143. PrivSysFreeString( pvarg->bstrVal );
  144. break;
  145. case VT_BSTR_BLOB:
  146. if (pvarg->bstrblobVal.pData != NULL)
  147. CoTaskMemFree( pvarg->bstrblobVal.pData );
  148. break;
  149. case VT_BOOL:
  150. case VT_ERROR:
  151. case VT_FILETIME:
  152. break;
  153. case VT_LPSTR:
  154. case VT_LPWSTR:
  155. case VT_CLSID:
  156. DfpAssert((void**)&pvarg->pszVal == (void**)&pvarg->pwszVal);
  157. DfpAssert((void**)&pvarg->pszVal == (void**)&pvarg->puuid);
  158. CoTaskMemFree( pvarg->pszVal ); // ptr at 0
  159. break;
  160. case VT_CF:
  161. if (pvarg->pclipdata != NULL)
  162. {
  163. CoTaskMemFree( pvarg->pclipdata->pClipData ); // ptr at 8
  164. CoTaskMemFree( pvarg->pclipdata );
  165. }
  166. break;
  167. case VT_BLOB:
  168. case VT_BLOB_OBJECT:
  169. CoTaskMemFree( pvarg->blob.pBlobData ); //ptr at 4
  170. break;
  171. case VT_STREAM:
  172. case VT_STREAMED_OBJECT:
  173. if (pvarg->pStream != NULL)
  174. pvarg->pStream->Release();
  175. break;
  176. case VT_VERSIONED_STREAM:
  177. if( NULL != pvarg->pVersionedStream )
  178. {
  179. if( NULL != pvarg->pVersionedStream->pStream )
  180. pvarg->pVersionedStream->pStream->Release();
  181. CoTaskMemFree( pvarg->pVersionedStream );
  182. }
  183. break;
  184. case VT_STORAGE:
  185. case VT_STORED_OBJECT:
  186. if (pvarg->pStorage != NULL)
  187. pvarg->pStorage->Release();
  188. break;
  189. case (VT_VECTOR | VT_I1):
  190. case (VT_VECTOR | VT_UI1):
  191. case (VT_VECTOR | VT_I2):
  192. case (VT_VECTOR | VT_UI2):
  193. case (VT_VECTOR | VT_I4):
  194. case (VT_VECTOR | VT_UI4):
  195. case (VT_VECTOR | VT_I8):
  196. case (VT_VECTOR | VT_UI8):
  197. case (VT_VECTOR | VT_R4):
  198. case (VT_VECTOR | VT_R8):
  199. case (VT_VECTOR | VT_CY):
  200. case (VT_VECTOR | VT_DATE):
  201. FreeArray:
  202. DfpAssert((void**)&pvarg->caub.pElems == (void**)&pvarg->cai.pElems);
  203. CoTaskMemFree( pvarg->caub.pElems );
  204. break;
  205. case (VT_VECTOR | VT_BSTR):
  206. if (pvarg->cabstr.pElems != NULL)
  207. {
  208. for (l=0; l< pvarg->cabstr.cElems; l++)
  209. {
  210. if (pvarg->cabstr.pElems[l] != NULL)
  211. {
  212. PrivSysFreeString( pvarg->cabstr.pElems[l] );
  213. }
  214. }
  215. }
  216. goto FreeArray;
  217. case (VT_VECTOR | VT_BSTR_BLOB):
  218. if (pvarg->cabstrblob.pElems != NULL)
  219. {
  220. for (l=0; l< pvarg->cabstrblob.cElems; l++)
  221. {
  222. if (pvarg->cabstrblob.pElems[l].pData != NULL)
  223. {
  224. CoTaskMemFree( pvarg->cabstrblob.pElems[l].pData );
  225. }
  226. }
  227. }
  228. goto FreeArray;
  229. case (VT_VECTOR | VT_BOOL):
  230. case (VT_VECTOR | VT_ERROR):
  231. goto FreeArray;
  232. case (VT_VECTOR | VT_LPSTR):
  233. case (VT_VECTOR | VT_LPWSTR):
  234. if (pvarg->calpstr.pElems != NULL)
  235. {
  236. for (l=0; l< pvarg->calpstr.cElems; l++)
  237. {
  238. CoTaskMemFree( pvarg->calpstr.pElems[l] );
  239. }
  240. }
  241. goto FreeArray;
  242. case (VT_VECTOR | VT_FILETIME):
  243. case (VT_VECTOR | VT_CLSID):
  244. goto FreeArray;
  245. case (VT_VECTOR | VT_CF):
  246. if (pvarg->caclipdata.pElems != NULL)
  247. for (l=0; l< pvarg->caclipdata.cElems; l++)
  248. {
  249. CoTaskMemFree( pvarg->caclipdata.pElems[l].pClipData );
  250. }
  251. goto FreeArray;
  252. case (VT_VECTOR | VT_VARIANT):
  253. if (pvarg->capropvar.pElems != NULL)
  254. hr = FreePropVariantArray(pvarg->capropvar.cElems, pvarg->capropvar.pElems);
  255. goto FreeArray;
  256. default:
  257. // If it's not a type we recognize, give oleaut a try
  258. hr = PrivVariantClear( reinterpret_cast<VARIANT*>(pvarg) );
  259. if( DISP_E_BADVARTYPE == hr )
  260. hr = STG_E_INVALIDPARAMETER;
  261. break;
  262. }
  263. // We have all of the important information about the variant, so
  264. // let's clear it out.
  265. //
  266. PropVariantInit(pvarg);
  267. return (hr);
  268. }
  269. //+---------------------------------------------------------------------------
  270. //
  271. // Function: FreePropVariantArray, public
  272. //
  273. // Synopsis: Frees a value array returned from ReadMultiple
  274. //
  275. // Arguments: [cval] - Number of elements
  276. // [rgvar] - Array
  277. //
  278. // Returns: S_OK if all types recognised and all freeable items were freed.
  279. // STG_E_INVALID_PARAMETER if one or more types were not
  280. // recognised but all items are freed too.
  281. //
  282. // Notes: Even if a vt-type is not understood, all the ones that are
  283. // understood are freed. The error code will indicate
  284. // if *any* of the members were illegal types.
  285. //
  286. //----------------------------------------------------------------------------
  287. STDAPI FreePropVariantArray (
  288. ULONG cVariants,
  289. PROPVARIANT *rgvars)
  290. {
  291. HRESULT hr = S_OK;
  292. VDATESIZEPTROUT_LABEL(rgvars, cVariants * sizeof(PROPVARIANT),
  293. Exit, hr );
  294. if (rgvars != NULL)
  295. {
  296. for ( ULONG I=0; I < cVariants; I++ )
  297. {
  298. if (STG_E_INVALIDPARAMETER == PropVariantClear ( rgvars + I ))
  299. hr = STG_E_INVALIDPARAMETER;
  300. }
  301. }
  302. Exit:
  303. return hr;
  304. }
  305. //+-------------------------------------------------------------------
  306. //
  307. // Function: AllocAndCopy
  308. //
  309. // Synopsis: Allocates enough memory to copy the passed data into and
  310. // then copies the data into the new buffer.
  311. //
  312. // Arguments: [cb] -- number of bytes of data to allocate and copy
  313. // [pvData] -- the source of the data to copy
  314. // [phr] -- optional pointer to an HRESULT set to
  315. // STG_E_INSUFFICIENTMEMORY if memory could
  316. // not be allocated.
  317. //
  318. //
  319. // Returns: NULL if no memory could be allocated,
  320. // Otherwise, pointer to allocated and copied data.
  321. //
  322. //--------------------------------------------------------------------
  323. void * AllocAndCopy(ULONG cb, void * pvData, HRESULT *phr /* = NULL */)
  324. {
  325. void * pvNew = CoTaskMemAlloc( cb );
  326. if (pvNew != NULL)
  327. {
  328. memcpy(pvNew, pvData, cb);
  329. }
  330. else
  331. {
  332. if (phr != NULL)
  333. {
  334. *phr = STG_E_INSUFFICIENTMEMORY;
  335. }
  336. }
  337. return(pvNew);
  338. }
  339. //+-------------------------------------------------------------------
  340. //
  341. // Function: PropSysAllocString
  342. // PropSysFreeString
  343. //
  344. // Synopsis: Wrappers for OleAut32 routines.
  345. //
  346. // Notes: These PropSys* functions simply forward the call to
  347. // the PrivSys* routines in OLE32. Those functions
  348. // will load OleAut32 if necessary, and forward the call.
  349. //
  350. // The PrivSys* wrapper functions are provided in order to
  351. // delay the OleAut32 load. The PropSys* functions below
  352. // are provided as a mechanism to allow the NTDLL PropSet
  353. // functions to call the PrivSys* function pointers.
  354. //
  355. // The PropSys* functions below are part of the
  356. // UNICODECALLOUTS structure used by NTDLL.
  357. // These functions should go away when the property set
  358. // code is moved from NTDLL to OLE32.
  359. //
  360. //--------------------------------------------------------------------
  361. STDAPI_(BSTR)
  362. PropSysAllocString(OLECHAR FAR* pwsz)
  363. {
  364. return( PrivSysAllocString( pwsz ));
  365. }
  366. STDAPI_(VOID)
  367. PropSysFreeString(BSTR bstr)
  368. {
  369. PrivSysFreeString( bstr );
  370. return;
  371. }
  372. //+---------------------------------------------------------------------------
  373. //
  374. // Class: CRGTypeSizes (instantiated in g_TypeSizes)
  375. //
  376. // Synopsis: This class maintains a table with an entry for
  377. // each of the VT types. Each entry contains
  378. // flags and a byte-size for the type (each entry is
  379. // only a byte).
  380. //
  381. // This was implemented as a class so that we could use
  382. // it like an array (using an overloaded subscript operator),
  383. // indexed by the VT. An actual array would require
  384. // 4K entries
  385. //
  386. // Internally, this class keeps two tables, each containing
  387. // a range of VTs (the VTs range from 0 to 31, and 64 to 72).
  388. // Other values are treated as a special-case.
  389. //
  390. //----------------------------------------------------------------------------
  391. // -----------------------
  392. // Flags for table entries
  393. // -----------------------
  394. #define BIT_VECTNOALLOC 0x80 // the VT_VECTOR with this type does not
  395. // use heap allocation
  396. #define BIT_SIMPNOALLOC 0x40 // the non VT_VECTOR with this type does not
  397. // use heap allocation
  398. #define BIT_INVALID 0x20 // marks an invalid type
  399. #define BIT_SIZEMASK 0x1F // mask for size of underlying type
  400. // Dimensions of the internal tables
  401. #define MIN_TYPE_SIZES_A VT_EMPTY // First contiguous range of VTs
  402. #define MAX_TYPE_SIZES_A VT_LPWSTR
  403. #define MIN_TYPE_SIZES_B VT_FILETIME // Second continuous range of VTs
  404. #define MAX_TYPE_SIZES_B VT_VERSIONED_STREAM
  405. // ----------------
  406. // class CRTTypeSizes
  407. // ----------------
  408. class CRGTypeSizes
  409. {
  410. public:
  411. // Subscript Operator
  412. //
  413. // This is the only method on this class. It is used to
  414. // read an entry in the table.
  415. unsigned char operator[]( int nSubscript )
  416. {
  417. // Is this in the first table?
  418. if( MIN_TYPE_SIZES_A <= nSubscript && nSubscript <= MAX_TYPE_SIZES_A )
  419. {
  420. return( m_ucTypeSizesA[ nSubscript ] );
  421. }
  422. // Or, is it in the second table?
  423. else if( MIN_TYPE_SIZES_B<= nSubscript && nSubscript <= MAX_TYPE_SIZES_B )
  424. {
  425. return( m_ucTypeSizesB[ nSubscript - MIN_TYPE_SIZES_B ] );
  426. }
  427. // Or, is it a special-case value (not in either table)?
  428. else if( VT_BSTR_BLOB == nSubscript )
  429. {
  430. return( sizeof(BSTRBLOB) );
  431. }
  432. // Otherwise, the VT is invalid.
  433. return( BIT_INVALID );
  434. }
  435. private:
  436. // There are two ranges of supported VTs, so we have
  437. // one table for each.
  438. static const unsigned char m_ucTypeSizesA[];
  439. static const unsigned char m_ucTypeSizesB[];
  440. };
  441. // --------------------------
  442. // Instantiate the CRGTypeSizes
  443. // --------------------------
  444. CRGTypeSizes g_TypeSizes;
  445. // ----------------------------
  446. // Define the CTypeSizes tables
  447. // ----------------------------
  448. const unsigned char CRGTypeSizes::m_ucTypeSizesA[] =
  449. { BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_EMPTY= 0,
  450. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_NULL = 1,
  451. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 2, //VT_I2 = 2,
  452. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 4, //VT_I4 = 3,
  453. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 4, //VT_R4 = 4,
  454. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 8, //VT_R8 = 5,
  455. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | sizeof(CY), //VT_CY = 6,
  456. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | sizeof(DATE), //VT_DATE = 7,
  457. sizeof(BSTR), //VT_BSTR = 8,
  458. BIT_INVALID | 0, //VT_DISPATCH = 9,
  459. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | sizeof(SCODE), //VT_ERROR = 10,
  460. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | sizeof(VARIANT_BOOL), //VT_BOOL = 11,
  461. sizeof(PROPVARIANT), //VT_VARIANT = 12,
  462. BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_UNKNOWN = 13,
  463. BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, // 14
  464. BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, // 15
  465. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 1, //VT_I1 = 16,
  466. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 1, //VT_UI1 = 17,
  467. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 2, //VT_UI2 = 18,
  468. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 4, //VT_UI4 = 19,
  469. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 8, //VT_I8 = 20,
  470. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 8, //VT_UI8 = 21,
  471. BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_INT = 22,
  472. BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_UINT = 23,
  473. BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_VOID = 24,
  474. BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_HRESULT = 25,
  475. BIT_INVALID | 0, //VT_PTR = 26,
  476. BIT_INVALID | 0, //VT_SAFEARRAY = 27,
  477. BIT_INVALID | 0, //VT_CARRAY = 28,
  478. BIT_INVALID | 0, //VT_USERDEFINED = 29,
  479. sizeof(LPSTR), //VT_LPSTR = 30,
  480. sizeof(LPWSTR) //VT_LPWSTR = 31,
  481. };
  482. const unsigned char CRGTypeSizes::m_ucTypeSizesB[] =
  483. {
  484. // sizes for vectors of types marked ** are determined dynamically
  485. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | sizeof(FILETIME), //VT_FILETIME = 64,
  486. 0, //**VT_BLOB = 65,
  487. 0, //**VT_STREAM = 66,
  488. 0, //**VT_STORAGE = 67,
  489. 0, //**VT_STREAMED_OBJECT = 68,
  490. 0, //**VT_STORED_OBJECT = 69,
  491. 0, //**VT_BLOB_OBJECT = 70,
  492. sizeof(CLIPDATA), //VT_CF = 71,
  493. BIT_VECTNOALLOC | sizeof(CLSID), //VT_CLSID = 72,
  494. 0 //**VT_VERSIONED_STREAM = 73
  495. };
  496. //+---------------------------------------------------------------------------
  497. //
  498. // Function: PropVariantCopy, public
  499. //
  500. // Synopsis: Copies a PROPVARIANT
  501. //
  502. // Arguments: [pDest] -- the destination PROPVARIANT
  503. // [pvarg] - the source PROPVARIANT
  504. //
  505. // Returns: Appropriate status code
  506. //
  507. //----------------------------------------------------------------------------
  508. STDAPI PropVariantCopy ( PROPVARIANT * pvOut, const PROPVARIANT * pvarg )
  509. {
  510. HRESULT hr = S_OK;
  511. register unsigned char TypeInfo;
  512. register int iBaseType;
  513. BOOL fInputValidated = FALSE;
  514. PROPVARIANT Temp, *pDest = &Temp;
  515. // ----------
  516. // Initialize
  517. // ----------
  518. // Validate the inputs
  519. VDATEREADPTRIN_LABEL( pvarg, PROPVARIANT, Exit, hr );
  520. VDATEPTROUT_LABEL( pvOut, PROPVARIANT, Exit, hr );
  521. fInputValidated = TRUE;
  522. // Duplicate the source propvar to the temp destination. For types with
  523. // no external buffer (e.g. an I4), this will be sufficient. For
  524. // types with an external buffer, we'll now have both propvars
  525. // pointing to the same buffer. So we'll have to re-allocate
  526. // for the destination propvar and copy the data into it.
  527. //
  528. *pDest = *pvarg;
  529. // Get allocation info for this type.
  530. iBaseType = pvarg->vt & ~VT_VECTOR;
  531. TypeInfo = g_TypeSizes[ iBaseType ]; // Not to be confused with an ITypeInfo
  532. // If this is an invalid type, see if it's an oleaut Variant type
  533. if( (TypeInfo & BIT_INVALID) != 0 )
  534. {
  535. // Try copying it as a regular Variant
  536. PropVariantInit( pDest );
  537. hr = PrivVariantCopy( reinterpret_cast<VARIANT*>(pDest),
  538. reinterpret_cast<VARIANT*>(const_cast<PROPVARIANT*>( pvarg )) );
  539. goto Exit;
  540. }
  541. // -----------------------
  542. // Handle non-vector types
  543. // -----------------------
  544. if ((pvarg->vt & VT_VECTOR) == 0)
  545. {
  546. // Is this a type which requires an allocation (otherwise there's
  547. // nothing to do)?
  548. if ((TypeInfo & BIT_SIMPNOALLOC) == 0)
  549. {
  550. // Yes - an allocation is required.
  551. // Keep a copy of the allocated buffer, so that at the end of
  552. // this switch, we can distiguish the out-of-memory condition from
  553. // the no-alloc-required condition.
  554. void * pvAllocated = (void*)-1;
  555. switch (pvarg->vt)
  556. {
  557. case VT_BSTR:
  558. if( NULL != pvarg->bstrVal )
  559. // This does an alloc and a copy
  560. pvAllocated = pDest->bstrVal = PrivSysAllocString( pvarg->bstrVal );
  561. break;
  562. case VT_BSTR_BLOB:
  563. if( NULL != pvarg->bstrblobVal.pData )
  564. pvAllocated = pDest->bstrblobVal.pData = (BYTE*)
  565. AllocAndCopy(pDest->bstrblobVal.cbSize, pvarg->bstrblobVal.pData);
  566. break;
  567. case VT_LPSTR:
  568. if (pvarg->pszVal != NULL)
  569. pvAllocated = pDest->pszVal = (CHAR *)
  570. AllocAndCopy((ULONG)strlen(pvarg->pszVal)+1, pvarg->pszVal);
  571. break;
  572. case VT_LPWSTR:
  573. if (pvarg->pwszVal != NULL)
  574. {
  575. ULONG cbString = ((ULONG)Prop_wcslen(pvarg->pwszVal)+1) * sizeof(WCHAR);
  576. pvAllocated = pDest->pwszVal = (WCHAR *)
  577. AllocAndCopy(cbString, pvarg->pwszVal);
  578. }
  579. break;
  580. case VT_CLSID:
  581. if (pvarg->puuid != NULL)
  582. pvAllocated = pDest->puuid = (GUID *)
  583. AllocAndCopy(sizeof(*(pvarg->puuid)), pvarg->puuid);
  584. break;
  585. case VT_CF:
  586. // first check if CLIPDATA is present
  587. if (pvarg->pclipdata != NULL)
  588. {
  589. // yes ... copy the clip data structure
  590. pvAllocated = pDest->pclipdata = (CLIPDATA*)AllocAndCopy(
  591. sizeof(*(pvarg->pclipdata)), pvarg->pclipdata);
  592. // did we allocate the CLIPDATA ?
  593. if (pvAllocated != NULL)
  594. {
  595. // yes ... initialize the destination.
  596. pDest->pclipdata->pClipData = NULL;
  597. // Is the input valid?
  598. if (NULL == pvarg->pclipdata->pClipData
  599. &&
  600. 0 != CBPCLIPDATA(*pvarg->pclipdata))
  601. {
  602. // no ... the input is not valid
  603. hr = STG_E_INVALIDPARAMETER;
  604. CoTaskMemFree( pDest->pclipdata );
  605. pvAllocated = pDest->pclipdata = NULL;
  606. break;
  607. }
  608. // Copy the actual clip data. Note that if the source
  609. // is non-NULL, we copy it, even if the length is 0.
  610. if( NULL != pvarg->pclipdata->pClipData )
  611. {
  612. pvAllocated = pDest->pclipdata->pClipData =
  613. (BYTE*)AllocAndCopy(CBPCLIPDATA(*pvarg->pclipdata),
  614. pvarg->pclipdata->pClipData);
  615. }
  616. } // if (pvAllocated != NULL)
  617. } // if (pvarg->pclipdata != NULL)
  618. break;
  619. case VT_BLOB:
  620. case VT_BLOB_OBJECT:
  621. // Is the input valid?
  622. if (NULL == pvarg->blob.pBlobData
  623. &&
  624. 0 != pvarg->blob.cbSize)
  625. {
  626. // no ... the input is not valid
  627. hr = STG_E_INVALIDPARAMETER;
  628. goto Exit;
  629. }
  630. // Copy the actual blob. Note that if the source
  631. // is non-NULL, we copy it, even if the length is 0.
  632. if( NULL != pvarg->blob.pBlobData )
  633. {
  634. pvAllocated = pDest->blob.pBlobData =
  635. (BYTE*)AllocAndCopy(pvarg->blob.cbSize,
  636. pvarg->blob.pBlobData);
  637. }
  638. break;
  639. case VT_STREAM:
  640. case VT_STREAMED_OBJECT:
  641. if (pDest->pStream != NULL)
  642. pDest->pStream->AddRef();
  643. break;
  644. case VT_VERSIONED_STREAM:
  645. if( NULL != pvarg->pVersionedStream )
  646. {
  647. LPVERSIONEDSTREAM pVersionedStream
  648. = reinterpret_cast<LPVERSIONEDSTREAM>(CoTaskMemAlloc( sizeof(VERSIONEDSTREAM) ));
  649. if( NULL == pVersionedStream )
  650. {
  651. hr = E_OUTOFMEMORY;
  652. goto Exit;
  653. }
  654. *pVersionedStream = *pvarg->pVersionedStream;
  655. if( NULL != pVersionedStream->pStream )
  656. pVersionedStream->pStream->AddRef();
  657. pDest->pVersionedStream = pVersionedStream;
  658. }
  659. break;
  660. case VT_STORAGE:
  661. case VT_STORED_OBJECT:
  662. if (pDest->pStorage != NULL)
  663. pDest->pStorage->AddRef();
  664. break;
  665. case VT_VARIANT:
  666. // drop through - this merely documents that VT_VARIANT has been thought of.
  667. // VT_VARIANT is only supported as part of a vector.
  668. default:
  669. hr = STG_E_INVALIDPARAMETER;
  670. goto Exit;
  671. } // switch (pvarg->vt)
  672. // If there was an error, we're done.
  673. if( FAILED(hr) )
  674. goto Exit;
  675. // pvAllocated was initialized to -1, so if it's NULL now,
  676. // there was an alloc failure.
  677. if (pvAllocated == NULL)
  678. {
  679. hr = STG_E_INSUFFICIENTMEMORY;
  680. goto Exit;
  681. }
  682. } // if ((TypeInfo & BIT_SIMPNOALLOC) == 0)
  683. } // if ((pvarg->vt & VT_VECTOR) == 0)
  684. // -------------------
  685. // Handle vector types
  686. // -------------------
  687. else
  688. {
  689. // What's the byte-size of this type.
  690. ULONG cbType = TypeInfo & BIT_SIZEMASK;
  691. if (cbType == 0)
  692. {
  693. hr = STG_E_INVALIDPARAMETER;
  694. goto Exit;
  695. }
  696. // This depends on the pointer and count being in the same place in
  697. // each of CAUI1 CAI2 etc
  698. // allocate the array for pElems
  699. if (pvarg->caub.pElems == NULL || pvarg->caub.cElems == 0)
  700. {
  701. DfpAssert( hr == S_OK );
  702. goto Exit; // not really an error
  703. }
  704. // Allocate the pElems array (the size of which is
  705. // type-dependent), and copy the source into it.
  706. void *pvAllocated = pDest->caub.pElems = (BYTE *)
  707. AllocAndCopy(cbType * pvarg->caub.cElems, pvarg->caub.pElems);
  708. if (pvAllocated == NULL)
  709. {
  710. hr = STG_E_INSUFFICIENTMEMORY;
  711. goto Exit;
  712. }
  713. // If this type doesn't require secondary allocation (e.g.
  714. // a VT_VECTOR | VT_I4), then we're done.
  715. if ((TypeInfo & BIT_VECTNOALLOC) != 0)
  716. {
  717. // the vector needs no further allocation
  718. DfpAssert( hr == S_OK );
  719. goto Exit;
  720. }
  721. ULONG l;
  722. // vector types that require allocation ...
  723. // we first zero out the pointers so that we can use PropVariantClear
  724. // to clean up in the error case
  725. switch (pvarg->vt)
  726. {
  727. case (VT_VECTOR | VT_BSTR):
  728. // initialize for error case
  729. for (l=0; l< pvarg->cabstr.cElems; l++)
  730. {
  731. pDest->cabstr.pElems[l] = NULL;
  732. }
  733. break;
  734. case (VT_VECTOR | VT_BSTR_BLOB):
  735. // initialize for error case
  736. for (l=0; l< pvarg->cabstrblob.cElems; l++)
  737. {
  738. memset( &pDest->cabstrblob.pElems[l], 0, sizeof(BSTRBLOB) );
  739. }
  740. break;
  741. case (VT_VECTOR | VT_LPSTR):
  742. case (VT_VECTOR | VT_LPWSTR):
  743. // initialize for error case
  744. for (l=0; l< pvarg->calpstr.cElems; l++)
  745. {
  746. pDest->calpstr.pElems[l] = NULL;
  747. }
  748. break;
  749. case (VT_VECTOR | VT_CF):
  750. // initialize for error case
  751. for (l=0; l< pvarg->caclipdata.cElems; l++)
  752. {
  753. pDest->caclipdata.pElems[l].pClipData = NULL;
  754. }
  755. break;
  756. case (VT_VECTOR | VT_VARIANT):
  757. // initialize for error case
  758. for (l=0; l< pvarg->capropvar.cElems; l++)
  759. {
  760. pDest->capropvar.pElems[l].vt = VT_ILLEGAL;
  761. }
  762. break;
  763. default:
  764. DfpAssert(!"Internal error: Unexpected type in PropVariantCopy");
  765. CoTaskMemFree( pvAllocated );
  766. hr = STG_E_INVALIDPARAMETER;
  767. goto Exit;
  768. }
  769. // This is a vector type which requires a secondary alloc.
  770. switch (pvarg->vt)
  771. {
  772. case (VT_VECTOR | VT_BSTR):
  773. for (l=0; l< pvarg->cabstr.cElems; l++)
  774. {
  775. if (pvarg->cabstr.pElems[l] != NULL)
  776. {
  777. pDest->cabstr.pElems[l] = PrivSysAllocString( pvarg->cabstr.pElems[l]);
  778. if (pDest->cabstr.pElems[l] == NULL)
  779. {
  780. hr = STG_E_INSUFFICIENTMEMORY;
  781. break;
  782. }
  783. }
  784. }
  785. break;
  786. case (VT_VECTOR | VT_BSTR_BLOB):
  787. for (l=0; l< pvarg->cabstrblob.cElems; l++)
  788. {
  789. if (pvarg->cabstrblob.pElems[l].pData != NULL)
  790. {
  791. pDest->cabstrblob.pElems[l].cbSize
  792. = pvarg->cabstrblob.pElems[l].cbSize;
  793. pDest->cabstrblob.pElems[l].pData = (BYTE*)AllocAndCopy(
  794. pvarg->cabstrblob.pElems[l].cbSize,
  795. pvarg->cabstrblob.pElems[l].pData,
  796. &hr );
  797. if (hr != S_OK)
  798. break;
  799. }
  800. }
  801. break;
  802. case (VT_VECTOR | VT_LPWSTR):
  803. for (l=0; l< pvarg->calpwstr.cElems; l++)
  804. {
  805. if (pvarg->calpwstr.pElems[l] != NULL)
  806. {
  807. pDest->calpwstr.pElems[l] = (LPWSTR)AllocAndCopy(
  808. sizeof(WCHAR)*((ULONG)Prop_wcslen(pvarg->calpwstr.pElems[l])+1),
  809. pvarg->calpwstr.pElems[l],
  810. &hr);
  811. if (hr != S_OK)
  812. break;
  813. }
  814. }
  815. break;
  816. case (VT_VECTOR | VT_LPSTR):
  817. for (l=0; l< pvarg->calpstr.cElems; l++)
  818. {
  819. if (pvarg->calpstr.pElems[l] != NULL)
  820. {
  821. pDest->calpstr.pElems[l] = (LPSTR)AllocAndCopy(
  822. (ULONG)strlen(pvarg->calpstr.pElems[l])+1,
  823. pvarg->calpstr.pElems[l],
  824. &hr);
  825. if (hr != S_OK)
  826. break;
  827. }
  828. }
  829. break;
  830. case (VT_VECTOR | VT_CF):
  831. for (l=0; l< pvarg->caclipdata.cElems; l++)
  832. {
  833. // Is the input valid?
  834. if (NULL == pvarg->caclipdata.pElems[l].pClipData
  835. &&
  836. 0 != CBPCLIPDATA(pvarg->caclipdata.pElems[l] ))
  837. {
  838. hr = STG_E_INVALIDPARAMETER;
  839. break;
  840. }
  841. // Is there data to copy?
  842. if (NULL != pvarg->caclipdata.pElems[l].pClipData)
  843. {
  844. pDest->caclipdata.pElems[l].pClipData = (BYTE*)AllocAndCopy(
  845. CBPCLIPDATA(pvarg->caclipdata.pElems[l]),
  846. pvarg->caclipdata.pElems[l].pClipData,
  847. &hr);
  848. if (hr != S_OK)
  849. break;
  850. }
  851. }
  852. break;
  853. case (VT_VECTOR | VT_VARIANT):
  854. for (l=0; l< pvarg->capropvar.cElems; l++)
  855. {
  856. hr = PropVariantCopy(pDest->capropvar.pElems + l,
  857. pvarg->capropvar.pElems + l);
  858. if (hr != S_OK)
  859. {
  860. break;
  861. }
  862. }
  863. break;
  864. default:
  865. DfpAssert(!"Internal error: Unexpected type in PropVariantCopy");
  866. CoTaskMemFree( pvAllocated );
  867. hr = STG_E_INVALIDPARAMETER;
  868. goto Exit;
  869. } // switch (pvarg->vt)
  870. } // if ((pvarg->vt & VT_VECTOR) == 0) ... else
  871. // ----
  872. // Exit
  873. // ----
  874. Exit:
  875. // If there was an error, and it wasn't a caller error
  876. // (in which case *pDest may not be writable), clear the
  877. // destination propvar.
  878. if (fInputValidated && hr != S_OK && E_INVALIDARG != hr)
  879. {
  880. // if *pDest == *pvarg, then we didn't alloc anything, and
  881. // nothing need be cleared, so we'll just init *pDest.
  882. // We can't free it because it may point to pvarg's buffers.
  883. if( !memcmp( pDest, pvarg, sizeof(PROPVARIANT) ))
  884. PropVariantInit( pDest );
  885. // Otherwise, we must have done some allocations for *pDest,
  886. // and must free them.
  887. else
  888. PropVariantClear( pDest );
  889. }
  890. if (SUCCEEDED(hr))
  891. *pvOut = Temp;
  892. return(hr);
  893. }
  894. //+---------------------------------------------------------------------------
  895. //
  896. // Function: NtStatusToScode, public
  897. //
  898. // Synopsis: Attempts to map an NTSTATUS code to an SCODE
  899. //
  900. // Arguments: [nts] - NTSTATUS
  901. //
  902. // Returns: Appropriate status code
  903. //
  904. // History: 29-Jun-93 DrewB Created
  905. //
  906. // Notes: Assumes [nts] is an error code
  907. // This function is by no means exhaustively complete
  908. //
  909. //----------------------------------------------------------------------------
  910. SCODE NtStatusToScode(NTSTATUS nts)
  911. {
  912. SCODE sc;
  913. propDbg((DEB_ITRACE, "In NtStatusToScode(%lX)\n", nts));
  914. switch(nts)
  915. {
  916. case STATUS_INVALID_PARAMETER:
  917. case STATUS_INVALID_PARAMETER_MIX:
  918. case STATUS_INVALID_PARAMETER_1:
  919. case STATUS_INVALID_PARAMETER_2:
  920. case STATUS_INVALID_PARAMETER_3:
  921. case STATUS_INVALID_PARAMETER_4:
  922. case STATUS_INVALID_PARAMETER_5:
  923. case STATUS_INVALID_PARAMETER_6:
  924. case STATUS_INVALID_PARAMETER_7:
  925. case STATUS_INVALID_PARAMETER_8:
  926. case STATUS_INVALID_PARAMETER_9:
  927. case STATUS_INVALID_PARAMETER_10:
  928. case STATUS_INVALID_PARAMETER_11:
  929. case STATUS_INVALID_PARAMETER_12:
  930. sc = STG_E_INVALIDPARAMETER;
  931. break;
  932. case STATUS_DUPLICATE_NAME:
  933. case STATUS_DUPLICATE_OBJECTID:
  934. case STATUS_OBJECTID_EXISTS:
  935. case STATUS_OBJECT_NAME_COLLISION:
  936. sc = STG_E_FILEALREADYEXISTS;
  937. break;
  938. case STATUS_NO_SUCH_DEVICE:
  939. case STATUS_NO_SUCH_FILE:
  940. case STATUS_OBJECT_NAME_NOT_FOUND:
  941. case STATUS_NOT_A_DIRECTORY:
  942. case STATUS_FILE_IS_A_DIRECTORY:
  943. case STATUS_PROPSET_NOT_FOUND:
  944. case STATUS_NOT_FOUND:
  945. case STATUS_OBJECT_TYPE_MISMATCH:
  946. sc = STG_E_FILENOTFOUND;
  947. break;
  948. case STATUS_OBJECT_NAME_INVALID:
  949. case STATUS_OBJECT_PATH_SYNTAX_BAD:
  950. case STATUS_OBJECT_PATH_INVALID:
  951. case STATUS_NAME_TOO_LONG:
  952. sc = STG_E_INVALIDNAME;
  953. break;
  954. case STATUS_ACCESS_DENIED:
  955. sc = STG_E_ACCESSDENIED;
  956. break;
  957. case STATUS_NO_MEMORY:
  958. case STATUS_INSUFFICIENT_RESOURCES:
  959. sc = STG_E_INSUFFICIENTMEMORY;
  960. break;
  961. case STATUS_INVALID_HANDLE:
  962. case STATUS_FILE_INVALID:
  963. case STATUS_FILE_FORCED_CLOSED:
  964. sc = STG_E_INVALIDHANDLE;
  965. break;
  966. case STATUS_INVALID_DEVICE_REQUEST:
  967. case STATUS_INVALID_SYSTEM_SERVICE:
  968. case STATUS_NOT_IMPLEMENTED:
  969. sc = STG_E_INVALIDFUNCTION;
  970. break;
  971. case STATUS_NO_MEDIA_IN_DEVICE:
  972. case STATUS_UNRECOGNIZED_MEDIA:
  973. case STATUS_DISK_CORRUPT_ERROR:
  974. case STATUS_DATA_ERROR:
  975. sc = STG_E_WRITEFAULT;
  976. break;
  977. case STATUS_OBJECT_PATH_NOT_FOUND:
  978. sc = STG_E_PATHNOTFOUND;
  979. break;
  980. case STATUS_SHARING_VIOLATION:
  981. sc = STG_E_SHAREVIOLATION;
  982. break;
  983. case STATUS_FILE_LOCK_CONFLICT:
  984. case STATUS_LOCK_NOT_GRANTED:
  985. sc = STG_E_LOCKVIOLATION;
  986. break;
  987. case STATUS_DISK_FULL:
  988. sc = STG_E_MEDIUMFULL;
  989. break;
  990. case STATUS_ACCESS_VIOLATION:
  991. case STATUS_INVALID_USER_BUFFER:
  992. sc = STG_E_INVALIDPOINTER;
  993. break;
  994. case STATUS_TOO_MANY_OPENED_FILES:
  995. sc = STG_E_TOOMANYOPENFILES;
  996. break;
  997. case STATUS_DIRECTORY_NOT_EMPTY:
  998. sc = HRESULT_FROM_WIN32(ERROR_DIR_NOT_EMPTY);
  999. break;
  1000. case STATUS_DELETE_PENDING:
  1001. sc = STG_E_REVERTED;
  1002. break;
  1003. case STATUS_INTERNAL_DB_CORRUPTION:
  1004. sc = STG_E_INVALIDHEADER;
  1005. break;
  1006. case STATUS_UNSUCCESSFUL:
  1007. sc = E_FAIL;
  1008. break;
  1009. case STATUS_UNMAPPABLE_CHARACTER:
  1010. sc = HRESULT_FROM_WIN32( ERROR_NO_UNICODE_TRANSLATION );
  1011. break;
  1012. default:
  1013. propDbg((DEB_TRACE, "NtStatusToScode: Unknown status %lX\n", nts));
  1014. sc = HRESULT_FROM_WIN32(RtlNtStatusToDosError(nts));
  1015. break;
  1016. }
  1017. propDbg((DEB_ITRACE, "Out NtStatusToScode => %lX\n", sc));
  1018. return sc;
  1019. }
  1020. #if DBG!=0 && !defined(WINNT)
  1021. ULONG
  1022. DbgPrint(
  1023. PCHAR Format,
  1024. ...
  1025. )
  1026. {
  1027. va_list arglist;
  1028. CHAR Buffer[512];
  1029. int cb;
  1030. //
  1031. // Format the output into a buffer and then print it.
  1032. //
  1033. va_start(arglist, Format);
  1034. cb = PropVsprintfA(Buffer, Format, arglist);
  1035. if (cb == -1) { // detect buffer overflow
  1036. cb = sizeof(Buffer);
  1037. Buffer[sizeof(Buffer) - 2] = '\n';
  1038. Buffer[sizeof(Buffer) - 1] = '\0';
  1039. }
  1040. OutputDebugString(Buffer);
  1041. return 0;
  1042. }
  1043. #endif
  1044. //+-------------------------------------------------------------------
  1045. //
  1046. // Member: ValidateInRGPROPVARIANT
  1047. //
  1048. // Synopsis: S_OK if PROPVARIANT[] is valid for Read.
  1049. // E_INVALIDARG otherwise.
  1050. //
  1051. //--------------------------------------------------------------------
  1052. HRESULT
  1053. ValidateInRGPROPVARIANT( ULONG cpspec, const PROPVARIANT rgpropvar[] )
  1054. {
  1055. // We verify that we can read the whole PropVariant[], but
  1056. // we don't validate the content of those elements.
  1057. HRESULT hr;
  1058. VDATESIZEREADPTRIN_LABEL(rgpropvar, cpspec * sizeof(PROPVARIANT), Exit, hr);
  1059. hr = S_OK;
  1060. Exit:
  1061. return( hr );
  1062. }
  1063. //+-------------------------------------------------------------------
  1064. //
  1065. // Member: ValidateOutRGPROPVARIANT
  1066. //
  1067. // Synopsis: S_OK if PROPVARIANT[] is valid for Write.
  1068. // E_INVALIDARG otherwise.
  1069. //
  1070. //--------------------------------------------------------------------
  1071. HRESULT
  1072. ValidateOutRGPROPVARIANT( ULONG cpspec, PROPVARIANT rgpropvar[] )
  1073. {
  1074. // We verify that we can write the whole PropVariant[], but
  1075. // we don't validate the content of those elements.
  1076. HRESULT hr;
  1077. VDATESIZEPTROUT_LABEL(rgpropvar, cpspec * sizeof(PROPVARIANT), Exit, hr);
  1078. hr = S_OK;
  1079. Exit:
  1080. return( hr );
  1081. }
  1082. //+-------------------------------------------------------------------
  1083. //
  1084. // Member: ValidateOutRGLPOLESTR.
  1085. //
  1086. // Synopsis: S_OK if LPOLESTR[] is valid for Write.
  1087. // E_INVALIDARG otherwise.
  1088. //
  1089. //--------------------------------------------------------------------
  1090. HRESULT
  1091. ValidateOutRGLPOLESTR( ULONG cpropid, LPOLESTR rglpwstrName[] )
  1092. {
  1093. HRESULT hr;
  1094. VDATESIZEPTROUT_LABEL( rglpwstrName, cpropid * sizeof(LPOLESTR), Exit, hr );
  1095. hr = S_OK;
  1096. Exit:
  1097. return( hr );
  1098. }
  1099. //+-------------------------------------------------------------------
  1100. //
  1101. // Member: ValidateInRGLPOLESTR
  1102. //
  1103. // Synopsis: S_OK if LPOLESTR[] is valid for Read.
  1104. // E_INVALIDARG otherwise.
  1105. //
  1106. //--------------------------------------------------------------------
  1107. HRESULT
  1108. ValidateInRGLPOLESTR( ULONG cpropid, const OLECHAR* const rglpwstrName[] )
  1109. {
  1110. // Validate that we can read the entire vector.
  1111. HRESULT hr;
  1112. VDATESIZEREADPTRIN_LABEL( rglpwstrName, cpropid * sizeof(LPOLESTR), Exit, hr );
  1113. // Validate that we can at least read the first character of
  1114. // each of the strings.
  1115. for( ; cpropid > 0; cpropid-- )
  1116. {
  1117. VDATEREADPTRIN_LABEL( rglpwstrName[cpropid-1], WCHAR, Exit, hr );
  1118. }
  1119. hr = S_OK;
  1120. Exit:
  1121. return( hr );
  1122. }
  1123. //+----------------------------------------------------------------------------
  1124. //
  1125. // Function: IsOriginalPropVariantType
  1126. //
  1127. // Determines if a VARTYPE was one of the ones in the original PropVariant
  1128. // definition (as defined in the OLE2 spec and shipped with NT4/DCOM95).
  1129. //
  1130. //+----------------------------------------------------------------------------
  1131. BOOL
  1132. IsOriginalPropVariantType( VARTYPE vt )
  1133. {
  1134. if( vt & ~VT_TYPEMASK & ~VT_VECTOR )
  1135. return( FALSE );
  1136. switch( vt )
  1137. {
  1138. case VT_EMPTY:
  1139. case VT_NULL:
  1140. case VT_UI1:
  1141. case VT_I2:
  1142. case VT_UI2:
  1143. case VT_BOOL:
  1144. case VT_I4:
  1145. case VT_UI4:
  1146. case VT_R4:
  1147. case VT_ERROR:
  1148. case VT_I8:
  1149. case VT_UI8:
  1150. case VT_R8:
  1151. case VT_CY:
  1152. case VT_DATE:
  1153. case VT_FILETIME:
  1154. case VT_CLSID:
  1155. case VT_BLOB:
  1156. case VT_BLOB_OBJECT:
  1157. case VT_CF:
  1158. case VT_STREAM:
  1159. case VT_STREAMED_OBJECT:
  1160. case VT_STORAGE:
  1161. case VT_STORED_OBJECT:
  1162. case VT_BSTR:
  1163. case VT_LPSTR:
  1164. case VT_LPWSTR:
  1165. case VT_UI1|VT_VECTOR:
  1166. case VT_I2|VT_VECTOR:
  1167. case VT_UI2|VT_VECTOR:
  1168. case VT_BOOL|VT_VECTOR:
  1169. case VT_I4|VT_VECTOR:
  1170. case VT_UI4|VT_VECTOR:
  1171. case VT_R4|VT_VECTOR:
  1172. case VT_ERROR|VT_VECTOR:
  1173. case VT_I8|VT_VECTOR:
  1174. case VT_UI8|VT_VECTOR:
  1175. case VT_R8|VT_VECTOR:
  1176. case VT_CY|VT_VECTOR:
  1177. case VT_DATE|VT_VECTOR:
  1178. case VT_FILETIME|VT_VECTOR:
  1179. case VT_CLSID|VT_VECTOR:
  1180. case VT_CF|VT_VECTOR:
  1181. case VT_BSTR|VT_VECTOR:
  1182. case VT_BSTR_BLOB|VT_VECTOR:
  1183. case VT_LPSTR|VT_VECTOR:
  1184. case VT_LPWSTR|VT_VECTOR:
  1185. case VT_VARIANT|VT_VECTOR:
  1186. return( TRUE );
  1187. }
  1188. return( FALSE );
  1189. }
  1190. //+----------------------------------------------------------------------------
  1191. //
  1192. // Function: IsVariantType
  1193. //
  1194. // Determines if a VARTYPE is one in the set of Variant types which are
  1195. // supported in the property set implementation.
  1196. //
  1197. //+----------------------------------------------------------------------------
  1198. BOOL
  1199. IsVariantType( VARTYPE vt )
  1200. {
  1201. // Vectors are unsupported
  1202. if( (VT_VECTOR | VT_RESERVED) & vt )
  1203. return( FALSE );
  1204. switch( VT_TYPEMASK & vt )
  1205. {
  1206. case VT_EMPTY:
  1207. case VT_NULL:
  1208. case VT_I1:
  1209. case VT_UI1:
  1210. case VT_I2:
  1211. case VT_UI2:
  1212. case VT_I4:
  1213. case VT_UI4:
  1214. case VT_INT:
  1215. case VT_UINT:
  1216. case VT_R4:
  1217. case VT_R8:
  1218. case VT_CY:
  1219. case VT_DATE:
  1220. case VT_BSTR:
  1221. case VT_UNKNOWN:
  1222. case VT_DISPATCH:
  1223. case VT_BOOL:
  1224. case VT_ERROR:
  1225. case VT_DECIMAL:
  1226. case VT_VARIANT:
  1227. return( TRUE );
  1228. default:
  1229. return( FALSE );
  1230. }
  1231. }