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.

1837 lines
39 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: cprops.cxx
  7. //
  8. // Contents: Property Cache functionality for NT
  9. //
  10. // Functions:
  11. // CPropertyCache::addproperty
  12. // CPropertyCache::updateproperty
  13. // CPropertyCache::findproperty
  14. // CPropertyCache::getproperty
  15. // CPropertyCache::putproperty
  16. // CProperyCache::CPropertyCache
  17. // CPropertyCache::~CPropertyCache
  18. // CPropertyCache::createpropertycache
  19. //
  20. // History: 17-June-1996 RamV Created.
  21. // cloned off NT property cache code
  22. //
  23. //
  24. //----------------------------------------------------------------------------
  25. #include "winnt.hxx"
  26. #pragma hdrstop
  27. #define INITGUID
  28. #if DBG
  29. DECLARE_INFOLEVEL(NTMarshall);
  30. DECLARE_DEBUG(NTMarshall);
  31. #define NTMarshallDebugOut(x) NTMarshallInlineDebugOut x
  32. #endif
  33. void
  34. ADsECodesToDispECodes(
  35. HRESULT *pHr
  36. );
  37. //+------------------------------------------------------------------------
  38. //
  39. // Function: CPropertyCache::addproperty
  40. //
  41. // Synopsis:
  42. //
  43. //
  44. //
  45. // Arguments: [szPropertyName] --
  46. // [vt] --
  47. // [vaData] --
  48. //
  49. //
  50. //-------------------------------------------------------------------------
  51. HRESULT
  52. CPropertyCache::
  53. addproperty(
  54. LPWSTR szPropertyName,
  55. DWORD dwSyntaxId,
  56. DWORD dwNumValues,
  57. PNTOBJECT pNtObject
  58. )
  59. {
  60. HRESULT hr = S_OK;
  61. PPROPERTY pNewProperty = NULL;
  62. LPWSTR tempString = NULL;
  63. //
  64. // Allocate the string first
  65. //
  66. tempString = AllocADsStr(szPropertyName);
  67. if (!tempString)
  68. BAIL_ON_FAILURE(hr=E_OUTOFMEMORY);
  69. //
  70. // extend the property cache by adding a new property entry
  71. //
  72. _pProperties = (PPROPERTY)ReallocADsMem(
  73. _pProperties,
  74. _cb,
  75. _cb + sizeof(PROPERTY)
  76. );
  77. if (!_pProperties) {
  78. hr = E_OUTOFMEMORY;
  79. BAIL_ON_FAILURE(hr);
  80. }
  81. pNewProperty = (PPROPERTY)((LPBYTE)_pProperties + _cb);
  82. if (pNewProperty->szPropertyName) {
  83. FreeADsStr(pNewProperty->szPropertyName);
  84. pNewProperty->szPropertyName = NULL;
  85. }
  86. pNewProperty->szPropertyName = tempString;
  87. //
  88. // Update the index
  89. //
  90. _dwMaxProperties++;
  91. _cb += sizeof(PROPERTY);
  92. //
  93. // add to dynamic dispatch table now ???
  94. // - don't check schema here, is it more efficient at all? inconsistency
  95. // ???
  96. //
  97. /*
  98. hr = DispatchAddProperty(
  99. szPropertyName
  100. );
  101. BAIL_ON_FAILURE(hr);
  102. */
  103. RRETURN(hr);
  104. error:
  105. if (tempString)
  106. FreeADsStr(tempString);
  107. RRETURN_EXP_IF_ERR(hr);
  108. }
  109. //+------------------------------------------------------------------------
  110. //
  111. // Function: CPropertyCache::updateproperty
  112. //
  113. // Synopsis:
  114. //
  115. //
  116. //
  117. // Arguments: [szPropertyName] --
  118. // [vaData] --
  119. //
  120. //-------------------------------------------------------------------------
  121. HRESULT
  122. CPropertyCache::updateproperty(
  123. LPWSTR szPropertyName,
  124. DWORD dwSyntaxId,
  125. DWORD dwNumValues,
  126. PNTOBJECT pNtObject,
  127. BOOL fExplicit
  128. )
  129. {
  130. HRESULT hr;
  131. DWORD dwIndex;
  132. PNTOBJECT pNtTempObject = NULL;
  133. PPROPERTY pThisProperty = NULL;
  134. hr = findproperty(
  135. szPropertyName,
  136. &dwIndex
  137. );
  138. BAIL_ON_FAILURE(hr);
  139. pThisProperty = _pProperties + dwIndex;
  140. if (!fExplicit) {
  141. if (PROPERTY_FLAGS(pThisProperty) & CACHE_PROPERTY_MODIFIED) {
  142. hr = S_OK;
  143. goto error;
  144. }
  145. }
  146. //
  147. // Factor in cases where object state is necessary to
  148. // decide on update.
  149. //
  150. if (PROPERTY_NTOBJECT(pThisProperty)) {
  151. NTTypeFreeNTObjects(
  152. PROPERTY_NTOBJECT(pThisProperty),
  153. PROPERTY_NUMVALUES(pThisProperty)
  154. );
  155. PROPERTY_NTOBJECT(pThisProperty) = NULL;
  156. }
  157. PROPERTY_SYNTAX(pThisProperty) = dwSyntaxId;
  158. PROPERTY_NUMVALUES(pThisProperty) = dwNumValues;
  159. hr = NtTypeCopyConstruct(
  160. pNtObject,
  161. dwNumValues,
  162. &pNtTempObject
  163. );
  164. BAIL_ON_FAILURE(hr);
  165. PROPERTY_NTOBJECT(pThisProperty) = pNtTempObject;
  166. PROPERTY_FLAGS(pThisProperty) &= ~PROPERTY_MODIFIED;
  167. error:
  168. RRETURN_EXP_IF_ERR(hr);
  169. }
  170. //+------------------------------------------------------------------------
  171. //
  172. // Function: CPropertyCache::findproperty
  173. //
  174. // Synopsis:
  175. //
  176. //
  177. //
  178. // Arguments: [szPropertyName] --
  179. // [pdwIndex] --
  180. //
  181. //-------------------------------------------------------------------------
  182. HRESULT
  183. CPropertyCache::findproperty(
  184. LPWSTR szPropertyName,
  185. PDWORD pdwIndex
  186. )
  187. {
  188. DWORD i = 0;
  189. PPROPERTY pThisProperty = NULL;
  190. for (i = 0; i < _dwMaxProperties; i++) {
  191. pThisProperty = _pProperties + i;
  192. if (!_wcsicmp(pThisProperty->szPropertyName, szPropertyName)) {
  193. *pdwIndex = i;
  194. RRETURN(S_OK);
  195. }
  196. }
  197. *pdwIndex = 0;
  198. RRETURN(E_ADS_PROPERTY_NOT_FOUND);
  199. }
  200. //+------------------------------------------------------------------------
  201. //
  202. // Function: CPropertyCache::getproperty
  203. //
  204. // Synopsis:
  205. //
  206. //
  207. //
  208. // Arguments: [szPropertyName] -- Property to retrieve from the cache
  209. // [pvaData] -- Data returned in a variant
  210. //
  211. //-------------------------------------------------------------------------
  212. HRESULT
  213. CPropertyCache::
  214. getproperty(
  215. LPWSTR szPropertyName,
  216. PDWORD pdwSyntaxId,
  217. PDWORD pdwNumValues,
  218. PNTOBJECT * ppNtObject,
  219. BOOL *pfModified
  220. )
  221. {
  222. HRESULT hr;
  223. DWORD dwIndex = 0L;
  224. PPROPERTY pThisProperty = NULL;
  225. DWORD dwResult;
  226. DWORD dwInfoLevel = 0;
  227. hr = findproperty(
  228. szPropertyName,
  229. &dwIndex
  230. );
  231. // don't do implicit GetInfo if there is no ADSI object backing the
  232. // property cache. This will be true for UMI interafec properties.
  233. if ((hr == E_ADS_PROPERTY_NOT_FOUND) && (_pCoreADsObject != NULL)) {
  234. hr = GetPropertyInfoLevel(
  235. szPropertyName,
  236. _pSchemaClassProps,
  237. _dwNumProperties,
  238. &dwInfoLevel
  239. );
  240. BAIL_ON_FAILURE(hr);
  241. //
  242. // Now call the GetInfo function
  243. //
  244. hr = _pCoreADsObject->GetInfo(
  245. dwInfoLevel,
  246. FALSE
  247. );
  248. BAIL_ON_FAILURE(hr);
  249. hr = findproperty(
  250. szPropertyName,
  251. &dwIndex
  252. );
  253. }
  254. BAIL_ON_FAILURE(hr);
  255. pThisProperty = _pProperties + dwIndex;
  256. if (PROPERTY_NTOBJECT(pThisProperty)) {
  257. *pdwSyntaxId = (DWORD)PROPERTY_SYNTAX(pThisProperty);
  258. *pdwNumValues = (DWORD)PROPERTY_NUMVALUES(pThisProperty);
  259. if(pfModified != NULL) { // caller wants to know if prop. was modified
  260. if(PROPERTY_FLAGS(pThisProperty) & CACHE_PROPERTY_MODIFIED)
  261. *pfModified = TRUE;
  262. else
  263. *pfModified = FALSE;
  264. }
  265. hr = NtTypeCopyConstruct(PROPERTY_NTOBJECT(pThisProperty),
  266. PROPERTY_NUMVALUES(pThisProperty),
  267. ppNtObject );
  268. BAIL_ON_FAILURE(hr);
  269. }else {
  270. *ppNtObject = NULL;
  271. *pdwNumValues = 0;
  272. *pdwSyntaxId = 0;
  273. hr = E_FAIL;
  274. }
  275. error:
  276. RRETURN_EXP_IF_ERR(hr);
  277. }
  278. //+------------------------------------------------------------------------
  279. //
  280. // Function: CPropertyCache::marshallgetproperty
  281. //
  282. // Synopsis:
  283. //
  284. //
  285. //
  286. // Arguments: [szPropertyName] -- Property to retrieve from the cache
  287. // [pvaData] -- Data returned in a variant
  288. //
  289. //-------------------------------------------------------------------------
  290. HRESULT
  291. CPropertyCache::
  292. marshallgetproperty(
  293. LPWSTR szPropertyName,
  294. PDWORD pdwSyntaxId,
  295. PDWORD pdwNumValues,
  296. PNTOBJECT * ppNtObject
  297. )
  298. {
  299. HRESULT hr;
  300. DWORD dwIndex = 0L;
  301. PPROPERTY pThisProperty = NULL;
  302. DWORD dwResult;
  303. DWORD dwInfoLevel = 0;
  304. hr = findproperty(
  305. szPropertyName,
  306. &dwIndex
  307. );
  308. BAIL_ON_FAILURE(hr);
  309. pThisProperty = _pProperties + dwIndex;
  310. //
  311. // If the data has not changed, then do not
  312. // return data from the cache
  313. //
  314. if (PROPERTY_FLAGS(pThisProperty) == 0) {
  315. hr = E_ADS_PROPERTY_NOT_MODIFIED;
  316. BAIL_ON_FAILURE(hr);
  317. }
  318. if (PROPERTY_NTOBJECT(pThisProperty)) {
  319. *pdwSyntaxId = (DWORD)PROPERTY_SYNTAX(pThisProperty);
  320. *pdwNumValues = (DWORD)PROPERTY_NUMVALUES(pThisProperty);
  321. hr = NtTypeCopyConstruct(PROPERTY_NTOBJECT(pThisProperty),
  322. PROPERTY_NUMVALUES(pThisProperty),
  323. ppNtObject );
  324. BAIL_ON_FAILURE(hr);
  325. }else {
  326. *ppNtObject = NULL;
  327. *pdwNumValues = 0;
  328. *pdwSyntaxId = 0;
  329. hr = E_FAIL;
  330. }
  331. error:
  332. RRETURN_EXP_IF_ERR(hr);
  333. }
  334. //+------------------------------------------------------------------------
  335. //
  336. // Function: CPropertyCache::putproperty
  337. //
  338. // Synopsis:
  339. //
  340. //
  341. //
  342. // Arguments: [szPropertyName] -- Clsid index
  343. // [vaData] -- Matching clsid returned in *pclsid
  344. //
  345. //-------------------------------------------------------------------------
  346. HRESULT
  347. CPropertyCache::putproperty(
  348. LPWSTR szPropertyName,
  349. DWORD dwSyntaxId,
  350. DWORD dwNumValues,
  351. PNTOBJECT pNtObject,
  352. BOOL fMarkAsClean
  353. )
  354. {
  355. HRESULT hr;
  356. DWORD dwIndex = 0L;
  357. PNTOBJECT pNtTempObject = NULL;
  358. PPROPERTY pThisProperty = NULL;
  359. hr = findproperty(
  360. szPropertyName,
  361. &dwIndex
  362. );
  363. BAIL_ON_FAILURE(hr);
  364. pThisProperty = _pProperties + dwIndex;
  365. if (PROPERTY_NTOBJECT(pThisProperty)) {
  366. NTTypeFreeNTObjects(
  367. PROPERTY_NTOBJECT(pThisProperty),
  368. PROPERTY_NUMVALUES(pThisProperty)
  369. );
  370. PROPERTY_NTOBJECT(pThisProperty) = NULL;
  371. }
  372. PROPERTY_SYNTAX(pThisProperty) = dwSyntaxId;
  373. PROPERTY_NUMVALUES(pThisProperty) = dwNumValues;
  374. hr = NtTypeCopyConstruct(
  375. pNtObject,
  376. dwNumValues,
  377. &pNtTempObject
  378. );
  379. BAIL_ON_FAILURE(hr);
  380. PROPERTY_NTOBJECT(pThisProperty) = pNtTempObject;
  381. if(FALSE == fMarkAsClean)
  382. PROPERTY_FLAGS(pThisProperty) |= CACHE_PROPERTY_MODIFIED;
  383. error:
  384. RRETURN_EXP_IF_ERR(hr);
  385. }
  386. //+------------------------------------------------------------------------
  387. //
  388. // Function: CPropertyCache
  389. //
  390. // Synopsis:
  391. //
  392. //
  393. //
  394. // Arguments:
  395. //
  396. //
  397. //-------------------------------------------------------------------------
  398. CPropertyCache::CPropertyCache():
  399. _pCoreADsObject(NULL),
  400. _pSchemaClassProps(NULL),
  401. _dwMaxProperties(0),
  402. _dwCurrentIndex(0),
  403. _pProperties(NULL),
  404. _cb(0),
  405. _pDispProperties(NULL),
  406. _dwDispMaxProperties(0),
  407. _cbDisp(0)
  408. {
  409. }
  410. //+------------------------------------------------------------------------
  411. //
  412. // Function: ~CPropertyCache
  413. //
  414. // Synopsis:
  415. //
  416. //
  417. //
  418. // Arguments:
  419. //
  420. //
  421. //-------------------------------------------------------------------------
  422. CPropertyCache::
  423. ~CPropertyCache()
  424. {
  425. DWORD i = 0;
  426. PPROPERTY pThisProperty = NULL;
  427. PDISPPROPERTY pThisDispProperty = NULL;
  428. if (_pProperties) {
  429. for (i = 0; i < _dwMaxProperties; i++) {
  430. pThisProperty = _pProperties + i;
  431. if (pThisProperty->szPropertyName) {
  432. FreeADsStr(pThisProperty->szPropertyName);
  433. pThisProperty->szPropertyName = NULL;
  434. }
  435. if (PROPERTY_NTOBJECT(pThisProperty)) {
  436. NTTypeFreeNTObjects(
  437. PROPERTY_NTOBJECT(pThisProperty),
  438. PROPERTY_NUMVALUES(pThisProperty)
  439. );
  440. PROPERTY_NTOBJECT(pThisProperty) = NULL;
  441. }
  442. }
  443. FreeADsMem(_pProperties);
  444. }
  445. //
  446. // Free Dynamic Dispid Table
  447. //
  448. if (_pDispProperties) {
  449. for ( DWORD i = 0; i < _dwDispMaxProperties; i++ ) {
  450. pThisDispProperty = _pDispProperties + i;
  451. if (pThisDispProperty->szPropertyName) {
  452. FreeADsStr(pThisDispProperty->szPropertyName);
  453. pThisDispProperty->szPropertyName = NULL;
  454. }
  455. }
  456. FreeADsMem(_pDispProperties);
  457. }
  458. }
  459. //+------------------------------------------------------------------------
  460. //
  461. // Function:
  462. //
  463. // Synopsis:
  464. //
  465. //
  466. //
  467. // Arguments:
  468. //
  469. //
  470. //-------------------------------------------------------------------------
  471. HRESULT
  472. CPropertyCache::
  473. createpropertycache(
  474. PPROPERTYINFO pSchemaClassProps,
  475. DWORD dwNumProperties,
  476. CCoreADsObject FAR * pCoreADsObject,
  477. CPropertyCache FAR *FAR * ppPropertyCache
  478. )
  479. {
  480. CPropertyCache FAR * pPropertyCache = NULL;
  481. pPropertyCache = new CPropertyCache();
  482. if (!pPropertyCache) {
  483. RRETURN_EXP_IF_ERR(E_OUTOFMEMORY);
  484. }
  485. pPropertyCache->_pCoreADsObject = pCoreADsObject;
  486. pPropertyCache->_pSchemaClassProps = pSchemaClassProps;
  487. pPropertyCache->_dwNumProperties = dwNumProperties;
  488. *ppPropertyCache = pPropertyCache;
  489. RRETURN(S_OK);
  490. }
  491. //+------------------------------------------------------------------------
  492. //
  493. // Function:
  494. //
  495. // Synopsis:
  496. //
  497. //
  498. //
  499. // Arguments:
  500. //
  501. //
  502. //-------------------------------------------------------------------------
  503. HRESULT
  504. CPropertyCache::
  505. unmarshallproperty(
  506. LPWSTR szPropertyName,
  507. LPBYTE lpValue,
  508. DWORD dwNumValues,
  509. DWORD dwSyntaxId,
  510. BOOL fExplicit
  511. )
  512. {
  513. DWORD dwIndex = 0;
  514. HRESULT hr = S_OK;
  515. PNTOBJECT pNTObject = NULL;
  516. hr = UnMarshallNTToNTSynId(
  517. dwSyntaxId,
  518. dwNumValues,
  519. lpValue,
  520. &pNTObject
  521. );
  522. BAIL_ON_FAILURE(hr);
  523. //
  524. // Find this property in the cache
  525. //
  526. hr = findproperty(
  527. szPropertyName,
  528. &dwIndex
  529. );
  530. //
  531. // If this property does not exist in the
  532. // cache, add this property into the cache.
  533. //
  534. if (FAILED(hr)) {
  535. hr = addproperty(
  536. szPropertyName,
  537. dwSyntaxId,
  538. dwNumValues,
  539. pNTObject
  540. );
  541. //
  542. // If the operation fails for some reason
  543. // move on to the next property
  544. //
  545. BAIL_ON_FAILURE(hr);
  546. }
  547. //
  548. // Now update the property in the cache
  549. //
  550. hr = updateproperty(
  551. szPropertyName,
  552. dwSyntaxId,
  553. dwNumValues,
  554. pNTObject,
  555. fExplicit
  556. );
  557. BAIL_ON_FAILURE(hr);
  558. error:
  559. if (pNTObject) {
  560. NTTypeFreeNTObjects(
  561. pNTObject,
  562. dwNumValues
  563. );
  564. }
  565. RRETURN_EXP_IF_ERR(hr);
  566. }
  567. HRESULT
  568. ValidatePropertyinSchemaClass(
  569. PPROPERTYINFO pSchemaClassProps,
  570. DWORD dwNumProperties,
  571. LPWSTR pszPropName,
  572. PDWORD pdwSyntaxId
  573. )
  574. {
  575. DWORD i = 0;
  576. PPROPERTYINFO pThisSchProperty = NULL;
  577. for (i = 0; i < dwNumProperties; i++) {
  578. pThisSchProperty = (pSchemaClassProps + i);
  579. if (!_wcsicmp(pszPropName, pThisSchProperty->szPropertyName)) {
  580. *pdwSyntaxId = pThisSchProperty->dwSyntaxId;
  581. RRETURN (S_OK);
  582. }
  583. }
  584. RRETURN(E_ADS_SCHEMA_VIOLATION);
  585. }
  586. HRESULT
  587. ValidateIfWriteableProperty(
  588. PPROPERTYINFO pSchemaClassProps,
  589. DWORD dwNumProperties,
  590. LPWSTR pszPropName
  591. )
  592. {
  593. DWORD i = 0;
  594. PPROPERTYINFO pThisSchProperty = NULL;
  595. for (i = 0; i < dwNumProperties; i++) {
  596. pThisSchProperty = (pSchemaClassProps + i);
  597. if (!_wcsicmp(pszPropName, pThisSchProperty->szPropertyName)) {
  598. RRETURN((pThisSchProperty->dwFlags & PROPERTY_WRITEABLE)
  599. ? S_OK : E_ADS_SCHEMA_VIOLATION);
  600. }
  601. }
  602. RRETURN(E_ADS_SCHEMA_VIOLATION);
  603. // for winnt & nw312, return E_ADS_SCHEMA_VIOLATION if not ok even
  604. // if just try to write to cache only
  605. }
  606. HRESULT
  607. GetPropertyInfoLevel(
  608. LPWSTR pszPropName,
  609. PPROPERTYINFO pSchemaClassProps,
  610. DWORD dwNumProperties,
  611. PDWORD pdwInfoLevel
  612. )
  613. {
  614. DWORD i = 0;
  615. PPROPERTYINFO pThisSchProperty = NULL;
  616. for (i = 0; i < dwNumProperties; i++) {
  617. pThisSchProperty = (pSchemaClassProps + i);
  618. if (!_wcsicmp(pszPropName, pThisSchProperty->szPropertyName)) {
  619. *pdwInfoLevel = pThisSchProperty->dwInfoLevel;
  620. RRETURN(S_OK);
  621. }
  622. }
  623. //
  624. // Returning E_ADS_PROPERTY_NOT_FOUND so that implicit
  625. // GetInfo fails gracefully
  626. //
  627. RRETURN(E_ADS_PROPERTY_NOT_FOUND);
  628. }
  629. //+------------------------------------------------------------------------
  630. //
  631. // Function: ~CPropertyCache
  632. //
  633. // Synopsis:
  634. //
  635. //
  636. //
  637. // Arguments:
  638. //
  639. //
  640. //-------------------------------------------------------------------------
  641. void
  642. CPropertyCache::
  643. flushpropcache()
  644. {
  645. DWORD i = 0;
  646. PPROPERTY pThisProperty = NULL;
  647. if (_pProperties) {
  648. for (i = 0; i < _dwMaxProperties; i++) {
  649. pThisProperty = _pProperties + i;
  650. if (pThisProperty->szPropertyName) {
  651. FreeADsStr(pThisProperty->szPropertyName);
  652. pThisProperty->szPropertyName = NULL;
  653. }
  654. if (PROPERTY_NTOBJECT(pThisProperty)) {
  655. NTTypeFreeNTObjects(
  656. PROPERTY_NTOBJECT(pThisProperty),
  657. PROPERTY_NUMVALUES(pThisProperty)
  658. );
  659. PROPERTY_NTOBJECT(pThisProperty) = NULL;
  660. }
  661. }
  662. FreeADsMem(_pProperties);
  663. }
  664. //
  665. // Reset the property cache
  666. //
  667. _pProperties = NULL;
  668. _dwMaxProperties = 0;
  669. _cb = 0;
  670. }
  671. //+------------------------------------------------------------------------
  672. //
  673. // Function: CPropertyCache::getproperty
  674. //
  675. // Synopsis:
  676. //
  677. //
  678. //
  679. // Arguments: [szPropertyName] -- Property to retrieve from the cache
  680. // [pvaData] -- Data returned in a variant
  681. //
  682. //-------------------------------------------------------------------------
  683. HRESULT
  684. CPropertyCache::
  685. unboundgetproperty(
  686. LPWSTR szPropertyName,
  687. PDWORD pdwSyntaxId,
  688. PDWORD pdwNumValues,
  689. PNTOBJECT * ppNtObject
  690. )
  691. {
  692. HRESULT hr;
  693. DWORD dwIndex = 0L;
  694. PPROPERTY pThisProperty = NULL;
  695. hr = findproperty(
  696. szPropertyName,
  697. &dwIndex
  698. );
  699. BAIL_ON_FAILURE(hr);
  700. pThisProperty = _pProperties + dwIndex;
  701. if (PROPERTY_NTOBJECT(pThisProperty)) {
  702. *pdwSyntaxId = (DWORD)PROPERTY_SYNTAX(pThisProperty);
  703. *pdwNumValues = (DWORD)PROPERTY_NUMVALUES(pThisProperty);
  704. hr = NtTypeCopyConstruct(
  705. PROPERTY_NTOBJECT(pThisProperty),
  706. PROPERTY_NUMVALUES(pThisProperty),
  707. ppNtObject
  708. );
  709. BAIL_ON_FAILURE(hr);
  710. }else {
  711. *ppNtObject = NULL;
  712. *pdwNumValues = 0;
  713. *pdwSyntaxId = 0;
  714. hr = E_FAIL;
  715. }
  716. error:
  717. RRETURN_EXP_IF_ERR(hr);
  718. }
  719. //+------------------------------------------------------------------------
  720. //
  721. // Function: CPropertyCache::getproperty
  722. //
  723. // Synopsis:
  724. //
  725. //
  726. //
  727. // Arguments: [szPropertyName] -- Property to retrieve from the cache
  728. // [pvaData] -- Data returned in a variant
  729. //
  730. //-------------------------------------------------------------------------
  731. HRESULT
  732. CPropertyCache::
  733. unboundgetproperty(
  734. DWORD dwIndex,
  735. PDWORD pdwSyntaxId,
  736. PDWORD pdwNumValues,
  737. PNTOBJECT * ppNtObject
  738. )
  739. {
  740. HRESULT hr;
  741. PPROPERTY pThisProperty = NULL;
  742. if (!index_valid(dwIndex)) {
  743. RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_FOUND);
  744. }
  745. pThisProperty = _pProperties + dwIndex;
  746. if (PROPERTY_NTOBJECT(pThisProperty)) {
  747. *pdwSyntaxId = (DWORD)PROPERTY_SYNTAX(pThisProperty);
  748. *pdwNumValues = (DWORD)PROPERTY_NUMVALUES(pThisProperty);
  749. hr = NtTypeCopyConstruct(
  750. PROPERTY_NTOBJECT(pThisProperty),
  751. PROPERTY_NUMVALUES(pThisProperty),
  752. ppNtObject
  753. );
  754. BAIL_ON_FAILURE(hr);
  755. }else {
  756. *ppNtObject = NULL;
  757. *pdwNumValues = 0;
  758. *pdwSyntaxId = 0;
  759. hr = E_FAIL;
  760. }
  761. error:
  762. RRETURN_EXP_IF_ERR(hr);
  763. }
  764. BOOL
  765. CPropertyCache::
  766. index_valid(
  767. )
  768. {
  769. //
  770. // need to check _dwMaxProperties==0 separately since a negative
  771. // DWORD is equal to +ve large #
  772. //
  773. if (_dwMaxProperties==0 || (_dwCurrentIndex>_dwMaxProperties-1) )
  774. return(FALSE);
  775. else
  776. return(TRUE);
  777. }
  778. BOOL
  779. CPropertyCache::
  780. index_valid(
  781. DWORD dwIndex
  782. )
  783. {
  784. //
  785. // need to check _dwMaxProperties==0 separately since a negative
  786. // DWORD is equal to +ve large #
  787. //
  788. if (_dwMaxProperties==0 || (dwIndex>_dwMaxProperties-1) )
  789. return(FALSE);
  790. else
  791. return(TRUE);
  792. }
  793. void
  794. CPropertyCache::
  795. reset_propindex(
  796. )
  797. {
  798. _dwCurrentIndex = 0;
  799. }
  800. HRESULT
  801. CPropertyCache::
  802. skip_propindex(
  803. DWORD dwElements
  804. )
  805. {
  806. DWORD newIndex = _dwCurrentIndex + dwElements;
  807. if (!index_valid())
  808. RRETURN_EXP_IF_ERR(E_FAIL);
  809. //
  810. // - allow current index to go from within range to out of range by 1
  811. // - by 1 since initial state is out of range by 1
  812. //
  813. if (newIndex>_dwMaxProperties) {
  814. RRETURN_EXP_IF_ERR(E_FAIL);
  815. }
  816. _dwCurrentIndex = newIndex;
  817. RRETURN(S_OK);
  818. }
  819. HRESULT
  820. CPropertyCache::
  821. get_PropertyCount(
  822. PDWORD pdwMaxProperties
  823. )
  824. {
  825. *pdwMaxProperties = _dwMaxProperties;
  826. RRETURN(S_OK);
  827. }
  828. DWORD
  829. CPropertyCache::
  830. get_CurrentIndex(
  831. )
  832. {
  833. return(_dwCurrentIndex);
  834. }
  835. LPWSTR
  836. CPropertyCache::
  837. get_CurrentPropName(
  838. )
  839. {
  840. PPROPERTY pThisProperty = NULL;
  841. if (!_dwMaxProperties) // if !_dwMaxProperties, pThisProperty=NULL, AV
  842. return NULL; // in PROPERTY_NAME(pThisProperty)
  843. if (!index_valid())
  844. return(NULL);
  845. pThisProperty = _pProperties + _dwCurrentIndex;
  846. return(PROPERTY_NAME(pThisProperty));
  847. }
  848. LPWSTR
  849. CPropertyCache::
  850. get_PropName(
  851. DWORD dwIndex
  852. )
  853. {
  854. PPROPERTY pThisProperty = NULL;
  855. if (!index_valid(dwIndex))
  856. return(NULL);
  857. pThisProperty = _pProperties + dwIndex;
  858. return(PROPERTY_NAME(pThisProperty));
  859. }
  860. HRESULT
  861. CPropertyCache::
  862. deleteproperty(
  863. DWORD dwIndex
  864. )
  865. {
  866. HRESULT hr = S_OK;
  867. PPROPERTY pNewProperties = NULL;
  868. PPROPERTY pThisProperty = _pProperties + dwIndex;
  869. if (!index_valid(dwIndex)) {
  870. hr = E_FAIL;
  871. BAIL_ON_FAILURE(hr);
  872. }
  873. if (_dwMaxProperties == 1) {
  874. //
  875. // Deleting everything
  876. //
  877. if (PROPERTY_NTOBJECT(pThisProperty)) {
  878. NTTypeFreeNTObjects(
  879. PROPERTY_NTOBJECT(pThisProperty),
  880. PROPERTY_NUMVALUES(pThisProperty)
  881. );
  882. PROPERTY_NTOBJECT(pThisProperty) = NULL;
  883. }
  884. FreeADsMem(_pProperties);
  885. _pProperties = NULL;
  886. _dwMaxProperties = 0;
  887. _cb = 0;
  888. //
  889. // Reset the current index just in case
  890. //
  891. _dwCurrentIndex = 0;
  892. RRETURN(hr);
  893. }
  894. pNewProperties = (PPROPERTY)AllocADsMem(
  895. _cb - sizeof(PROPERTY)
  896. );
  897. if (!pNewProperties) {
  898. hr = E_OUTOFMEMORY;
  899. BAIL_ON_FAILURE(hr);
  900. }
  901. //
  902. // Copying the memory before the deleted item
  903. //
  904. if (dwIndex != 0) {
  905. memcpy( pNewProperties,
  906. _pProperties,
  907. dwIndex * sizeof(PROPERTY));
  908. }
  909. //
  910. // Copying the memory following the deleted item
  911. //
  912. if (dwIndex != (_dwMaxProperties-1)) {
  913. memcpy( pNewProperties + dwIndex,
  914. _pProperties + dwIndex + 1,
  915. (_dwMaxProperties - dwIndex - 1) * sizeof(PROPERTY));
  916. }
  917. if (PROPERTY_NTOBJECT(pThisProperty)) {
  918. NTTypeFreeNTObjects(
  919. PROPERTY_NTOBJECT(pThisProperty),
  920. PROPERTY_NUMVALUES(pThisProperty)
  921. );
  922. PROPERTY_NTOBJECT(pThisProperty) = NULL;
  923. }
  924. FreeADsMem(_pProperties);
  925. _pProperties = pNewProperties;
  926. _dwMaxProperties--;
  927. _cb -= sizeof(PROPERTY);
  928. //
  929. // Reset the current index if necesary so we do not skip a property.
  930. //
  931. if (_dwCurrentIndex > dwIndex) {
  932. _dwCurrentIndex--;
  933. }
  934. error:
  935. RRETURN_EXP_IF_ERR(hr);
  936. }
  937. ////////////////////////////////////////////////////////////////////////
  938. //
  939. // IPropertyCache
  940. //
  941. HRESULT
  942. CPropertyCache::
  943. locateproperty(
  944. LPWSTR szPropertyName,
  945. PDWORD pdwDispid
  946. )
  947. {
  948. HRESULT hr;
  949. hr = DispatchLocateProperty(
  950. szPropertyName,
  951. pdwDispid
  952. );
  953. RRETURN(hr);
  954. }
  955. HRESULT
  956. CPropertyCache::
  957. putproperty(
  958. DWORD dwDispid,
  959. VARIANT varValue
  960. )
  961. {
  962. HRESULT hr;
  963. hr = DispatchPutProperty(
  964. dwDispid,
  965. varValue
  966. );
  967. RRETURN(hr);
  968. }
  969. HRESULT
  970. CPropertyCache::
  971. getproperty(
  972. DWORD dwDispid,
  973. VARIANT * pvarValue
  974. )
  975. {
  976. HRESULT hr;
  977. hr = DispatchGetProperty(
  978. dwDispid,
  979. pvarValue
  980. );
  981. RRETURN(hr);
  982. }
  983. ////////////////////////////////////////////////////////////////////////
  984. //
  985. // Dynamic Dispid Table
  986. //
  987. HRESULT
  988. CPropertyCache::
  989. DispatchFindProperty(
  990. LPWSTR szPropertyName,
  991. PDWORD pdwDispid
  992. )
  993. {
  994. DWORD i = 0;
  995. PDISPPROPERTY pDispProp = NULL;
  996. //
  997. // use ADs Error codes since this funct'n does not go directly into
  998. // the dispatch interface
  999. //
  1000. if (!pdwDispid || !szPropertyName)
  1001. RRETURN(E_ADS_BAD_PARAMETER);
  1002. for (i=0; i<_dwDispMaxProperties; i++) {
  1003. pDispProp = _pDispProperties + i;
  1004. if (!_wcsicmp(DISPATCH_NAME(pDispProp), szPropertyName)) {
  1005. *pdwDispid=i;
  1006. RRETURN(S_OK);
  1007. }
  1008. }
  1009. *pdwDispid = (DWORD) -1;
  1010. RRETURN(E_ADS_PROPERTY_NOT_FOUND);
  1011. }
  1012. HRESULT
  1013. CPropertyCache::
  1014. DispatchAddProperty(
  1015. LPWSTR szPropertyName,
  1016. PDWORD pdwDispid /* optional */
  1017. )
  1018. {
  1019. HRESULT hr = E_FAIL;
  1020. DWORD dwDispid = (DWORD) -1;
  1021. PDISPPROPERTY pNewDispProps = NULL;
  1022. LPWSTR pszTempName = NULL;
  1023. //
  1024. // use ADs Error codes since this funct'n does not go directly into
  1025. // the dispatch interface
  1026. //
  1027. if (!szPropertyName)
  1028. RRETURN(E_ADS_BAD_PARAMETER);
  1029. hr = DispatchFindProperty(
  1030. szPropertyName,
  1031. &dwDispid
  1032. );
  1033. if (hr==E_ADS_PROPERTY_NOT_FOUND) {
  1034. pszTempName = AllocADsStr(szPropertyName);
  1035. if (!pszTempName)
  1036. BAIL_ON_FAILURE(hr=E_OUTOFMEMORY);
  1037. //
  1038. // increase the size of Dynamic Dispid Table by 1 property
  1039. //
  1040. pNewDispProps = (PDISPPROPERTY) ReallocADsMem(
  1041. _pDispProperties,
  1042. _cbDisp,
  1043. _cbDisp + sizeof(DISPPROPERTY)
  1044. );
  1045. if (!pNewDispProps)
  1046. BAIL_ON_FAILURE(hr=E_OUTOFMEMORY);
  1047. //
  1048. // must succeeded at this pt. okay to change table & indexes
  1049. //
  1050. _pDispProperties = pNewDispProps;
  1051. DISPATCH_NAME(_pDispProperties+_dwDispMaxProperties) = pszTempName;
  1052. dwDispid = _dwDispMaxProperties++;
  1053. _cbDisp += sizeof(DISPPROPERTY);
  1054. hr = S_OK;
  1055. }
  1056. //
  1057. // return valid, or invalid (-1) in case of failure, dispid of
  1058. // szProperty iff asked for
  1059. //
  1060. if (pdwDispid)
  1061. *pdwDispid = dwDispid;
  1062. RRETURN(hr);
  1063. error:
  1064. if (pszTempName)
  1065. FreeADsStr(pszTempName);
  1066. RRETURN(hr);
  1067. }
  1068. HRESULT
  1069. CPropertyCache::
  1070. DispatchLocateProperty(
  1071. LPWSTR szPropertyName,
  1072. PDWORD pdwDispid
  1073. )
  1074. {
  1075. HRESULT hr;
  1076. DWORD dwSyntaxId; // (dummy)
  1077. //
  1078. // - pdwDispid not optional here
  1079. // - Use DISP_E_ERROR codes since this function directly called by
  1080. // the dispatch manager
  1081. //
  1082. if (!pdwDispid || !szPropertyName)
  1083. RRETURN(DISP_E_PARAMNOTOPTIONAL);
  1084. //
  1085. // return dispid of property if already in table;
  1086. //
  1087. hr = DispatchFindProperty(
  1088. szPropertyName,
  1089. pdwDispid
  1090. );
  1091. if (hr==E_ADS_PROPERTY_NOT_FOUND) {
  1092. //
  1093. // check if property in schema
  1094. // - this is necessary; otherwise, property not in schema will
  1095. // be allowed to be added to cache and will not be given the
  1096. // chance to be handled by 3rd party extension.
  1097. // - note that property not in schema but added to the cache
  1098. // thru' IADsProperty list will not be handled by 3rd
  1099. // party extension either.
  1100. //
  1101. hr = ValidatePropertyinSchemaClass(
  1102. _pSchemaClassProps,
  1103. _dwNumProperties,
  1104. szPropertyName,
  1105. &dwSyntaxId
  1106. );
  1107. //
  1108. // Add property that is in the schema but not in the cache to
  1109. // the dynamic dispid table. That is, property which is in the
  1110. // schema will always be handled by the cache/server thur ADSI but
  1111. // will NOT be handled by 3rd party extension.
  1112. //
  1113. if (SUCCEEDED(hr)) {
  1114. hr = DispatchAddProperty(
  1115. szPropertyName,
  1116. pdwDispid
  1117. );
  1118. BAIL_ON_FAILURE(hr);
  1119. }
  1120. //
  1121. // Property Not in the schema will nto be added to the dynamic
  1122. // dispid table and could be handled by 3rd party extension.
  1123. //
  1124. else {
  1125. hr = DISP_E_MEMBERNOTFOUND;
  1126. BAIL_ON_FAILURE(hr);
  1127. }
  1128. }
  1129. RRETURN(hr);
  1130. error:
  1131. //
  1132. // translate E_ADS_ error codes to DISP_E if appropriate, see above
  1133. //
  1134. ADsECodesToDispECodes(&hr);
  1135. *pdwDispid = (DWORD) DISPID_UNKNOWN;
  1136. RRETURN(hr);
  1137. }
  1138. HRESULT
  1139. CPropertyCache::
  1140. DispatchGetProperty(
  1141. DWORD dwDispid,
  1142. VARIANT * pvarVal
  1143. )
  1144. {
  1145. HRESULT hr;
  1146. LPWSTR szPropName = NULL;
  1147. DWORD dwSyntaxId = (DWORD) -1;
  1148. DWORD dwNumValues = 0;
  1149. PNTOBJECT pNtObjs = NULL;
  1150. //
  1151. // Use DISP_E_ERROR codes since this function directly called by
  1152. // the dispatch manager
  1153. //
  1154. if (!pvarVal)
  1155. RRETURN(DISP_E_PARAMNOTOPTIONAL);
  1156. if (!DISPATCH_INDEX_VALID(dwDispid))
  1157. RRETURN(DISP_E_MEMBERNOTFOUND);
  1158. szPropName = DISPATCH_PROPERTY_NAME(dwDispid);
  1159. //
  1160. // return value in cache for szPropName; retrieve value from server
  1161. // if not already in cache; fail if none on sever
  1162. //
  1163. hr = getproperty(
  1164. szPropName,
  1165. &dwSyntaxId,
  1166. &dwNumValues,
  1167. &pNtObjs
  1168. );
  1169. BAIL_ON_FAILURE(hr);
  1170. //
  1171. // translate NT objects into variants
  1172. //
  1173. if (dwNumValues == 1) {
  1174. hr = NtTypeToVarTypeCopy(
  1175. pNtObjs,
  1176. pvarVal
  1177. );
  1178. } else {
  1179. hr = NtTypeToVarTypeCopyConstruct(
  1180. pNtObjs,
  1181. dwNumValues,
  1182. pvarVal
  1183. );
  1184. }
  1185. BAIL_ON_FAILURE(hr);
  1186. error:
  1187. if (pNtObjs) {
  1188. NTTypeFreeNTObjects(
  1189. pNtObjs,
  1190. dwNumValues
  1191. );
  1192. }
  1193. if (FAILED(hr)) {
  1194. //
  1195. // return DISP_E errors instead E_ADS_ errors , see above
  1196. //
  1197. ADsECodesToDispECodes(&hr);
  1198. V_VT(pvarVal) = VT_ERROR;
  1199. }
  1200. RRETURN(hr);
  1201. }
  1202. HRESULT
  1203. CPropertyCache::
  1204. DispatchPutProperty(
  1205. DWORD dwDispid,
  1206. VARIANT& varVal
  1207. )
  1208. {
  1209. HRESULT hr;
  1210. LPWSTR szPropName = NULL;
  1211. VARIANT * pvProp = NULL; // do not free
  1212. DWORD dwNumValues = 0;
  1213. VARIANT * pTempVarArray = NULL; // to be freed
  1214. DWORD dwSyntaxId = (DWORD) -1;
  1215. LPNTOBJECT pNtObjs = NULL;
  1216. DWORD dwIndex = (DWORD) -1;
  1217. //
  1218. // Use DISP_E_ERROR codes since this function directly called by
  1219. // the dispatch manager
  1220. //
  1221. if (!DISPATCH_INDEX_VALID(dwDispid))
  1222. RRETURN(DISP_E_MEMBERNOTFOUND);
  1223. //
  1224. // retreive property name from Dynamic Dispatch Table
  1225. //
  1226. szPropName = DISPATCH_PROPERTY_NAME(dwDispid);
  1227. //
  1228. // translate variant to NT Objects
  1229. //
  1230. //
  1231. // A VT_BYREF|VT_VARIANT may expand to a VT_VARIANT|VT_ARRAY.
  1232. // We should dereference a VT_BYREF|VT_VARIANT once and see
  1233. // what's inside. ??
  1234. //
  1235. pvProp = &varVal;
  1236. if (V_VT(pvProp) == (VT_BYREF|VT_VARIANT)) {
  1237. pvProp = V_VARIANTREF(pvProp);
  1238. }
  1239. if ((V_VT(pvProp) == (VT_VARIANT|VT_ARRAY)) ||
  1240. (V_VT(pvProp) == (VT_VARIANT|VT_ARRAY|VT_BYREF))) {
  1241. hr = ConvertByRefSafeArrayToVariantArray(
  1242. varVal,
  1243. &pTempVarArray,
  1244. &dwNumValues
  1245. );
  1246. BAIL_ON_FAILURE(hr);
  1247. if(NULL == pTempVarArray) {
  1248. BAIL_ON_FAILURE(hr = E_INVALIDARG);
  1249. }
  1250. pvProp = pTempVarArray;
  1251. }else {
  1252. //
  1253. // Single value NOT stored in array MUST BE ALLOWED since clients
  1254. // would expect Put() to behave the same whether the dipatch
  1255. // manager is invoked or not. (This funct'n has to be consitent
  1256. // GenericPutPropertyManager(), but NOT GenericPutExProperty...)
  1257. dwNumValues = 1;
  1258. }
  1259. //
  1260. // Need the syntax of this property on the cache.
  1261. //
  1262. hr = ValidatePropertyinSchemaClass(
  1263. _pSchemaClassProps,
  1264. _dwNumProperties,
  1265. szPropName,
  1266. &dwSyntaxId
  1267. );
  1268. BAIL_ON_FAILURE(hr);
  1269. //
  1270. // check if this is a writeable property in schema
  1271. //
  1272. hr = ValidateIfWriteableProperty(
  1273. _pSchemaClassProps,
  1274. _dwNumProperties,
  1275. szPropName
  1276. );
  1277. BAIL_ON_FAILURE(hr);
  1278. //
  1279. // Variant Array to Nt Objects
  1280. //
  1281. hr = VarTypeToNtTypeCopyConstruct(
  1282. dwSyntaxId,
  1283. pvProp,
  1284. dwNumValues,
  1285. &pNtObjs
  1286. );
  1287. BAIL_ON_FAILURE(hr);
  1288. //
  1289. // add the property to cache if not already in since DispatchAddProperty
  1290. // does not addproperty
  1291. //
  1292. hr = findproperty(
  1293. szPropName,
  1294. &dwIndex
  1295. );
  1296. if (FAILED(hr)) {
  1297. hr = addproperty(
  1298. szPropName,
  1299. dwSyntaxId,
  1300. dwNumValues,
  1301. pNtObjs
  1302. );
  1303. BAIL_ON_FAILURE(hr);
  1304. }
  1305. //
  1306. // update property value in cache
  1307. //
  1308. hr = putproperty(
  1309. szPropName,
  1310. dwSyntaxId,
  1311. dwNumValues,
  1312. pNtObjs
  1313. );
  1314. BAIL_ON_FAILURE(hr);
  1315. error:
  1316. if (pNtObjs) {
  1317. NTTypeFreeNTObjects(
  1318. pNtObjs,
  1319. dwNumValues
  1320. );
  1321. }
  1322. if (pTempVarArray) {
  1323. DWORD i = 0;
  1324. for (i = 0; i < dwNumValues; i++) {
  1325. VariantClear(pTempVarArray + i);
  1326. }
  1327. FreeADsMem(pTempVarArray);
  1328. }
  1329. if (FAILED(hr)) {
  1330. //
  1331. // return DISP_E errors instead E_ADS_ errors , see above
  1332. //
  1333. ADsECodesToDispECodes(&hr);
  1334. }
  1335. RRETURN(hr);
  1336. }
  1337. //----------------------------------------------------------------------------
  1338. // Function: GetPropNames
  1339. //
  1340. // Synopsis: Returns the names of all properties in the cache.
  1341. //
  1342. // Arguments:
  1343. //
  1344. // pProps Returns the names of the properties, without any data
  1345. //
  1346. // Returns: UMI_S_NO_ERROR on success. Error code otherwise.
  1347. //
  1348. // Modifies: *pProps to return the property names
  1349. //
  1350. //----------------------------------------------------------------------------
  1351. HRESULT CPropertyCache::GetPropNames(
  1352. UMI_PROPERTY_VALUES **pProps
  1353. )
  1354. {
  1355. UMI_PROPERTY_VALUES *pUmiPropVals = NULL;
  1356. UMI_PROPERTY *pUmiProps = NULL;
  1357. HRESULT hr = UMI_S_NO_ERROR;
  1358. ULONG ulIndex = 0;
  1359. PPROPERTY pNextProperty = NULL;
  1360. ADsAssert(pProps != NULL);
  1361. pUmiPropVals = (UMI_PROPERTY_VALUES *) AllocADsMem(
  1362. sizeof(UMI_PROPERTY_VALUES));
  1363. if(NULL == pUmiPropVals)
  1364. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  1365. memset(pUmiPropVals, 0, sizeof(UMI_PROPERTY_VALUES));
  1366. if(0 == _dwMaxProperties) {
  1367. // no properties in cache
  1368. *pProps = pUmiPropVals;
  1369. RRETURN(UMI_S_NO_ERROR);
  1370. }
  1371. pUmiProps = (UMI_PROPERTY *) AllocADsMem(
  1372. _dwMaxProperties * sizeof(UMI_PROPERTY));
  1373. if(NULL == pUmiProps)
  1374. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  1375. memset(pUmiProps, 0, _dwMaxProperties * sizeof(UMI_PROPERTY));
  1376. for(ulIndex = 0; ulIndex < _dwMaxProperties; ulIndex++) {
  1377. pNextProperty = _pProperties + ulIndex;
  1378. pUmiProps[ulIndex].pszPropertyName =
  1379. (LPWSTR) AllocADsStr(pNextProperty->szPropertyName);
  1380. if(NULL == pUmiProps[ulIndex].pszPropertyName)
  1381. BAIL_ON_FAILURE(hr = UMI_E_OUT_OF_MEMORY);
  1382. }
  1383. pUmiPropVals->uCount = _dwMaxProperties;
  1384. pUmiPropVals->pPropArray = pUmiProps;
  1385. *pProps = pUmiPropVals;
  1386. RRETURN(UMI_S_NO_ERROR);
  1387. error:
  1388. if(pUmiProps != NULL) {
  1389. for(ulIndex = 0; ulIndex < _dwMaxProperties; ulIndex++)
  1390. if(pUmiProps[ulIndex].pszPropertyName != NULL)
  1391. FreeADsStr(pUmiProps[ulIndex].pszPropertyName);
  1392. FreeADsMem(pUmiProps);
  1393. }
  1394. if(pUmiPropVals != NULL)
  1395. FreeADsMem(pUmiPropVals);
  1396. RRETURN(hr);
  1397. }
  1398. //----------------------------------------------------------------------------
  1399. // Function: ClearModifiedFlag
  1400. //
  1401. // Synopsis: Clears the modified flag for all properties in the cache. This
  1402. // is done after a successful SetInfo so that subsequent Get
  1403. // operations return the correct state of the property.
  1404. //
  1405. // Arguments:
  1406. //
  1407. // None
  1408. //
  1409. // Returns: Nothing
  1410. //
  1411. // Modifies: Nothing
  1412. //
  1413. //----------------------------------------------------------------------------
  1414. void
  1415. CPropertyCache::ClearModifiedFlags(void)
  1416. {
  1417. DWORD i = 0;
  1418. PPROPERTY pThisProperty = NULL;
  1419. for (i = 0; i < _dwMaxProperties; i++) {
  1420. pThisProperty = _pProperties + i;
  1421. if (PROPERTY_NTOBJECT(pThisProperty))
  1422. PROPERTY_FLAGS(pThisProperty) &= ~CACHE_PROPERTY_MODIFIED;
  1423. }
  1424. }
  1425. //
  1426. // Move This function out of this file, out of adsnt in fact. LATER
  1427. // Moving it out may make the conversion more difficult since each
  1428. // provider return error codes in its own way. May be local is better.
  1429. //
  1430. void
  1431. ADsECodesToDispECodes(
  1432. HRESULT *pHr
  1433. )
  1434. {
  1435. DWORD dwADsErr = *pHr;
  1436. switch (dwADsErr) {
  1437. case E_ADS_UNKNOWN_OBJECT:
  1438. case E_ADS_PROPERTY_NOT_SUPPORTED:
  1439. case E_ADS_PROPERTY_INVALID:
  1440. case E_ADS_PROPERTY_NOT_FOUND:
  1441. *pHr = DISP_E_MEMBERNOTFOUND;
  1442. break;
  1443. case E_ADS_BAD_PARAMETER:
  1444. //*pHr = DISP_E_PARAMNOTOPTIONAL;
  1445. break;
  1446. case E_ADS_CANT_CONVERT_DATATYPE:
  1447. *pHr = DISP_E_TYPEMISMATCH;
  1448. //*pHr = DISP_E_BADVARTYPE;
  1449. break;
  1450. case E_ADS_SCHEMA_VIOLATION:
  1451. // depends
  1452. break;
  1453. default:
  1454. break;
  1455. // should make it s.t. E_ADS_xxx -> E_FAIL and no changes on others
  1456. // LATER
  1457. };
  1458. }