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.

1028 lines
20 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: cdomain.cxx
  7. //
  8. // Contents: Microsoft ADs NDS Provider Tree Object
  9. //
  10. //
  11. // History: 01-30-95 krishnag Created.
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "nds.hxx"
  15. #pragma hdrstop
  16. // Class CNDSTree
  17. DEFINE_IDispatch_Implementation(CNDSTree)
  18. DEFINE_IADs_Implementation(CNDSTree)
  19. CNDSTree::CNDSTree():
  20. _pPropertyCache(NULL)
  21. {
  22. VariantInit(&_vFilter);
  23. ENLIST_TRACKING(CNDSTree);
  24. }
  25. HRESULT
  26. CNDSTree::CreateTreeObject(
  27. BSTR bstrADsPath,
  28. CCredentials& Credentials,
  29. DWORD dwObjectState,
  30. REFIID riid,
  31. void **ppvObj
  32. )
  33. {
  34. HRESULT hr = S_OK;
  35. WCHAR szADsParent[MAX_PATH];
  36. WCHAR szCommonName[MAX_PATH];
  37. memset(szADsParent, 0, sizeof(szADsParent));
  38. memset(szCommonName, 0, sizeof(szCommonName));
  39. //
  40. // Determine the parent and rdn name
  41. //
  42. hr = BuildADsParentPath(
  43. bstrADsPath,
  44. szADsParent,
  45. szCommonName
  46. );
  47. //
  48. // call the helper function
  49. //
  50. hr = CNDSTree::CreateTreeObject(
  51. szADsParent,
  52. szCommonName,
  53. L"user",
  54. Credentials,
  55. dwObjectState,
  56. riid,
  57. ppvObj
  58. );
  59. RRETURN_EXP_IF_ERR(hr);
  60. }
  61. HRESULT
  62. CNDSTree::CreateTreeObject(
  63. BSTR Parent,
  64. BSTR CommonName,
  65. BSTR ClassName,
  66. CCredentials& Credentials,
  67. DWORD dwObjectState,
  68. REFIID riid,
  69. void **ppvObj
  70. )
  71. {
  72. CNDSTree FAR * pTree = NULL;
  73. HRESULT hr = S_OK;
  74. hr = AllocateTree(Credentials, &pTree);
  75. BAIL_ON_FAILURE(hr);
  76. hr = pTree->InitializeCoreObject(
  77. Parent,
  78. CommonName,
  79. ClassName,
  80. L"",
  81. CLSID_NDSTree,
  82. dwObjectState
  83. );
  84. BAIL_ON_FAILURE(hr);
  85. hr = pTree->QueryInterface(riid, ppvObj);
  86. BAIL_ON_FAILURE(hr);
  87. pTree->Release();
  88. RRETURN(hr);
  89. error:
  90. delete pTree;
  91. RRETURN_EXP_IF_ERR(hr);
  92. }
  93. CNDSTree::~CNDSTree( )
  94. {
  95. VariantClear(&_vFilter);
  96. delete _pDispMgr;
  97. delete _pPropertyCache;
  98. }
  99. STDMETHODIMP
  100. CNDSTree::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  101. {
  102. if (ppv == NULL) {
  103. RRETURN(E_POINTER);
  104. }
  105. if (IsEqualIID(iid, IID_IUnknown))
  106. {
  107. *ppv = (IADs FAR *) this;
  108. }
  109. else if (IsEqualIID(iid, IID_IADsContainer))
  110. {
  111. *ppv = (IADsContainer FAR *) this;
  112. }
  113. else if (IsEqualIID(iid, IID_IADs))
  114. {
  115. *ppv = (IADs FAR *) this;
  116. }
  117. else if (IsEqualIID(iid, IID_IDispatch))
  118. {
  119. *ppv = (IADs FAR *) this;
  120. }
  121. else if (IsEqualIID(iid, IID_ISupportErrorInfo))
  122. {
  123. *ppv = (ISupportErrorInfo FAR *) this;
  124. }
  125. else
  126. {
  127. *ppv = NULL;
  128. return E_NOINTERFACE;
  129. }
  130. AddRef();
  131. return NOERROR;
  132. }
  133. HRESULT
  134. CNDSTree::InterfaceSupportsErrorInfo(
  135. THIS_ REFIID riid
  136. )
  137. {
  138. if (IsEqualIID(riid, IID_IADs) ||
  139. IsEqualIID(riid, IID_IADsContainer)) {
  140. RRETURN(S_OK);
  141. } else {
  142. RRETURN(S_FALSE);
  143. }
  144. }
  145. HRESULT
  146. CNDSTree::SetInfo()
  147. {
  148. DWORD dwStatus = 0L;
  149. WCHAR szNDSPathName[MAX_PATH];
  150. HANDLE hOperationData = NULL;
  151. HANDLE hObject = NULL;
  152. HRESULT hr = S_OK;
  153. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  154. hr = NDSCreateObject();
  155. BAIL_ON_FAILURE(hr);
  156. //
  157. // If the create succeded, set the object type to bound
  158. //
  159. SetObjectState(ADS_OBJECT_BOUND);
  160. }else {
  161. hr = NDSSetObject();
  162. BAIL_ON_FAILURE(hr);
  163. }
  164. error:
  165. RRETURN_EXP_IF_ERR(hr);
  166. }
  167. HRESULT
  168. CNDSTree::NDSSetObject()
  169. {
  170. DWORD dwStatus = 0L;
  171. LPWSTR pszNDSPathName = NULL;
  172. HANDLE hOperationData = NULL;
  173. HANDLE hObject = NULL;
  174. HRESULT hr = S_OK;
  175. hr = BuildNDSPathFromADsPath(
  176. _ADsPath,
  177. &pszNDSPathName
  178. );
  179. BAIL_ON_FAILURE(hr);
  180. dwStatus = ADsNwNdsOpenObject(
  181. pszNDSPathName,
  182. _Credentials,
  183. &hObject,
  184. NULL,
  185. NULL,
  186. NULL,
  187. NULL
  188. );
  189. if (dwStatus) {
  190. hr = HRESULT_FROM_WIN32(GetLastError());
  191. BAIL_ON_FAILURE(hr);
  192. }
  193. dwStatus = NwNdsCreateBuffer(
  194. NDS_OBJECT_MODIFY,
  195. &hOperationData
  196. );
  197. if (dwStatus) {
  198. hr = HRESULT_FROM_WIN32(GetLastError());
  199. BAIL_ON_FAILURE(hr);
  200. }
  201. hr = _pPropertyCache->NDSMarshallProperties(
  202. hOperationData
  203. );
  204. BAIL_ON_FAILURE(hr);
  205. dwStatus = NwNdsModifyObject(
  206. hObject,
  207. hOperationData
  208. );
  209. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  210. error:
  211. if (hOperationData) {
  212. dwStatus = NwNdsFreeBuffer(hOperationData);
  213. }
  214. if (hObject) {
  215. dwStatus = NwNdsCloseObject(hObject);
  216. }
  217. if (pszNDSPathName) {
  218. FreeADsStr(pszNDSPathName);
  219. }
  220. RRETURN_EXP_IF_ERR(hr);
  221. }
  222. HRESULT
  223. CNDSTree::NDSCreateObject()
  224. {
  225. DWORD dwStatus = 0L;
  226. LPWSTR pszNDSParentName = NULL;
  227. HANDLE hOperationData = NULL;
  228. HANDLE hObject = NULL;
  229. HRESULT hr = S_OK;
  230. hr = BuildNDSPathFromADsPath(
  231. _Parent,
  232. &pszNDSParentName
  233. );
  234. BAIL_ON_FAILURE(hr);
  235. dwStatus = ADsNwNdsOpenObject(
  236. pszNDSParentName,
  237. _Credentials,
  238. &hObject,
  239. NULL,
  240. NULL,
  241. NULL,
  242. NULL
  243. );
  244. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  245. dwStatus = NwNdsCreateBuffer(
  246. NDS_OBJECT_ADD,
  247. &hOperationData
  248. );
  249. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  250. hr = _pPropertyCache->NDSMarshallProperties(
  251. hOperationData
  252. );
  253. BAIL_ON_FAILURE(hr);
  254. dwStatus = NwNdsAddObject(
  255. hObject,
  256. _Name,
  257. hOperationData
  258. );
  259. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  260. error:
  261. if (hOperationData) {
  262. dwStatus = NwNdsFreeBuffer(hOperationData);
  263. }
  264. if (hObject) {
  265. dwStatus = NwNdsCloseObject(hObject);
  266. }
  267. if (pszNDSParentName) {
  268. FreeADsStr(pszNDSParentName);
  269. }
  270. RRETURN_EXP_IF_ERR(hr);
  271. }
  272. HRESULT
  273. CNDSTree::GetInfo()
  274. {
  275. RRETURN(GetInfo(TRUE));
  276. }
  277. HRESULT
  278. CNDSTree::GetInfo(
  279. BOOL fExplicit
  280. )
  281. {
  282. DWORD dwStatus = 0L;
  283. HANDLE hObject = NULL;
  284. HANDLE hOperationData = NULL;
  285. HRESULT hr = S_OK;
  286. LPWSTR pszNDSPathName = NULL;
  287. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  288. hr = E_ADS_OBJECT_UNBOUND;
  289. BAIL_ON_FAILURE(hr);
  290. }
  291. hr = BuildNDSPathFromADsPath(
  292. _ADsPath,
  293. &pszNDSPathName
  294. );
  295. BAIL_ON_FAILURE(hr);
  296. dwStatus = ADsNwNdsOpenObject(
  297. pszNDSPathName,
  298. _Credentials,
  299. &hObject,
  300. NULL,
  301. NULL,
  302. NULL,
  303. NULL
  304. );
  305. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  306. hOperationData = NULL;
  307. dwStatus = NwNdsReadObject(
  308. hObject,
  309. NDS_INFO_ATTR_NAMES_VALUES,
  310. &hOperationData
  311. );
  312. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  313. hr = _pPropertyCache->NDSUnMarshallProperties(
  314. hOperationData,
  315. fExplicit
  316. );
  317. BAIL_ON_FAILURE(hr);
  318. error:
  319. if (hOperationData) {
  320. dwStatus = NwNdsFreeBuffer(hOperationData);
  321. }
  322. if (hObject) {
  323. dwStatus = NwNdsCloseObject(hObject);
  324. }
  325. if (pszNDSPathName) {
  326. FreeADsStr(pszNDSPathName);
  327. }
  328. RRETURN_EXP_IF_ERR(hr);
  329. }
  330. STDMETHODIMP
  331. CNDSTree::GetInfoEx(THIS_ VARIANT vProperties, long lnReserved)
  332. {
  333. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  334. }
  335. /* IADsContainer methods */
  336. STDMETHODIMP
  337. CNDSTree::get_Count(long FAR* retval)
  338. {
  339. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  340. }
  341. STDMETHODIMP
  342. CNDSTree::get_Filter(THIS_ VARIANT FAR* pVar)
  343. {
  344. HRESULT hr;
  345. VariantInit(pVar);
  346. hr = VariantCopy(pVar, &_vFilter);
  347. RRETURN_EXP_IF_ERR(hr);
  348. }
  349. STDMETHODIMP
  350. CNDSTree::put_Filter(THIS_ VARIANT Var)
  351. {
  352. HRESULT hr;
  353. hr = VariantCopy(&_vFilter, &Var);
  354. RRETURN_EXP_IF_ERR(hr);
  355. }
  356. STDMETHODIMP
  357. CNDSTree::put_Hints(THIS_ VARIANT Var)
  358. {
  359. RRETURN_EXP_IF_ERR( E_NOTIMPL);
  360. }
  361. STDMETHODIMP
  362. CNDSTree::get_Hints(THIS_ VARIANT FAR* pVar)
  363. {
  364. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  365. }
  366. STDMETHODIMP
  367. CNDSTree::GetObject(
  368. BSTR ClassName,
  369. BSTR RelativeName,
  370. IDispatch * FAR* ppObject
  371. )
  372. {
  373. HRESULT hr = S_OK;
  374. hr = ::RelativeGetObject(
  375. _ADsPath,
  376. ClassName,
  377. RelativeName,
  378. _Credentials,
  379. ppObject,
  380. FALSE
  381. );
  382. RRETURN_EXP_IF_ERR(hr);
  383. }
  384. STDMETHODIMP
  385. CNDSTree::get__NewEnum(
  386. THIS_ IUnknown * FAR* retval
  387. )
  388. {
  389. HRESULT hr;
  390. IUnknown FAR* punkEnum=NULL;
  391. IEnumVARIANT * penum = NULL;
  392. *retval = NULL;
  393. hr = CNDSTreeEnum::Create(
  394. (CNDSTreeEnum **)&penum,
  395. _ADsPath,
  396. _vFilter,
  397. _Credentials
  398. );
  399. BAIL_ON_FAILURE(hr);
  400. hr = penum->QueryInterface(
  401. IID_IUnknown,
  402. (VOID FAR* FAR*)retval
  403. );
  404. BAIL_ON_FAILURE(hr);
  405. if (penum) {
  406. penum->Release();
  407. }
  408. RRETURN(NOERROR);
  409. error:
  410. if (penum) {
  411. delete penum;
  412. }
  413. RRETURN_EXP_IF_ERR(hr);
  414. }
  415. STDMETHODIMP
  416. CNDSTree::Create(
  417. THIS_ BSTR ClassName,
  418. BSTR RelativeName,
  419. IDispatch * FAR* ppObject
  420. )
  421. {
  422. HRESULT hr = S_OK;
  423. IADs * pADs = NULL;
  424. VARIANT var;
  425. WCHAR szNDSTreeName[MAX_PATH];
  426. DWORD dwSyntaxId = 0;
  427. //
  428. // Get the TreeName for this object
  429. //
  430. hr = BuildNDSTreeNameFromADsPath(
  431. _ADsPath,
  432. szNDSTreeName
  433. );
  434. BAIL_ON_FAILURE(hr);
  435. //
  436. // Validate if this class really exists in the schema
  437. // and validate that this object can be created in this
  438. // container
  439. //
  440. hr = CNDSGenObject::CreateGenericObject(
  441. _ADsPath,
  442. RelativeName,
  443. ClassName,
  444. _Credentials,
  445. ADS_OBJECT_UNBOUND,
  446. IID_IDispatch,
  447. (void **)ppObject
  448. );
  449. BAIL_ON_FAILURE(hr);
  450. error:
  451. RRETURN_EXP_IF_ERR(hr);
  452. }
  453. STDMETHODIMP
  454. CNDSTree::Delete(
  455. THIS_ BSTR bstrClassName,
  456. BSTR bstrRelativeName
  457. )
  458. {
  459. LPWSTR pszNDSPathName = NULL;
  460. HRESULT hr = S_OK;
  461. DWORD dwStatus = 0;
  462. HANDLE hParentObject = NULL;
  463. hr = BuildNDSPathFromADsPath(
  464. _ADsPath,
  465. &pszNDSPathName
  466. );
  467. BAIL_ON_FAILURE(hr);
  468. dwStatus = ADsNwNdsOpenObject(
  469. pszNDSPathName,
  470. _Credentials,
  471. &hParentObject,
  472. NULL,
  473. NULL,
  474. NULL,
  475. NULL
  476. );
  477. if (dwStatus) {
  478. hr = HRESULT_FROM_WIN32(GetLastError());
  479. BAIL_ON_FAILURE(hr);
  480. }
  481. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  482. dwStatus = NwNdsRemoveObject(
  483. hParentObject,
  484. bstrRelativeName
  485. );
  486. CHECK_AND_SET_EXTENDED_ERROR(dwStatus, hr);
  487. error:
  488. if (hParentObject) {
  489. NwNdsCloseObject(
  490. hParentObject
  491. );
  492. }
  493. if (pszNDSPathName) {
  494. FreeADsStr(pszNDSPathName);
  495. }
  496. RRETURN_EXP_IF_ERR(hr);
  497. }
  498. STDMETHODIMP
  499. CNDSTree::CopyHere(
  500. THIS_ BSTR SourceName,
  501. BSTR NewName,
  502. IDispatch * FAR* ppObject
  503. )
  504. {
  505. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  506. }
  507. STDMETHODIMP
  508. CNDSTree::MoveHere(
  509. THIS_ BSTR SourceName,
  510. BSTR NewName,
  511. IDispatch * FAR* ppObject
  512. )
  513. {
  514. RRETURN_EXP_IF_ERR(E_NOTIMPL);
  515. }
  516. HRESULT
  517. CNDSTree::AllocateTree(
  518. CCredentials& Credentials,
  519. CNDSTree ** ppTree
  520. )
  521. {
  522. CNDSTree FAR * pTree = NULL;
  523. CDispatchMgr FAR * pDispMgr = NULL;
  524. CPropertyCache FAR * pPropertyCache = NULL;
  525. HRESULT hr = S_OK;
  526. pTree = new CNDSTree();
  527. if (pTree == NULL) {
  528. hr = E_OUTOFMEMORY;
  529. }
  530. BAIL_ON_FAILURE(hr);
  531. pDispMgr = new CDispatchMgr;
  532. if (pDispMgr == NULL) {
  533. hr = E_OUTOFMEMORY;
  534. }
  535. BAIL_ON_FAILURE(hr);
  536. hr = LoadTypeInfoEntry(pDispMgr,
  537. LIBID_ADs,
  538. IID_IADs,
  539. (IADs *)pTree,
  540. DISPID_REGULAR
  541. );
  542. BAIL_ON_FAILURE(hr);
  543. hr = LoadTypeInfoEntry(pDispMgr,
  544. LIBID_ADs,
  545. IID_IADsContainer,
  546. (IADsContainer *)pTree,
  547. DISPID_NEWENUM
  548. );
  549. BAIL_ON_FAILURE(hr);
  550. hr = CPropertyCache::createpropertycache(
  551. (CCoreADsObject FAR *)pTree,
  552. &pPropertyCache
  553. );
  554. BAIL_ON_FAILURE(hr);
  555. pTree->_Credentials = Credentials;
  556. pTree->_pPropertyCache = pPropertyCache;
  557. pTree->_pDispMgr = pDispMgr;
  558. *ppTree = pTree;
  559. RRETURN(hr);
  560. error:
  561. delete pDispMgr;
  562. RRETURN(hr);
  563. }
  564. STDMETHODIMP
  565. CNDSTree::Get(
  566. THIS_ BSTR bstrName,
  567. VARIANT FAR* pvProp
  568. )
  569. {
  570. HRESULT hr = S_OK;
  571. DWORD dwSyntaxId;
  572. DWORD dwNumValues;
  573. LPNDSOBJECT pNdsSrcObjects = NULL;
  574. //
  575. // retrieve data object from cache; if one exists
  576. //
  577. hr = _pPropertyCache->getproperty(
  578. bstrName,
  579. &dwSyntaxId,
  580. &dwNumValues,
  581. &pNdsSrcObjects
  582. );
  583. BAIL_ON_FAILURE(hr);
  584. //
  585. // translate the Nds objects to variants
  586. //
  587. hr = NdsTypeToVarTypeCopyConstruct(
  588. pNdsSrcObjects,
  589. dwNumValues,
  590. pvProp,
  591. FALSE
  592. );
  593. BAIL_ON_FAILURE(hr);
  594. error:
  595. if (pNdsSrcObjects) {
  596. NdsTypeFreeNdsObjects(
  597. pNdsSrcObjects,
  598. dwNumValues
  599. );
  600. }
  601. RRETURN_EXP_IF_ERR(hr);
  602. }
  603. STDMETHODIMP
  604. CNDSTree::GetEx(
  605. THIS_ BSTR bstrName,
  606. VARIANT FAR* pvProp
  607. )
  608. {
  609. HRESULT hr = S_OK;
  610. DWORD dwSyntaxId;
  611. DWORD dwNumValues;
  612. LPNDSOBJECT pNdsSrcObjects = NULL;
  613. //
  614. // retrieve data object from cache; if one exists
  615. //
  616. hr = _pPropertyCache->getproperty(
  617. bstrName,
  618. &dwSyntaxId,
  619. &dwNumValues,
  620. &pNdsSrcObjects
  621. );
  622. BAIL_ON_FAILURE(hr);
  623. //
  624. // translate the Nds objects to variants
  625. //
  626. hr = NdsTypeToVarTypeCopyConstruct(
  627. pNdsSrcObjects,
  628. dwNumValues,
  629. pvProp,
  630. TRUE
  631. );
  632. BAIL_ON_FAILURE(hr);
  633. error:
  634. if (pNdsSrcObjects) {
  635. NdsTypeFreeNdsObjects(
  636. pNdsSrcObjects,
  637. dwNumValues
  638. );
  639. }
  640. RRETURN_EXP_IF_ERR(hr);
  641. }
  642. STDMETHODIMP
  643. CNDSTree::Put(
  644. THIS_ BSTR bstrName,
  645. VARIANT vProp
  646. )
  647. {
  648. HRESULT hr = S_OK;
  649. DWORD dwSyntaxId = 0;
  650. DWORD dwIndex = 0;
  651. LPNDSOBJECT pNdsDestObjects = NULL;
  652. WCHAR szNDSTreeName[MAX_PATH];
  653. //
  654. // Issue: How do we handle multi-valued support
  655. //
  656. DWORD dwNumValues = 1;
  657. //
  658. // Get the TreeName for this object
  659. //
  660. hr = BuildNDSTreeNameFromADsPath(
  661. _ADsPath,
  662. szNDSTreeName
  663. );
  664. BAIL_ON_FAILURE(hr);
  665. //
  666. // check if this is a legal property for this object,
  667. //
  668. hr = ValidatePropertyinCache(
  669. szNDSTreeName,
  670. _ADsClass,
  671. bstrName,
  672. _Credentials,
  673. &dwSyntaxId
  674. );
  675. BAIL_ON_FAILURE(hr);
  676. //
  677. // check if the variant maps to the syntax of this property
  678. //
  679. hr = VarTypeToNdsTypeCopyConstruct(
  680. dwSyntaxId,
  681. &vProp,
  682. &dwNumValues,
  683. &pNdsDestObjects
  684. );
  685. BAIL_ON_FAILURE(hr);
  686. //
  687. // Find this property in the cache
  688. //
  689. hr = _pPropertyCache->findproperty(
  690. bstrName,
  691. &dwIndex
  692. );
  693. //
  694. // If this property does not exist in the
  695. // cache, add this property into the cache.
  696. //
  697. if (FAILED(hr)) {
  698. hr = _pPropertyCache->addproperty(
  699. bstrName,
  700. dwSyntaxId
  701. );
  702. //
  703. // If the operation fails for some reason
  704. // move on to the next property
  705. //
  706. BAIL_ON_FAILURE(hr);
  707. }
  708. //
  709. // Now update the property in the cache
  710. //
  711. hr = _pPropertyCache->putproperty(
  712. bstrName,
  713. CACHE_PROPERTY_MODIFIED,
  714. dwSyntaxId,
  715. dwNumValues,
  716. pNdsDestObjects
  717. );
  718. BAIL_ON_FAILURE(hr);
  719. error:
  720. if (pNdsDestObjects) {
  721. NdsTypeFreeNdsObjects(
  722. pNdsDestObjects,
  723. dwNumValues
  724. );
  725. }
  726. RRETURN_EXP_IF_ERR(hr);
  727. }
  728. STDMETHODIMP
  729. CNDSTree::PutEx(
  730. THIS_ long lnControlCode,
  731. BSTR bstrName,
  732. VARIANT vProp
  733. )
  734. {
  735. HRESULT hr = S_OK;
  736. DWORD dwSyntaxId = 0;
  737. DWORD dwIndex = 0;
  738. LPNDSOBJECT pNdsDestObjects = NULL;
  739. WCHAR szNDSTreeName[MAX_PATH];
  740. //
  741. // Issue: How do we handle multi-valued support
  742. //
  743. DWORD dwNumValues = 1;
  744. //
  745. // Get the TreeName for this object
  746. //
  747. hr = BuildNDSTreeNameFromADsPath(
  748. _ADsPath,
  749. szNDSTreeName
  750. );
  751. BAIL_ON_FAILURE(hr);
  752. //
  753. // check if this is a legal property for this object,
  754. //
  755. hr = ValidatePropertyinCache(
  756. szNDSTreeName,
  757. _ADsClass,
  758. bstrName,
  759. _Credentials,
  760. &dwSyntaxId
  761. );
  762. BAIL_ON_FAILURE(hr);
  763. //
  764. // check if the variant maps to the syntax of this property
  765. //
  766. hr = VarTypeToNdsTypeCopyConstruct(
  767. dwSyntaxId,
  768. &vProp,
  769. &dwNumValues,
  770. &pNdsDestObjects
  771. );
  772. BAIL_ON_FAILURE(hr);
  773. //
  774. // Find this property in the cache
  775. //
  776. hr = _pPropertyCache->findproperty(
  777. bstrName,
  778. &dwIndex
  779. );
  780. //
  781. // If this property does not exist in the
  782. // cache, add this property into the cache.
  783. //
  784. if (FAILED(hr)) {
  785. hr = _pPropertyCache->addproperty(
  786. bstrName,
  787. dwSyntaxId
  788. );
  789. //
  790. // If the operation fails for some reason
  791. // move on to the next property
  792. //
  793. BAIL_ON_FAILURE(hr);
  794. }
  795. //
  796. // Now update the property in the cache
  797. //
  798. hr = _pPropertyCache->putproperty(
  799. bstrName,
  800. CACHE_PROPERTY_MODIFIED,
  801. dwSyntaxId,
  802. dwNumValues,
  803. pNdsDestObjects
  804. );
  805. BAIL_ON_FAILURE(hr);
  806. error:
  807. if (pNdsDestObjects) {
  808. NdsTypeFreeNdsObjects(
  809. pNdsDestObjects,
  810. dwNumValues
  811. );
  812. }
  813. RRETURN_EXP_IF_ERR(hr);
  814. }