Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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