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.

942 lines
30 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  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. // PropSysAllocString
  19. // PropSysFreeString
  20. //
  21. //
  22. //--------------------------------------------------------------------------
  23. #include "pch.cxx"
  24. //+-------------------------------------------------------------------
  25. //
  26. // Member: CPropSetName::CPropSetName
  27. //
  28. // Synopsis: Initialize internal buffer with converted FMTID
  29. //
  30. // Arguments: [rfmtid] -- FMTID to convert
  31. //
  32. //--------------------------------------------------------------------
  33. CPropSetName::CPropSetName(REFFMTID rfmtid)
  34. {
  35. RtlGuidToPropertySetName(&rfmtid, _oszName);
  36. }
  37. //+-------------------------------------------------------------------
  38. //
  39. // Member: CStackBuffer::Init
  40. //
  41. // Synopsis: Determine whether the class derived from this one
  42. // needs to have additional buffer allocated on the
  43. // heap and allocate it if neccessary. Otherwise, if
  44. // there is space, use the internal buffer in the
  45. // derived class.
  46. //
  47. // Arguments: [cElements] -- the number of elements required.
  48. //
  49. // Returns: S_OK if buffer available
  50. // STG_E_INSUFFICIENTMEMORY if stack buffer was not
  51. // big enough AND heap allocation failed.
  52. //
  53. // Notes: To be called directly by client after the derived
  54. // classes constructor initialized CStackBuffer.
  55. //
  56. //--------------------------------------------------------------------
  57. HRESULT CStackBuffer::Init(ULONG cElements)
  58. {
  59. if (cElements > _cStackElements)
  60. {
  61. _pbHeapBuf = new BYTE[cElements * _cbElementSize];
  62. if (_pbHeapBuf == NULL)
  63. {
  64. return(STG_E_INSUFFICIENTMEMORY);
  65. }
  66. }
  67. return(S_OK);
  68. }
  69. //+-------------------------------------------------------------------------
  70. //
  71. // Function: PropVariantClear
  72. //
  73. // Synopsis: Deallocates the members of the PROPVARIANT that require
  74. // deallocation.
  75. //
  76. // Arguments: [pvarg] - variant to clear
  77. //
  78. // Returns: S_OK if successful,
  79. // STG_E_INVALIDPARAMETER if any part of the variant has
  80. // an unknown vt type. (In this case, ALL the elements
  81. // that can be freed, will be freed.)
  82. //
  83. // Modifies: [pvarg] - the variant is left with vt = VT_EMPTY
  84. //
  85. //--------------------------------------------------------------------------
  86. STDAPI PropVariantClear(PROPVARIANT *pvarg)
  87. {
  88. ULONG l;
  89. HRESULT hr = S_OK;
  90. if (pvarg == NULL)
  91. return(hr);
  92. switch (pvarg->vt)
  93. {
  94. case VT_EMPTY:
  95. case VT_NULL:
  96. case VT_ILLEGAL:
  97. #ifdef PROPVAR_VT_I1
  98. case VT_I1:
  99. #endif
  100. case VT_UI1:
  101. case VT_I2:
  102. case VT_UI2:
  103. case VT_I4:
  104. case VT_UI4:
  105. case VT_I8:
  106. case VT_UI8:
  107. case VT_R4:
  108. case VT_R8:
  109. case VT_CY:
  110. case VT_DATE:
  111. break;
  112. case VT_BSTR:
  113. if (pvarg->bstrVal != NULL)
  114. PropSysFreeString( pvarg->bstrVal );
  115. break;
  116. case VT_BOOL:
  117. case VT_ERROR:
  118. case VT_FILETIME:
  119. break;
  120. case VT_LPSTR:
  121. case VT_LPWSTR:
  122. case VT_CLSID:
  123. PROPASSERT((void**)&pvarg->pszVal == (void**)&pvarg->pwszVal);
  124. PROPASSERT((void**)&pvarg->pszVal == (void**)&pvarg->puuid);
  125. CoTaskMemFree(pvarg->pszVal); // ptr at 0
  126. break;
  127. case VT_CF:
  128. if (pvarg->pclipdata != NULL)
  129. {
  130. CoTaskMemFree(pvarg->pclipdata->pClipData); // ptr at 8
  131. CoTaskMemFree(pvarg->pclipdata);
  132. }
  133. break;
  134. case VT_BLOB:
  135. case VT_BLOB_OBJECT:
  136. CoTaskMemFree(pvarg->blob.pBlobData); //ptr at 4
  137. break;
  138. #ifdef PROPVAR_VT_I1
  139. case (VT_VECTOR | VT_I1):
  140. #endif
  141. case (VT_VECTOR | VT_UI1):
  142. case (VT_VECTOR | VT_I2):
  143. case (VT_VECTOR | VT_UI2):
  144. case (VT_VECTOR | VT_I4):
  145. case (VT_VECTOR | VT_UI4):
  146. case (VT_VECTOR | VT_I8):
  147. case (VT_VECTOR | VT_UI8):
  148. case (VT_VECTOR | VT_R4):
  149. case (VT_VECTOR | VT_R8):
  150. case (VT_VECTOR | VT_CY):
  151. case (VT_VECTOR | VT_DATE):
  152. FreeArray:
  153. PROPASSERT((void**)&pvarg->caub.pElems == (void**)&pvarg->cai.pElems);
  154. CoTaskMemFree(pvarg->caub.pElems);
  155. break;
  156. case (VT_VECTOR | VT_BSTR):
  157. if (pvarg->cabstr.pElems != NULL)
  158. {
  159. for (l=0; l< pvarg->cabstr.cElems; l++)
  160. {
  161. if (pvarg->cabstr.pElems[l] != NULL)
  162. {
  163. PropSysFreeString( pvarg->cabstr.pElems[l] );
  164. }
  165. }
  166. }
  167. goto FreeArray;
  168. case (VT_VECTOR | VT_BOOL):
  169. case (VT_VECTOR | VT_ERROR):
  170. goto FreeArray;
  171. case (VT_VECTOR | VT_LPSTR):
  172. case (VT_VECTOR | VT_LPWSTR):
  173. if (pvarg->calpstr.pElems != NULL)
  174. for (l=0; l< pvarg->calpstr.cElems; l++)
  175. {
  176. CoTaskMemFree(pvarg->calpstr.pElems[l]);
  177. }
  178. goto FreeArray;
  179. case (VT_VECTOR | VT_FILETIME):
  180. case (VT_VECTOR | VT_CLSID):
  181. goto FreeArray;
  182. case (VT_VECTOR | VT_CF):
  183. if (pvarg->caclipdata.pElems != NULL)
  184. for (l=0; l< pvarg->caclipdata.cElems; l++)
  185. {
  186. CoTaskMemFree(pvarg->caclipdata.pElems[l].pClipData);
  187. }
  188. goto FreeArray;
  189. case (VT_VECTOR | VT_VARIANT):
  190. if (pvarg->capropvar.pElems != NULL)
  191. hr = FreePropVariantArray(pvarg->capropvar.cElems, pvarg->capropvar.pElems);
  192. goto FreeArray;
  193. default:
  194. hr = STG_E_INVALIDPARAMETER;
  195. break;
  196. }
  197. // We have all of the important information about the variant, so
  198. // let's clear it out.
  199. //
  200. PropVariantInit(pvarg);
  201. return (hr);
  202. }
  203. //+---------------------------------------------------------------------------
  204. //
  205. // Function: FreePropVariantArray, public
  206. //
  207. // Synopsis: Frees a value array returned from ReadMultiple
  208. //
  209. // Arguments: [cval] - Number of elements
  210. // [rgvar] - Array
  211. //
  212. // Returns: S_OK if all types recognised and all freeable items were freed.
  213. // STG_E_INVALID_PARAMETER if one or more types were not
  214. // recognised but all items are freed too.
  215. //
  216. // Notes: Even if a vt-type is not understood, all the ones that are
  217. // understood are freed. The error code will indicate
  218. // if *any* of the members were illegal types.
  219. //
  220. //----------------------------------------------------------------------------
  221. STDAPI FreePropVariantArray (
  222. ULONG cVariants,
  223. PROPVARIANT *rgvars)
  224. {
  225. HRESULT hr = S_OK;
  226. if (rgvars != NULL)
  227. for ( ULONG I=0; I < cVariants; I++ )
  228. if (STG_E_INVALIDPARAMETER == PropVariantClear ( rgvars + I ))
  229. hr = STG_E_INVALIDPARAMETER;
  230. return hr;
  231. }
  232. //+-------------------------------------------------------------------
  233. //
  234. // Function: AllocAndCopy
  235. //
  236. // Synopsis: Allocates enough memory to copy the passed data into and
  237. // then copies the data into the new buffer.
  238. //
  239. // Arguments: [cb] -- number of bytes of data to allocate and copy
  240. // [pvData] -- the source of the data to copy
  241. // [phr] -- optional pointer to an HRESULT set to
  242. // STG_E_INSUFFICIENTMEMORY if memory could
  243. // not be allocated.
  244. //
  245. //
  246. // Returns: NULL if no memory could be allocated,
  247. // Otherwise, pointer to allocated and copied data.
  248. //
  249. //--------------------------------------------------------------------
  250. void * AllocAndCopy(ULONG cb, void * pvData, HRESULT *phr = NULL)
  251. {
  252. PROPASSERT(cb!=0);
  253. void * pvNew = CoTaskMemAlloc(cb);
  254. if (pvNew != NULL)
  255. {
  256. memcpy(pvNew, pvData, cb);
  257. }
  258. else
  259. {
  260. if (phr != NULL)
  261. {
  262. *phr = STG_E_INSUFFICIENTMEMORY;
  263. }
  264. }
  265. return(pvNew);
  266. }
  267. //+-------------------------------------------------------------------
  268. //
  269. // Function: SysAllocString
  270. // SysFreeString
  271. //
  272. // Synopsis: Exported BSTR allocation and deallocation routines
  273. //
  274. //
  275. //--------------------------------------------------------------------
  276. STDAPI_(void) SysFreeString(BSTR bstr)
  277. {
  278. if (bstr)
  279. {
  280. BYTE* pab = (BYTE*) bstr;
  281. delete[] (pab - sizeof(DWORD));
  282. }
  283. }
  284. STDAPI_(BSTR) SysAllocString(LPOLECHAR pwsz)
  285. {
  286. if (!pwsz) return NULL;
  287. DWORD cch = _tcslen(pwsz);
  288. /* a BSTR points to a DWORD length, followed by the string */
  289. BYTE *pab = new BYTE[sizeof(DWORD) + ((cch+1)*sizeof(OLECHAR))];
  290. if (pab)
  291. {
  292. *((DWORD*) pab) = cch*sizeof(OLECHAR);
  293. pab += sizeof(DWORD);
  294. _tcscpy( (LPOLECHAR)pab, pwsz );
  295. }
  296. return ((BSTR) pab);
  297. }
  298. //+---------------------------------------------------------------------------
  299. //
  300. // Table: g_TypeSizes, g_TypeSizesB
  301. //
  302. // Synopsis: Tables containing byte sizes and flags for various VT_ types.
  303. //
  304. //----------------------------------------------------------------------------
  305. #define BIT_VECTNOALLOC 0x80 // the VT_VECTOR with this type does not
  306. // use heap allocation
  307. #define BIT_SIMPNOALLOC 0x40 // the non VT_VECTOR with this type does not
  308. // use heap allocation
  309. #define BIT_INVALID 0x20 // marks an invalid type
  310. #define BIT_SIZEMASK 0x1F // mask for size of underlying type
  311. const unsigned char g_TypeSizes[] =
  312. { BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_EMPTY= 0,
  313. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_NULL = 1,
  314. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 2, //VT_I2 = 2,
  315. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 4, //VT_I4 = 3,
  316. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 4, //VT_R4 = 4,
  317. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 8, //VT_R8 = 5,
  318. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | sizeof(CY), //VT_CY = 6,
  319. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | sizeof(DATE), //VT_DATE = 7,
  320. sizeof(BSTR), //VT_BSTR = 8,
  321. BIT_INVALID | 0, //VT_DISPATCH = 9,
  322. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | sizeof(SCODE), //VT_ERROR = 10,
  323. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | sizeof(VARIANT_BOOL), //VT_BOOL = 11,
  324. sizeof(PROPVARIANT), //VT_VARIANT = 12,
  325. BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_UNKNOWN = 13,
  326. BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, // 14
  327. BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, // 15
  328. #ifdef PROPVAR_VT_I1
  329. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 1, //VT_I1 = 16,
  330. #else
  331. BIT_INVALID /*BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 1,*/ | 0, //VT_I1 = 16,
  332. #endif
  333. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 1, //VT_UI1 = 17,
  334. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 2, //VT_UI2 = 18,
  335. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 4, //VT_UI4 = 19,
  336. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 8, //VT_I8 = 20,
  337. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 8, //VT_UI8 = 21,
  338. BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_INT = 22,
  339. BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_UINT = 23,
  340. BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_VOID = 24,
  341. BIT_INVALID | BIT_SIMPNOALLOC | BIT_VECTNOALLOC | 0, //VT_HRESULT = 25,
  342. BIT_INVALID | 0, //VT_PTR = 26,
  343. BIT_INVALID | 0, //VT_SAFEARRAY = 27,
  344. BIT_INVALID | 0, //VT_CARRAY = 28,
  345. BIT_INVALID | 0, //VT_USERDEFINED = 29,
  346. sizeof(LPSTR), //VT_LPSTR = 30,
  347. sizeof(LPWSTR) //VT_LPWSTR = 31,
  348. };
  349. const unsigned char g_TypeSizesB[] =
  350. {
  351. // NOTE: vectors of types marked ** are determined dynamically
  352. BIT_SIMPNOALLOC | BIT_VECTNOALLOC | sizeof(FILETIME), //VT_FILETIME = 64,
  353. 0, //**VT_BLOB = 65,
  354. 0, //**VT_STREAM = 66,
  355. 0, //**VT_STORAGE = 67,
  356. 0, //**VT_STREAMED_OBJECT = 68,
  357. 0, //**VT_STORED_OBJECT = 69,
  358. 0, //**VT_BLOB_OBJECT = 70,
  359. sizeof(CLIPDATA), //VT_CF = 71,
  360. BIT_VECTNOALLOC | sizeof(CLSID) //VT_CLSID = 72
  361. };
  362. //+---------------------------------------------------------------------------
  363. //
  364. // Function: PropVariantCopy, public
  365. //
  366. // Synopsis: Copies a PROPVARIANT
  367. //
  368. // Arguments: [pDest] -- the destination PROPVARIANT
  369. // [pvarg] - the source PROPVARIANT
  370. //
  371. // Returns: Appropriate status code
  372. //
  373. //----------------------------------------------------------------------------
  374. STDAPI PropVariantCopy ( PROPVARIANT * pDest, const PROPVARIANT * pvarg )
  375. {
  376. HRESULT hr = S_OK;
  377. register unsigned char TypeInfo;
  378. register int iBaseType;
  379. // handle the simple types quickly
  380. iBaseType = pvarg->vt & ~VT_VECTOR;
  381. if (iBaseType <= VT_LPWSTR)
  382. {
  383. TypeInfo = g_TypeSizes[iBaseType];
  384. }
  385. else
  386. if (VT_FILETIME <= iBaseType && iBaseType <= VT_CLSID)
  387. {
  388. TypeInfo = g_TypeSizesB[iBaseType-VT_FILETIME];
  389. }
  390. else
  391. {
  392. hr = STG_E_INVALIDPARAMETER;
  393. goto errRet;
  394. }
  395. if ((TypeInfo & BIT_INVALID) != 0)
  396. {
  397. hr = STG_E_INVALIDPARAMETER;
  398. goto errRet;
  399. }
  400. *pDest = *pvarg;
  401. if ((pvarg->vt & VT_VECTOR) == 0)
  402. {
  403. // handle non-vector types
  404. if ((TypeInfo & BIT_SIMPNOALLOC) == 0)
  405. {
  406. void * pvAllocated = (void*)-1;
  407. switch (pvarg->vt)
  408. {
  409. case VT_BSTR:
  410. pvAllocated = pDest->bstrVal = PropSysAllocString( pvarg->bstrVal );
  411. break;
  412. case VT_LPSTR:
  413. if (pvarg->pszVal != NULL)
  414. pvAllocated = pDest->pszVal = (CHAR *)
  415. AllocAndCopy(strlen(pvarg->pszVal)+1, pvarg->pszVal);
  416. break;
  417. case VT_LPWSTR:
  418. if (pvarg->pwszVal != NULL)
  419. {
  420. ULONG cbString = (Prop_wcslen(pvarg->pwszVal)+1) * sizeof(WCHAR);
  421. pvAllocated = pDest->pwszVal = (WCHAR *)
  422. AllocAndCopy(cbString, pvarg->pwszVal);
  423. }
  424. break;
  425. case VT_CLSID:
  426. if (pvarg->puuid != NULL)
  427. pvAllocated = pDest->puuid = (GUID *)
  428. AllocAndCopy(sizeof(*(pvarg->puuid)), pvarg->puuid);
  429. break;
  430. case VT_CF:
  431. // first check if CLIPDATA is present
  432. if (pvarg->pclipdata != NULL)
  433. {
  434. // yes ... copy the clip data structure
  435. pvAllocated = pDest->pclipdata = (CLIPDATA*)AllocAndCopy(
  436. sizeof(*(pvarg->pclipdata)), pvarg->pclipdata);
  437. // did we allocate the CLIPDATA ?
  438. if (pvAllocated != NULL)
  439. {
  440. // yes ... initialize the destination.
  441. pDest->pclipdata->pClipData = NULL;
  442. // Is the input valid?
  443. if (NULL == pvarg->pclipdata->pClipData
  444. &&
  445. 0 != CBPCLIPDATA(*pvarg->pclipdata))
  446. {
  447. // no ... the input is not valid
  448. hr = STG_E_INVALIDPARAMETER;
  449. }
  450. // Is there is any actual clip data ?
  451. else if (0 != CBPCLIPDATA(*pvarg->pclipdata))
  452. {
  453. // yes ... copy the actual clip data
  454. pvAllocated = pDest->pclipdata->pClipData =
  455. (BYTE*)AllocAndCopy(CBPCLIPDATA(*pvarg->pclipdata),
  456. pvarg->pclipdata->pClipData);
  457. }
  458. } // if (pvAllocated != NULL)
  459. } // if (pvarg->pclipdata != NULL)
  460. break;
  461. case VT_BLOB:
  462. case VT_BLOB_OBJECT:
  463. if (pvarg->blob.pBlobData != NULL && pvarg->blob.cbSize != 0)
  464. {
  465. pvAllocated = pDest->blob.pBlobData = (BYTE *)
  466. AllocAndCopy(pvarg->blob.cbSize,
  467. pvarg->blob.pBlobData);
  468. }
  469. else
  470. {
  471. // if the cbsize is 0 or pBlobData is NULL, make
  472. // sure both values are consistent in the destination
  473. pDest->blob.pBlobData = NULL;
  474. pDest->blob.cbSize = 0;
  475. }
  476. break;
  477. case VT_VARIANT:
  478. // drop through - this merely documents that VT_VARIANT has been thought of.
  479. default:
  480. //PROPASSERT(!"Unexpected non-vector type in PropVariantCopy");
  481. hr = STG_E_INVALIDPARAMETER;
  482. goto errRet;
  483. }
  484. if( FAILED(hr) )
  485. goto errRet;
  486. if (pvAllocated == NULL)
  487. {
  488. hr = STG_E_INSUFFICIENTMEMORY;
  489. goto errRet;
  490. }
  491. } // if ((TypeInfo & BIT_SIMPNOALLOC) == 0)
  492. } // if ((pvarg->vt & VT_VECTOR) == 0)
  493. else
  494. {
  495. ULONG cbType = TypeInfo & BIT_SIZEMASK;
  496. if (cbType == 0)
  497. {
  498. hr = STG_E_INVALIDPARAMETER;
  499. goto errRet;
  500. }
  501. // handle the vector types
  502. // this depends on the pointer and count being in the same place in
  503. // each of CAUI1 CAI2 etc
  504. // allocate the array for pElems
  505. if (pvarg->caub.pElems == NULL || pvarg->caub.cElems == 0)
  506. {
  507. PROPASSERT( hr == S_OK );
  508. goto errRet; // not really an error
  509. }
  510. void *pvAllocated = pDest->caub.pElems = (BYTE *)
  511. AllocAndCopy(cbType * pvarg->caub.cElems, pvarg->caub.pElems);
  512. if (pvAllocated == NULL)
  513. {
  514. hr = STG_E_INSUFFICIENTMEMORY;
  515. goto errRet;
  516. }
  517. if ((TypeInfo & BIT_VECTNOALLOC) != 0)
  518. {
  519. // the vector needs no further allocation
  520. PROPASSERT( hr == S_OK );
  521. goto errRet;
  522. }
  523. ULONG l;
  524. // vector types that require allocation ...
  525. // we first zero out the pointers so that we can use PropVariantClear
  526. // to clean up in the error case
  527. switch (pvarg->vt)
  528. {
  529. case (VT_VECTOR | VT_BSTR):
  530. // initialize for error case
  531. for (l=0; l< pvarg->cabstr.cElems; l++)
  532. {
  533. pDest->cabstr.pElems[l] = NULL;
  534. }
  535. break;
  536. case (VT_VECTOR | VT_LPSTR):
  537. case (VT_VECTOR | VT_LPWSTR):
  538. // initialize for error case
  539. for (l=0; l< pvarg->calpstr.cElems; l++)
  540. {
  541. pDest->calpstr.pElems[l] = NULL;
  542. }
  543. break;
  544. case (VT_VECTOR | VT_CF):
  545. // initialize for error case
  546. for (l=0; l< pvarg->caclipdata.cElems; l++)
  547. {
  548. pDest->caclipdata.pElems[l].pClipData = NULL;
  549. }
  550. break;
  551. case (VT_VECTOR | VT_VARIANT):
  552. // initialize for error case
  553. for (l=0; l< pvarg->capropvar.cElems; l++)
  554. {
  555. pDest->capropvar.pElems[l].vt = VT_ILLEGAL;
  556. }
  557. break;
  558. default:
  559. PROPASSERT(!"Internal error: Unexpected type in PropVariantCopy");
  560. CoTaskMemFree(pvAllocated);
  561. hr = STG_E_INVALIDPARAMETER;
  562. goto errRet;
  563. }
  564. // now do the vector copy...
  565. switch (pvarg->vt)
  566. {
  567. case (VT_VECTOR | VT_BSTR):
  568. for (l=0; l< pvarg->cabstr.cElems; l++)
  569. {
  570. if (pvarg->cabstr.pElems[l] != NULL)
  571. {
  572. pDest->cabstr.pElems[l] = PropSysAllocString( pvarg->cabstr.pElems[l]);
  573. if (pDest->cabstr.pElems[l] == NULL)
  574. {
  575. hr = STG_E_INSUFFICIENTMEMORY;
  576. break;
  577. }
  578. }
  579. }
  580. break;
  581. case (VT_VECTOR | VT_LPWSTR):
  582. for (l=0; l< pvarg->calpwstr.cElems; l++)
  583. {
  584. if (pvarg->calpwstr.pElems[l] != NULL)
  585. {
  586. pDest->calpwstr.pElems[l] = (LPWSTR)AllocAndCopy(
  587. sizeof(WCHAR)*(Prop_wcslen(pvarg->calpwstr.pElems[l])+1),
  588. pvarg->calpwstr.pElems[l],
  589. &hr);
  590. if (hr != S_OK)
  591. break;
  592. }
  593. }
  594. break;
  595. case (VT_VECTOR | VT_LPSTR):
  596. for (l=0; l< pvarg->calpstr.cElems; l++)
  597. {
  598. if (pvarg->calpstr.pElems[l] != NULL)
  599. {
  600. pDest->calpstr.pElems[l] = (LPSTR)AllocAndCopy(
  601. strlen(pvarg->calpstr.pElems[l])+1,
  602. pvarg->calpstr.pElems[l],
  603. &hr);
  604. if (hr != S_OK)
  605. break;
  606. }
  607. }
  608. break;
  609. case (VT_VECTOR | VT_CF):
  610. for (l=0; l< pvarg->caclipdata.cElems; l++)
  611. {
  612. // Is the input valid?
  613. if (NULL == pvarg->caclipdata.pElems[l].pClipData
  614. &&
  615. 0 != CBPCLIPDATA(pvarg->caclipdata.pElems[l] ))
  616. {
  617. hr = STG_E_INVALIDPARAMETER;
  618. break;
  619. }
  620. // Is there data to copy?
  621. if (0 != CBPCLIPDATA(pvarg->caclipdata.pElems[l]))
  622. {
  623. pDest->caclipdata.pElems[l].pClipData = (BYTE*)AllocAndCopy(
  624. CBPCLIPDATA(pvarg->caclipdata.pElems[l]),
  625. pvarg->caclipdata.pElems[l].pClipData,
  626. &hr);
  627. if (hr != S_OK)
  628. break;
  629. }
  630. }
  631. break;
  632. case (VT_VECTOR | VT_VARIANT):
  633. for (l=0; l< pvarg->capropvar.cElems; l++)
  634. {
  635. hr = PropVariantCopy(pDest->capropvar.pElems + l,
  636. pvarg->capropvar.pElems + l);
  637. if (hr != S_OK)
  638. {
  639. break;
  640. }
  641. }
  642. break;
  643. default:
  644. PROPASSERT(!"Internal error: Unexpected type in PropVariantCopy");
  645. CoTaskMemFree(pvAllocated);
  646. hr = STG_E_INVALIDPARAMETER;
  647. goto errRet;
  648. }
  649. if (hr != S_OK)
  650. {
  651. PropVariantClear(pDest);
  652. goto errRet;
  653. }
  654. }
  655. errRet:
  656. if (hr != S_OK)
  657. {
  658. // VT_EMPTY
  659. PROPASSERT(VT_EMPTY == 0);
  660. memset(pDest, 0, sizeof(*pDest));
  661. }
  662. return(hr);
  663. }
  664. //+---------------------------------------------------------------------------
  665. //
  666. // Function: NtStatusToScode, public
  667. //
  668. // Synopsis: Attempts to map an NTSTATUS code to an SCODE
  669. //
  670. // Arguments: [nts] - NTSTATUS
  671. //
  672. // Returns: Appropriate status code
  673. //
  674. // History: 29-Jun-93 DrewB Created
  675. //
  676. // Notes: Assumes [nts] is an error code
  677. // This function is by no means exhaustively complete
  678. //
  679. //----------------------------------------------------------------------------
  680. SCODE NtStatusToScode(NTSTATUS nts)
  681. {
  682. SCODE sc;
  683. PropDbg((DEB_ITRACE, "In NtStatusToScode(%lX)\n", nts));
  684. switch(nts)
  685. {
  686. case STATUS_INVALID_PARAMETER:
  687. case STATUS_INVALID_PARAMETER_MIX:
  688. case STATUS_INVALID_PARAMETER_1:
  689. case STATUS_INVALID_PARAMETER_2:
  690. case STATUS_INVALID_PARAMETER_3:
  691. case STATUS_INVALID_PARAMETER_4:
  692. case STATUS_INVALID_PARAMETER_5:
  693. case STATUS_INVALID_PARAMETER_6:
  694. case STATUS_INVALID_PARAMETER_7:
  695. case STATUS_INVALID_PARAMETER_8:
  696. case STATUS_INVALID_PARAMETER_9:
  697. case STATUS_INVALID_PARAMETER_10:
  698. case STATUS_INVALID_PARAMETER_11:
  699. case STATUS_INVALID_PARAMETER_12:
  700. sc = STG_E_INVALIDPARAMETER;
  701. break;
  702. case STATUS_DUPLICATE_NAME:
  703. case STATUS_DUPLICATE_OBJECTID:
  704. case STATUS_OBJECTID_EXISTS:
  705. case STATUS_OBJECT_NAME_COLLISION:
  706. sc = STG_E_FILEALREADYEXISTS;
  707. break;
  708. case STATUS_NO_SUCH_DEVICE:
  709. case STATUS_NO_SUCH_FILE:
  710. case STATUS_OBJECT_NAME_NOT_FOUND:
  711. case STATUS_NOT_A_DIRECTORY:
  712. case STATUS_FILE_IS_A_DIRECTORY:
  713. case STATUS_PROPSET_NOT_FOUND:
  714. case STATUS_NOT_FOUND:
  715. case STATUS_OBJECT_TYPE_MISMATCH:
  716. sc = STG_E_FILENOTFOUND;
  717. break;
  718. case STATUS_OBJECT_NAME_INVALID:
  719. case STATUS_OBJECT_PATH_SYNTAX_BAD:
  720. case STATUS_OBJECT_PATH_INVALID:
  721. case STATUS_NAME_TOO_LONG:
  722. sc = STG_E_INVALIDNAME;
  723. break;
  724. case STATUS_ACCESS_DENIED:
  725. sc = STG_E_ACCESSDENIED;
  726. break;
  727. case STATUS_NO_MEMORY:
  728. case STATUS_INSUFFICIENT_RESOURCES:
  729. sc = STG_E_INSUFFICIENTMEMORY;
  730. break;
  731. case STATUS_INVALID_HANDLE:
  732. case STATUS_FILE_INVALID:
  733. case STATUS_FILE_FORCED_CLOSED:
  734. sc = STG_E_INVALIDHANDLE;
  735. break;
  736. case STATUS_INVALID_DEVICE_REQUEST:
  737. case STATUS_INVALID_SYSTEM_SERVICE:
  738. case STATUS_NOT_IMPLEMENTED:
  739. sc = STG_E_INVALIDFUNCTION;
  740. break;
  741. case STATUS_NO_MEDIA_IN_DEVICE:
  742. case STATUS_UNRECOGNIZED_MEDIA:
  743. case STATUS_DISK_CORRUPT_ERROR:
  744. case STATUS_DATA_ERROR:
  745. sc = STG_E_WRITEFAULT;
  746. break;
  747. case STATUS_OBJECT_PATH_NOT_FOUND:
  748. sc = STG_E_PATHNOTFOUND;
  749. break;
  750. case STATUS_SHARING_VIOLATION:
  751. sc = STG_E_SHAREVIOLATION;
  752. break;
  753. case STATUS_FILE_LOCK_CONFLICT:
  754. case STATUS_LOCK_NOT_GRANTED:
  755. sc = STG_E_LOCKVIOLATION;
  756. break;
  757. case STATUS_DISK_FULL:
  758. sc = STG_E_MEDIUMFULL;
  759. break;
  760. case STATUS_ACCESS_VIOLATION:
  761. case STATUS_INVALID_USER_BUFFER:
  762. sc = STG_E_INVALIDPOINTER;
  763. break;
  764. case STATUS_TOO_MANY_OPENED_FILES:
  765. sc = STG_E_TOOMANYOPENFILES;
  766. break;
  767. case STATUS_DIRECTORY_NOT_EMPTY:
  768. sc = WIN32_SCODE(ERROR_DIR_NOT_EMPTY);
  769. break;
  770. case STATUS_DELETE_PENDING:
  771. sc = STG_E_REVERTED;
  772. break;
  773. case STATUS_INTERNAL_DB_CORRUPTION:
  774. sc = STG_E_INVALIDHEADER;
  775. break;
  776. case STATUS_UNSUCCESSFUL:
  777. sc = E_FAIL;
  778. break;
  779. case STATUS_UNMAPPABLE_CHARACTER:
  780. sc = HRESULT_FROM_WIN32( ERROR_NO_UNICODE_TRANSLATION );
  781. break;
  782. default:
  783. PropDbg((DEB_ERROR, "NtStatusToScode: Unknown status %lX\n", nts));
  784. sc = HRESULT_FROM_NT(nts);
  785. break;
  786. }
  787. PropDbg((DEB_ITRACE, "Out NtStatusToScode => %lX\n", sc));
  788. return sc;
  789. }
  790. #if DBG!=0
  791. ULONG
  792. DbgPrint(
  793. PCHAR Format,
  794. ...
  795. )
  796. {
  797. va_list arglist;
  798. CHAR Buffer[512];
  799. int cb;
  800. //
  801. // Format the output into a buffer and then print it.
  802. //
  803. va_start(arglist, Format);
  804. cb = PropVsprintfA(Buffer, Format, arglist);
  805. if (cb == -1) { // detect buffer overflow
  806. cb = sizeof(Buffer);
  807. Buffer[sizeof(Buffer) - 2] = '\n';
  808. Buffer[sizeof(Buffer) - 1] = '\0';
  809. }
  810. OutputDebugString(Buffer);
  811. return 0;
  812. }
  813. #endif