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.

513 lines
11 KiB

  1. //+--------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1996.
  5. //
  6. // File: cpropvar.cxx
  7. //
  8. //---------------------------------------------------------------
  9. #include "cpropvar.hxx"
  10. #include "chresult.hxx"
  11. #include <stdio.h>
  12. #include "../../h/tchar.h"
  13. // this function is from refstg
  14. BOOLEAN STDCALL
  15. RtlCompareVariants(
  16. USHORT CodePage,
  17. PROPVARIANT const *pvar1,
  18. PROPVARIANT const *pvar2);
  19. DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(LPSTR, LPSTR);
  20. DEFINE_CPROPVARIANT_CONVERSION_OPERATOR(LPSTR, calpstr, pszVal );
  21. DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(LPWSTR, LPWSTR);
  22. DEFINE_CPROPVARIANT_CONVERSION_OPERATOR(LPWSTR, calpwstr, pwszVal );
  23. DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(CF, CLIPDATA&);
  24. DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(CF, CClipData&);
  25. DEFINE_CPROPVARIANT_ASSIGNMENT_OPERATOR(CLSID, CLSID);
  26. CPropVariant::CPropVariant( VARENUM v, ULONG cElements)
  27. {
  28. Init(v, cElements);
  29. }
  30. void CPropVariant::Init(
  31. VARENUM v,
  32. ULONG cElements)
  33. {
  34. ULONG cbElement;
  35. BOOLEAN fZero = FALSE;
  36. // Ignore vector flag. This constructor is always for vectors only.
  37. vt = v | VT_VECTOR;
  38. switch (vt)
  39. {
  40. case VT_VECTOR | VT_UI1:
  41. cbElement = sizeof(caub.pElems[0]);
  42. break;
  43. case VT_VECTOR | VT_I2:
  44. case VT_VECTOR | VT_UI2:
  45. case VT_VECTOR | VT_BOOL:
  46. cbElement = sizeof(cai.pElems[0]);
  47. break;
  48. case VT_VECTOR | VT_I4:
  49. case VT_VECTOR | VT_UI4:
  50. case VT_VECTOR | VT_R4:
  51. case VT_VECTOR | VT_ERROR:
  52. cbElement = sizeof(cal.pElems[0]);
  53. break;
  54. case VT_VECTOR | VT_I8:
  55. case VT_VECTOR | VT_UI8:
  56. case VT_VECTOR | VT_R8:
  57. case VT_VECTOR | VT_CY:
  58. case VT_VECTOR | VT_DATE:
  59. case VT_VECTOR | VT_FILETIME:
  60. cbElement = sizeof(cah.pElems[0]);
  61. break;
  62. case VT_VECTOR | VT_CLSID:
  63. cbElement = sizeof(GUID);
  64. fZero = TRUE;
  65. break;
  66. case VT_VECTOR | VT_CF:
  67. cbElement = sizeof(CLIPDATA);
  68. fZero = TRUE;
  69. break;
  70. case VT_VECTOR | VT_BSTR:
  71. case VT_VECTOR | VT_LPSTR:
  72. case VT_VECTOR | VT_LPWSTR:
  73. cbElement = sizeof(VOID *);
  74. fZero = TRUE;
  75. break;
  76. case VT_VECTOR | VT_VARIANT:
  77. cbElement = sizeof(PROPVARIANT);
  78. ASSERT(VT_EMPTY == 0);
  79. fZero = TRUE;
  80. break;
  81. default:
  82. ASSERT(!"CAllocStorageVariant -- Invalid vector type");
  83. vt = VT_EMPTY;
  84. break;
  85. }
  86. if (vt != VT_EMPTY)
  87. {
  88. caub.cElems = 0;
  89. caub.pElems = (BYTE *) CoTaskMemAlloc(cElements * cbElement);
  90. if (caub.pElems != NULL)
  91. {
  92. if (fZero)
  93. {
  94. memset(caub.pElems, 0, cElements * cbElement);
  95. }
  96. caub.cElems = cElements;
  97. }
  98. }
  99. }
  100. VOID *
  101. CPropVariant::_AddStringToVector(
  102. unsigned pos,
  103. VOID *pv,
  104. ULONG cb)
  105. {
  106. ASSERT(vt == (VT_VECTOR | VT_BSTR) ||
  107. vt == (VT_VECTOR | VT_LPSTR) ||
  108. vt == (VT_VECTOR | VT_LPWSTR) ||
  109. vt == (VT_VECTOR | VT_CF) );
  110. ASSERT(calpstr.pElems != NULL);
  111. if (pos >= calpstr.cElems)
  112. {
  113. char **ppsz = calpstr.pElems;
  114. calpstr.pElems =
  115. (char **) CoTaskMemAlloc((pos + 1) * sizeof(calpstr.pElems[0]));
  116. if (calpstr.pElems == NULL)
  117. {
  118. calpstr.pElems = ppsz;
  119. return(NULL);
  120. }
  121. memcpy(calpstr.pElems, ppsz, calpstr.cElems * sizeof(calpstr.pElems[0]));
  122. memset(
  123. &calpstr.pElems[calpstr.cElems],
  124. 0,
  125. ((pos + 1) - calpstr.cElems) * sizeof(calpstr.pElems[0]));
  126. calpstr.cElems = pos + 1;
  127. CoTaskMemFree(ppsz);
  128. }
  129. LPSTR psz;
  130. if( (VT_VECTOR | VT_BSTR) == vt )
  131. {
  132. psz = (LPSTR) SysAllocString( (BSTR) pv );
  133. if (psz == NULL)
  134. {
  135. return(NULL);
  136. }
  137. if (calpstr.pElems[pos] != NULL)
  138. {
  139. SysFreeString((BSTR) calpstr.pElems[pos]);
  140. }
  141. calpstr.pElems[pos] = psz;
  142. }
  143. else
  144. {
  145. psz = (LPSTR) CoTaskMemAlloc((VT_BSTR == (vt & ~VT_VECTOR) )
  146. ? cb + sizeof(ULONG)
  147. : cb );
  148. if (psz == NULL)
  149. {
  150. return(NULL);
  151. }
  152. memcpy(psz, pv, cb);
  153. if (calpstr.pElems[pos] != NULL)
  154. {
  155. CoTaskMemFree(calpstr.pElems[pos]);
  156. }
  157. calpstr.pElems[pos] = psz;
  158. }
  159. return(calpstr.pElems[pos]);
  160. }
  161. VOID *
  162. CPropVariant::_AddScalerToVector(
  163. unsigned pos,
  164. VOID *pv,
  165. ULONG cb)
  166. {
  167. ASSERT(calpstr.pElems != NULL);
  168. if (pos >= calpstr.cElems)
  169. {
  170. char **ppsz = calpstr.pElems;
  171. calpstr.pElems =
  172. (char **) CoTaskMemAlloc((pos + 1) * cb);
  173. if (calpstr.pElems == NULL)
  174. {
  175. calpstr.pElems = ppsz;
  176. return(NULL);
  177. }
  178. memset(
  179. calpstr.pElems,
  180. 0,
  181. ((pos + 1) - calpstr.cElems) * cb);
  182. memcpy(calpstr.pElems, ppsz, calpstr.cElems * cb);
  183. calpstr.cElems = pos + 1;
  184. CoTaskMemFree(ppsz);
  185. }
  186. memcpy( (BYTE*)calpstr.pElems + pos*cb, pv, cb );
  187. return( (BYTE*)calpstr.pElems + pos*cb );
  188. }
  189. void
  190. CPropVariant::SetLPSTR(
  191. char const *psz,
  192. unsigned pos)
  193. {
  194. if (vt != (VT_VECTOR | VT_LPSTR))
  195. {
  196. PropVariantClear( this );
  197. new (this) CPropVariant(VT_LPSTR, pos);
  198. }
  199. _AddStringToVector(pos, (VOID *) psz, strlen(psz) + 1);
  200. }
  201. void
  202. CPropVariant::SetLPWSTR(
  203. WCHAR const *pwsz,
  204. unsigned pos)
  205. {
  206. if (vt != (VT_VECTOR | VT_LPWSTR))
  207. {
  208. PropVariantClear( this );
  209. new (this) CPropVariant(VT_LPWSTR, pos);
  210. }
  211. _AddStringToVector(pos, (VOID *) pwsz,
  212. sizeof(WCHAR) * (wcslen(pwsz) + 1) );
  213. }
  214. void
  215. CPropVariant::SetCF(
  216. const CLIPDATA *pclipdata,
  217. unsigned pos)
  218. {
  219. CLIPDATA *pclipdataNew;
  220. if (vt != (VT_VECTOR | VT_CF))
  221. {
  222. PropVariantClear( this );
  223. new (this) CPropVariant(VT_CF, pos);
  224. }
  225. pclipdataNew = (CLIPDATA*) _AddScalerToVector(pos, (VOID *) pclipdata, sizeof(CLIPDATA) );
  226. if( NULL != pclipdataNew
  227. &&
  228. NULL != pclipdata )
  229. {
  230. pclipdataNew->pClipData = (BYTE*) CoTaskMemAlloc( CBPCLIPDATA(*pclipdata) );
  231. if( NULL == pclipdataNew->pClipData )
  232. {
  233. ASSERT( !"Couldn't allocate pclipdataNew" );
  234. return;
  235. }
  236. else
  237. {
  238. pclipdataNew->cbSize = pclipdata->cbSize;
  239. pclipdataNew->ulClipFmt = pclipdata->ulClipFmt;
  240. memcpy( pclipdataNew->pClipData,
  241. pclipdata->pClipData,
  242. CBPCLIPDATA(*pclipdata) );
  243. return;
  244. }
  245. }
  246. }
  247. void
  248. CPropVariant::SetBSTR(
  249. const BSTR pbstr,
  250. unsigned int pos)
  251. {
  252. if (vt != (VT_VECTOR | VT_BSTR))
  253. {
  254. PropVariantClear( this );
  255. new (this) CPropVariant(VT_BSTR, pos+1);
  256. }
  257. _AddStringToVector(pos, (VOID *) pbstr,
  258. sizeof(OLECHAR) * (ocslen(pbstr) + 1) );
  259. }
  260. BSTR
  261. CPropVariant::GetBSTR( int nSubscript )
  262. {
  263. ASSERT( vt & VT_VECTOR );
  264. ASSERT( vt == (VT_BSTR | VT_VECTOR) );
  265. ASSERT( wReserved1 > 0 );
  266. if( wReserved1 > 0
  267. &&
  268. cabstr.cElems > 0
  269. &&
  270. wReserved1 <= cabstr.cElems )
  271. {
  272. int nSubscript = wReserved1 - 1;
  273. wReserved1 = INVALID_SUBSCRIPT;
  274. return( cabstr.pElems[ nSubscript ] );
  275. }
  276. else
  277. return( NULL );
  278. }
  279. CPropVariant & CPropVariant::operator=(LPPROPVARIANT lppropvar)
  280. {
  281. if( INVALID_SUBSCRIPT == wReserved1 )
  282. {
  283. ASSERT( INVALID_SUBSCRIPT != wReserved1 );
  284. PropVariantClear(this);
  285. Init();
  286. return (*this);
  287. }
  288. else
  289. {
  290. if( !(vt & VT_VECTOR)
  291. ||
  292. (vt & ~VT_VECTOR) != VT_VARIANT )
  293. {
  294. USHORT wReserved1Save = wReserved1;
  295. PropVariantClear(this);
  296. Init(VT_VARIANT, wReserved1Save );
  297. wReserved1 = wReserved1Save;
  298. }
  299. SetLPPROPVARIANT( lppropvar, wReserved1 - 1 );
  300. wReserved1 = INVALID_SUBSCRIPT;
  301. return (*this);
  302. }
  303. }
  304. CPropVariant::operator LPPROPVARIANT()
  305. {
  306. if( vt & VT_VECTOR )
  307. {
  308. if( wReserved1 > 0
  309. &&
  310. capropvar.cElems > 0
  311. &&
  312. wReserved1 <= capropvar.cElems )
  313. {
  314. int nSubscript = wReserved1 - 1;
  315. wReserved1 = INVALID_SUBSCRIPT;
  316. return( &capropvar.pElems[ nSubscript ] );
  317. }
  318. else
  319. {
  320. ASSERT( INVALID_SUBSCRIPT == wReserved1 );
  321. return( (LPPROPVARIANT) this );
  322. }
  323. }
  324. else
  325. return( (LPPROPVARIANT) this );
  326. }
  327. void
  328. CPropVariant::SetLPPROPVARIANT( LPPROPVARIANT lppropvar, unsigned pos )
  329. {
  330. if (vt != (VT_VECTOR | VT_VARIANT))
  331. {
  332. PropVariantClear( this );
  333. new (this) CPropVariant(VT_VARIANT, pos + 1);
  334. }
  335. if (pos >= capropvar.cElems)
  336. {
  337. LPPROPVARIANT rgpropvar = capropvar.pElems;
  338. capropvar.pElems =
  339. (PROPVARIANT *) CoTaskMemAlloc((pos + 1) * sizeof(capropvar.pElems[0]));
  340. if (capropvar.pElems == NULL)
  341. {
  342. capropvar.pElems = rgpropvar;
  343. return;
  344. }
  345. memcpy(capropvar.pElems, rgpropvar, capropvar.cElems * sizeof(capropvar.pElems[0]));
  346. memset(
  347. &capropvar.pElems[capropvar.cElems],
  348. 0,
  349. ((pos + 1) - capropvar.cElems) * sizeof(capropvar.pElems[0]));
  350. capropvar.cElems = pos + 1;
  351. CoTaskMemFree(rgpropvar);
  352. }
  353. PropVariantClear( &capropvar.pElems[pos] );
  354. PropVariantCopy( &capropvar.pElems[pos], lppropvar );
  355. return;
  356. }
  357. void CPropVariant::Init(const CLIPDATA *p)
  358. {
  359. Init();
  360. if( NULL == p )
  361. return;
  362. pclipdata = (CLIPDATA*) CoTaskMemAlloc( sizeof(CLIPDATA) );
  363. if( NULL == pclipdata )
  364. {
  365. return;
  366. }
  367. pclipdata->cbSize = p->cbSize;
  368. pclipdata->ulClipFmt = p->ulClipFmt;
  369. pclipdata->pClipData = NULL;
  370. if( sizeof(pclipdata->ulClipFmt) > p->cbSize )
  371. {
  372. Init();
  373. return;
  374. }
  375. if( NULL != p->pClipData )
  376. {
  377. pclipdata->pClipData = (BYTE*) CoTaskMemAlloc( pclipdata->cbSize
  378. - sizeof(pclipdata->ulClipFmt) );
  379. if( NULL == pclipdata->pClipData )
  380. return;
  381. memcpy( pclipdata->pClipData, p->pClipData, pclipdata->cbSize - sizeof(pclipdata->ulClipFmt) );
  382. }
  383. vt = VT_CF;
  384. }
  385. void
  386. CPropVariant::SetCLSID( const CLSID &clsid )
  387. {
  388. PropVariantClear( this );
  389. puuid = (CLSID*) CoTaskMemAlloc( sizeof(CLSID) );
  390. if( NULL == puuid )
  391. {
  392. assert(FALSE && "out of memory!");
  393. exit(-1);
  394. }
  395. *puuid = clsid;
  396. vt = VT_CLSID;
  397. }
  398. void
  399. CPropVariant::SetCLSID(
  400. const CLSID &clsid,
  401. unsigned pos)
  402. {
  403. CLSID *pclsidNew;
  404. if (vt != (VT_VECTOR | VT_CLSID))
  405. {
  406. PropVariantClear( this );
  407. new (this) CPropVariant(VT_CLSID, pos);
  408. }
  409. pclsidNew = (CLSID*) _AddScalerToVector(pos, (VOID *) &clsid, sizeof(CLSID) );
  410. if( NULL != pclsidNew )
  411. {
  412. *pclsidNew = clsid;
  413. }
  414. }
  415. HRESULT
  416. CPropVariant::Compare( PROPVARIANT *ppropvar1, PROPVARIANT *ppropvar2 )
  417. {
  418. if( RtlCompareVariants( CP_ACP, // Ignored,
  419. ppropvar1,
  420. ppropvar2 ))
  421. {
  422. return( S_OK );
  423. }
  424. else
  425. {
  426. return( S_FALSE );
  427. }
  428. }