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.

841 lines
30 KiB

  1. #include "oleds.hxx"
  2. #if (!defined(BUILD_FOR_NT40))
  3. // ---------------- C D B P R O P E R T I E S C O D E ----------------------
  4. //-----------------------------------------------------------------------------
  5. // CDBProperties::CDBProperties
  6. //
  7. // @mfunc
  8. // CDBProperties constructor.
  9. //
  10. // @rdesc NONE
  11. //-----------------------------------------------------------------------------
  12. CDBProperties::CDBProperties():
  13. _cPropSets(0),
  14. _aPropSets(0),
  15. _cPropInfoSets(0),
  16. _aPropInfoSets(0)
  17. {
  18. }
  19. //-----------------------------------------------------------------------------
  20. // CDBProperties::~CDBProperties
  21. //
  22. // @mfunc
  23. // CDBProperties destructor. Release storage used by CDBProperties.
  24. //
  25. // @rdesc NONE
  26. //-----------------------------------------------------------------------------
  27. CDBProperties::~CDBProperties()
  28. {
  29. ULONG iSet, iProp, iSetInfo;
  30. for (iSet=0; iSet<_cPropSets; ++iSet)
  31. {
  32. for (iProp=0; iProp <_aPropSets[iSet].cProperties; ++iProp)
  33. VariantClear(&(_aPropSets[iSet].rgProperties[iProp].vValue));
  34. delete [] _aPropSets[iSet].rgProperties;
  35. }
  36. delete [] _aPropSets;
  37. for (iSet=0; iSet<_cPropInfoSets; ++iSet)
  38. {
  39. delete [] _aPropInfoSets[iSet].rgPropertyInfos;
  40. }
  41. delete [] _aPropInfoSets;
  42. }
  43. //-----------------------------------------------------------------------------
  44. // CDBProperties::GetPropertySet
  45. //
  46. // @mfunc Looks up a property set by its GUID.
  47. //
  48. // @rdesc Pointer to desired property set, or 0 if not found.
  49. //-----------------------------------------------------------------------------
  50. DBPROPSET*
  51. CDBProperties::GetPropertySet(const GUID& guid) const
  52. {
  53. DBPROPSET* pPropSet = 0; // the answer, assume not found
  54. // linear search
  55. ULONG iPropSet;
  56. for (iPropSet=0; iPropSet<_cPropSets; ++iPropSet)
  57. {
  58. if (IsEqualGUID(guid, _aPropSets[iPropSet].guidPropertySet))
  59. {
  60. pPropSet = &_aPropSets[iPropSet];
  61. break;
  62. }
  63. }
  64. return ( pPropSet );
  65. }
  66. //-----------------------------------------------------------------------------
  67. // CDBProperties::GetPropertyInfoSet
  68. //
  69. // @mfunc Looks up a property info set by its GUID.
  70. //
  71. // @rdesc Pointer to desired property info set, or 0 if not found.
  72. //-----------------------------------------------------------------------------
  73. DBPROPINFOSET*
  74. CDBProperties::GetPropertyInfoSet(const GUID& guid) const
  75. {
  76. DBPROPINFOSET* pPropInfoSet = 0; // the answer, assume not found
  77. // linear search
  78. ULONG iPropSet;
  79. for (iPropSet=0; iPropSet<_cPropInfoSets; ++iPropSet)
  80. {
  81. if (IsEqualGUID(guid, _aPropInfoSets[iPropSet].guidPropertySet))
  82. {
  83. pPropInfoSet = &_aPropInfoSets[iPropSet];
  84. break;
  85. }
  86. }
  87. return ( pPropInfoSet );
  88. }
  89. //-----------------------------------------------------------------------------
  90. // CDBProperties::CopyPropertySet
  91. //
  92. // @mfunc Makes a copy of a property set, given its GUID.
  93. //
  94. // @rdesc
  95. // @flag S_OK | copying succeeded,
  96. // @flag E_FAIL | no property set for given GUID,
  97. // @flag E_OUTOFMEMORY | copying failed because of memory allocation.
  98. //-----------------------------------------------------------------------------
  99. HRESULT
  100. CDBProperties::CopyPropertySet(const GUID& guid, DBPROPSET* pPropSetDst) const
  101. {
  102. ADsAssert(pPropSetDst && "must supply a PropSet pointer");
  103. HRESULT hr = S_OK;
  104. const DBPROPSET* pPropSetSrc = GetPropertySet(guid);
  105. ULONG iProp;
  106. if (pPropSetSrc == 0) // not found
  107. {
  108. hr = E_FAIL;
  109. goto Cleanup;
  110. }
  111. // start with shallow copy
  112. *pPropSetDst = *pPropSetSrc;
  113. // allocate property array
  114. pPropSetDst->rgProperties = (DBPROP*)
  115. CoTaskMemAlloc(pPropSetSrc->cProperties * sizeof(DBPROP));
  116. if (pPropSetDst->rgProperties == 0)
  117. {
  118. pPropSetDst->cProperties = 0; // defensive
  119. hr = E_OUTOFMEMORY;
  120. goto Cleanup;
  121. }
  122. memcpy( pPropSetDst->rgProperties,
  123. pPropSetSrc->rgProperties,
  124. pPropSetSrc->cProperties*sizeof(DBPROP));
  125. // copy the property array
  126. for (iProp=0; iProp<pPropSetSrc->cProperties; ++iProp)
  127. {
  128. VariantInit(&(pPropSetDst->rgProperties[iProp].vValue));
  129. if(FAILED(hr = VariantCopy(&(pPropSetDst->rgProperties[iProp].vValue),
  130. (VARIANT *)&(pPropSetSrc->rgProperties[iProp].vValue))))
  131. {
  132. while(iProp)
  133. {
  134. iProp--;
  135. VariantClear(&(pPropSetDst->rgProperties[iProp].vValue));
  136. }
  137. CoTaskMemFree(pPropSetDst->rgProperties);
  138. pPropSetDst->rgProperties = NULL;
  139. pPropSetDst->cProperties = 0; // defensive
  140. goto Cleanup;
  141. }
  142. }
  143. Cleanup:
  144. RRETURN ( hr );
  145. }
  146. //-----------------------------------------------------------------------------
  147. // CDBProperties::CopyPropertyInfoSet
  148. //
  149. // @mfunc Makes a copy of a property info set, given its GUID.
  150. //
  151. // @rdesc
  152. // @flag S_OK | copying succeeded,
  153. // @flag E_FAIL | no property set for given GUID,
  154. // @flag E_OUTOFMEMORY | copying failed because of memory allocation.
  155. //-----------------------------------------------------------------------------
  156. HRESULT
  157. CDBProperties::CopyPropertyInfoSet
  158. (
  159. const GUID& guid,
  160. DBPROPINFOSET* pPropInfoSetDst,
  161. WCHAR** ppDescBuffer,
  162. ULONG_PTR* pcchDescBuffer,
  163. ULONG_PTR* pichCurrent
  164. ) const
  165. {
  166. ADsAssert(pPropInfoSetDst && "must supply a PropSet pointer");
  167. HRESULT hr = S_OK;
  168. const DBPROPINFOSET* pPropInfoSetSrc = GetPropertyInfoSet(guid);
  169. if (pPropInfoSetSrc == 0) // not found
  170. {
  171. hr = E_FAIL;
  172. goto Cleanup;
  173. }
  174. // start with shallow copy
  175. *pPropInfoSetDst = *pPropInfoSetSrc;
  176. // allocate property array
  177. pPropInfoSetDst->rgPropertyInfos = (DBPROPINFO *) CoTaskMemAlloc(
  178. pPropInfoSetSrc->cPropertyInfos * sizeof(DBPROPINFO));
  179. if (pPropInfoSetDst->rgPropertyInfos == 0)
  180. {
  181. pPropInfoSetDst->cPropertyInfos = 0; // defensive
  182. hr = E_OUTOFMEMORY;
  183. goto Cleanup;
  184. }
  185. memcpy( pPropInfoSetDst->rgPropertyInfos,
  186. pPropInfoSetSrc->rgPropertyInfos,
  187. pPropInfoSetSrc->cPropertyInfos*sizeof(DBPROPINFO));
  188. if(FAILED(hr =CopyPropertyDescriptions(
  189. pPropInfoSetDst,
  190. ppDescBuffer,
  191. pcchDescBuffer,
  192. pichCurrent)))
  193. {
  194. CoTaskMemFree(pPropInfoSetDst->rgPropertyInfos);
  195. pPropInfoSetDst->rgPropertyInfos = NULL;
  196. pPropInfoSetDst->cPropertyInfos = 0; // defensive
  197. hr = E_OUTOFMEMORY;
  198. }
  199. Cleanup:
  200. RRETURN ( hr );
  201. }
  202. //-----------------------------------------------------------------------------
  203. // CDBProperties::GetProperty
  204. //
  205. // @mfunc Looks up a property by its property set GUID and ID.
  206. //
  207. // @rdesc Pointer to DBPROP for the property, or 0 if not found.
  208. //-----------------------------------------------------------------------------
  209. const DBPROP*
  210. CDBProperties::GetProperty(const GUID& guid, DBPROPID dwId) const
  211. {
  212. ULONG iProp;
  213. const DBPROPSET* pPropSet = GetPropertySet(guid);
  214. const DBPROP* pProp = 0; // the answer, assume not found
  215. if (pPropSet == 0) // no properties for desired property set
  216. goto Cleanup;
  217. // look up the desired property in the property set
  218. for (iProp=0; iProp<pPropSet->cProperties; ++iProp)
  219. {
  220. if (dwId == pPropSet->rgProperties[iProp].dwPropertyID)
  221. {
  222. pProp = & pPropSet->rgProperties[iProp];
  223. break;
  224. }
  225. }
  226. Cleanup:
  227. return ( pProp );
  228. }
  229. //-----------------------------------------------------------------------------
  230. // CDBProperties::GetPropertyInfo
  231. //
  232. // @mfunc Looks up a property info by its property set GUID and ID.
  233. //
  234. // @rdesc Pointer to DBPROPINFO for the property info, or 0 if not found.
  235. //-----------------------------------------------------------------------------
  236. const DBPROPINFO UNALIGNED*
  237. CDBProperties::GetPropertyInfo(const GUID& guid, DBPROPID dwId) const
  238. {
  239. ULONG iPropInfo;
  240. const DBPROPINFOSET* pPropInfoSet = GetPropertyInfoSet(guid);
  241. const DBPROPINFO UNALIGNED* pPropInfo = 0; // the answer, assume not found
  242. if (pPropInfoSet == 0) // no properties for desired property set
  243. goto Cleanup;
  244. // look up the desired property in the property set
  245. for (iPropInfo=0; iPropInfo <pPropInfoSet->cPropertyInfos; ++iPropInfo)
  246. {
  247. if (dwId == pPropInfoSet->rgPropertyInfos[iPropInfo].dwPropertyID)
  248. {
  249. pPropInfo = & pPropInfoSet->rgPropertyInfos[iPropInfo];
  250. break;
  251. }
  252. }
  253. Cleanup:
  254. return ( pPropInfo );
  255. }
  256. //-----------------------------------------------------------------------------
  257. // CDBProperties::SetProperty
  258. //
  259. // @mfunc Adds a new property, or resets an existing one
  260. // This overloaded function is same as the other except that the
  261. // last parameter is of type PWSTR [mgorti]
  262. //
  263. // @rdesc
  264. // @flag S_OK | property added/reset,
  265. // @flag E_OUTOFMEMORY | no memory for new property set or new property.
  266. //-----------------------------------------------------------------------------
  267. HRESULT
  268. CDBProperties::SetProperty(const GUID& guid,
  269. const DBPROP& prop,
  270. BOOL fAddNew,
  271. PWSTR pwszDesc)
  272. {
  273. HRESULT hr;
  274. DBPROP *pProp; // pointer to array entry for new property
  275. ULONG iProp;
  276. DBPROPSET* pPropSet = GetPropertySet(guid);
  277. if (pPropSet == 0) // no properties yet in desired property set
  278. {
  279. if(!fAddNew)
  280. {
  281. hr = E_FAIL;
  282. goto Cleanup;
  283. }
  284. // get a new property set array
  285. DBPROPSET * aNewPropSets = new DBPROPSET[_cPropSets + 1];
  286. if (aNewPropSets == 0)
  287. {
  288. hr = E_OUTOFMEMORY;
  289. goto Cleanup;
  290. }
  291. memcpy(aNewPropSets, _aPropSets, _cPropSets *sizeof(DBPROPSET));
  292. // add the new property set
  293. pPropSet = & aNewPropSets[_cPropSets];
  294. pPropSet->guidPropertySet = guid;
  295. pPropSet->cProperties = 0;
  296. pPropSet->rgProperties = 0;
  297. // release the old array, install the new one
  298. delete [] _aPropSets;
  299. _aPropSets = aNewPropSets;
  300. ++ _cPropSets;
  301. }
  302. // look for the desired property.
  303. if(!fAddNew)
  304. {
  305. pProp = 0;
  306. for (iProp=0; iProp<pPropSet->cProperties; ++iProp)
  307. {
  308. if (pPropSet->rgProperties[iProp].dwPropertyID ==
  309. prop.dwPropertyID)
  310. {
  311. pProp = &pPropSet->rgProperties[iProp];
  312. break;
  313. }
  314. }
  315. if (pProp == 0)
  316. {
  317. hr = E_FAIL;
  318. goto Cleanup;
  319. }
  320. }
  321. // if it's a new property, add it. OLE-DB doesn't provide for any "unused"
  322. // portion in the array of DBPROPS, so we must reallocate the array every
  323. // time we add a property.
  324. else
  325. {
  326. ULONG cPropLeftOver;
  327. // allocate new property array
  328. cPropLeftOver =
  329. C_PROP_INCR -
  330. (pPropSet->cProperties + C_PROP_INCR - 1)%C_PROP_INCR - 1;
  331. if(cPropLeftOver)
  332. {
  333. pProp = &pPropSet->rgProperties[pPropSet->cProperties];
  334. }
  335. else
  336. {
  337. DBPROP* aNewProperties =
  338. new DBPROP[pPropSet->cProperties + C_PROP_INCR];
  339. if (aNewProperties == 0)
  340. {
  341. hr = E_OUTOFMEMORY;
  342. goto Cleanup;
  343. }
  344. // copy old array into new
  345. memcpy( aNewProperties,
  346. pPropSet->rgProperties,
  347. pPropSet->cProperties *sizeof(DBPROP));
  348. // prepare to use new property entry
  349. pProp = & aNewProperties[pPropSet->cProperties];
  350. // release old array, install new
  351. delete [] pPropSet->rgProperties;
  352. pPropSet->rgProperties = aNewProperties;
  353. }
  354. ++ pPropSet->cProperties;
  355. }
  356. // copy the property into my array
  357. if(!fAddNew)
  358. {
  359. DBPROP propSave;
  360. propSave = *pProp;
  361. *pProp = prop;
  362. VariantInit(&(pProp->vValue));
  363. if(FAILED(hr = VariantCopy( &(pProp->vValue),
  364. (VARIANT *)&(prop.vValue))))
  365. {
  366. *pProp = propSave;
  367. goto Cleanup;
  368. }
  369. }
  370. else
  371. {
  372. DBPROPINFO propinfo;
  373. *pProp = prop;
  374. propinfo.pwszDescription = pwszDesc;
  375. propinfo.dwPropertyID = prop.dwPropertyID;
  376. propinfo.dwFlags = DBPROPFLAGS_READ;
  377. if(guid == DBPROPSET_DBINIT)
  378. propinfo.dwFlags |= DBPROPFLAGS_DBINIT;
  379. else if(guid == DBPROPSET_DATASOURCEINFO)
  380. propinfo.dwFlags |= DBPROPFLAGS_DATASOURCEINFO;
  381. else
  382. propinfo.dwFlags |= DBPROPFLAGS_ROWSET;
  383. propinfo.vtType = V_VT(&(prop.vValue));
  384. VariantInit(&(propinfo.vValues));
  385. if(FAILED(hr = SetPropertyInfo(guid, propinfo)))
  386. goto Cleanup;
  387. }
  388. hr = S_OK;
  389. Cleanup:
  390. RRETURN ( hr );
  391. }
  392. //-----------------------------------------------------------------------------
  393. // CDBProperties::SetPropertyInfo
  394. //
  395. // @mfunc Adds a new property info, or resets an existing one.
  396. //
  397. // @rdesc
  398. // @flag S_OK | property info added/reset,
  399. // @flag E_OUTOFMEMORY | no memory for new property info set
  400. // or new property info.
  401. //-----------------------------------------------------------------------------
  402. HRESULT
  403. CDBProperties::SetPropertyInfo(const GUID& guid, const DBPROPINFO& propinfo)
  404. {
  405. HRESULT hr;
  406. PDBPROPINFO pPropInfo; // pointer to array entry for new property
  407. ULONG iPropInfo;
  408. DBPROPINFOSET* pPropInfoSet = GetPropertyInfoSet(guid);
  409. if (pPropInfoSet == 0) // no properties yet in desired property set
  410. {
  411. // get a new property set array
  412. DBPROPINFOSET * aNewPropInfoSets =
  413. new DBPROPINFOSET[_cPropInfoSets + 1];
  414. if (aNewPropInfoSets == 0)
  415. {
  416. hr = E_OUTOFMEMORY;
  417. goto Cleanup;
  418. }
  419. memcpy( aNewPropInfoSets,
  420. _aPropInfoSets,
  421. _cPropInfoSets *sizeof(DBPROPINFOSET));
  422. // add the new property set
  423. pPropInfoSet = & aNewPropInfoSets[_cPropInfoSets];
  424. pPropInfoSet->guidPropertySet = guid;
  425. pPropInfoSet->cPropertyInfos = 0;
  426. pPropInfoSet->rgPropertyInfos = 0;
  427. // release the old array, install the new one
  428. delete [] _aPropInfoSets;
  429. _aPropInfoSets = aNewPropInfoSets;
  430. ++ _cPropInfoSets;
  431. }
  432. // look for the desired property.
  433. pPropInfo = 0;
  434. for (iPropInfo=0; iPropInfo<pPropInfoSet->cPropertyInfos; ++iPropInfo)
  435. {
  436. if (pPropInfoSet->rgPropertyInfos[iPropInfo].dwPropertyID ==
  437. propinfo.dwPropertyID)
  438. {
  439. pPropInfo = &pPropInfoSet->rgPropertyInfos[iPropInfo];
  440. break;
  441. }
  442. }
  443. // if it's a new property, add it. OLE-DB doesn't provide for any "unused"
  444. // portion in the array of DBPROPS, so we must reallocate the array every
  445. // time we add a property.
  446. if (pPropInfo == 0)
  447. {
  448. ULONG cPropLeftOver;
  449. // allocate new property array
  450. cPropLeftOver =
  451. C_PROP_INCR -
  452. (pPropInfoSet->cPropertyInfos + C_PROP_INCR - 1)%C_PROP_INCR - 1;
  453. if(cPropLeftOver)
  454. {
  455. pPropInfo =
  456. &pPropInfoSet->rgPropertyInfos[pPropInfoSet->cPropertyInfos];
  457. }
  458. else
  459. {
  460. DBPROPINFO* aNewPropertyInfos =
  461. new DBPROPINFO[pPropInfoSet->cPropertyInfos + C_PROP_INCR];
  462. if (aNewPropertyInfos == 0)
  463. {
  464. hr = E_OUTOFMEMORY;
  465. goto Cleanup;
  466. }
  467. // copy old array into new
  468. memcpy( aNewPropertyInfos,
  469. pPropInfoSet->rgPropertyInfos,
  470. pPropInfoSet->cPropertyInfos *sizeof(DBPROPINFO));
  471. // prepare to use new property entry
  472. pPropInfo = & aNewPropertyInfos[pPropInfoSet->cPropertyInfos];
  473. // release old array, install new
  474. delete [] pPropInfoSet->rgPropertyInfos;
  475. pPropInfoSet->rgPropertyInfos = aNewPropertyInfos;
  476. }
  477. ++ pPropInfoSet->cPropertyInfos;
  478. }
  479. // copy the property into my array
  480. *pPropInfo = propinfo;
  481. hr = S_OK;
  482. Cleanup:
  483. RRETURN ( hr );
  484. }
  485. //-----------------------------------------------------------------------------
  486. // CDBProperties::LoadDescription
  487. //
  488. // @mfunc Loads a localized string from the localization DLL.
  489. //
  490. // @rdesc Count of characters returned in the buffer.
  491. //-----------------------------------------------------------------------------
  492. int
  493. CDBProperties::LoadDescription
  494. (
  495. ULONG ids, //@parm IN | String ID
  496. PWSTR pwszBuff, //@parm OUT | Temporary buffer
  497. ULONG cchBuff //@parm IN | Count of characters buffer can hold
  498. ) const
  499. {
  500. return ( 0 );
  501. // return( LoadStringW(g_hinstDll, ids, pwszBuff, cchBuff) );
  502. }
  503. //-----------------------------------------------------------------------------
  504. // CDBProperties::CopyPropertyDescriptions
  505. //
  506. // @mfunc Copies into a buffer descriptions of properties in a given set.
  507. //
  508. // @rdesc
  509. // @flag S_OK | copying of property descriptions succeeded,
  510. // @flag E_OUTOFMEMORY | buffer for property descriptions could not
  511. // be allocated/extended.
  512. //-----------------------------------------------------------------------------
  513. HRESULT
  514. CDBProperties::CopyPropertyDescriptions
  515. (
  516. DBPROPINFOSET* pPropInfoSet,
  517. WCHAR** ppDescBuffer,
  518. ULONG_PTR* pcchDescBuffer,
  519. ULONG_PTR* pichCurrent
  520. ) const
  521. {
  522. LONG iprop, cchLeft, cchNew;
  523. int cchCopied;
  524. WCHAR *pwszTmp;
  525. if(ppDescBuffer)
  526. {
  527. cchLeft = (LONG)*pcchDescBuffer - (LONG)*pichCurrent;
  528. for(iprop =0; (ULONG)iprop <pPropInfoSet->cPropertyInfos; iprop++)
  529. {
  530. if(pPropInfoSet->rgPropertyInfos[iprop].dwFlags ==
  531. DBPROPFLAGS_NOTSUPPORTED)
  532. continue;
  533. if(cchLeft < (LONG)CCHAR_MAX_PROP_STR_LENGTH)
  534. {
  535. cchNew = CCHAR_AVERAGE_PROP_STR_LENGTH *
  536. (pPropInfoSet->cPropertyInfos - iprop - 1) +
  537. CCHAR_MAX_PROP_STR_LENGTH +
  538. *pcchDescBuffer - cchLeft;
  539. pwszTmp = (WCHAR *)CoTaskMemAlloc(cchNew *sizeof(WCHAR));
  540. if(pwszTmp == NULL)
  541. RRETURN ( E_OUTOFMEMORY );
  542. if(*ppDescBuffer)
  543. {
  544. memcpy( pwszTmp,
  545. *ppDescBuffer,
  546. (*pcchDescBuffer -cchLeft)*sizeof(WCHAR));
  547. CoTaskMemFree(*ppDescBuffer);
  548. }
  549. cchLeft += cchNew -(LONG)*pcchDescBuffer;
  550. *ppDescBuffer = pwszTmp;
  551. *pcchDescBuffer = cchNew;
  552. }
  553. //?? Do we need to load these strings from resources ??
  554. //$TODO$ Raid #86943 Copy property descriptions from source to destination buffer.
  555. cchCopied = wcslen(pPropInfoSet->rgPropertyInfos[iprop].pwszDescription);
  556. wcscpy((WCHAR *)(*ppDescBuffer) + *pichCurrent,
  557. pPropInfoSet->rgPropertyInfos[iprop].pwszDescription);
  558. pPropInfoSet->rgPropertyInfos[iprop].pwszDescription =
  559. (WCHAR *)(*pichCurrent);
  560. *pichCurrent += (cchCopied +1);
  561. cchLeft -= (cchCopied +1);
  562. }
  563. }
  564. else {
  565. // We need to NULL out the pwszDescription values:
  566. //
  567. for(iprop =0; (ULONG)iprop <pPropInfoSet->cPropertyInfos; iprop++)
  568. {
  569. pPropInfoSet->rgPropertyInfos[iprop].pwszDescription = NULL;
  570. }
  571. }
  572. RRETURN ( NOERROR );
  573. }
  574. //-----------------------------------------------------------------------------
  575. // CDBProperties::CheckAndInitPropArgs
  576. //
  577. // @mfunc Helper function used while getting property sets.
  578. // Used to check and get information about property sets.
  579. // Tells if the caller is requesting
  580. // special sets or the set of properties in error.
  581. //
  582. // @rdesc
  583. // @flag S_OK | check succeeded,
  584. // @flag E_INVALIDARG | one of the arguments is invalid.
  585. //-----------------------------------------------------------------------------
  586. HRESULT
  587. CDBProperties::CheckAndInitPropArgs
  588. (
  589. ULONG cPropertySets, // IN | Number of property sets
  590. const DBPROPIDSET rgPropertySets[], // IN | Property Sets
  591. ULONG *pcPropertySets, // OUT | Count of structs returned
  592. void **prgPropertySets,// OUT | Array of Properties
  593. BOOL *pfPropInError,
  594. BOOL *pfPropSpecial
  595. )
  596. {
  597. LONG ipropset;
  598. ULONG cpropsetSpecial;
  599. // Initialize
  600. if( pcPropertySets )
  601. *pcPropertySets = 0;
  602. if( prgPropertySets )
  603. *prgPropertySets = NULL;
  604. if(pfPropInError)
  605. *pfPropInError = FALSE;
  606. if(pfPropSpecial)
  607. *pfPropSpecial = FALSE;
  608. // Check Arguments, on failure post HRESULT to error queue
  609. if( ((cPropertySets > 0) && !rgPropertySets) ||
  610. !pcPropertySets ||
  611. !prgPropertySets )
  612. RRETURN ( E_INVALIDARG );
  613. // New argument check for > 1 cPropertyIDs and NULL pointer for
  614. // array of property ids.
  615. for(ipropset=0, cpropsetSpecial = 0;
  616. (ULONG)ipropset<cPropertySets;
  617. ipropset++)
  618. {
  619. if( rgPropertySets[ipropset].cPropertyIDs &&
  620. !(rgPropertySets[ipropset].rgPropertyIDs) )
  621. RRETURN (E_INVALIDARG);
  622. //when passing property set DBPROPSET_PROPERTIESINERROR,
  623. //this is the only set the caller can ask. Also, the
  624. //count of propertyIDs and the propertyID array must be
  625. //NULL in this case.
  626. if( rgPropertySets[ipropset].guidPropertySet ==
  627. DBPROPSET_PROPERTIESINERROR )
  628. {
  629. if(pfPropInError)
  630. {
  631. if(cPropertySets >1
  632. || rgPropertySets[ipropset].cPropertyIDs
  633. || rgPropertySets[ipropset].rgPropertyIDs)
  634. RRETURN (E_INVALIDARG);
  635. else
  636. *pfPropInError = TRUE;
  637. }
  638. }
  639. //Count the number of special property sets being asked.
  640. else if( rgPropertySets[ipropset].guidPropertySet ==
  641. DBPROPSET_DATASOURCEALL
  642. || rgPropertySets[ipropset].guidPropertySet ==
  643. DBPROPSET_DATASOURCEINFOALL
  644. || rgPropertySets[ipropset].guidPropertySet ==
  645. DBPROPSET_DBINITALL
  646. || rgPropertySets[ipropset].guidPropertySet ==
  647. DBPROPSET_SESSIONALL
  648. || rgPropertySets[ipropset].guidPropertySet ==
  649. DBPROPSET_ROWSETALL)
  650. cpropsetSpecial++;
  651. }
  652. //When requesting special property sets, all of them
  653. //must be special or none.
  654. if(cpropsetSpecial)
  655. {
  656. if(pfPropSpecial)
  657. *pfPropSpecial = TRUE;
  658. if(cpropsetSpecial < cPropertySets)
  659. RRETURN (E_INVALIDARG);
  660. }
  661. else if(pfPropSpecial)
  662. *pfPropSpecial = FALSE;
  663. RRETURN ( NOERROR );
  664. }
  665. //-----------------------------------------------------------------------------
  666. // CDBProperties::VerifySetPropertiesArgs
  667. //
  668. // @mfunc Helper function used in IDBProperties::SetProperties. Validates
  669. // arguments passed to IDBProperties::SetProperties.
  670. //
  671. // @rdesc
  672. // @flag S_OK | Validation succeeded.
  673. // @flag E_INVALIDARG | Validation failed - one of the arguments
  674. // is in error.
  675. //-----------------------------------------------------------------------------
  676. HRESULT
  677. CDBProperties::VerifySetPropertiesArgs
  678. (
  679. ULONG cPropertySets, //@parm IN | Count of properties
  680. DBPROPSET rgPropertySets[] //@parm IN | Properties
  681. )
  682. {
  683. ULONG ipropset;
  684. if(cPropertySets && rgPropertySets == NULL)
  685. RRETURN (E_INVALIDARG);
  686. for(ipropset =0; ipropset <cPropertySets; ipropset++)
  687. if( rgPropertySets[ipropset].cProperties &&
  688. rgPropertySets[ipropset].rgProperties == NULL)
  689. RRETURN (E_INVALIDARG);
  690. RRETURN ( NOERROR );
  691. }
  692. //-----------------------------------------------------------------------------
  693. // VariantsEqual
  694. //
  695. // @mfunc Tests two variants holding property values for equality.
  696. //
  697. // @rdesc
  698. // @flag TRUE | values equal,
  699. // @flag FALSE | values unequal.
  700. //-----------------------------------------------------------------------------
  701. BOOL VariantsEqual
  702. (
  703. VARIANT *pvar1,
  704. VARIANT *pvar2
  705. )
  706. {
  707. if(V_VT(pvar1) != V_VT(pvar1))
  708. return ( FALSE );
  709. else if(V_VT(pvar1) == VT_I2)
  710. return (V_I2(pvar1) == V_I2(pvar2));
  711. else if(V_VT(pvar1) == VT_BOOL)
  712. return (V_BOOL(pvar1) == V_BOOL(pvar2));
  713. else if(V_VT(pvar1) == VT_BSTR)
  714. {
  715. if(V_BSTR(pvar1) == NULL || V_BSTR(pvar2) == NULL)
  716. return (V_BSTR(pvar1) == V_BSTR(pvar2));
  717. else
  718. return (wcscmp(V_BSTR(pvar1), V_BSTR(pvar2)) == 0);
  719. }
  720. else
  721. return (V_I4(pvar1) == V_I4(pvar2));
  722. }
  723. #endif