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.

2110 lines
70 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1994 - 1999.
  5. //
  6. // File: propbase.cxx
  7. //
  8. // Contents: Utility object containing implementation of base property
  9. //
  10. // Classes: CUtlProps
  11. //
  12. // History: 10-28-97 danleg Created from monarch uprops.cpp
  13. //
  14. //----------------------------------------------------------------------------
  15. #include <pch.cxx>
  16. #pragma hdrstop
  17. #include "propbase.hxx"
  18. //+---------------------------------------------------------------------------
  19. //
  20. // Method: CUtlProps::CUtlProps, public
  21. //
  22. // Synopsis: Constructor for CUtlProps
  23. //
  24. // History: 11-12-97 danleg Created from Monarch
  25. //
  26. //----------------------------------------------------------------------------
  27. CUtlProps::CUtlProps( DWORD dwFlags ) :
  28. _cPropSetDex(0),
  29. _cUPropSet(0),
  30. _cUPropSetHidden(0),
  31. _pUPropSet(0),
  32. _dwFlags(dwFlags),
  33. _xaUProp(),
  34. _cElemPerSupported(0),
  35. _xadwSupported(),
  36. _xadwPropsInError(),
  37. _xaiPropSetDex()
  38. {
  39. }
  40. //+---------------------------------------------------------------------------
  41. //
  42. // Method: CUtlProps::~CUtlProps, public
  43. //
  44. // Synopsis: Destructor for CUtlProps
  45. //
  46. // History: 11-12-97 danleg Created from Monarch
  47. //
  48. //----------------------------------------------------------------------------
  49. CUtlProps::~CUtlProps()
  50. {
  51. FreeMemory();
  52. }
  53. //+---------------------------------------------------------------------------
  54. //
  55. // Method: CUtlProps::FillDefaultValues, public
  56. //
  57. // Synopsis: Fill all the default values. Note that failure might leave
  58. // things only half done.
  59. //
  60. // Arguments: [ulPropSetTarget] - Propset to fill if only one
  61. //
  62. // History: 11-12-97 danleg Created from Monarch
  63. //
  64. //----------------------------------------------------------------------------
  65. SCODE CUtlProps::FillDefaultValues( ULONG ulPropSetTarget )
  66. {
  67. SCODE sc = S_OK;
  68. ULONG ulPropId;
  69. ULONG iNewDex;
  70. // Fill in all the actual values.
  71. // Note that the UPROP (with values) array may be a subset of the UPROPINFO array.
  72. // Only writable properties are in UPROP array.
  73. // Maybe restrict to a single PropSet if within valid range [0..._cUPropSet-1].
  74. // Otherwise do all propsets.
  75. ULONG iPropSet = (ulPropSetTarget < _cUPropSet) ? ulPropSetTarget : 0;
  76. for( ; iPropSet<_cUPropSet; iPropSet++)
  77. {
  78. iNewDex = 0;
  79. for(ulPropId=0; ulPropId<_pUPropSet[iPropSet].cUPropInfo; ulPropId++)
  80. {
  81. if ( _pUPropSet[iPropSet].pUPropInfo[ulPropId].dwFlags &
  82. (DBPROPFLAGS_WRITE | DBPROPFLAGS_CHANGE) )
  83. {
  84. // Initialize dwFlags element of UPropVal
  85. _xaUProp[iPropSet].pUPropVal[iNewDex].dwFlags = 0;
  86. VariantClear( &_xaUProp[iPropSet].pUPropVal[iNewDex].vValue );
  87. sc = GetDefaultValue(
  88. iPropSet,
  89. _pUPropSet[iPropSet].pUPropInfo[ulPropId].dwPropId,
  90. &_xaUProp[iPropSet].pUPropVal[iNewDex].dwOption,
  91. &_xaUProp[iPropSet].pUPropVal[iNewDex].vValue );
  92. if ( FAILED(sc) )
  93. return sc;
  94. iNewDex++;
  95. }
  96. }
  97. // We're through if restricting to single PropSet.
  98. if ( ulPropSetTarget < _cUPropSet )
  99. break;
  100. }
  101. return S_OK;
  102. }
  103. //+---------------------------------------------------------------------------
  104. //
  105. // Method: CUtlProps::GetPropertiesArgChk, public
  106. //
  107. // Synopsis: Initialize the buffers and check for E_INVALIDARG cases.
  108. // This routine is used by RowsetInfo, CommandProperties and
  109. // IDBProperties
  110. //
  111. // Arguments: [cPropertySets] - number of property sets
  112. // [rgPropertySets] - property classes and ids
  113. // [pcProperties] - count of structs returned [out]
  114. // [prgProperties] - array of properties [out]
  115. //
  116. // History: 11-12-97 danleg Created from Monarch
  117. //
  118. //----------------------------------------------------------------------------
  119. void CUtlProps::GetPropertiesArgChk
  120. (
  121. const ULONG cPropertySets,
  122. const DBPROPIDSET rgPropertySets[],
  123. ULONG* pcProperties,
  124. DBPROPSET** prgProperties
  125. )
  126. {
  127. ULONG ul;
  128. // Initialize values
  129. if ( pcProperties )
  130. *pcProperties = 0;
  131. if ( prgProperties )
  132. *prgProperties = 0;
  133. // Check Arguments
  134. if ( ((cPropertySets > 0) && !rgPropertySets) ||
  135. !pcProperties || !prgProperties )
  136. THROW( CException(E_INVALIDARG) );
  137. // New argument check for > 1 cPropertyIDs and NULL pointer for
  138. // array of property ids.
  139. for(ul=0; ul<cPropertySets; ul++)
  140. {
  141. if ( rgPropertySets[ul].cPropertyIDs &&
  142. !(rgPropertySets[ul].rgPropertyIDs) )
  143. THROW( CException(E_INVALIDARG) );
  144. // Check for propper formation of DBPROPSET_PROPERTIESINERROR
  145. if ( (_dwFlags & ARGCHK_PROPERTIESINERROR) &&
  146. rgPropertySets[ul].guidPropertySet == DBPROPSET_PROPERTIESINERROR )
  147. {
  148. if ( (cPropertySets > 1) ||
  149. (rgPropertySets[ul].cPropertyIDs != 0) ||
  150. (rgPropertySets[ul].rgPropertyIDs != 0) )
  151. THROW( CException(E_INVALIDARG) );
  152. }
  153. }
  154. }
  155. //+---------------------------------------------------------------------------
  156. //
  157. // Method: CUtlProps::SetPropertiesArgChk, public
  158. //
  159. // Synopsis: Initialize the buffers and check for E_INVALIDARG cases
  160. // NOTE: This routine is used by CommandProperties and
  161. // IDBProperties
  162. //
  163. // Arguments: [cPropertySets] - count of structs returned
  164. // [rgPropertySets] - array of propertysets
  165. //
  166. // History: 11-12-97 danleg Created from Monarch
  167. //
  168. //----------------------------------------------------------------------------
  169. void CUtlProps::SetPropertiesArgChk
  170. (
  171. const ULONG cPropertySets,
  172. const DBPROPSET rgPropertySets[]
  173. )
  174. {
  175. ULONG ul;
  176. // Argument Checking
  177. if ( cPropertySets > 0 && !rgPropertySets )
  178. THROW( CException(E_INVALIDARG) );
  179. // New argument check for > 1 cPropertyIDs and NULL pointer for
  180. // array of property ids.
  181. for(ul=0; ul<cPropertySets; ul++)
  182. {
  183. if ( rgPropertySets[ul].cProperties &&
  184. !(rgPropertySets[ul].rgProperties) )
  185. THROW( CException(E_INVALIDARG) );
  186. }
  187. }
  188. //+---------------------------------------------------------------------------
  189. //
  190. // Method: CUtlProps::GetProperties, public
  191. //
  192. // Synopsis: Collect the property information that the consumer is
  193. // interested in. If no restriction guids are supplied,
  194. // return all known properties.
  195. //
  196. // NOTE: If cProperties is 0, this function will return an array
  197. // of guids that had been previously set. IF cProperties is non 0,
  198. // the routine will use the array of property guids passed in and
  199. // return informatino about the properties asked for only.
  200. //
  201. // This routine is used by RowsetInfo and CommandProperties.
  202. //
  203. // Arguments: [cPropertySets] - number of property setes
  204. // [rgPropertySets] - property classes and ids
  205. // [pcProperties] - count of structs returned [out]
  206. // [prgProperties] - array of properties [out]
  207. //
  208. // History: 11-12-97 danleg Created from Monarch
  209. //
  210. //----------------------------------------------------------------------------
  211. SCODE CUtlProps::GetProperties(
  212. const ULONG cPropertySets,
  213. const DBPROPIDSET rgPropertySets[],
  214. ULONG* pcProperties,
  215. DBPROPSET** prgProperties )
  216. {
  217. UPROPVAL* pUPropVal;
  218. ULONG ulCurProp;
  219. ULONG cTmpPropertySets = cPropertySets;
  220. SCODE sc = S_OK;
  221. ULONG ulSet = 0;
  222. ULONG ulNext = 0;
  223. ULONG cSets = 0;
  224. ULONG cProps = 0;
  225. ULONG ulProp = 0;
  226. DWORD dwStatus = 0;
  227. DBPROP* pProp = 0;
  228. UPROPINFO* pUPropInfo = 0;
  229. ULONG ulCurSet;
  230. ULONG iPropSet;
  231. // We need to have special handling for DBPROPSET_PROPERTIESINERROR.
  232. // Turn on a flags to indicate this mode and make cTmpPropertySets
  233. // appear to be 0.
  234. if ( (_dwFlags & ARGCHK_PROPERTIESINERROR) &&
  235. rgPropertySets &&
  236. (rgPropertySets[0].guidPropertySet == DBPROPSET_PROPERTIESINERROR) )
  237. {
  238. cTmpPropertySets = 0;
  239. dwStatus |= GETPROP_PROPSINERROR;
  240. }
  241. // If the consumer does not restrict the property sets by specify an
  242. // array of property sets and a cTmpPropertySets greater than 0, then we
  243. // need to make sure we have some to return
  244. if ( 0 == cTmpPropertySets )
  245. {
  246. // Determine the number of property sets supported
  247. cSets = _cUPropSet;
  248. }
  249. else
  250. {
  251. // Since special property set guids are not supported by
  252. // GetProperties, we can just use the count of property sets given to
  253. // us.
  254. cSets = cTmpPropertySets;
  255. }
  256. // If no properties set, then return
  257. if ( 0 == cSets )
  258. return S_OK;
  259. // Allocate the DBPROPSET structures
  260. DBPROPSET * pPropSet = (DBPROPSET *) CoTaskMemAlloc( cSets * sizeof DBPROPSET );
  261. if ( 0 != pPropSet )
  262. {
  263. RtlZeroMemory( pPropSet, cSets * sizeof(DBPROPSET) );
  264. // Fill in the output array
  265. iPropSet = 0;
  266. for(ulSet=0; ulSet<cSets; ulSet++)
  267. {
  268. // Depending of if Property sets are specified store the
  269. // return property set.
  270. if ( cTmpPropertySets == 0 )
  271. {
  272. if ( _pUPropSet[ulSet].dwFlags & UPROPSET_HIDDEN )
  273. continue;
  274. pPropSet[iPropSet].guidPropertySet = *(_pUPropSet[ulSet].pPropSet);
  275. }
  276. else
  277. pPropSet[iPropSet].guidPropertySet = rgPropertySets[ulSet].guidPropertySet;
  278. iPropSet++;
  279. }
  280. }
  281. else
  282. {
  283. vqDebugOut(( DEB_ERROR, "Could not allocate DBPROPSET array for GetProperties\n" ));
  284. return E_OUTOFMEMORY;
  285. }
  286. TRY
  287. {
  288. // Process requested or derived Property sets
  289. iPropSet=0;
  290. for( ulSet = 0; ulSet < cSets; ulSet++ )
  291. {
  292. XCoMem<DBPROP> xProp;
  293. cProps = 0;
  294. pProp = 0;
  295. ulNext = 0;
  296. dwStatus &= (GETPROP_ERRORSOCCURRED | GETPROP_VALIDPROP | GETPROP_PROPSINERROR);
  297. // Calculate the number of property nodes needed for this
  298. // property set.
  299. if ( 0 == cTmpPropertySets )
  300. {
  301. // If processing requesting all property sets, do not
  302. // return the hidden sets.
  303. if ( _pUPropSet[ulSet].dwFlags & UPROPSET_HIDDEN )
  304. continue;
  305. cProps = _pUPropSet[ulSet].cUPropInfo;
  306. dwStatus |= GETPROP_ALLPROPIDS;
  307. ulCurSet = ulSet;
  308. }
  309. else
  310. {
  311. Win4Assert( ulSet == iPropSet );
  312. // If the count of PROPIDs is 0 or it is a special property set,
  313. // then the consumer is requesting all propids for this property
  314. // set.
  315. if ( 0 == rgPropertySets[ulSet].cPropertyIDs )
  316. {
  317. dwStatus |= GETPROP_ALLPROPIDS;
  318. // We have to determine if the property set is supported and
  319. // if so the count of properties in the set.
  320. if ( S_OK == GetIndexofPropSet( &(pPropSet[iPropSet].guidPropertySet),
  321. &ulCurSet ) )
  322. {
  323. cProps += _pUPropSet[ulCurSet].cUPropInfo;
  324. }
  325. else
  326. {
  327. // Not Supported
  328. dwStatus |= GETPROP_ERRORSOCCURRED;
  329. goto NEXT_SET;
  330. }
  331. }
  332. else
  333. {
  334. cProps = rgPropertySets[ulSet].cPropertyIDs;
  335. //@TODO determine extra nodes needed for colids based on restriction array, it is
  336. //possible that the same restriction is used twice, thus using our other calculation method
  337. //would cause an overflow.
  338. if (GetIndexofPropSet(&(pPropSet[iPropSet].guidPropertySet), &ulCurSet) != S_OK)
  339. {
  340. dwStatus |= GETPROP_NOTSUPPORTED;
  341. dwStatus |= GETPROP_ERRORSOCCURRED;
  342. }
  343. }
  344. }
  345. // Allocate DBPROP array
  346. if ( 0 == cProps ) //Possible with Hidden Passthrough sets
  347. goto NEXT_SET;
  348. pProp = (DBPROP *) CoTaskMemAlloc( cProps * sizeof(DBPROP) );
  349. xProp.Set( pProp );
  350. if ( 0 != pProp )
  351. {
  352. // Now that we have determined we can support the property set,
  353. // we need to gather current property values
  354. for( ulProp=0; ulProp < cProps; ulProp++ )
  355. {
  356. // initialize the structure. Memberwise initialization is
  357. // faster than old memset code -- MDW
  358. pProp[ulProp].dwPropertyID = 0;
  359. pProp[ulProp].dwOptions = 0;
  360. pProp[ulProp].dwStatus = 0;
  361. RtlZeroMemory( &(pProp[ulProp].colid), sizeof DBID );
  362. VariantInit( &(pProp[ulProp].vValue) );
  363. if ( 0 != ( dwStatus & GETPROP_NOTSUPPORTED ) )
  364. {
  365. // Not supported, so we need to mark all as NOT_SUPPORTED
  366. pProp[ulProp].dwPropertyID = rgPropertySets[ulSet].rgPropertyIDs[ulProp];
  367. pProp[ulProp].dwStatus = DBPROPSTATUS_NOTSUPPORTED;
  368. continue;
  369. }
  370. DBPROP * pCurProp = &(pProp[ulNext]);
  371. // Initialize Variant Value
  372. pCurProp->dwStatus = DBPROPSTATUS_OK;
  373. // Retrieve current value of properties
  374. if ( 0 != ( dwStatus & GETPROP_ALLPROPIDS ) )
  375. {
  376. // Verify property is supported, if not do not return
  377. if ( !TESTBIT(&(_xadwSupported[ulCurSet * _cElemPerSupported]), ulProp) )
  378. continue;
  379. // If we are looking for properties in error, then we
  380. // should ignore all that are not in error.
  381. if ( ( 0 != (dwStatus & GETPROP_PROPSINERROR) ) &&
  382. !TESTBIT(&(_xadwPropsInError[ulCurSet * _cElemPerSupported]), ulProp) )
  383. continue;
  384. pUPropInfo = (UPROPINFO*)&(_pUPropSet[ulCurSet].pUPropInfo[ulProp]);
  385. Win4Assert( pUPropInfo );
  386. pCurProp->dwPropertyID = pUPropInfo->dwPropId;
  387. pCurProp->colid = DB_NULLID;
  388. // If the property is WRITEABLE or CHANGABLE and not
  389. // inerror, then the value will be gotten from the
  390. // UPROPVAL array, else it will be derive from the
  391. // GetDefaultValue
  392. if ( 0 != ( pUPropInfo->dwFlags &
  393. ( DBPROPFLAGS_WRITE | DBPROPFLAGS_CHANGE ) ) )
  394. {
  395. pUPropVal = &(_xaUProp[ulCurSet].
  396. pUPropVal[GetUPropValIndex( ulCurSet,
  397. pCurProp->dwPropertyID )]);
  398. Win4Assert( 0 != pUPropVal );
  399. if ( 0 != ( pUPropVal->dwFlags & DBINTERNFLAGS_INERROR ) )
  400. {
  401. sc = GetDefaultValue( ulCurSet,
  402. pUPropInfo->dwPropId,
  403. &(pCurProp->dwOptions),
  404. &(pCurProp->vValue) );
  405. if ( FAILED( sc ) )
  406. {
  407. pCurProp->vValue.vt = VT_EMPTY;
  408. THROW( CException( sc ) );
  409. }
  410. }
  411. else
  412. {
  413. pCurProp->dwOptions = pUPropVal->dwOption;
  414. sc = VariantCopy( &(pCurProp->vValue),
  415. &(pUPropVal->vValue) );
  416. if ( FAILED( sc ) )
  417. {
  418. pCurProp->vValue.vt = VT_EMPTY;
  419. THROW( CException( sc ) );
  420. }
  421. }
  422. }
  423. else
  424. {
  425. sc = GetDefaultValue( ulCurSet,
  426. pUPropInfo->dwPropId,
  427. &(pCurProp->dwOptions),
  428. &(pCurProp->vValue) );
  429. if ( FAILED( sc ) )
  430. {
  431. pCurProp->vValue.vt = VT_EMPTY;
  432. THROW( CException( sc ) );
  433. }
  434. }
  435. // Return all Properties in Error with CONFLICT status
  436. if ( 0 != ( dwStatus & GETPROP_PROPSINERROR ) )
  437. pCurProp->dwStatus = DBPROPSTATUS_CONFLICTING;
  438. dwStatus |= GETPROP_VALIDPROP;
  439. }
  440. else
  441. {
  442. // Process Properties based on Restriction array.
  443. pCurProp->dwPropertyID = rgPropertySets[ulSet].rgPropertyIDs[ulProp];
  444. pCurProp->colid = DB_NULLID;
  445. if ( S_OK == GetIndexofPropIdinPropSet( ulCurSet,
  446. pCurProp->dwPropertyID,
  447. &ulCurProp ) )
  448. {
  449. // Supported
  450. pUPropInfo = (UPROPINFO*)&(_pUPropSet[ulCurSet].pUPropInfo[ulCurProp]);
  451. Win4Assert( 0 != pUPropInfo );
  452. // If the property is WRITEABLE, then the value will
  453. // be gotten from the UPROPVAL array, else it will be
  454. // derive from the GetDefaultValue
  455. if ( 0 != ( pUPropInfo->dwFlags &
  456. (DBPROPFLAGS_WRITE | DBPROPFLAGS_CHANGE) ) )
  457. {
  458. pUPropVal = &(_xaUProp[ulCurSet].
  459. pUPropVal[GetUPropValIndex(ulCurSet, pCurProp->dwPropertyID)]);
  460. Win4Assert( 0 != pUPropVal );
  461. pCurProp->dwOptions = pUPropVal->dwOption;
  462. sc = VariantCopy(&(pCurProp->vValue), &(pUPropVal->vValue));
  463. }
  464. else
  465. {
  466. sc = GetDefaultValue( ulCurSet,
  467. pUPropInfo->dwPropId,
  468. &(pCurProp->dwOptions),
  469. &(pCurProp->vValue) );
  470. }
  471. if ( FAILED( sc ) )
  472. {
  473. pCurProp->vValue.vt = VT_EMPTY;
  474. THROW( CException( sc ) );
  475. }
  476. dwStatus |= GETPROP_VALIDPROP;
  477. }
  478. else
  479. {
  480. // Not Supported
  481. pCurProp->dwStatus = DBPROPSTATUS_NOTSUPPORTED;
  482. dwStatus |= GETPROP_ERRORSOCCURRED;
  483. }
  484. }
  485. // Increment return nodes count
  486. ulNext++;
  487. }
  488. // Make sure we support the property set
  489. if ( 0 != ( dwStatus & GETPROP_NOTSUPPORTED ) )
  490. {
  491. ulNext = cProps;
  492. goto NEXT_SET;
  493. }
  494. }
  495. else
  496. {
  497. THROW( CException( E_OUTOFMEMORY ) );
  498. }
  499. NEXT_SET:
  500. // It is possible that all properties are not supported,
  501. // thus we should delete that memory and set rgProperties
  502. // to NULL
  503. if ( 0 == ulNext && 0 != pProp )
  504. {
  505. CoTaskMemFree( pProp );
  506. pProp = 0;
  507. }
  508. xProp.Acquire();
  509. pPropSet[iPropSet].cProperties = ulNext;
  510. pPropSet[iPropSet].rgProperties = pProp;
  511. iPropSet++;
  512. Win4Assert( iPropSet <= cSets );
  513. }
  514. Win4Assert( iPropSet <= cSets );
  515. *pcProperties = iPropSet;
  516. *prgProperties = pPropSet;
  517. // At least one propid was marked as not S_OK
  518. if ( dwStatus & GETPROP_ERRORSOCCURRED )
  519. {
  520. // If at least 1 property was set
  521. if ( dwStatus & GETPROP_VALIDPROP )
  522. return DB_S_ERRORSOCCURRED;
  523. else
  524. {
  525. // Do not free any of the memory on a DB_E_
  526. return DB_E_ERRORSOCCURRED;
  527. }
  528. }
  529. sc = S_OK;
  530. }
  531. CATCH( CException, e )
  532. {
  533. // Since we have no properties to return we need to free allocated memory
  534. if ( 0 != pPropSet )
  535. {
  536. // Free any DBPROP arrays
  537. for( ulSet = 0; ulSet < cSets; ulSet++ )
  538. {
  539. // Need to loop through all the VARIANTS and clear them
  540. for( ulProp = 0; ulProp < pPropSet[ulSet].cProperties; ulProp++ )
  541. VariantClear(&(pPropSet[ulSet].rgProperties[ulProp].vValue));
  542. CoTaskMemFree( pPropSet[ulSet].rgProperties );
  543. }
  544. // Free DBPROPSET
  545. CoTaskMemFree( pPropSet );
  546. }
  547. *pcProperties = 0;
  548. *prgProperties = 0;
  549. sc = e.GetErrorCode();
  550. }
  551. END_CATCH
  552. return sc;
  553. } //CUtlProps::GetProperties
  554. //+---------------------------------------------------------------------------
  555. //
  556. // Method: CUtlProp::SetProperties, public
  557. //
  558. // Synopsis: This routine takes the array of properties that the consumer
  559. // has give, determines whether each property can be supported.
  560. // For the ones supported, it sets a bit.
  561. //
  562. // Arguments: [cPropertySets] - count of DBPROPSETS in rgPropertySets
  563. // [rgPropertySets] - array of DBPROPSETS of values to be set
  564. //
  565. // Returns: SCODE indicating the following:
  566. // S_OK - Success
  567. // E_FAIL - Provider specific error
  568. // DB_S_ERRORSOCCURRED - One or more properties not set
  569. //
  570. // History: 11-12-97 danleg Created from Monarch
  571. //
  572. //----------------------------------------------------------------------------
  573. SCODE CUtlProps::SetProperties
  574. (
  575. const ULONG cPropertySets,
  576. const DBPROPSET rgPropertySets[]
  577. )
  578. {
  579. DWORD dwState = 0;
  580. ULONG ulSet, ulCurSet, ulCurProp, ulProp;
  581. DBPROP* rgDBProp;
  582. UPROPINFO* pUPropInfo;
  583. VARIANT vDefaultValue;
  584. DWORD dwOption;
  585. Win4Assert( ! cPropertySets || rgPropertySets );
  586. // Initialize Variant
  587. VariantInit(&vDefaultValue);
  588. // Process property sets
  589. for(ulSet=0; ulSet<cPropertySets; ulSet++)
  590. {
  591. Win4Assert( ! rgPropertySets[ulSet].cProperties || rgPropertySets[ulSet].rgProperties );
  592. // Make sure we support the property set
  593. if ( GetIndexofPropSet(&(rgPropertySets[ulSet].guidPropertySet),
  594. &ulCurSet) == S_FALSE )
  595. {
  596. // Not supported, thus we need to mark all as NOT_SUPPORTED
  597. rgDBProp = rgPropertySets[ulSet].rgProperties;
  598. for(ulProp=0; ulProp<rgPropertySets[ulSet].cProperties; ulProp++)
  599. {
  600. dwState |= SETPROP_ERRORS;
  601. rgDBProp[ulProp].dwStatus = DBPROPSTATUS_NOTSUPPORTED;
  602. }
  603. continue;
  604. }
  605. // Handle properties of a supported property set
  606. rgDBProp = rgPropertySets[ulSet].rgProperties;
  607. for(ulProp=0; ulProp<rgPropertySets[ulSet].cProperties; ulProp++)
  608. {
  609. // Is this a supported PROPID for this property set
  610. if ( GetIndexofPropIdinPropSet(ulCurSet, rgDBProp[ulProp].dwPropertyID,
  611. &ulCurProp) == S_FALSE)
  612. {
  613. dwState |= SETPROP_ERRORS;
  614. rgDBProp[ulProp].dwStatus = DBPROPSTATUS_NOTSUPPORTED;
  615. continue;
  616. }
  617. // Set the pUPropInfo pointer
  618. pUPropInfo = (UPROPINFO*)&(_pUPropSet[ulCurSet].pUPropInfo[ulCurProp]);
  619. Win4Assert( pUPropInfo );
  620. // check dwOption for a valid option
  621. if ( (rgDBProp[ulProp].dwOptions != DBPROPOPTIONS_REQUIRED) &&
  622. (rgDBProp[ulProp].dwOptions != DBPROPOPTIONS_OPTIONAL) )
  623. {
  624. vqDebugOut(( DEB_WARN, "SetProperties dwOptions Invalid: %u\n", rgDBProp[ulProp].dwOptions ));
  625. dwState |= SETPROP_ERRORS;
  626. rgDBProp[ulProp].dwStatus = DBPROPSTATUS_BADOPTION;
  627. continue;
  628. }
  629. // Check that the property is settable
  630. // @devnote: We do not check against DBPROPFLAGS_CHANGE here
  631. if ( (pUPropInfo->dwFlags & DBPROPFLAGS_WRITE) == 0 )
  632. {
  633. rgDBProp[ulProp].dwStatus = DBPROPSTATUS_OK;
  634. VariantClear(&vDefaultValue);
  635. // VT_EMPTY against a read only property should be a no-op since
  636. // the VT_EMPTY means the default.
  637. if ( V_VT(&rgDBProp[ulProp].vValue) == VT_EMPTY )
  638. {
  639. dwState |= SETPROP_VALIDPROP;
  640. continue;
  641. }
  642. if ( SUCCEEDED(GetDefaultValue(ulCurSet, rgDBProp[ulProp].dwPropertyID,
  643. &dwOption, &(vDefaultValue))) )
  644. {
  645. if ( V_VT(&rgDBProp[ulProp].vValue) == V_VT(&vDefaultValue) )
  646. {
  647. switch( V_VT(&vDefaultValue) )
  648. {
  649. case VT_BOOL:
  650. if ( V_BOOL(&rgDBProp[ulProp].vValue) == V_BOOL(&vDefaultValue) )
  651. {
  652. dwState |= SETPROP_VALIDPROP;
  653. continue;
  654. }
  655. break;
  656. case VT_I2:
  657. if ( V_I2(&rgDBProp[ulProp].vValue) == V_I2(&vDefaultValue) )
  658. {
  659. dwState |= SETPROP_VALIDPROP;
  660. continue;
  661. }
  662. break;
  663. case VT_I4:
  664. if ( V_I4(&rgDBProp[ulProp].vValue) == V_I4(&vDefaultValue) )
  665. {
  666. dwState |= SETPROP_VALIDPROP;
  667. continue;
  668. }
  669. break;
  670. case VT_BSTR:
  671. if ( wcscmp(V_BSTR(&rgDBProp[ulProp].vValue), V_BSTR(&vDefaultValue)) == 0 )
  672. {
  673. dwState |= SETPROP_VALIDPROP;
  674. continue;
  675. }
  676. break;
  677. }
  678. }
  679. }
  680. dwState |= SETPROP_ERRORS;
  681. rgDBProp[ulProp].dwStatus = DBPROPSTATUS_NOTSETTABLE;
  682. continue;
  683. }
  684. // Check that the property is being set with the correct VARTYPE
  685. if ( (rgDBProp[ulProp].vValue.vt != pUPropInfo->VarType) &&
  686. (rgDBProp[ulProp].vValue.vt != VT_EMPTY) )
  687. {
  688. dwState |= SETPROP_ERRORS;
  689. rgDBProp[ulProp].dwStatus = DBPROPSTATUS_BADVALUE;
  690. continue;
  691. }
  692. // Check that the value is legal
  693. if ( (rgDBProp[ulProp].vValue.vt != VT_EMPTY) &&
  694. IsValidValue(ulCurSet, &(rgDBProp[ulProp])) == S_FALSE )
  695. {
  696. dwState |= SETPROP_ERRORS;
  697. rgDBProp[ulProp].dwStatus = DBPROPSTATUS_BADVALUE;
  698. continue;
  699. }
  700. if ( SUCCEEDED(SetProperty(ulCurSet, ulCurProp, &(rgDBProp[ulProp]))) )
  701. {
  702. dwState |= SETPROP_VALIDPROP;
  703. }
  704. }
  705. }
  706. VariantClear(&vDefaultValue);
  707. // At least one propid was marked as not S_OK
  708. if ( dwState & SETPROP_ERRORS )
  709. {
  710. // If at least 1 property was set
  711. if ( dwState & SETPROP_VALIDPROP )
  712. return DB_S_ERRORSOCCURRED;
  713. else
  714. return DB_E_ERRORSOCCURRED;
  715. }
  716. return S_OK;
  717. } // CUtlProp::SetProperties
  718. //+---------------------------------------------------------------------------
  719. //
  720. // Method: CUtlProp::IsPropSet, public
  721. //
  722. // Synopsis: Check if a VT_BOOL property is true or false
  723. //
  724. // History: 11-12-97 danleg Created from Monarch
  725. //
  726. //----------------------------------------------------------------------------
  727. BOOL CUtlProps::IsPropSet
  728. (
  729. const GUID* pguidPropSet,
  730. DBPROPID dwPropId
  731. )
  732. {
  733. SCODE sc = S_OK;
  734. ULONG iPropSet;
  735. ULONG iPropId;
  736. VARIANT vValue;
  737. DWORD dwOptions;
  738. VariantInit(&vValue);
  739. if ( GetIndexofPropSet(pguidPropSet, &iPropSet) == S_OK )
  740. {
  741. if ( GetIndexofPropIdinPropSet(iPropSet, dwPropId, &iPropId) == S_OK )
  742. {
  743. if ( _pUPropSet[iPropSet].pUPropInfo[iPropId].dwFlags &
  744. (DBPROPFLAGS_WRITE | DBPROPFLAGS_CHANGE) )
  745. {
  746. ULONG iPropVal = GetUPropValIndex(iPropSet, dwPropId);
  747. dwOptions = _xaUProp[iPropSet].pUPropVal[iPropVal].dwOption;
  748. sc = VariantCopy( &vValue,
  749. &(_xaUProp[iPropSet].pUPropVal[iPropVal].vValue) );
  750. }
  751. else
  752. {
  753. sc = GetDefaultValue( iPropSet, dwPropId,
  754. &dwOptions, &vValue );
  755. }
  756. if ( dwOptions == DBPROPOPTIONS_REQUIRED )
  757. {
  758. if ( SUCCEEDED(sc) )
  759. {
  760. Win4Assert( vValue.vt == VT_BOOL );
  761. if ( V_BOOL(&vValue) == VARIANT_TRUE )
  762. {
  763. VariantClear(&vValue);
  764. return TRUE;
  765. }
  766. }
  767. }
  768. }
  769. }
  770. VariantClear(&vValue);
  771. return FALSE;
  772. }
  773. //+---------------------------------------------------------------------------
  774. //
  775. // Method: CUtlProp::GetPropValue, public
  776. //
  777. // Synopsis:
  778. //
  779. // History: 11-12-97 danleg Created from Monarch
  780. //
  781. //----------------------------------------------------------------------------
  782. SCODE CUtlProps::GetPropValue
  783. (
  784. const GUID* pguidPropSet,
  785. DBPROPID dwPropId,
  786. VARIANT* pvValue
  787. )
  788. {
  789. SCODE sc = E_FAIL;
  790. ULONG iPropSet;
  791. ULONG iPropId;
  792. DWORD dwOptions;
  793. if ( GetIndexofPropSet(pguidPropSet, &iPropSet) == S_OK )
  794. {
  795. if ( GetIndexofPropIdinPropSet(iPropSet, dwPropId, &iPropId) == S_OK )
  796. {
  797. if ( _pUPropSet[iPropSet].pUPropInfo[iPropId].dwFlags & (DBPROPFLAGS_WRITE | DBPROPFLAGS_CHANGE) )
  798. {
  799. sc = VariantCopy( pvValue,
  800. &(_xaUProp[iPropSet].pUPropVal[
  801. GetUPropValIndex(iPropSet, dwPropId)].vValue) );
  802. }
  803. else
  804. {
  805. VariantClear(pvValue);
  806. sc = GetDefaultValue( iPropSet,
  807. dwPropId,
  808. &dwOptions,
  809. pvValue );
  810. }
  811. }
  812. }
  813. return sc;
  814. }
  815. //+---------------------------------------------------------------------------
  816. //
  817. // Method: CUtlProp::SetPropValue, public
  818. //
  819. // Synopsis:
  820. //
  821. // History: 11-12-97 danleg Created from Monarch
  822. //
  823. //----------------------------------------------------------------------------
  824. HRESULT CUtlProps::SetPropValue
  825. (
  826. const GUID* pguidPropSet,
  827. DBPROPID dwPropId,
  828. VARIANT* pvValue
  829. )
  830. {
  831. SCODE sc = E_FAIL;
  832. ULONG iPropSet;
  833. ULONG iPropId;
  834. if ( GetIndexofPropSet(pguidPropSet, &iPropSet) == S_OK )
  835. {
  836. if ( GetIndexofPropIdinPropSet(iPropSet, dwPropId, &iPropId) == S_OK )
  837. {
  838. Win4Assert( _pUPropSet[iPropSet].pUPropInfo[iPropId].dwFlags & (DBPROPFLAGS_WRITE | DBPROPFLAGS_CHANGE) );
  839. sc = VariantCopy( &(_xaUProp[iPropSet].pUPropVal[
  840. GetUPropValIndex(iPropSet, dwPropId)].vValue),
  841. pvValue );
  842. }
  843. }
  844. return sc;
  845. }
  846. //+---------------------------------------------------------------------------
  847. //
  848. // Method: CUtlProps::CopyUPropVal, public
  849. //
  850. // Synopsis: Copy the values stored in UpropVal
  851. //
  852. // History: 11-12-97 danleg Created from Monarch
  853. //
  854. //----------------------------------------------------------------------------
  855. SCODE CUtlProps::CopyUPropVal
  856. (
  857. ULONG iPropSet,
  858. UPROPVAL* rgUPropVal
  859. )
  860. {
  861. SCODE sc = S_OK;
  862. DBPROP dbProp;
  863. Win4Assert( rgUPropVal );
  864. Win4Assert( iPropSet < _cUPropSet );
  865. VariantInit(&dbProp.vValue);
  866. UPROP * pUProp = &(_xaUProp[iPropSet]);
  867. for(ULONG ul=0; ul<pUProp->cPropIds; ul++)
  868. {
  869. UPROPVAL * pUPropVal = &(pUProp->pUPropVal[ul]);
  870. // Transfer dwOptions
  871. rgUPropVal[ul].dwOption = pUPropVal->dwOption;
  872. // Transfer Flags
  873. rgUPropVal[ul].dwFlags = pUPropVal->dwFlags;
  874. // Transfer value
  875. VariantInit(&(rgUPropVal[ul].vValue));
  876. sc = VariantCopy( &(rgUPropVal[ul].vValue), &(pUPropVal->vValue) );
  877. if ( FAILED(sc) )
  878. break;
  879. }
  880. VariantClear( &(dbProp.vValue) );
  881. return sc;
  882. }
  883. //+---------------------------------------------------------------------------
  884. //
  885. // Method: CUtlProps::GetIndexofPropSet, public
  886. //
  887. // Synopsis: Given a propset guid, find the index of the propset in our
  888. // current set to be returned.
  889. //
  890. // Arguments: [pPropset] - Guid of propset to find index of
  891. // [pulCurSet] - Index of current property set [out]
  892. //
  893. // Returns: SCODE indicating the following:
  894. // S_OK - guid was matched and index returned
  895. // S_FALSE - guid was not matched
  896. //
  897. // History: 11-12-97 danleg Created from Monarch
  898. //
  899. //----------------------------------------------------------------------------
  900. SCODE CUtlProps::GetIndexofPropSet
  901. (
  902. const GUID* pPropSet,
  903. ULONG* pulCurSet
  904. )
  905. {
  906. ULONG ul;
  907. Win4Assert( pPropSet && pulCurSet );
  908. for(ul=0; ul<_cUPropSet; ul++)
  909. {
  910. if ( *pPropSet == *(_pUPropSet[ul].pPropSet) )
  911. {
  912. *pulCurSet = ul;
  913. return S_OK;
  914. }
  915. }
  916. return S_FALSE;
  917. }
  918. //+---------------------------------------------------------------------------
  919. //
  920. // Method: CUtlProps::GetIndexofPropIdinPropSet, public
  921. //
  922. // Synopsis: Given a propertyset guid, determine what index in our current
  923. // set of property sets is to be returned
  924. //
  925. // Arguments: [iCurSet] - Index of current property set
  926. // [dwPropertyId] - Property id
  927. // [piCurPropId] - Index of requeted id [out]
  928. //
  929. // Returns: SCODE as follows:
  930. // S_OK - Propid found in propset
  931. // S_FALSE - Propid not found in propset
  932. //
  933. // History: 11-12-97 danleg Created from Monarch
  934. //
  935. //----------------------------------------------------------------------------
  936. SCODE CUtlProps::GetIndexofPropIdinPropSet
  937. (
  938. ULONG iCurSet,
  939. DBPROPID dwPropertyId,
  940. ULONG* piCurPropId
  941. )
  942. {
  943. ULONG ul;
  944. UPROPINFO* pUPropInfo;
  945. Win4Assert( piCurPropId );
  946. pUPropInfo = (UPROPINFO*)_pUPropSet[iCurSet].pUPropInfo;
  947. for(ul=0; ul<_pUPropSet[iCurSet].cUPropInfo; ul++)
  948. {
  949. if ( dwPropertyId == pUPropInfo[ul].dwPropId )
  950. {
  951. *piCurPropId = ul;
  952. // Test to see if the property is supported for this
  953. // instantiation
  954. if ( TESTBIT(&(_xadwSupported[iCurSet * _cElemPerSupported]), ul) )
  955. return S_OK;
  956. else
  957. return S_FALSE;
  958. }
  959. }
  960. return S_FALSE;
  961. }
  962. //+---------------------------------------------------------------------------
  963. //
  964. // Method: CUtlProps::FInit, protected
  965. //
  966. // Synopsis: Initialization. Called from constructors of derived classes.
  967. //
  968. // History: 11-12-97 danleg Created from Monarch
  969. //
  970. //----------------------------------------------------------------------------
  971. void CUtlProps::FInit( CUtlProps * pCopyMe )
  972. {
  973. SCODE sc = S_OK;
  974. ULONG ulPropId;
  975. ULONG cPropIds;
  976. ULONG iPropSet;
  977. ULONG iNewDex;
  978. XArray<UPROPINFO*> xapUPropInfo;
  979. XArray<UPROPVAL> xaUPropVal;
  980. UPROPINFO * pUPropInfo;
  981. // If a pointer is passed in, we should copy that property object
  982. if ( pCopyMe )
  983. {
  984. // Establish some base values
  985. pCopyMe->CopyAvailUPropSets( &_cUPropSet,
  986. &_pUPropSet,
  987. &_cElemPerSupported );
  988. Win4Assert( (_cUPropSet != 0) && (_cElemPerSupported != 0) );
  989. // Retrieve Supported Bitmask
  990. _xadwPropsInError.Init( _cUPropSet * _cElemPerSupported );
  991. ClearPropertyInError();
  992. // This uses XArray<>::Init to allocate and copy into _xadwSupported
  993. pCopyMe->CopyUPropSetsSupported( _xadwSupported );
  994. }
  995. else
  996. {
  997. sc = InitAvailUPropSets( &_cUPropSet, &_pUPropSet, &_cElemPerSupported );
  998. if ( FAILED(sc) )
  999. THROW( CException(sc) );
  1000. Win4Assert( (_cUPropSet != 0) && (_cElemPerSupported != 0) );
  1001. if ( !_cUPropSet || !_cElemPerSupported )
  1002. THROW( CException(E_FAIL) );
  1003. _xadwSupported.Init( _cUPropSet * _cElemPerSupported );
  1004. _xadwPropsInError.Init( _cUPropSet * _cElemPerSupported );
  1005. ClearPropertyInError();
  1006. // Set all slots to an initial value
  1007. sc = InitUPropSetsSupported( _xadwSupported.GetPointer() );
  1008. if ( FAILED(sc) )
  1009. {
  1010. _xadwSupported.Free();
  1011. THROW( CException(sc) );
  1012. }
  1013. }
  1014. // Allocate UPROPS structures for the count of Property sets
  1015. _xaUProp.Init( _cUPropSet );
  1016. RtlZeroMemory( _xaUProp.GetPointer(), _cUPropSet * sizeof(UPROP) );
  1017. // Within the UPROPS Structure allocate and intialize the
  1018. // Property IDs that belong to this property set.
  1019. for(iPropSet=0; iPropSet<_cUPropSet; iPropSet++)
  1020. {
  1021. cPropIds = GetCountofWritablePropsInPropSet( iPropSet );
  1022. if ( cPropIds > 0 )
  1023. {
  1024. // Initialize/allocate xaUPropVal. Even when we are copying, the
  1025. // copy routine simply does a member-wise value assignment.
  1026. xaUPropVal.Init( cPropIds );
  1027. if ( pCopyMe )
  1028. {
  1029. // CopyUPropInfo uses XArray<>::Init to allocate/copy xapUPropInfo
  1030. pCopyMe->CopyUPropInfo( iPropSet, xapUPropInfo );
  1031. // CopyUPropVal only transfers values. Allocate xaUPropVal before calling this
  1032. Win4Assert( !xaUPropVal.IsNull() );
  1033. sc = pCopyMe->CopyUPropVal( iPropSet, xaUPropVal.GetPointer() );
  1034. if ( FAILED(sc) )
  1035. THROW( CException(sc) );
  1036. }
  1037. else
  1038. {
  1039. // Initialize and allocate arrays
  1040. xapUPropInfo.Init( cPropIds );
  1041. // Clear Pointer Array
  1042. RtlZeroMemory( xapUPropInfo.GetPointer(), cPropIds * sizeof(UPROPINFO *) );
  1043. // Set Pointer to correct property ids with a property set
  1044. pUPropInfo = (UPROPINFO *) _pUPropSet[iPropSet].pUPropInfo;
  1045. // Set up the writable property buffers
  1046. iNewDex = 0;
  1047. for(ulPropId=0; ulPropId<_pUPropSet[iPropSet].cUPropInfo; ulPropId++)
  1048. {
  1049. if ( pUPropInfo[ulPropId].dwFlags & (DBPROPFLAGS_WRITE | DBPROPFLAGS_CHANGE) )
  1050. {
  1051. // Following assert indicates that the are more
  1052. // writable properties then space allocated
  1053. Win4Assert( iNewDex < cPropIds );
  1054. xapUPropInfo[iNewDex] = &(pUPropInfo[ulPropId]);
  1055. xaUPropVal[iNewDex].dwOption = DBPROPOPTIONS_OPTIONAL;
  1056. xaUPropVal[iNewDex].dwFlags = 0;
  1057. VariantInit(&(xaUPropVal[iNewDex].vValue));
  1058. sc = GetDefaultValue( iPropSet,
  1059. pUPropInfo[ulPropId].dwPropId,
  1060. &(xaUPropVal[iNewDex].dwOption),
  1061. &(xaUPropVal[iNewDex].vValue) );
  1062. if ( FAILED( sc ) )
  1063. THROW( CException(sc) );
  1064. iNewDex++;
  1065. }
  1066. }
  1067. Win4Assert( cPropIds == iNewDex );
  1068. }
  1069. _xaUProp[iPropSet].rgpUPropInfo = xapUPropInfo.Acquire();
  1070. _xaUProp[iPropSet].pUPropVal = xaUPropVal.Acquire();
  1071. _xaUProp[iPropSet].cPropIds = cPropIds;
  1072. }
  1073. }
  1074. // Finally determine if there are any hidden property sets.. Those
  1075. // that do not show up in GetPropertyInfo and should not be returns on
  1076. // a 0, NULL call to GetProperties
  1077. for(iPropSet=0; iPropSet<_cUPropSet; iPropSet++)
  1078. {
  1079. if ( _pUPropSet[iPropSet].dwFlags & UPROPSET_HIDDEN )
  1080. _cUPropSetHidden++;
  1081. }
  1082. } // CUtlProps::FInit
  1083. //+---------------------------------------------------------------------------
  1084. //
  1085. // Method: CUtlProps::FreeMemory, private
  1086. //
  1087. // Synopsis: Free all memory
  1088. //
  1089. // History: 11-12-97 danleg Created from Monarch
  1090. //
  1091. //----------------------------------------------------------------------------
  1092. void CUtlProps::FreeMemory()
  1093. {
  1094. ULONG ulPropSet;
  1095. ULONG ulPropId;
  1096. UPROPVAL* pUPropVal;
  1097. // Remove Property Information
  1098. if ( !_xaUProp.IsNull() )
  1099. {
  1100. //
  1101. // Reset _cUPropSet to its max. Used by derived classes that expose a subset
  1102. // of their prop sets in some states. (eg. CMDSProps hides all but DBPROPSET_INIT
  1103. // if the datasource is in an uninitlaized state)
  1104. //
  1105. for(ulPropSet=0; ulPropSet<_cUPropSet; ulPropSet++)
  1106. {
  1107. pUPropVal = _xaUProp[ulPropSet].pUPropVal;
  1108. for(ulPropId=0; ulPropId<_xaUProp[ulPropSet].cPropIds; ulPropId++)
  1109. {
  1110. VariantClear(&(pUPropVal[ulPropId].vValue));
  1111. }
  1112. // TODO: UPROPSET change structure to use XArray
  1113. delete[] _xaUProp[ulPropSet].rgpUPropInfo;
  1114. delete[] _xaUProp[ulPropSet].pUPropVal;
  1115. }
  1116. _xaUProp.Free();
  1117. }
  1118. _xadwSupported.Free();
  1119. _xadwPropsInError.Free();
  1120. _xaiPropSetDex.Free();
  1121. _cPropSetDex = 0;
  1122. _cUPropSet = 0;
  1123. _cUPropSetHidden = 0;
  1124. _dwFlags = 0;
  1125. _cElemPerSupported = 0;
  1126. }
  1127. //+---------------------------------------------------------------------------
  1128. //
  1129. // Method: CUtlProps::GetCountofWritablePropsInPropSet, private
  1130. //
  1131. // Synopsis: Given an index to the property set, count the number of
  1132. // writable or changable properties under this property set.
  1133. // devnote: this includes properties with the internal flag of
  1134. // DBPROPFLAGS_CHANGE along with DBPROPFLAGS_WRITE
  1135. //
  1136. // Returns: Count of writable properties
  1137. //
  1138. // History: 11-12-97 danleg Created from Monarch
  1139. //
  1140. //----------------------------------------------------------------------------
  1141. ULONG CUtlProps::GetCountofWritablePropsInPropSet
  1142. (
  1143. ULONG iPropSet //@parm IN | Index of Property Set
  1144. )
  1145. {
  1146. ULONG ul;
  1147. ULONG cWritable = 0;
  1148. UPROPINFO* pUPropInfo;
  1149. Win4Assert( _pUPropSet );
  1150. Win4Assert( iPropSet < _cUPropSet );
  1151. pUPropInfo = (UPROPINFO*)_pUPropSet[iPropSet].pUPropInfo;
  1152. for(ul=0; ul<_pUPropSet[iPropSet].cUPropInfo; ul++)
  1153. {
  1154. if ( pUPropInfo[ul].dwFlags & (DBPROPFLAGS_WRITE | DBPROPFLAGS_CHANGE) )
  1155. cWritable++;
  1156. }
  1157. return cWritable;
  1158. }
  1159. //+---------------------------------------------------------------------------
  1160. //
  1161. // Method: CUtlProps::GetUPropValIndex, private
  1162. //
  1163. // Synopsis:
  1164. //
  1165. // History: 11-12-97 danleg Created from Monarch
  1166. //
  1167. //----------------------------------------------------------------------------
  1168. ULONG CUtlProps::GetUPropValIndex
  1169. (
  1170. ULONG iCurSet,
  1171. DBPROPID dwPropId
  1172. )
  1173. {
  1174. ULONG ul;
  1175. for(ul=0; ul<_xaUProp[iCurSet].cPropIds; ul++)
  1176. {
  1177. if ( (_xaUProp[iCurSet].rgpUPropInfo[ul])->dwPropId == dwPropId )
  1178. return ul;
  1179. }
  1180. return 0;
  1181. }
  1182. //+---------------------------------------------------------------------------
  1183. //
  1184. // Method: CUtlProps::SetProperty, private
  1185. //
  1186. // Synopsis: The iCurProp is an index into _pUPropSet, not into _xaUProp
  1187. //
  1188. // Arguments: [iCurSet] - Index within _xaUProp and _pUPropSet
  1189. // [iCurProp] -
  1190. // [pDBProp] - Pointer to current property node [out]
  1191. //
  1192. // History: 11-12-97 danleg Created from Monarch
  1193. //
  1194. //----------------------------------------------------------------------------
  1195. SCODE CUtlProps::SetProperty
  1196. (
  1197. ULONG iCurSet, //@parm IN | Index within _xaUProp and _pUPropSet
  1198. ULONG iCurProp,
  1199. DBPROP* pDBProp //@PARM INOUT | Pointer to current property node
  1200. )
  1201. {
  1202. SCODE sc = S_OK;
  1203. UPROP* pUProp;
  1204. UPROPVAL* pUPropVal;
  1205. UPROPINFO* pUPropInfo;
  1206. ULONG iUProp;
  1207. Win4Assert( pDBProp );
  1208. // Set pointer to correct set
  1209. pUProp = &(_xaUProp[iCurSet]);
  1210. Win4Assert( pUProp );
  1211. pUPropInfo = (UPROPINFO*)&(_pUPropSet[iCurSet].pUPropInfo[iCurProp]);
  1212. Win4Assert( pUPropInfo );
  1213. // Determine the index within _xaUProp
  1214. for(iUProp=0; iUProp<pUProp->cPropIds; iUProp++)
  1215. {
  1216. if ( (pUProp->rgpUPropInfo[iUProp])->dwPropId == pDBProp->dwPropertyID )
  1217. break;
  1218. }
  1219. if ( iUProp >= pUProp->cPropIds )
  1220. {
  1221. Win4Assert( !"Should have found index of property to set" );
  1222. sc = E_FAIL;
  1223. pDBProp->dwStatus = DBPROPSTATUS_NOTSUPPORTED;
  1224. goto EXIT;
  1225. }
  1226. //Get the UPROPVAL node pointer within that propset.
  1227. pUPropVal = &(pUProp->pUPropVal[iUProp]);
  1228. Win4Assert( pUPropVal );
  1229. // Handle VT_EMPTY, which indicates to the provider to
  1230. // reset this property to the providers default
  1231. if ( pDBProp->vValue.vt == VT_EMPTY )
  1232. {
  1233. // Should clear here, since previous values may already
  1234. // have been cached and need to be replaced.
  1235. VariantClear(&(pUPropVal->vValue));
  1236. pUPropVal->dwFlags &= ~DBINTERNFLAGS_CHANGED;
  1237. sc = GetDefaultValue( iCurSet,
  1238. pDBProp->dwPropertyID,
  1239. &(pUPropVal->dwOption),
  1240. &(pUPropVal->vValue) );
  1241. goto EXIT;
  1242. }
  1243. pUPropVal->dwOption = pDBProp->dwOptions;
  1244. sc = VariantCopy( &(pUPropVal->vValue), &(pDBProp->vValue) );
  1245. if ( FAILED(sc) )
  1246. goto EXIT;
  1247. pUPropVal->dwFlags |= DBINTERNFLAGS_CHANGED;
  1248. EXIT:
  1249. if ( SUCCEEDED(sc) )
  1250. pDBProp->dwStatus = DBPROPSTATUS_OK;
  1251. return sc;
  1252. }
  1253. //
  1254. // CUtlPropInfo methods
  1255. //
  1256. //+---------------------------------------------------------------------------
  1257. //
  1258. // Method: CUtlPropInfo::CUtlPropInfo, public
  1259. //
  1260. // Synopsis: Constructor
  1261. //
  1262. // History: 11-12-97 danleg Created from Monarch
  1263. //
  1264. //----------------------------------------------------------------------------
  1265. CUtlPropInfo::CUtlPropInfo() :
  1266. _cUPropSet(0),
  1267. _cPropSetDex(0),
  1268. _cElemPerSupported(0),
  1269. _pUPropSet(0)
  1270. {
  1271. }
  1272. //+---------------------------------------------------------------------------
  1273. //
  1274. // Method: CUtlPropInfo::GetPropertyInfo, public
  1275. //
  1276. // Synopsis: Retrieve the requested property info
  1277. //
  1278. // Arguments: [cPropertySets] - Count of property sets
  1279. // [rgPropertySets] - Property sets
  1280. // [pcPropertyInfoSets] - Count of properties returned [out]
  1281. // [prgPropertyInfoSets] - Property information returned [out]
  1282. // [ppDescBuffer] - Buffer for returned descriptions [out]
  1283. //
  1284. // Returns: SCODE as follows:
  1285. // S_OK - At least one index returned
  1286. // S_FALSE - No matching property set found
  1287. //
  1288. // History: 11-12-97 danleg Created from Monarch
  1289. //
  1290. //----------------------------------------------------------------------------
  1291. SCODE CUtlPropInfo::GetPropertyInfo
  1292. (
  1293. ULONG cPropertySets,
  1294. const DBPROPIDSET rgPropertySets[],
  1295. ULONG* pcPropertyInfoSets,
  1296. DBPROPINFOSET** prgPropertyInfoSets,
  1297. WCHAR** ppDescBuffer
  1298. )
  1299. {
  1300. SCODE sc = S_OK;
  1301. ULONG ul, ulSet, ulNext, ulEnd, ulProp;
  1302. ULONG ulOutIndex;
  1303. ULONG cSets;
  1304. ULONG cPropInfos;
  1305. DWORD dwStatus = 0;
  1306. DBPROPINFO* pCurPropInfo = 0;
  1307. WCHAR* pDescBuffer = 0;
  1308. UPROPINFO* pUPropInfo = 0;
  1309. WCHAR wszBuff[256];
  1310. int cch;
  1311. XArrayOLE<DBPROPINFO> xaPropInfo;
  1312. XArrayOLE<WCHAR> xawszDescBuffer;
  1313. // If the consumer does not restrict the property sets
  1314. // by specify an array of property sets and a cPropertySets
  1315. // greater than 0, then we need to make sure we
  1316. // have some to return
  1317. if ( cPropertySets == 0 )
  1318. {
  1319. // Determine the number of property sets supported
  1320. cSets = _cUPropSet;
  1321. }
  1322. else
  1323. {
  1324. cSets = 0;
  1325. // Determine number of property sets required
  1326. // This is only required when any of the "special" property set GUIDs were specified
  1327. for(ulSet=0; ulSet<cPropertySets; ulSet++)
  1328. {
  1329. // Note that we always allocate nodes, mark all bad properties,
  1330. // and return DB_E_ERRORSOCCURRED. See Nile spec bug 2665.
  1331. // We always allocate at least one.
  1332. if ( GetPropertySetIndex(&(rgPropertySets[ulSet].guidPropertySet)) == S_OK )
  1333. cSets += _cPropSetDex;
  1334. else
  1335. cSets++;
  1336. }
  1337. }
  1338. Win4Assert( cSets );
  1339. //
  1340. // Allocate the DBPROPINFOSET structures. XArray zeors out the memory.
  1341. //
  1342. XArrayOLE<DBPROPINFOSET> xaPropInfoSet( cSets );
  1343. ulOutIndex = 0;
  1344. ulEnd = cPropertySets == 0 ? cSets : cPropertySets;
  1345. // Fill in the output array
  1346. for(ulSet=0; ulSet<ulEnd; ulSet++)
  1347. {
  1348. // Depending of if Property sets are specified store the
  1349. // return property set.
  1350. if (cPropertySets == 0)
  1351. {
  1352. xaPropInfoSet[ulSet].guidPropertySet = *(_pUPropSet[ulSet].pPropSet);
  1353. }
  1354. else
  1355. {
  1356. if ( ((rgPropertySets[ulSet].guidPropertySet == DBPROPSET_DATASOURCEALL) ||
  1357. (rgPropertySets[ulSet].guidPropertySet == DBPROPSET_DATASOURCEINFOALL) ||
  1358. (rgPropertySets[ulSet].guidPropertySet == DBPROPSET_DBINITALL) ||
  1359. (rgPropertySets[ulSet].guidPropertySet == DBPROPSET_SESSIONALL) ||
  1360. (rgPropertySets[ulSet].guidPropertySet == DBPROPSET_ROWSETALL)) &&
  1361. (GetPropertySetIndex(&(rgPropertySets[ulSet].guidPropertySet)) == S_OK) )
  1362. {
  1363. for(ul=0; ul<_cPropSetDex; ul++,ulOutIndex++)
  1364. {
  1365. xaPropInfoSet[ulOutIndex].guidPropertySet = *(_pUPropSet[_xaiPropSetDex[ul]].pPropSet);
  1366. xaPropInfoSet[ulOutIndex].cPropertyInfos = 0;
  1367. }
  1368. }
  1369. else
  1370. {
  1371. // Handle non-category property sets
  1372. // Handle unknown property sets
  1373. xaPropInfoSet[ulOutIndex].guidPropertySet = rgPropertySets[ulSet].guidPropertySet;
  1374. xaPropInfoSet[ulOutIndex].cPropertyInfos = rgPropertySets[ulSet].cPropertyIDs;
  1375. ulOutIndex++;
  1376. }
  1377. }
  1378. }
  1379. // Allocate a Description Buffer if needed
  1380. if ( ppDescBuffer )
  1381. {
  1382. ULONG cBuffers = CalcDescripBuffers(cSets, xaPropInfoSet.GetPointer());
  1383. if ( 0 != cBuffers )
  1384. {
  1385. xawszDescBuffer.Init( cBuffers * CCH_GETPROPERTYINFO_DESCRIP_BUFFER_SIZE );
  1386. pDescBuffer = xawszDescBuffer.GetPointer();
  1387. }
  1388. else
  1389. {
  1390. // No buffers needed. Make sure client already set to NULL.
  1391. Win4Assert( 0 == *ppDescBuffer );
  1392. }
  1393. }
  1394. TRANSLATE_EXCEPTIONS;
  1395. TRY
  1396. {
  1397. // Process requested or derived Property sets
  1398. dwStatus = 0;
  1399. for(ulSet=0; ulSet<cSets; ulSet++)
  1400. {
  1401. ulNext=0;
  1402. cPropInfos = 0;
  1403. dwStatus &= (GETPROPINFO_ERRORSOCCURRED | GETPROPINFO_VALIDPROP);
  1404. // Calculate the number of property nodes needed for this
  1405. // property set.
  1406. if ( cPropertySets == 0 )
  1407. {
  1408. cPropInfos = _pUPropSet[ulSet].cUPropInfo;
  1409. dwStatus |= GETPROPINFO_ALLPROPIDS;
  1410. _xaiPropSetDex[0] = ulSet;
  1411. _cPropSetDex = 1;
  1412. }
  1413. else
  1414. {
  1415. // If the count of PROPIDs is 0 (NOTE: the above routine already determined
  1416. // if it belonged to a category and if so set the count of properties to 0 for
  1417. // each propset in that category.
  1418. if ( 0 == xaPropInfoSet[ulSet].cPropertyInfos )
  1419. {
  1420. dwStatus |= GETPROPINFO_ALLPROPIDS;
  1421. // We have to determine if the property set is supported and if so
  1422. // the count of properties in the set.
  1423. if ( GetPropertySetIndex(&(xaPropInfoSet[ulSet].guidPropertySet)) == S_OK )
  1424. {
  1425. Win4Assert( _cPropSetDex == 1 );
  1426. cPropInfos += _pUPropSet[_xaiPropSetDex[0]].cUPropInfo;
  1427. }
  1428. else
  1429. {
  1430. // Not Supported
  1431. dwStatus |= GETPROPINFO_ERRORSOCCURRED;
  1432. goto NEXT_SET;
  1433. }
  1434. }
  1435. else
  1436. {
  1437. cPropInfos = xaPropInfoSet[ulSet].cPropertyInfos;
  1438. if ( GetPropertySetIndex(&(xaPropInfoSet[ulSet].guidPropertySet)) == S_FALSE )
  1439. {
  1440. dwStatus |= GETPROPINFO_NOTSUPPORTED;
  1441. dwStatus |= GETPROPINFO_ERRORSOCCURRED;
  1442. }
  1443. }
  1444. }
  1445. // Allocate DBPROP array
  1446. Win4Assert( cPropInfos != 0 );
  1447. xaPropInfo.Init( cPropInfos );
  1448. for(ulProp=0; ulProp<cPropInfos; ulProp++)
  1449. {
  1450. VariantInit(&(xaPropInfo[ulProp].vValues));
  1451. if ( dwStatus & GETPROPINFO_NOTSUPPORTED )
  1452. {
  1453. // Not supported, thus we need to mark all as NOT_SUPPORTED
  1454. xaPropInfo[ulProp].dwPropertyID = rgPropertySets[ulSet].rgPropertyIDs[ulProp];
  1455. xaPropInfo[ulProp].dwFlags = DBPROPFLAGS_NOTSUPPORTED;
  1456. dwStatus |= GETPROPINFO_ERRORSOCCURRED;
  1457. }
  1458. }
  1459. // Make sure we support the property set
  1460. if ( dwStatus & GETPROPINFO_NOTSUPPORTED )
  1461. {
  1462. ulNext = cPropInfos;
  1463. goto NEXT_SET;
  1464. }
  1465. // Retrieve the property information for this property set
  1466. for(ul=0; ul<_cPropSetDex; ul++)
  1467. {
  1468. pUPropInfo = (UPROPINFO*)(_pUPropSet[_xaiPropSetDex[ul]].pUPropInfo);
  1469. Win4Assert( pUPropInfo );
  1470. // Retrieve current value of properties
  1471. if ( dwStatus & GETPROPINFO_ALLPROPIDS )
  1472. {
  1473. for(ulProp=0; ulProp<_pUPropSet[_xaiPropSetDex[ul]].cUPropInfo; ulProp++)
  1474. {
  1475. // Verify property is supported, if not do not return
  1476. if ( !TESTBIT(&(_xadwSupported[_xaiPropSetDex[ul] * _cElemPerSupported]), ulProp) )
  1477. continue;
  1478. pCurPropInfo = &(xaPropInfo[ulNext]);
  1479. // If the ppDescBuffer pointer was not NULL, then
  1480. // we need supply description of the properties
  1481. if ( ppDescBuffer )
  1482. {
  1483. // Set Buffer pointer
  1484. pCurPropInfo->pwszDescription = pDescBuffer;
  1485. // Load the string into temp buffer
  1486. //@TODO Add Reallocation routine
  1487. cch = LoadDescription( pUPropInfo[ulProp].pwszDesc,
  1488. wszBuff,
  1489. NUMELEM(wszBuff) );
  1490. if ( 0 != cch )
  1491. {
  1492. // Adjust for '\0'
  1493. cch++;
  1494. // Transfer to official buffer if room
  1495. RtlCopyMemory( pDescBuffer, wszBuff, cch * sizeof(WCHAR) );
  1496. pDescBuffer += cch;
  1497. }
  1498. else
  1499. {
  1500. wcscpy( pDescBuffer, L"UNKNOWN" );
  1501. pDescBuffer += NUMELEM(L"UNKNOWN");
  1502. }
  1503. }
  1504. pCurPropInfo->dwPropertyID = pUPropInfo[ulProp].dwPropId;
  1505. pCurPropInfo->dwFlags = pUPropInfo[ulProp].dwFlags;
  1506. pCurPropInfo->vtType = pUPropInfo[ulProp].VarType;
  1507. //@TODO for some there will be a list
  1508. pCurPropInfo->vValues.vt = VT_EMPTY;
  1509. dwStatus |= GETPROPINFO_VALIDPROP;
  1510. // Increment to next available buffer
  1511. ulNext++;
  1512. }
  1513. }
  1514. else
  1515. {
  1516. Win4Assert( _cPropSetDex == 1 );
  1517. for( ulProp = 0; ulProp < cPropInfos; ulProp++, ulNext++ )
  1518. {
  1519. pCurPropInfo = &(xaPropInfo[ulNext]);
  1520. // Process Properties based on Restriction array.
  1521. pCurPropInfo->dwPropertyID = rgPropertySets[ulSet].rgPropertyIDs[ulProp];
  1522. if ( S_OK == GetUPropInfoPtr( _xaiPropSetDex[ul],
  1523. pCurPropInfo->dwPropertyID,
  1524. &pUPropInfo) )
  1525. {
  1526. // If the ppDescBuffer pointer was not NULL, then
  1527. // we need supply description of the properties
  1528. if ( ppDescBuffer )
  1529. {
  1530. // Set Buffer pointer
  1531. pCurPropInfo->pwszDescription = pDescBuffer;
  1532. // Load the string into temp buffer
  1533. if ( cch = LoadDescription( pUPropInfo->pwszDesc,
  1534. wszBuff,
  1535. NUMELEM(wszBuff)) )
  1536. {
  1537. // Adjust for '\0'
  1538. cch++;
  1539. // Transfer to official buffer if room
  1540. RtlCopyMemory( pDescBuffer, wszBuff, cch * sizeof(WCHAR) );
  1541. pDescBuffer += cch;
  1542. }
  1543. else
  1544. {
  1545. wcscpy(pDescBuffer, L"UNKNOWN");
  1546. pDescBuffer += (wcslen(L"UNKNOWN") + 1);
  1547. }
  1548. }
  1549. pCurPropInfo->dwPropertyID = pUPropInfo->dwPropId;
  1550. pCurPropInfo->dwFlags = pUPropInfo->dwFlags;
  1551. pCurPropInfo->vtType = pUPropInfo->VarType;
  1552. dwStatus |= GETPROPINFO_VALIDPROP;
  1553. }
  1554. else
  1555. {
  1556. // Not Supported
  1557. pCurPropInfo->dwFlags = DBPROPFLAGS_NOTSUPPORTED;
  1558. dwStatus |= GETPROPINFO_ERRORSOCCURRED;
  1559. }
  1560. }
  1561. }
  1562. }
  1563. NEXT_SET:
  1564. xaPropInfoSet[ulSet].cPropertyInfos = ulNext;
  1565. xaPropInfoSet[ulSet].rgPropertyInfos = xaPropInfo.Acquire();
  1566. }
  1567. // Success, set return values
  1568. *pcPropertyInfoSets = cSets;
  1569. *prgPropertyInfoSets = xaPropInfoSet.Acquire();
  1570. if ( ppDescBuffer )
  1571. *ppDescBuffer = xawszDescBuffer.Acquire();
  1572. // At least one propid was marked as not S_OK
  1573. if ( dwStatus & GETPROPINFO_ERRORSOCCURRED )
  1574. {
  1575. // If at least 1 property was set
  1576. if ( dwStatus & GETPROPINFO_VALIDPROP )
  1577. return DB_S_ERRORSOCCURRED;
  1578. else
  1579. {
  1580. // Do not free any of the rgPropertyInfoSets, but
  1581. // do free the ppDescBuffer
  1582. if ( pDescBuffer )
  1583. {
  1584. Win4Assert( ppDescBuffer );
  1585. CoTaskMemFree( pDescBuffer );
  1586. *ppDescBuffer = 0;
  1587. }
  1588. return DB_E_ERRORSOCCURRED;
  1589. }
  1590. }
  1591. }
  1592. CATCH( CException, e )
  1593. {
  1594. // most likely E_OUTOFMEMORY
  1595. sc = e.GetErrorCode();
  1596. // Check if failure and clean up any allocated memory
  1597. if ( FAILED(sc) )
  1598. {
  1599. // Free Description Buffer
  1600. if ( pDescBuffer )
  1601. {
  1602. Win4Assert( ppDescBuffer );
  1603. CoTaskMemFree( *ppDescBuffer );
  1604. *ppDescBuffer = 0;
  1605. }
  1606. if ( !xaPropInfoSet.IsNull() )
  1607. {
  1608. // Loop through Property Sets
  1609. for(ulSet=0; ulSet<cSets; ulSet++)
  1610. {
  1611. if ( xaPropInfoSet[ulSet].rgPropertyInfos )
  1612. CoTaskMemFree( xaPropInfoSet[ulSet].rgPropertyInfos );
  1613. }
  1614. }
  1615. }
  1616. // Rethrow exception to the calling function
  1617. RETHROW();
  1618. }
  1619. END_CATCH;
  1620. UNTRANSLATE_EXCEPTIONS;
  1621. return S_OK;
  1622. }
  1623. //+---------------------------------------------------------------------------
  1624. //
  1625. // Method: CUtlPropInfo::FInit, protected
  1626. //
  1627. // Synopsis: Initialization. Called from constructors of derived classes.
  1628. //
  1629. // History: 11-12-97 danleg Created from Monarch
  1630. //
  1631. //----------------------------------------------------------------------------
  1632. void CUtlPropInfo::FInit
  1633. (
  1634. )
  1635. {
  1636. SCODE sc = S_OK;
  1637. InitAvailUPropSets( &_cUPropSet,
  1638. &_pUPropSet,
  1639. &_cElemPerSupported );
  1640. Win4Assert( (_cUPropSet != 0) && (_cElemPerSupported != 0) );
  1641. if ( !_cUPropSet || !_cElemPerSupported )
  1642. THROW( CException(E_FAIL) );
  1643. _xadwSupported.Init( _cUPropSet * _cElemPerSupported );
  1644. sc = InitUPropSetsSupported( _xadwSupported.GetPointer() );
  1645. if ( FAILED(sc) )
  1646. {
  1647. _xadwSupported.Free();
  1648. THROW( CException(sc) );
  1649. }
  1650. if ( _cUPropSet )
  1651. {
  1652. _xaiPropSetDex.Init( _cUPropSet );
  1653. }
  1654. return;
  1655. }
  1656. //+---------------------------------------------------------------------------
  1657. //
  1658. // Method: CUtlPropInfo::GetUPropInfoPtr, private
  1659. //
  1660. // Synopsis: Retrieve a pointer to the UPROPINFO structure that contains
  1661. // information about this property id within this property set
  1662. //
  1663. // Arguments: [iPropSetDex] - Index into UPropSets
  1664. // [dwPropertyId] - Property to search for with UPropSet
  1665. // [ppUPropInfo] - Pointer in which to return ptr to UPropInfo [out]
  1666. //
  1667. // Returns: SCODE as follows:
  1668. // S_OK - Property id found
  1669. // S_FALSE - No matching prop id found or property not supported
  1670. //
  1671. // History: 11-12-97 danleg Created from Monarch
  1672. //
  1673. //----------------------------------------------------------------------------
  1674. SCODE CUtlPropInfo::GetUPropInfoPtr
  1675. (
  1676. ULONG iPropSetDex, //@parm IN | Index into UPropSets
  1677. DBPROPID dwPropertyId, //@parm IN | Propery to search for with UPropSet
  1678. UPROPINFO** ppUPropInfo //@parm OUT | Pointer in which to return ptr to UPropInfo
  1679. )
  1680. {
  1681. ULONG ulProps;
  1682. // Scan through the property sets looking for matching attributes
  1683. for(ulProps=0; ulProps<_pUPropSet[iPropSetDex].cUPropInfo; ulProps++)
  1684. {
  1685. if ( _pUPropSet[iPropSetDex].pUPropInfo[ulProps].dwPropId == dwPropertyId )
  1686. {
  1687. *ppUPropInfo = (UPROPINFO*)&(_pUPropSet[iPropSetDex].pUPropInfo[ulProps]);
  1688. // Test to see if the property is supported for this instantiation
  1689. if ( TESTBIT(&(_xadwSupported[iPropSetDex * _cElemPerSupported]), ulProps) )
  1690. return S_OK;
  1691. else
  1692. return S_FALSE;
  1693. }
  1694. }
  1695. return S_FALSE;
  1696. }
  1697. //+---------------------------------------------------------------------------
  1698. //
  1699. // Method: CUtlPropInfo::GetPropertySetIndex, private
  1700. //
  1701. // Synopsis: Retrieve the index or indices of PropertySets that match the
  1702. // given guid.
  1703. //
  1704. // NOTE: If given a DBPROPET_DATASOURCEALL, DBPROPSET_DATASOURCEINFOALL
  1705. // or DBPROPSET_ROWSETALL, the routine may return multiple
  1706. // indices.
  1707. // Returns: SCODE as follows:
  1708. // S_OK - At least one index was returned.
  1709. // S_FALSE - No matching property set found
  1710. //
  1711. // History: 11-12-97 danleg Created from Monarch
  1712. //
  1713. //----------------------------------------------------------------------------
  1714. SCODE CUtlPropInfo::GetPropertySetIndex
  1715. (
  1716. const GUID* pPropertySet //@parm IN | Pointer to Property Set Guid
  1717. )
  1718. {
  1719. DWORD dwFlag = 0;
  1720. ULONG ulSet;
  1721. Win4Assert( _cUPropSet && _pUPropSet );
  1722. Win4Assert( !_xaiPropSetDex.IsNull() );
  1723. Win4Assert( pPropertySet );
  1724. _cPropSetDex = 0;
  1725. if ( *pPropertySet == DBPROPSET_DATASOURCEALL )
  1726. {
  1727. dwFlag = DBPROPFLAGS_DATASOURCE;
  1728. }
  1729. else if ( *pPropertySet == DBPROPSET_DATASOURCEINFOALL )
  1730. {
  1731. dwFlag = DBPROPFLAGS_DATASOURCEINFO;
  1732. }
  1733. else if ( *pPropertySet == DBPROPSET_ROWSETALL )
  1734. {
  1735. dwFlag = DBPROPFLAGS_ROWSET;
  1736. }
  1737. else if ( *pPropertySet == DBPROPSET_DBINITALL )
  1738. {
  1739. dwFlag = DBPROPFLAGS_DBINIT;
  1740. }
  1741. else if ( *pPropertySet == DBPROPSET_SESSIONALL )
  1742. {
  1743. dwFlag = DBPROPFLAGS_SESSION;
  1744. }
  1745. else // No scan required, just look for match.
  1746. {
  1747. for(ulSet=0; ulSet<_cUPropSet; ulSet++)
  1748. {
  1749. if ( *(_pUPropSet[ulSet].pPropSet) == *pPropertySet )
  1750. {
  1751. _xaiPropSetDex[_cPropSetDex] = ulSet;
  1752. _cPropSetDex++;
  1753. break;
  1754. }
  1755. }
  1756. goto EXIT;
  1757. }
  1758. // Scan through the property sets looking for matching attributes
  1759. for(ulSet=0; ulSet<_cUPropSet; ulSet++)
  1760. {
  1761. if ( _pUPropSet[ulSet].pUPropInfo[0].dwFlags & dwFlag )
  1762. {
  1763. _xaiPropSetDex[_cPropSetDex] = ulSet;
  1764. _cPropSetDex++;
  1765. }
  1766. }
  1767. EXIT:
  1768. return (_cPropSetDex) ? S_OK : S_FALSE;
  1769. }
  1770. //+---------------------------------------------------------------------------
  1771. //
  1772. // Method: CUtlPropInfo::CalcDescripBuffers, private
  1773. //
  1774. // Synopsis: Calculate the number of description buffers that will be needed
  1775. //
  1776. // Argunemts: [cPropInfoSet] - Count of propinfo sets
  1777. // [pPropInfoSet] - Property info sets
  1778. //
  1779. // Returns: Number of buffers needed
  1780. //
  1781. // History: 11-12-97 danleg Created from Monarch
  1782. //
  1783. //----------------------------------------------------------------------------
  1784. ULONG CUtlPropInfo::CalcDescripBuffers
  1785. (
  1786. ULONG cPropInfoSet, //@parm IN | count of property info sets
  1787. DBPROPINFOSET* pPropInfoSet //@parm IN | property info sets
  1788. )
  1789. {
  1790. ULONG ul, ulSet;
  1791. ULONG cBuffers = 0;
  1792. Win4Assert( _pUPropSet && cPropInfoSet && pPropInfoSet );
  1793. for(ulSet=0; ulSet<cPropInfoSet; ulSet++)
  1794. {
  1795. if ( GetPropertySetIndex(&(pPropInfoSet[ulSet].guidPropertySet)) == S_OK)
  1796. {
  1797. for(ul=0; ul<_cPropSetDex; ul++)
  1798. {
  1799. cBuffers += _pUPropSet[_xaiPropSetDex[ul]].cUPropInfo;
  1800. }
  1801. }
  1802. }
  1803. return cBuffers;
  1804. }