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.

2116 lines
42 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 Generic Object
  9. //
  10. //
  11. // History: 01-30-95 krishnag Created.
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "nds.hxx"
  15. #pragma hdrstop
  16. // Class CNDSGenObject
  17. DEFINE_IDispatch_Implementation(CNDSGenObject)
  18. DEFINE_IADs_Implementation(CNDSGenObject)
  19. CNDSGenObject::CNDSGenObject():
  20. _pPropertyCache(NULL)
  21. {
  22. _pOuterUnknown = NULL;
  23. _hADsContext = NULL;
  24. _pszNDSTreeName = _pszNDSDn = NULL;
  25. VariantInit(&_vFilter);
  26. InitSearchPrefs();
  27. ENLIST_TRACKING(CNDSGenObject);
  28. }
  29. HRESULT
  30. CNDSGenObject::CreateGenericObject(
  31. BSTR bstrADsPath,
  32. BSTR ClassName,
  33. CCredentials& Credentials,
  34. DWORD dwObjectState,
  35. REFIID riid,
  36. void **ppvObj
  37. )
  38. {
  39. HRESULT hr = S_OK;
  40. WCHAR szADsParent[MAX_PATH];
  41. WCHAR szCommonName[MAX_PATH];
  42. //
  43. // Determine the parent and rdn name
  44. //
  45. hr = BuildADsParentPath(
  46. bstrADsPath,
  47. szADsParent,
  48. szCommonName
  49. );
  50. //
  51. // call the helper function
  52. //
  53. hr = CNDSGenObject::CreateGenericObject(
  54. szADsParent,
  55. szCommonName,
  56. ClassName,
  57. Credentials,
  58. dwObjectState,
  59. riid,
  60. ppvObj
  61. );
  62. RRETURN(hr);
  63. }
  64. HRESULT
  65. CNDSGenObject::CreateGenericObject(
  66. BSTR Parent,
  67. BSTR CommonName,
  68. BSTR ClassName,
  69. CCredentials& Credentials,
  70. DWORD dwObjectState,
  71. REFIID riid,
  72. void **ppvObj
  73. )
  74. {
  75. CNDSGenObject FAR * pGenObject = NULL;
  76. HRESULT hr = S_OK;
  77. hr = AllocateGenObject(Credentials, &pGenObject);
  78. BAIL_ON_FAILURE(hr);
  79. hr = pGenObject->InitializeCoreObject(
  80. Parent,
  81. CommonName,
  82. ClassName,
  83. L"",
  84. CLSID_NDSGenObject,
  85. dwObjectState
  86. );
  87. BAIL_ON_FAILURE(hr);
  88. hr = BuildNDSPathFromADsPath2(
  89. pGenObject->_ADsPath,
  90. &(pGenObject->_pszNDSTreeName),
  91. &(pGenObject->_pszNDSDn)
  92. );
  93. BAIL_ON_FAILURE(hr);
  94. hr = ADsNdsOpenContext(
  95. pGenObject->_pszNDSTreeName,
  96. Credentials,
  97. &(pGenObject->_hADsContext)
  98. );
  99. BAIL_ON_FAILURE(hr);
  100. hr = pGenObject->QueryInterface(riid, ppvObj);
  101. BAIL_ON_FAILURE(hr);
  102. pGenObject->Release();
  103. RRETURN(hr);
  104. error:
  105. delete pGenObject;
  106. RRETURN(hr);
  107. }
  108. CNDSGenObject::~CNDSGenObject( )
  109. {
  110. VariantClear(&_vFilter);
  111. delete _pDispMgr;
  112. delete _pPropertyCache;
  113. if (_hADsContext) {
  114. ADsNdsCloseContext(_hADsContext);
  115. }
  116. if (_pszNDSTreeName) {
  117. FreeADsMem(_pszNDSTreeName);
  118. }
  119. if (_pszNDSDn) {
  120. FreeADsMem(_pszNDSDn);
  121. }
  122. }
  123. STDMETHODIMP
  124. CNDSGenObject::QueryInterface(REFIID iid, LPVOID FAR* ppv)
  125. {
  126. if (ppv == NULL) {
  127. RRETURN(E_POINTER);
  128. }
  129. if (IsEqualIID(iid, IID_IUnknown))
  130. {
  131. *ppv = (IADs FAR *) this;
  132. }
  133. else if (IsEqualIID(iid, IID_IADsContainer))
  134. {
  135. *ppv = (IADsContainer FAR *) this;
  136. }
  137. else if (IsEqualIID(iid, IID_IADs))
  138. {
  139. *ppv = (IADs FAR *) this;
  140. }
  141. else if (IsEqualIID(iid, IID_IDispatch))
  142. {
  143. *ppv = (IADs FAR *) this;
  144. }
  145. else if (IsEqualIID(iid, IID_IDirectoryObject))
  146. {
  147. *ppv = (IDirectoryObject FAR *) this;
  148. }
  149. else if (IsEqualIID(iid, IID_IDirectorySearch))
  150. {
  151. *ppv = (IDirectorySearch FAR *) this;
  152. }
  153. else if (IsEqualIID(iid, IID_IDirectorySchemaMgmt))
  154. {
  155. *ppv = (IDirectorySchemaMgmt FAR *) this;
  156. }
  157. else if (IsEqualIID(iid, IID_IADsPropertyList))
  158. {
  159. *ppv = (IADsPropertyList FAR *) this;
  160. }
  161. else
  162. {
  163. *ppv = NULL;
  164. return E_NOINTERFACE;
  165. }
  166. AddRef();
  167. return NOERROR;
  168. }
  169. HRESULT
  170. CNDSGenObject::SetInfo()
  171. {
  172. DWORD dwStatus = 0L;
  173. WCHAR szNDSPathName[MAX_PATH];
  174. HANDLE hOperationData = NULL;
  175. HANDLE hObject = NULL;
  176. HRESULT hr = S_OK;
  177. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  178. hr = NDSCreateObject();
  179. BAIL_ON_FAILURE(hr);
  180. //
  181. // If the create succeded, set the object type to bound
  182. //
  183. SetObjectState(ADS_OBJECT_BOUND);
  184. }else {
  185. hr = NDSSetObject();
  186. BAIL_ON_FAILURE(hr);
  187. }
  188. error:
  189. RRETURN(hr);
  190. }
  191. HRESULT
  192. CNDSGenObject::NDSSetObject()
  193. {
  194. NDS_BUFFER_HANDLE hOperationData = NULL;
  195. HRESULT hr = S_OK;
  196. hr = ADsNdsCreateBuffer(
  197. _hADsContext,
  198. DSV_MODIFY_ENTRY,
  199. &hOperationData
  200. );
  201. BAIL_ON_FAILURE(hr);
  202. hr = _pPropertyCache->NDSMarshallProperties(
  203. _hADsContext,
  204. hOperationData
  205. );
  206. BAIL_ON_FAILURE(hr);
  207. hr = ADsNdsModifyObject(
  208. _hADsContext,
  209. _pszNDSDn,
  210. hOperationData
  211. );
  212. BAIL_ON_FAILURE(hr);
  213. error:
  214. if (hOperationData) {
  215. ADsNdsFreeBuffer(hOperationData);
  216. }
  217. RRETURN(hr);
  218. }
  219. HRESULT
  220. CNDSGenObject::NDSCreateObject()
  221. {
  222. NDS_BUFFER_HANDLE hOperationData = NULL;
  223. HRESULT hr = S_OK;
  224. BOOLEAN fUserObject = FALSE;
  225. BSTR bstrClass = NULL;
  226. hr = ADsNdsCreateBuffer(
  227. _hADsContext,
  228. DSV_ADD_ENTRY,
  229. &hOperationData
  230. );
  231. BAIL_ON_FAILURE(hr);
  232. hr = get_CoreADsClass(&bstrClass);
  233. if (SUCCEEDED(hr)) {
  234. if (_wcsicmp(bstrClass, L"user") == 0) {
  235. fUserObject = TRUE;
  236. }
  237. }
  238. hr = _pPropertyCache->NDSMarshallProperties(
  239. _hADsContext,
  240. hOperationData
  241. );
  242. BAIL_ON_FAILURE(hr);
  243. hr = ADsNdsAddObject(
  244. _hADsContext,
  245. _pszNDSDn,
  246. hOperationData
  247. );
  248. BAIL_ON_FAILURE(hr);
  249. //
  250. // If it is a user object, we'll set the initial password to 'NULL'
  251. //
  252. if (fUserObject) {
  253. hr = ADsNdsGenObjectKey(_hADsContext,
  254. _pszNDSDn);
  255. BAIL_ON_FAILURE(hr);
  256. }
  257. error:
  258. if (bstrClass) {
  259. ADsFreeString(bstrClass);
  260. }
  261. if (hOperationData) {
  262. ADsNdsFreeBuffer(hOperationData);
  263. }
  264. RRETURN(hr);
  265. }
  266. HRESULT
  267. CNDSGenObject::GetInfo()
  268. {
  269. _pPropertyCache->flushpropcache();
  270. RRETURN(GetInfo(TRUE));
  271. }
  272. HRESULT
  273. CNDSGenObject::GetInfo(
  274. BOOL fExplicit
  275. )
  276. {
  277. HRESULT hr = S_OK;
  278. PNDS_ATTR_INFO lpEntries = NULL;
  279. DWORD dwNumEntries = 0, i = 0;
  280. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  281. hr = E_ADS_OBJECT_UNBOUND;
  282. BAIL_ON_FAILURE(hr);
  283. }
  284. hr = ADsNdsReadObject(
  285. _hADsContext,
  286. _pszNDSDn,
  287. DS_ATTRIBUTE_VALUES,
  288. NULL,
  289. (DWORD) -1, // signifies all attributes need to be returned
  290. NULL,
  291. &lpEntries,
  292. &dwNumEntries
  293. );
  294. BAIL_ON_FAILURE(hr);
  295. for (i = 0; i < dwNumEntries; i++) {
  296. //
  297. // unmarshall this property into the
  298. // property cache
  299. //
  300. //
  301. hr = _pPropertyCache->unmarshallproperty(
  302. lpEntries[i].szAttributeName,
  303. lpEntries[i].lpValue,
  304. lpEntries[i].dwNumberOfValues,
  305. lpEntries[i].dwSyntaxId,
  306. fExplicit
  307. );
  308. CONTINUE_ON_FAILURE(hr);
  309. }
  310. error:
  311. if (_pPropertyCache) {
  312. Reset();
  313. }
  314. FreeNdsAttrInfo( lpEntries, dwNumEntries );
  315. RRETURN(hr);
  316. }
  317. STDMETHODIMP
  318. CNDSGenObject::GetInfoEx(THIS_ VARIANT vProperties, long lnReserved)
  319. {
  320. HRESULT hr = S_OK;
  321. DWORD dwStatus = 0L;
  322. VARIANT *vVarArray = NULL;
  323. DWORD dwNumVariants = 0;
  324. PNDS_ATTR_INFO lpEntries = NULL;
  325. DWORD dwNumEntries = 0, i = 0;
  326. LPWSTR *ppszStrArray = NULL;
  327. UNREFERENCED_PARAMETER(lnReserved);
  328. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  329. hr = E_ADS_OBJECT_UNBOUND;
  330. BAIL_ON_FAILURE(hr);
  331. }
  332. hr = ConvertSafeArrayToVariantArray(
  333. vProperties,
  334. &vVarArray,
  335. &dwNumVariants
  336. );
  337. BAIL_ON_FAILURE(hr);
  338. hr = ConvertVariantArrayToStringArray(
  339. vVarArray,
  340. &ppszStrArray,
  341. dwNumVariants
  342. );
  343. BAIL_ON_FAILURE(hr);
  344. hr = ADsNdsReadObject(
  345. _hADsContext,
  346. _pszNDSDn,
  347. DS_ATTRIBUTE_VALUES,
  348. ppszStrArray,
  349. dwNumVariants,
  350. NULL,
  351. &lpEntries,
  352. &dwNumEntries
  353. );
  354. BAIL_ON_FAILURE(hr);
  355. for (i = 0; i < dwNumEntries; i++) {
  356. //
  357. // unmarshall this property into the
  358. // property cache
  359. //
  360. // The TRUE is "fExplicit" -- we want to make sure that any
  361. // properties we get back from the server get updated in the
  362. // property cache.
  363. //
  364. hr = _pPropertyCache->unmarshallproperty(
  365. lpEntries[i].szAttributeName,
  366. lpEntries[i].lpValue,
  367. lpEntries[i].dwNumberOfValues,
  368. lpEntries[i].dwSyntaxId,
  369. TRUE
  370. );
  371. CONTINUE_ON_FAILURE(hr);
  372. }
  373. error:
  374. if (ppszStrArray) {
  375. for (DWORD i=0; i < dwNumVariants; i++) {
  376. FreeADsStr(ppszStrArray[i]);
  377. }
  378. FreeADsMem(ppszStrArray);
  379. }
  380. if (vVarArray)
  381. {
  382. DWORD i = 0;
  383. for (i = 0; i < dwNumVariants; i++) {
  384. VariantClear(vVarArray + i);
  385. }
  386. FreeADsMem(vVarArray);
  387. }
  388. FreeNdsAttrInfo( lpEntries, dwNumEntries );
  389. RRETURN(hr);
  390. }
  391. /* IADsContainer methods */
  392. STDMETHODIMP
  393. CNDSGenObject::get_Count(long FAR* retval)
  394. {
  395. RRETURN(E_NOTIMPL);
  396. }
  397. STDMETHODIMP
  398. CNDSGenObject::get_Filter(THIS_ VARIANT FAR* pVar)
  399. {
  400. VariantInit(pVar);
  401. RRETURN(VariantCopy(pVar, &_vFilter));
  402. }
  403. STDMETHODIMP
  404. CNDSGenObject::put_Filter(THIS_ VARIANT Var)
  405. {
  406. VariantClear(&_vFilter);
  407. RRETURN(VariantCopy(&_vFilter, &Var));
  408. }
  409. STDMETHODIMP
  410. CNDSGenObject::put_Hints(THIS_ VARIANT Var)
  411. {
  412. RRETURN( E_NOTIMPL);
  413. }
  414. STDMETHODIMP
  415. CNDSGenObject::get_Hints(THIS_ VARIANT FAR* pVar)
  416. {
  417. RRETURN(E_NOTIMPL);
  418. }
  419. STDMETHODIMP
  420. CNDSGenObject::GetObject(
  421. BSTR ClassName,
  422. BSTR RelativeName,
  423. IDispatch * FAR* ppObject
  424. )
  425. {
  426. HRESULT hr = S_OK;
  427. hr = ::RelativeGetObject(
  428. _ADsPath,
  429. ClassName,
  430. RelativeName,
  431. _Credentials,
  432. ppObject,
  433. FALSE
  434. );
  435. RRETURN(hr);
  436. }
  437. STDMETHODIMP
  438. CNDSGenObject::get__NewEnum(
  439. THIS_ IUnknown * FAR* retval
  440. )
  441. {
  442. HRESULT hr;
  443. IUnknown FAR* punkEnum=NULL;
  444. IEnumVARIANT * penum = NULL;
  445. *retval = NULL;
  446. hr = CNDSGenObjectEnum::Create(
  447. (CNDSGenObjectEnum **)&penum,
  448. _ADsPath,
  449. _vFilter,
  450. _Credentials
  451. );
  452. BAIL_ON_FAILURE(hr);
  453. hr = penum->QueryInterface(
  454. IID_IUnknown,
  455. (VOID FAR* FAR*)retval
  456. );
  457. BAIL_ON_FAILURE(hr);
  458. if (penum) {
  459. penum->Release();
  460. }
  461. RRETURN(NOERROR);
  462. error:
  463. if (penum) {
  464. delete penum;
  465. }
  466. RRETURN(hr);
  467. }
  468. STDMETHODIMP
  469. CNDSGenObject::Create(
  470. THIS_ BSTR ClassName,
  471. BSTR RelativeName,
  472. IDispatch * FAR* ppObject
  473. )
  474. {
  475. HRESULT hr = S_OK;
  476. IADs * pADs = NULL;
  477. VARIANT var;
  478. WCHAR szNDSTreeName[MAX_PATH];
  479. DWORD dwSyntaxId = 0;
  480. VARIANT vNewValue;
  481. //
  482. // Get the TreeName for this object
  483. //
  484. hr = BuildNDSTreeNameFromADsPath(
  485. _ADsPath,
  486. szNDSTreeName
  487. );
  488. BAIL_ON_FAILURE(hr);
  489. //
  490. // Validate if this class really exists in the schema
  491. // and validate that this object can be created in this
  492. // container
  493. //
  494. hr = CNDSGenObject::CreateGenericObject(
  495. _ADsPath,
  496. RelativeName,
  497. ClassName,
  498. _Credentials,
  499. ADS_OBJECT_UNBOUND,
  500. IID_IADs,
  501. (void **)&pADs
  502. );
  503. BAIL_ON_FAILURE(hr);
  504. VariantInit(&vNewValue);
  505. V_BSTR(&vNewValue) = ClassName;
  506. V_VT(&vNewValue) = VT_BSTR;
  507. hr = pADs->Put(L"Object Class", vNewValue);
  508. BAIL_ON_FAILURE(hr);
  509. //
  510. // InstantiateDerivedObject should addref this pointer for us.
  511. //
  512. hr = InstantiateDerivedObject(
  513. pADs,
  514. _Credentials,
  515. IID_IDispatch,
  516. (void **)ppObject
  517. );
  518. if (FAILED(hr)) {
  519. hr = pADs->QueryInterface(
  520. IID_IDispatch,
  521. (void **)ppObject
  522. );
  523. BAIL_ON_FAILURE(hr);
  524. }
  525. error:
  526. //
  527. // Free the intermediate pADs pointer.
  528. //
  529. if (pADs) {
  530. pADs->Release();
  531. }
  532. RRETURN(hr);
  533. }
  534. STDMETHODIMP
  535. CNDSGenObject::Delete(
  536. THIS_ BSTR bstrClassName,
  537. BSTR bstrRelativeName
  538. )
  539. {
  540. HRESULT hr = S_OK;
  541. BSTR bstrChildPath = NULL;
  542. LPWSTR pszNDSTreeName = NULL;
  543. LPWSTR pszChildNDSDn = NULL;
  544. LPWSTR ppszAttrs[] = {L"object Class"};
  545. PNDS_ATTR_INFO pAttrEntries = NULL;
  546. DWORD dwNumEntries = 0;
  547. LPWSTR pszObjectClassName = NULL;
  548. hr = BuildADsPath(
  549. _ADsPath,
  550. bstrRelativeName,
  551. &bstrChildPath
  552. );
  553. BAIL_ON_FAILURE(hr);
  554. hr = BuildNDSPathFromADsPath2(
  555. bstrChildPath,
  556. &pszNDSTreeName,
  557. &pszChildNDSDn
  558. );
  559. BAIL_ON_FAILURE(hr);
  560. hr = ADsNdsReadObject(
  561. _hADsContext,
  562. pszChildNDSDn,
  563. DS_ATTRIBUTE_VALUES,
  564. ppszAttrs,
  565. 1,
  566. NULL,
  567. &pAttrEntries,
  568. &dwNumEntries
  569. );
  570. BAIL_ON_FAILURE(hr);
  571. if (dwNumEntries != 1) {
  572. BAIL_ON_FAILURE(hr = E_ADS_BAD_PATHNAME);
  573. }
  574. pszObjectClassName = (pAttrEntries[0].lpValue) ?
  575. pAttrEntries[0].lpValue[0].NdsValue.value_20.ClassName :
  576. NULL;
  577. if (!pszObjectClassName) {
  578. BAIL_ON_FAILURE(E_FAIL);
  579. }
  580. if (_wcsicmp(pszObjectClassName, bstrClassName)) {
  581. hr = E_ADS_BAD_PARAMETER;
  582. BAIL_ON_FAILURE(hr);
  583. }
  584. hr = ADsNdsRemoveObject(
  585. _hADsContext,
  586. pszChildNDSDn
  587. );
  588. BAIL_ON_FAILURE(hr);
  589. error:
  590. if (bstrChildPath) {
  591. SysFreeString(bstrChildPath);
  592. }
  593. if (pszNDSTreeName) {
  594. FreeADsStr(pszNDSTreeName);
  595. }
  596. if (pszChildNDSDn) {
  597. FreeADsStr(pszChildNDSDn);
  598. }
  599. if (pAttrEntries) {
  600. FreeNdsAttrInfo(pAttrEntries, dwNumEntries);
  601. }
  602. RRETURN(hr);
  603. }
  604. STDMETHODIMP
  605. CNDSGenObject::CopyHere(
  606. THIS_ BSTR SourceName,
  607. BSTR NewName,
  608. IDispatch * FAR* ppObject
  609. )
  610. {
  611. HRESULT hr = S_OK;
  612. IUnknown *pUnk = NULL;
  613. hr = CopyObject(
  614. _hADsContext,
  615. SourceName,
  616. _ADsPath,
  617. NewName,
  618. _Credentials,
  619. (void**)&pUnk
  620. );
  621. BAIL_ON_FAILURE(hr);
  622. hr = pUnk->QueryInterface(IID_IDispatch, (void **)ppObject);
  623. error:
  624. if (pUnk) {
  625. pUnk->Release();
  626. }
  627. RRETURN(hr);
  628. }
  629. STDMETHODIMP
  630. CNDSGenObject::MoveHere(
  631. THIS_ BSTR SourceName,
  632. BSTR NewName,
  633. IDispatch * FAR* ppObject
  634. )
  635. {
  636. HRESULT hr = S_OK;
  637. IUnknown *pUnk = NULL;
  638. hr = MoveObject(
  639. _hADsContext,
  640. SourceName,
  641. _ADsPath,
  642. NewName,
  643. _Credentials,
  644. (void**)&pUnk
  645. );
  646. BAIL_ON_FAILURE(hr);
  647. if (ppObject) {
  648. hr = pUnk->QueryInterface(IID_IDispatch, (void **)ppObject);
  649. }
  650. error:
  651. if (pUnk) {
  652. pUnk->Release();
  653. }
  654. RRETURN(hr);
  655. }
  656. HRESULT
  657. CNDSGenObject::AllocateGenObject(
  658. CCredentials& Credentials,
  659. CNDSGenObject ** ppGenObject
  660. )
  661. {
  662. CNDSGenObject FAR * pGenObject = NULL;
  663. CDispatchMgr FAR * pDispMgr = NULL;
  664. CPropertyCache FAR * pPropertyCache = NULL;
  665. HRESULT hr = S_OK;
  666. pGenObject = new CNDSGenObject();
  667. if (pGenObject == NULL) {
  668. hr = E_OUTOFMEMORY;
  669. }
  670. BAIL_ON_FAILURE(hr);
  671. pDispMgr = new CDispatchMgr;
  672. if (pDispMgr == NULL) {
  673. hr = E_OUTOFMEMORY;
  674. }
  675. BAIL_ON_FAILURE(hr);
  676. hr = LoadTypeInfoEntry(pDispMgr,
  677. LIBID_ADs,
  678. IID_IADs,
  679. (IADs *)pGenObject,
  680. DISPID_REGULAR
  681. );
  682. BAIL_ON_FAILURE(hr);
  683. hr = LoadTypeInfoEntry(pDispMgr,
  684. LIBID_ADs,
  685. IID_IADsContainer,
  686. (IADsContainer *)pGenObject,
  687. DISPID_NEWENUM
  688. );
  689. BAIL_ON_FAILURE(hr);
  690. hr = LoadTypeInfoEntry(pDispMgr,
  691. LIBID_ADs,
  692. IID_IADsPropertyList,
  693. (IADsPropertyList *)pGenObject,
  694. DISPID_VALUE
  695. );
  696. BAIL_ON_FAILURE(hr);
  697. hr = CPropertyCache::createpropertycache(
  698. (CCoreADsObject FAR *)pGenObject,
  699. &pPropertyCache
  700. );
  701. BAIL_ON_FAILURE(hr);
  702. pGenObject->_Credentials = Credentials;
  703. pGenObject->_pPropertyCache = pPropertyCache;
  704. pGenObject->_pDispMgr = pDispMgr;
  705. *ppGenObject = pGenObject;
  706. RRETURN(hr);
  707. error:
  708. delete pDispMgr;
  709. RRETURN(hr);
  710. }
  711. STDMETHODIMP
  712. CNDSGenObject::Get(
  713. THIS_ BSTR bstrName,
  714. VARIANT FAR* pvProp
  715. )
  716. {
  717. HRESULT hr = S_OK;
  718. DWORD dwSyntaxId;
  719. DWORD dwNumValues;
  720. LPNDSOBJECT pNdsSrcObjects = NULL;
  721. //
  722. // retrieve data object from cache; if one exists
  723. //
  724. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  725. hr = _pPropertyCache->unboundgetproperty(
  726. bstrName,
  727. &dwSyntaxId,
  728. &dwNumValues,
  729. &pNdsSrcObjects
  730. );
  731. BAIL_ON_FAILURE(hr);
  732. }else {
  733. hr = _pPropertyCache->getproperty(
  734. bstrName,
  735. &dwSyntaxId,
  736. &dwNumValues,
  737. &pNdsSrcObjects
  738. );
  739. BAIL_ON_FAILURE(hr);
  740. }
  741. //
  742. // translate the Nds objects to variants
  743. //
  744. hr = NdsTypeToVarTypeCopyConstruct(
  745. pNdsSrcObjects,
  746. dwNumValues,
  747. pvProp,
  748. FALSE
  749. );
  750. BAIL_ON_FAILURE(hr);
  751. error:
  752. if (pNdsSrcObjects) {
  753. NdsTypeFreeNdsObjects(
  754. pNdsSrcObjects,
  755. dwNumValues
  756. );
  757. }
  758. RRETURN(hr);
  759. }
  760. STDMETHODIMP
  761. CNDSGenObject::Put(
  762. THIS_ BSTR bstrName,
  763. VARIANT vProp
  764. )
  765. {
  766. HRESULT hr = S_OK;
  767. DWORD dwSyntaxId = 0;
  768. DWORD dwIndex = 0;
  769. LPNDSOBJECT pNdsDestObjects = NULL;
  770. DWORD dwNumValues = 0;
  771. VARIANT * pVarArray = NULL;
  772. VARIANT * pvProp = NULL;
  773. //
  774. // Issue: How do we handle multi-valued support
  775. //
  776. if ((V_VT(&vProp) & VT_VARIANT) && V_ISARRAY(&vProp)) {
  777. hr = ConvertSafeArrayToVariantArray(
  778. vProp,
  779. &pVarArray,
  780. &dwNumValues
  781. );
  782. BAIL_ON_FAILURE(hr);
  783. pvProp = pVarArray;
  784. } else if ((V_VT(&vProp) & VT_VARIANT) && V_ISARRAY(&vProp) && V_ISBYREF(&vProp)) {
  785. hr = ConvertByRefSafeArrayToVariantArray(
  786. vProp,
  787. &pVarArray,
  788. &dwNumValues
  789. );
  790. BAIL_ON_FAILURE(hr);
  791. pvProp = pVarArray;
  792. }else {
  793. dwNumValues = 1;
  794. pvProp = &vProp;
  795. }
  796. //
  797. // check if this is a legal property for this object,
  798. //
  799. hr = ValidatePropertyinCache(
  800. _pszNDSTreeName,
  801. _ADsClass,
  802. bstrName,
  803. _Credentials,
  804. &dwSyntaxId
  805. );
  806. BAIL_ON_FAILURE(hr);
  807. //
  808. // check if the variant maps to the syntax of this property
  809. //
  810. hr = VarTypeToNdsTypeCopyConstruct(
  811. dwSyntaxId,
  812. pvProp,
  813. &dwNumValues,
  814. &pNdsDestObjects
  815. );
  816. BAIL_ON_FAILURE(hr);
  817. //
  818. // Find this property in the cache
  819. //
  820. hr = _pPropertyCache->findproperty(
  821. bstrName,
  822. &dwIndex
  823. );
  824. //
  825. // If this property does not exist in the
  826. // cache, add this property into the cache.
  827. //
  828. if (FAILED(hr)) {
  829. hr = _pPropertyCache->addproperty(
  830. bstrName,
  831. dwSyntaxId,
  832. dwNumValues,
  833. pNdsDestObjects
  834. );
  835. //
  836. // If the operation fails for some reason
  837. // move on to the next property
  838. //
  839. BAIL_ON_FAILURE(hr);
  840. }
  841. //
  842. // Now update the property in the cache
  843. //
  844. hr = _pPropertyCache->putproperty(
  845. bstrName,
  846. CACHE_PROPERTY_MODIFIED,
  847. dwSyntaxId,
  848. dwNumValues,
  849. pNdsDestObjects
  850. );
  851. BAIL_ON_FAILURE(hr);
  852. error:
  853. if (pNdsDestObjects) {
  854. NdsTypeFreeNdsObjects(
  855. pNdsDestObjects,
  856. dwNumValues
  857. );
  858. }
  859. if (pVarArray) {
  860. DWORD i = 0;
  861. for (i = 0; i < dwNumValues; i++) {
  862. VariantClear(pVarArray + i);
  863. }
  864. FreeADsMem(pVarArray);
  865. }
  866. RRETURN(hr);
  867. }
  868. STDMETHODIMP
  869. CNDSGenObject::PutEx(
  870. THIS_ long lnControlCode,
  871. BSTR bstrName,
  872. VARIANT vProp
  873. )
  874. {
  875. HRESULT hr = S_OK;
  876. DWORD dwSyntaxId = 0;
  877. DWORD dwIndex = 0;
  878. LPNDSOBJECT pNdsDestObjects = NULL;
  879. DWORD dwNumValues = 0;
  880. DWORD dwFlags = 0;
  881. VARIANT * pVarArray = NULL;
  882. VARIANT * pvProp = NULL;
  883. //
  884. // check if this is a legal property for this object,
  885. //
  886. hr = ValidatePropertyinCache(
  887. _pszNDSTreeName,
  888. _ADsClass,
  889. bstrName,
  890. _Credentials,
  891. &dwSyntaxId
  892. );
  893. BAIL_ON_FAILURE(hr);
  894. switch (lnControlCode) {
  895. case ADS_PROPERTY_CLEAR:
  896. dwFlags = CACHE_PROPERTY_CLEARED;
  897. pNdsDestObjects = NULL;
  898. dwNumValues = 0;
  899. break;
  900. case ADS_PROPERTY_UPDATE:
  901. case ADS_PROPERTY_APPEND:
  902. case ADS_PROPERTY_DELETE:
  903. if (lnControlCode == ADS_PROPERTY_UPDATE) {
  904. dwFlags = CACHE_PROPERTY_MODIFIED;
  905. }
  906. else if (lnControlCode == ADS_PROPERTY_APPEND) {
  907. dwFlags = CACHE_PROPERTY_APPENDED;
  908. }
  909. else {
  910. dwFlags = CACHE_PROPERTY_DELETED;
  911. }
  912. //
  913. // Now begin the rest of the processing
  914. //
  915. if ((V_VT(&vProp) & VT_VARIANT) && V_ISARRAY(&vProp)) {
  916. hr = ConvertSafeArrayToVariantArray(
  917. vProp,
  918. &pVarArray,
  919. &dwNumValues
  920. );
  921. BAIL_ON_FAILURE(hr);
  922. pvProp = pVarArray;
  923. } else if ((V_VT(&vProp) & VT_VARIANT) && V_ISARRAY(&vProp) && V_ISBYREF(&vProp)) {
  924. hr = ConvertByRefSafeArrayToVariantArray(
  925. vProp,
  926. &pVarArray,
  927. &dwNumValues
  928. );
  929. BAIL_ON_FAILURE(hr);
  930. pvProp = pVarArray;
  931. }else {
  932. hr = E_FAIL;
  933. BAIL_ON_FAILURE(hr);
  934. }
  935. //
  936. // check if the variant maps to the syntax of this property
  937. //
  938. hr = VarTypeToNdsTypeCopyConstruct(
  939. dwSyntaxId,
  940. pvProp,
  941. &dwNumValues,
  942. &pNdsDestObjects
  943. );
  944. BAIL_ON_FAILURE(hr);
  945. break;
  946. default:
  947. RRETURN(hr = E_ADS_BAD_PARAMETER);
  948. }
  949. //
  950. // Find this property in the cache
  951. //
  952. hr = _pPropertyCache->findproperty(
  953. bstrName,
  954. &dwIndex
  955. );
  956. //
  957. // If this property does not exist in the
  958. // cache, add this property into the cache.
  959. //
  960. if (FAILED(hr)) {
  961. hr = _pPropertyCache->addproperty(
  962. bstrName,
  963. dwSyntaxId,
  964. dwNumValues,
  965. pNdsDestObjects
  966. );
  967. //
  968. // If the operation fails for some reason
  969. // move on to the next property
  970. //
  971. BAIL_ON_FAILURE(hr);
  972. }
  973. //
  974. // Now update the property in the cache
  975. //
  976. hr = _pPropertyCache->putproperty(
  977. bstrName,
  978. dwFlags,
  979. dwSyntaxId,
  980. dwNumValues,
  981. pNdsDestObjects
  982. );
  983. BAIL_ON_FAILURE(hr);
  984. error:
  985. if (pNdsDestObjects) {
  986. NdsTypeFreeNdsObjects(
  987. pNdsDestObjects,
  988. dwNumValues
  989. );
  990. }
  991. if (pVarArray) {
  992. DWORD i = 0;
  993. for (i = 0; i < dwNumValues; i++) {
  994. VariantClear(pVarArray + i);
  995. }
  996. FreeADsMem(pVarArray);
  997. }
  998. RRETURN(hr);
  999. }
  1000. STDMETHODIMP
  1001. CNDSGenObject::GetEx(
  1002. THIS_ BSTR bstrName,
  1003. VARIANT FAR* pvProp
  1004. )
  1005. {
  1006. HRESULT hr = S_OK;
  1007. DWORD dwSyntaxId;
  1008. DWORD dwNumValues;
  1009. LPNDSOBJECT pNdsSrcObjects = NULL;
  1010. //
  1011. // retrieve data object from cache; if one exists
  1012. //
  1013. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  1014. hr = _pPropertyCache->unboundgetproperty(
  1015. bstrName,
  1016. &dwSyntaxId,
  1017. &dwNumValues,
  1018. &pNdsSrcObjects
  1019. );
  1020. BAIL_ON_FAILURE(hr);
  1021. }else {
  1022. hr = _pPropertyCache->getproperty(
  1023. bstrName,
  1024. &dwSyntaxId,
  1025. &dwNumValues,
  1026. &pNdsSrcObjects
  1027. );
  1028. BAIL_ON_FAILURE(hr);
  1029. }
  1030. //
  1031. // translate the Nds objects to variants
  1032. //
  1033. hr = NdsTypeToVarTypeCopyConstruct(
  1034. pNdsSrcObjects,
  1035. dwNumValues,
  1036. pvProp,
  1037. TRUE
  1038. );
  1039. BAIL_ON_FAILURE(hr);
  1040. error:
  1041. if (pNdsSrcObjects) {
  1042. NdsTypeFreeNdsObjects(
  1043. pNdsSrcObjects,
  1044. dwNumValues
  1045. );
  1046. }
  1047. RRETURN(hr);
  1048. }
  1049. void
  1050. CNDSGenObject::InitSearchPrefs()
  1051. {
  1052. _SearchPref._dwSearchScope = DS_SEARCH_SUBTREE;
  1053. _SearchPref._fDerefAliases = FALSE;
  1054. _SearchPref._fAttrsOnly = FALSE;
  1055. _SearchPref._fCacheResults = TRUE;
  1056. }
  1057. STDMETHODIMP
  1058. CNDSGenObject::get_PropertyCount(
  1059. THIS_ long FAR *plCount
  1060. )
  1061. {
  1062. HRESULT hr = E_FAIL;
  1063. if (_pPropertyCache) {
  1064. hr = _pPropertyCache->get_PropertyCount((PDWORD)plCount);
  1065. }
  1066. RRETURN(hr);
  1067. }
  1068. STDMETHODIMP
  1069. CNDSGenObject::Next(
  1070. THIS_ VARIANT FAR *pVariant
  1071. )
  1072. {
  1073. HRESULT hr = E_FAIL;
  1074. DWORD dwSyntaxId = 0;
  1075. DWORD dwNumValues = 0;
  1076. LPNDSOBJECT pNdsSrcObjects = NULL;
  1077. VARIANT varData;
  1078. IDispatch * pDispatch = NULL;
  1079. PADSVALUE pAdsValues = NULL;
  1080. if (!_pPropertyCache->index_valid())
  1081. RRETURN(E_FAIL);
  1082. VariantInit(&varData);
  1083. hr = _pPropertyCache->unboundgetproperty(
  1084. _pPropertyCache->get_CurrentIndex(),
  1085. &dwSyntaxId,
  1086. &dwNumValues,
  1087. &pNdsSrcObjects
  1088. );
  1089. BAIL_ON_FAILURE(hr);
  1090. //
  1091. // translate the Nds objects to variants
  1092. //
  1093. hr = ConvertNdsValuesToVariant(
  1094. _pPropertyCache->get_CurrentPropName(),
  1095. pNdsSrcObjects,
  1096. dwNumValues,
  1097. pVariant
  1098. );
  1099. BAIL_ON_FAILURE(hr);
  1100. //
  1101. // We're successful so far, now skip by 1
  1102. //
  1103. hr = Skip(1);
  1104. error:
  1105. if (pNdsSrcObjects) {
  1106. NdsTypeFreeNdsObjects(pNdsSrcObjects, dwNumValues);
  1107. }
  1108. RRETURN(hr);
  1109. }
  1110. STDMETHODIMP
  1111. CNDSGenObject::Skip(
  1112. THIS_ long cElements
  1113. )
  1114. {
  1115. HRESULT hr = S_OK;
  1116. hr = _pPropertyCache->skip_propindex(
  1117. cElements
  1118. );
  1119. RRETURN(hr);
  1120. }
  1121. STDMETHODIMP
  1122. CNDSGenObject::Reset(
  1123. )
  1124. {
  1125. _pPropertyCache->reset_propindex();
  1126. RRETURN(S_OK);
  1127. }
  1128. STDMETHODIMP
  1129. CNDSGenObject::ResetPropertyItem(THIS_ VARIANT varEntry)
  1130. {
  1131. HRESULT hr = S_OK;
  1132. DWORD dwIndex = 0;
  1133. switch (V_VT(&varEntry)) {
  1134. case VT_BSTR:
  1135. hr = _pPropertyCache->findproperty(
  1136. V_BSTR(&varEntry),
  1137. &dwIndex
  1138. );
  1139. BAIL_ON_FAILURE(hr);
  1140. break;
  1141. case VT_I4:
  1142. dwIndex = V_I4(&varEntry);
  1143. break;
  1144. case VT_I2:
  1145. dwIndex = V_I2(&varEntry);
  1146. break;
  1147. default:
  1148. hr = E_FAIL;
  1149. BAIL_ON_FAILURE(hr);
  1150. }
  1151. hr = _pPropertyCache->deleteproperty(
  1152. dwIndex
  1153. );
  1154. error:
  1155. RRETURN(hr);
  1156. }
  1157. STDMETHODIMP
  1158. CNDSGenObject::GetPropertyItem(
  1159. THIS_ BSTR bstrName,
  1160. LONG lnType,
  1161. VARIANT * pVariant
  1162. )
  1163. {
  1164. HRESULT hr = S_OK;
  1165. DWORD dwSyntaxId;
  1166. DWORD dwNumValues;
  1167. LPNDSOBJECT pNdsSrcObjects = NULL;
  1168. PADSVALUE pAdsValues = NULL;
  1169. //
  1170. // retrieve data object from cache; if one exists
  1171. //
  1172. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  1173. hr = _pPropertyCache->unboundgetproperty(
  1174. bstrName,
  1175. &dwSyntaxId,
  1176. &dwNumValues,
  1177. &pNdsSrcObjects
  1178. );
  1179. BAIL_ON_FAILURE(hr);
  1180. }else {
  1181. hr = _pPropertyCache->getproperty(
  1182. bstrName,
  1183. &dwSyntaxId,
  1184. &dwNumValues,
  1185. &pNdsSrcObjects
  1186. );
  1187. BAIL_ON_FAILURE(hr);
  1188. }
  1189. //
  1190. // translate the Nds objects to variants
  1191. //
  1192. hr = ConvertNdsValuesToVariant(
  1193. bstrName,
  1194. pNdsSrcObjects,
  1195. dwNumValues,
  1196. pVariant
  1197. );
  1198. error:
  1199. if (pNdsSrcObjects) {
  1200. NdsTypeFreeNdsObjects(
  1201. pNdsSrcObjects,
  1202. dwNumValues
  1203. );
  1204. }
  1205. RRETURN(hr);
  1206. }
  1207. STDMETHODIMP
  1208. CNDSGenObject::PutPropertyItem(THIS_ VARIANT varData)
  1209. {
  1210. HRESULT hr = S_OK;
  1211. DWORD dwSyntaxId = 0;
  1212. DWORD dwIndex = 0;
  1213. WCHAR szPropertyName[MAX_PATH];
  1214. DWORD dwControlCode = 0;
  1215. LPNDSOBJECT pNdsDestObjects = NULL;
  1216. DWORD dwNumValues = 0;
  1217. DWORD dwFlags = 0;
  1218. VARIANT * pVarArray = NULL;
  1219. VARIANT * pvarData = NULL;
  1220. PADSVALUE pAdsValues = NULL;
  1221. DWORD dwAdsValues = 0;
  1222. DWORD dwSyntaxId2 = 0;
  1223. DWORD dwNumNdsValues = 0;
  1224. hr = ConvertVariantToNdsValues(
  1225. varData,
  1226. szPropertyName,
  1227. &dwControlCode,
  1228. &pNdsDestObjects,
  1229. &dwNumValues,
  1230. &dwSyntaxId
  1231. );
  1232. BAIL_ON_FAILURE(hr);
  1233. switch (dwControlCode) {
  1234. case ADS_PROPERTY_CLEAR:
  1235. dwFlags = CACHE_PROPERTY_CLEARED;
  1236. pNdsDestObjects = NULL;
  1237. dwNumValues = 0;
  1238. break;
  1239. case ADS_PROPERTY_UPDATE:
  1240. dwFlags = CACHE_PROPERTY_MODIFIED;
  1241. break;
  1242. case ADS_PROPERTY_APPEND:
  1243. dwFlags = CACHE_PROPERTY_APPENDED;
  1244. break;
  1245. case ADS_PROPERTY_DELETE:
  1246. dwFlags = CACHE_PROPERTY_DELETED;
  1247. break;
  1248. default:
  1249. RRETURN(hr = E_ADS_BAD_PARAMETER);
  1250. }
  1251. //
  1252. // Find this property in the cache
  1253. //
  1254. hr = _pPropertyCache->findproperty(
  1255. szPropertyName,
  1256. &dwIndex
  1257. );
  1258. //
  1259. // If this property does not exist in the
  1260. // cache, add this property into the cache.
  1261. //
  1262. if (FAILED(hr)) {
  1263. hr = _pPropertyCache->addproperty(
  1264. szPropertyName,
  1265. dwSyntaxId,
  1266. dwNumValues,
  1267. pNdsDestObjects
  1268. );
  1269. //
  1270. // If the operation fails for some reason
  1271. // move on to the next property
  1272. //
  1273. BAIL_ON_FAILURE(hr);
  1274. }
  1275. //
  1276. // Now update the property in the cache
  1277. //
  1278. hr = _pPropertyCache->putproperty(
  1279. szPropertyName,
  1280. dwFlags,
  1281. dwSyntaxId,
  1282. dwNumValues,
  1283. pNdsDestObjects
  1284. );
  1285. BAIL_ON_FAILURE(hr);
  1286. error:
  1287. if (pNdsDestObjects) {
  1288. NdsTypeFreeNdsObjects(
  1289. pNdsDestObjects,
  1290. dwNumValues
  1291. );
  1292. }
  1293. RRETURN(hr);
  1294. }
  1295. HRESULT
  1296. CreatePropEntry(
  1297. LPWSTR szPropName,
  1298. DWORD ADsType,
  1299. DWORD numValues,
  1300. VARIANT varData,
  1301. REFIID riid,
  1302. LPVOID * ppDispatch
  1303. )
  1304. {
  1305. HRESULT hr = S_OK;
  1306. IADsPropertyEntry * pPropEntry = NULL;
  1307. hr = CoCreateInstance(
  1308. CLSID_PropertyEntry,
  1309. NULL,
  1310. CLSCTX_INPROC_SERVER,
  1311. IID_IADsPropertyEntry,
  1312. (void **)&pPropEntry
  1313. );
  1314. BAIL_ON_FAILURE(hr);
  1315. hr = pPropEntry->put_Name(szPropName);
  1316. BAIL_ON_FAILURE(hr);
  1317. hr = pPropEntry->put_ADsType(ADsType);
  1318. BAIL_ON_FAILURE(hr);
  1319. hr = pPropEntry->put_Values(varData);
  1320. BAIL_ON_FAILURE(hr);
  1321. hr = pPropEntry->QueryInterface(
  1322. riid,
  1323. ppDispatch
  1324. );
  1325. BAIL_ON_FAILURE(hr);
  1326. error:
  1327. if (pPropEntry) {
  1328. pPropEntry->Release();
  1329. }
  1330. RRETURN(hr);
  1331. }
  1332. STDMETHODIMP
  1333. CNDSGenObject::Item(
  1334. THIS_ VARIANT varIndex,
  1335. VARIANT * pVariant
  1336. )
  1337. {
  1338. HRESULT hr = S_OK;
  1339. DWORD dwSyntaxId;
  1340. DWORD dwNumValues;
  1341. LPNDSOBJECT pNdsSrcObjects = NULL;
  1342. PADSVALUE pAdsValues = NULL;
  1343. LPWSTR szPropName = NULL;
  1344. //
  1345. // retrieve data object from cache; if one exis
  1346. //
  1347. switch (V_VT(&varIndex)) {
  1348. case VT_BSTR:
  1349. //
  1350. // retrieve data object from cache; if one exists
  1351. //
  1352. if (GetObjectState() == ADS_OBJECT_UNBOUND) {
  1353. hr = _pPropertyCache->unboundgetproperty(
  1354. V_BSTR(&varIndex),
  1355. &dwSyntaxId,
  1356. &dwNumValues,
  1357. &pNdsSrcObjects
  1358. );
  1359. BAIL_ON_FAILURE(hr);
  1360. }else {
  1361. hr = _pPropertyCache->getproperty(
  1362. V_BSTR(&varIndex),
  1363. &dwSyntaxId,
  1364. &dwNumValues,
  1365. &pNdsSrcObjects
  1366. );
  1367. BAIL_ON_FAILURE(hr);
  1368. }
  1369. hr = ConvertNdsValuesToVariant(
  1370. V_BSTR(&varIndex),
  1371. pNdsSrcObjects,
  1372. dwNumValues,
  1373. pVariant
  1374. );
  1375. BAIL_ON_FAILURE(hr);
  1376. break;
  1377. case VT_I4:
  1378. hr = _pPropertyCache->unboundgetproperty(
  1379. V_I4(&varIndex),
  1380. &dwSyntaxId,
  1381. &dwNumValues,
  1382. &pNdsSrcObjects
  1383. );
  1384. BAIL_ON_FAILURE(hr);
  1385. szPropName = _pPropertyCache->get_PropName(V_I4(&varIndex));
  1386. hr = ConvertNdsValuesToVariant(
  1387. szPropName,
  1388. pNdsSrcObjects,
  1389. dwNumValues,
  1390. pVariant
  1391. );
  1392. BAIL_ON_FAILURE(hr);
  1393. break;
  1394. case VT_I2:
  1395. hr = _pPropertyCache->unboundgetproperty(
  1396. (DWORD)V_I2(&varIndex),
  1397. &dwSyntaxId,
  1398. &dwNumValues,
  1399. &pNdsSrcObjects
  1400. );
  1401. BAIL_ON_FAILURE(hr);
  1402. szPropName = _pPropertyCache->get_PropName(V_I2(&varIndex));
  1403. hr = ConvertNdsValuesToVariant(
  1404. szPropName,
  1405. pNdsSrcObjects,
  1406. dwNumValues,
  1407. pVariant
  1408. );
  1409. BAIL_ON_FAILURE(hr);
  1410. break;
  1411. default:
  1412. hr = E_FAIL;
  1413. BAIL_ON_FAILURE(hr);
  1414. }
  1415. error:
  1416. if (pNdsSrcObjects) {
  1417. NdsTypeFreeNdsObjects(
  1418. pNdsSrcObjects,
  1419. dwNumValues
  1420. );
  1421. }
  1422. RRETURN(hr);
  1423. }
  1424. STDMETHODIMP
  1425. CNDSGenObject::PurgePropertyList()
  1426. {
  1427. _pPropertyCache->flushpropcache();
  1428. RRETURN(S_OK);
  1429. }
  1430. HRESULT
  1431. ConvertVariantToVariantArray(
  1432. VARIANT varData,
  1433. VARIANT ** ppVarArray,
  1434. DWORD * pdwNumValues
  1435. )
  1436. {
  1437. DWORD dwNumValues = 0;
  1438. VARIANT * pVarArray = NULL;
  1439. HRESULT hr = S_OK;
  1440. *ppVarArray = NULL;
  1441. *pdwNumValues = 0;
  1442. if ((V_VT(&varData) & VT_VARIANT) && V_ISARRAY(&varData) && V_ISBYREF(&varData)){
  1443. hr = ConvertByRefSafeArrayToVariantArray(
  1444. varData,
  1445. &pVarArray,
  1446. &dwNumValues
  1447. );
  1448. BAIL_ON_FAILURE(hr);
  1449. } else if ((V_VT(&varData) & VT_VARIANT) && V_ISARRAY(&varData)) {
  1450. hr = ConvertSafeArrayToVariantArray(
  1451. varData,
  1452. &pVarArray,
  1453. &dwNumValues
  1454. );
  1455. BAIL_ON_FAILURE(hr);
  1456. } else {
  1457. pVarArray = NULL;
  1458. dwNumValues = 0;
  1459. }
  1460. *ppVarArray = pVarArray;
  1461. *pdwNumValues = dwNumValues;
  1462. error:
  1463. RRETURN(hr);
  1464. }
  1465. void
  1466. FreeVariantArray(
  1467. VARIANT * pVarArray,
  1468. DWORD dwNumValues
  1469. )
  1470. {
  1471. if (pVarArray) {
  1472. DWORD i = 0;
  1473. for (i = 0; i < dwNumValues; i++) {
  1474. VariantClear(pVarArray + i);
  1475. }
  1476. FreeADsMem(pVarArray);
  1477. }
  1478. }
  1479. HRESULT
  1480. ConvertVariantToNdsValues(
  1481. VARIANT varData,
  1482. LPWSTR szPropertyName,
  1483. PDWORD pdwControlCode,
  1484. PNDSOBJECT * ppNdsDestObjects,
  1485. PDWORD pdwNumValues,
  1486. PDWORD pdwSyntaxId
  1487. )
  1488. {
  1489. HRESULT hr = S_OK;
  1490. IADsPropertyEntry * pPropEntry = NULL;
  1491. IDispatch * pDispatch = NULL;
  1492. BSTR bstrPropName = NULL;
  1493. DWORD dwControlCode = 0;
  1494. DWORD dwAdsType = 0;
  1495. VARIANT varValues;
  1496. VARIANT * pVarArray = NULL;
  1497. DWORD dwNumValues = 0;
  1498. PADSVALUE pAdsValues = NULL;
  1499. DWORD dwAdsValues = 0;
  1500. PNDSOBJECT pNdsDestObjects = 0;
  1501. DWORD dwNumNdsObjects = 0;
  1502. DWORD dwNdsSyntaxId = 0;
  1503. if (V_VT(&varData) != VT_DISPATCH) {
  1504. RRETURN (hr = DISP_E_TYPEMISMATCH);
  1505. }
  1506. pDispatch = V_DISPATCH(&varData);
  1507. hr = pDispatch->QueryInterface(
  1508. IID_IADsPropertyEntry,
  1509. (void **)&pPropEntry
  1510. );
  1511. BAIL_ON_FAILURE(hr);
  1512. VariantInit(&varValues);
  1513. VariantClear(&varValues);
  1514. hr = pPropEntry->get_Name(&bstrPropName);
  1515. BAIL_ON_FAILURE(hr);
  1516. wcscpy(szPropertyName, bstrPropName);
  1517. hr = pPropEntry->get_ControlCode((long *)&dwControlCode);
  1518. BAIL_ON_FAILURE(hr);
  1519. *pdwControlCode = dwControlCode;
  1520. hr = pPropEntry->get_ADsType((long *)&dwAdsType);
  1521. BAIL_ON_FAILURE(hr);
  1522. hr = pPropEntry->get_Values(&varValues);
  1523. BAIL_ON_FAILURE(hr);
  1524. hr = ConvertVariantToVariantArray(
  1525. varValues,
  1526. &pVarArray,
  1527. &dwNumValues
  1528. );
  1529. BAIL_ON_FAILURE(hr);
  1530. if (dwNumValues) {
  1531. hr = PropVariantToAdsType(
  1532. pVarArray,
  1533. dwNumValues,
  1534. &pAdsValues,
  1535. &dwAdsValues
  1536. );
  1537. BAIL_ON_FAILURE(hr);
  1538. hr = AdsTypeToNdsTypeCopyConstruct(
  1539. pAdsValues,
  1540. dwAdsValues,
  1541. &pNdsDestObjects,
  1542. &dwNumNdsObjects,
  1543. &dwNdsSyntaxId
  1544. );
  1545. BAIL_ON_FAILURE(hr);
  1546. }
  1547. *ppNdsDestObjects = pNdsDestObjects;
  1548. *pdwNumValues = dwNumNdsObjects;
  1549. *pdwSyntaxId = dwNdsSyntaxId;
  1550. cleanup:
  1551. if (bstrPropName) {
  1552. ADsFreeString(bstrPropName);
  1553. }
  1554. if (pAdsValues) {
  1555. AdsFreeAdsValues(
  1556. pAdsValues,
  1557. dwNumValues
  1558. );
  1559. FreeADsMem( pAdsValues );
  1560. }
  1561. if (pVarArray) {
  1562. FreeVariantArray(
  1563. pVarArray,
  1564. dwAdsValues
  1565. );
  1566. }
  1567. if (pPropEntry) {
  1568. pPropEntry->Release();
  1569. }
  1570. RRETURN(hr);
  1571. error:
  1572. if (pNdsDestObjects) {
  1573. NdsTypeFreeNdsObjects(
  1574. pNdsDestObjects,
  1575. dwNumNdsObjects
  1576. );
  1577. }
  1578. *ppNdsDestObjects = NULL;
  1579. *pdwNumValues = 0;
  1580. goto cleanup;
  1581. }
  1582. HRESULT
  1583. ConvertNdsValuesToVariant(
  1584. BSTR bstrPropName,
  1585. LPNDSOBJECT pNdsSrcObjects,
  1586. DWORD dwNumValues,
  1587. PVARIANT pVarProp
  1588. )
  1589. {
  1590. HRESULT hr = S_OK;
  1591. PADSVALUE pAdsValues = NULL;
  1592. DWORD dwNumAdsValues = 0;
  1593. VARIANT varData;
  1594. IDispatch * pDispatch = NULL;
  1595. DWORD dwADsType = 0;
  1596. VariantInit(&varData);
  1597. VariantInit(pVarProp);
  1598. //
  1599. // translate the Nds objects to variants
  1600. //
  1601. hr = NdsTypeToAdsTypeCopyConstruct(
  1602. pNdsSrcObjects,
  1603. dwNumValues,
  1604. &pAdsValues
  1605. );
  1606. if (SUCCEEDED(hr)){
  1607. hr = AdsTypeToPropVariant(
  1608. pAdsValues,
  1609. dwNumValues,
  1610. &varData
  1611. );
  1612. if (SUCCEEDED(hr)) {
  1613. dwADsType = pAdsValues->dwType;
  1614. }else {
  1615. VariantClear(&varData);
  1616. hr = S_OK;
  1617. }
  1618. }else {
  1619. VariantClear(&varData);
  1620. VariantInit(&varData);
  1621. hr = S_OK;
  1622. }
  1623. hr = CreatePropEntry(
  1624. bstrPropName,
  1625. dwADsType,
  1626. dwNumValues,
  1627. varData,
  1628. IID_IDispatch,
  1629. (void **)&pDispatch
  1630. );
  1631. BAIL_ON_FAILURE(hr);
  1632. V_DISPATCH(pVarProp) = pDispatch;
  1633. V_VT(pVarProp) = VT_DISPATCH;
  1634. RRETURN(hr);
  1635. error:
  1636. if (pAdsValues) {
  1637. AdsFreeAdsValues(
  1638. pAdsValues,
  1639. dwNumValues
  1640. );
  1641. FreeADsMem( pAdsValues );
  1642. }
  1643. RRETURN(hr);
  1644. }