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.

1115 lines
22 KiB

  1. //---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995
  5. //
  6. // File: cggi.cxx
  7. //
  8. // Contents: This file contains the Group Object's
  9. // IADsGroup and IADsGroupOperation methods
  10. //
  11. // History: 11-1-95 krishnag Created.
  12. //
  13. //----------------------------------------------------------------------------
  14. #include "nds.hxx"
  15. #pragma hdrstop
  16. BOOL
  17. VerifyIfMember(
  18. BSTR bstrMember,
  19. VARIANT * VariantArray,
  20. ULONG cElementFetched
  21. );
  22. // Class CNDSGroup
  23. STDMETHODIMP CNDSGroup::get_Description(THIS_ BSTR FAR* retval)
  24. {
  25. GET_PROPERTY_BSTR((IADsGroup *)this,Description);
  26. }
  27. STDMETHODIMP CNDSGroup::put_Description(THIS_ BSTR bstrDescription)
  28. {
  29. PUT_PROPERTY_BSTR((IADsGroup *)this,Description);
  30. }
  31. STDMETHODIMP
  32. CNDSGroup::Members(
  33. THIS_ IADsMembers FAR* FAR* ppMembers
  34. )
  35. {
  36. VARIANT varProp;
  37. HRESULT hr = S_OK;
  38. BSTR bstrADsPath = NULL;
  39. if (!ppMembers) {
  40. RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
  41. }
  42. VariantInit(&varProp);
  43. hr = _pADs->GetEx(L"Member", &varProp);
  44. //
  45. // Do not bail out on failure here if you could not find
  46. // any data set for the Members property. You need to
  47. // pass it all the way through and on enumeration
  48. // return nothing.
  49. //
  50. if (hr == E_ADS_PROPERTY_NOT_FOUND) {
  51. SAFEARRAY *aList = NULL;
  52. VariantInit(&varProp);
  53. SAFEARRAYBOUND aBound;
  54. aBound.lLbound = 0;
  55. aBound.cElements = 0;
  56. aList = SafeArrayCreate( VT_VARIANT, 1, &aBound );
  57. if ( aList == NULL ) {
  58. hr = E_OUTOFMEMORY;
  59. BAIL_ON_FAILURE(hr);
  60. }
  61. V_VT(&varProp) = VT_ARRAY | VT_VARIANT;
  62. V_ARRAY(&varProp) = aList;
  63. }
  64. else {
  65. BAIL_ON_FAILURE(hr);
  66. }
  67. hr = _pADs->get_ADsPath(&bstrADsPath);
  68. hr = CNDSGroupCollection::CreateGroupCollection(
  69. bstrADsPath,
  70. varProp,
  71. _Credentials,
  72. IID_IADsMembers,
  73. (void **)ppMembers
  74. );
  75. BAIL_ON_FAILURE(hr);
  76. error:
  77. if (bstrADsPath) {
  78. ADsFreeString(bstrADsPath);
  79. }
  80. VariantClear(&varProp);
  81. RRETURN_EXP_IF_ERR(hr);
  82. }
  83. STDMETHODIMP
  84. CNDSGroup::IsMember(
  85. THIS_ BSTR bstrMember,
  86. VARIANT_BOOL FAR* bMember
  87. )
  88. {
  89. IADsMembers FAR * pMembers = NULL;
  90. IUnknown FAR * pUnknown = NULL;
  91. IEnumVARIANT FAR * pEnumVar = NULL;
  92. DWORD i = 0;
  93. HRESULT hr = S_OK;
  94. VARIANT_BOOL fMember = FALSE;
  95. VARIANT VariantArray[10];
  96. BOOL fContinue = TRUE;
  97. ULONG cElementFetched = 0;
  98. if (!bstrMember) {
  99. RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
  100. }
  101. if (!bMember) {
  102. RRETURN_EXP_IF_ERR(E_ADS_BAD_PARAMETER);
  103. }
  104. hr = Members(
  105. &pMembers
  106. );
  107. BAIL_ON_FAILURE(hr);
  108. hr = pMembers->get__NewEnum(
  109. &pUnknown
  110. );
  111. //
  112. // If it has no members, we will return FALSE
  113. //
  114. if (hr == E_FAIL) {
  115. hr = S_OK;
  116. goto error;
  117. }
  118. hr = pUnknown->QueryInterface(
  119. IID_IEnumVARIANT,
  120. (void **)&pEnumVar
  121. );
  122. BAIL_ON_FAILURE(hr);
  123. while (fContinue) {
  124. hr = pEnumVar->Next(
  125. 10,
  126. VariantArray,
  127. &cElementFetched
  128. );
  129. if (hr == S_FALSE) {
  130. fContinue = FALSE;
  131. //
  132. // Reset hr to S_OK, we want to return success
  133. //
  134. hr = S_OK;
  135. }
  136. fMember = (VARIANT_BOOL)VerifyIfMember(
  137. bstrMember,
  138. VariantArray,
  139. cElementFetched
  140. );
  141. if (fMember) {
  142. fContinue = FALSE;
  143. }
  144. for (i = 0; i < cElementFetched; i++ ) {
  145. IDispatch *pDispatch = NULL;
  146. pDispatch = VariantArray[i].pdispVal;
  147. pDispatch->Release();
  148. }
  149. memset(VariantArray, 0, sizeof(VARIANT)*10);
  150. }
  151. error:
  152. *bMember = fMember? VARIANT_TRUE: VARIANT_FALSE;
  153. if (pEnumVar) {
  154. pEnumVar->Release();
  155. }
  156. if (pUnknown) {
  157. pUnknown->Release();
  158. }
  159. if (pMembers) {
  160. pMembers->Release();
  161. }
  162. RRETURN_EXP_IF_ERR(hr);
  163. }
  164. BOOL
  165. VerifyIfMember(
  166. BSTR bstrMember,
  167. VARIANT * VariantArray,
  168. ULONG cElementFetched
  169. )
  170. {
  171. DWORD i = 0;
  172. HRESULT hr = S_OK;
  173. IADs FAR * pObject = NULL;
  174. IDispatch FAR * pDispatch = NULL;
  175. for (i = 0; i < cElementFetched; i++ ) {
  176. IDispatch *pDispatch = NULL;
  177. BSTR bstrName = NULL;
  178. pDispatch = VariantArray[i].pdispVal;
  179. hr = pDispatch->QueryInterface(
  180. IID_IADs,
  181. (VOID **) &pObject
  182. );
  183. BAIL_ON_FAILURE(hr);
  184. hr = pObject->get_ADsPath(&bstrName);
  185. BAIL_ON_FAILURE(hr);
  186. if (!_wcsicmp(bstrName, bstrMember)) {
  187. SysFreeString(bstrName);
  188. bstrName = NULL;
  189. pObject->Release();
  190. return(TRUE);
  191. }
  192. SysFreeString(bstrName);
  193. bstrName = NULL;
  194. pObject->Release();
  195. }
  196. error:
  197. return(FALSE);
  198. }
  199. STDMETHODIMP
  200. CNDSGroup::Add(THIS_ BSTR bstrNewItem)
  201. {
  202. HRESULT hr = S_OK;
  203. WCHAR szNDSUserPathName[MAX_PATH];
  204. WCHAR szNDSUserTreeName[MAX_PATH];
  205. IUnknown * pUnknown = NULL;
  206. IADs * pUser = NULL;
  207. WCHAR szNDSGroupPathName[MAX_PATH];
  208. WCHAR szNDSGroupTreeName[MAX_PATH];
  209. BSTR bstrPathName = NULL;
  210. BSTR pszClass = NULL;
  211. hr = ::GetObject(
  212. bstrNewItem,
  213. _Credentials,
  214. (void **)&pUnknown
  215. );
  216. BAIL_ON_FAILURE(hr);
  217. hr = pUnknown->QueryInterface(IID_IADs, (void **)&pUser);
  218. BAIL_ON_FAILURE(hr);
  219. hr = BuildNDSPathFromADsPath(
  220. bstrNewItem,
  221. szNDSUserTreeName,
  222. szNDSUserPathName
  223. );
  224. BAIL_ON_FAILURE(hr);
  225. hr = _pADs->get_ADsPath(&bstrPathName);
  226. BAIL_ON_FAILURE(hr);
  227. hr = BuildNDSPathFromADsPath(
  228. bstrPathName,
  229. szNDSGroupTreeName,
  230. szNDSGroupPathName
  231. );
  232. BAIL_ON_FAILURE(hr);
  233. hr = AddEntry(_pADs, L"Member",szNDSUserPathName);
  234. BAIL_ON_FAILURE(hr);
  235. // hr = AddEntry(_pADs, L"Equivalent To Me", szNDSUserPathName);
  236. // BAIL_ON_FAILURE(hr);
  237. //
  238. // Groups do not have a "Group Membership" attribute
  239. //
  240. hr = pUser->get_Class(&pszClass);
  241. BAIL_ON_FAILURE(hr);
  242. if (_wcsicmp(pszClass, L"group") != 0) {
  243. hr = AddEntry(pUser, L"Group Membership", szNDSGroupPathName);
  244. BAIL_ON_FAILURE(hr);
  245. }
  246. error:
  247. if (pszClass) {
  248. ADsFreeString(pszClass);
  249. }
  250. if (bstrPathName) {
  251. ADsFreeString(bstrPathName);
  252. }
  253. if (pUnknown) {
  254. pUnknown->Release();
  255. }
  256. if (pUser) {
  257. pUser->Release();
  258. }
  259. RRETURN_EXP_IF_ERR(hr);
  260. }
  261. STDMETHODIMP
  262. CNDSGroup::Remove(THIS_ BSTR bstrNewItem)
  263. {
  264. HRESULT hr = S_OK;
  265. WCHAR szNDSUserPathName[MAX_PATH];
  266. WCHAR szNDSUserTreeName[MAX_PATH];
  267. IUnknown * pUnknown = NULL;
  268. IADs * pUser = NULL;
  269. WCHAR szNDSGroupPathName[MAX_PATH];
  270. WCHAR szNDSGroupTreeName[MAX_PATH];
  271. BSTR bstrPathName = NULL;
  272. BSTR pszClass = NULL;
  273. hr = ::GetObject(
  274. bstrNewItem,
  275. _Credentials,
  276. (void **)&pUnknown
  277. );
  278. BAIL_ON_FAILURE(hr);
  279. hr = pUnknown->QueryInterface(IID_IADs, (void **)&pUser);
  280. BAIL_ON_FAILURE(hr);
  281. hr = BuildNDSPathFromADsPath(
  282. bstrNewItem,
  283. szNDSUserTreeName,
  284. szNDSUserPathName
  285. );
  286. BAIL_ON_FAILURE(hr);
  287. hr = _pADs->get_ADsPath(&bstrPathName);
  288. BAIL_ON_FAILURE(hr);
  289. hr = BuildNDSPathFromADsPath(
  290. bstrPathName,
  291. szNDSGroupTreeName,
  292. szNDSGroupPathName
  293. );
  294. BAIL_ON_FAILURE(hr);
  295. hr = RemoveEntry(_pADs, L"Member",szNDSUserPathName);
  296. BAIL_ON_FAILURE(hr);
  297. // hr = RemoveEntry(_pADs, L"Equivalent To Me", szNDSUserPathName);
  298. // BAIL_ON_FAILURE(hr);
  299. //
  300. // Groups do not have a "Group Membership" attribute
  301. //
  302. hr = pUser->get_Class(&pszClass);
  303. BAIL_ON_FAILURE(hr);
  304. if (_wcsicmp(pszClass, L"group") != 0) {
  305. hr = RemoveEntry(pUser, L"Group Membership", szNDSGroupPathName);
  306. BAIL_ON_FAILURE(hr);
  307. }
  308. error:
  309. if (pszClass) {
  310. ADsFreeString(pszClass);
  311. }
  312. if (bstrPathName) {
  313. ADsFreeString(bstrPathName);
  314. }
  315. if (pUnknown) {
  316. pUnknown->Release();
  317. }
  318. if (pUser) {
  319. pUser->Release();
  320. }
  321. RRETURN_EXP_IF_ERR(hr);
  322. }
  323. HRESULT
  324. AddEntry(
  325. IADs * pADs,
  326. LPWSTR pszAttribute,
  327. LPWSTR pszValue
  328. )
  329. {
  330. HRESULT hr = S_OK;
  331. VARIANT vOldValue;
  332. VARIANT vNewValue;
  333. SAFEARRAY * pArray = NULL;
  334. VariantInit(&vOldValue);
  335. VariantInit(&vNewValue);
  336. #if defined(BUILD_FOR_NT40)
  337. hr = pADs->Get(pszAttribute, &vOldValue);
  338. if (hr == E_ADS_PROPERTY_NOT_FOUND) {
  339. VariantInit(&vNewValue);
  340. V_BSTR(&vNewValue) = SysAllocString(pszValue);
  341. V_VT(&vNewValue) = VT_BSTR;
  342. hr = pADs->Put(pszAttribute, vNewValue);
  343. BAIL_ON_FAILURE(hr);
  344. }else{
  345. hr = VarAddEntry(
  346. pszValue,
  347. vOldValue,
  348. &vNewValue
  349. );
  350. BAIL_ON_FAILURE(hr);
  351. hr = pADs->Put(pszAttribute, vNewValue);
  352. BAIL_ON_FAILURE(hr);
  353. }
  354. #else
  355. //
  356. // NT5 supports appending values. So we don't need to read everything.
  357. // append ourselves and write everything
  358. //
  359. SAFEARRAYBOUND sabNewArray;
  360. int i;
  361. VARIANT v;
  362. sabNewArray.cElements = 1;
  363. sabNewArray.lLbound = 0;
  364. pArray = SafeArrayCreate(
  365. VT_VARIANT,
  366. 1,
  367. &sabNewArray
  368. );
  369. if (!pArray) {
  370. hr = E_OUTOFMEMORY;
  371. BAIL_ON_FAILURE(hr);
  372. }
  373. VariantInit(&v);
  374. V_BSTR(&v) = SysAllocString(pszValue);
  375. V_VT(&v) = VT_BSTR;
  376. i = 0;
  377. hr = SafeArrayPutElement(
  378. pArray,
  379. (long *)&i,
  380. (void *)&v
  381. );
  382. VariantClear(&v);
  383. BAIL_ON_FAILURE(hr);
  384. V_VT(&vNewValue) = VT_ARRAY | VT_VARIANT;
  385. V_ARRAY(&vNewValue) = pArray;
  386. hr = pADs->PutEx(ADS_PROPERTY_APPEND, pszAttribute, vNewValue);
  387. BAIL_ON_FAILURE(hr);
  388. #endif
  389. hr = pADs->SetInfo();
  390. BAIL_ON_FAILURE(hr);
  391. error:
  392. VariantClear(&vOldValue);
  393. VariantClear(&vNewValue);
  394. RRETURN(hr);
  395. }
  396. HRESULT
  397. RemoveEntry(
  398. IADs * pADs,
  399. LPWSTR pszAttribute,
  400. LPWSTR pszValue
  401. )
  402. {
  403. HRESULT hr = S_OK;
  404. VARIANT vOldValue;
  405. VARIANT vNewValue;
  406. SAFEARRAY * pArray = NULL;
  407. VariantInit(&vOldValue);
  408. VariantInit(&vNewValue);
  409. #if defined(BUILD_FOR_NT40)
  410. hr = pADs->Get(pszAttribute, &vOldValue);
  411. BAIL_ON_FAILURE(hr);
  412. hr = VarRemoveEntry(
  413. pszValue,
  414. vOldValue,
  415. &vNewValue
  416. );
  417. BAIL_ON_FAILURE(hr);
  418. if (V_VT(&vNewValue) == VT_EMPTY) {
  419. hr = pADs->PutEx(ADS_PROPERTY_CLEAR, pszAttribute, vNewValue);
  420. }else {
  421. hr = pADs->Put(pszAttribute, vNewValue);
  422. }
  423. BAIL_ON_FAILURE(hr);
  424. #else
  425. SAFEARRAYBOUND sabNewArray;
  426. VARIANT v;
  427. int i;
  428. //
  429. // NT5 supports deleting values. So we don't need to read everything.
  430. // delete ourselves and write everything - Very inefficient!
  431. //
  432. sabNewArray.cElements = 1;
  433. sabNewArray.lLbound = 0;
  434. pArray = SafeArrayCreate(
  435. VT_VARIANT,
  436. 1,
  437. &sabNewArray
  438. );
  439. if (!pArray) {
  440. hr = E_OUTOFMEMORY;
  441. BAIL_ON_FAILURE(hr);
  442. }
  443. VariantInit(&v);
  444. V_BSTR(&v) = SysAllocString(pszValue);
  445. V_VT(&v) = VT_BSTR;
  446. i = 0;
  447. hr = SafeArrayPutElement(
  448. pArray,
  449. (long *)&i,
  450. (void *)&v
  451. );
  452. VariantClear(&v);
  453. BAIL_ON_FAILURE(hr);
  454. V_VT(&vNewValue) = VT_ARRAY | VT_VARIANT;
  455. V_ARRAY(&vNewValue) = pArray;
  456. hr = pADs->PutEx(ADS_PROPERTY_DELETE, pszAttribute, vNewValue);
  457. BAIL_ON_FAILURE(hr);
  458. #endif
  459. hr = pADs->SetInfo();
  460. BAIL_ON_FAILURE(hr);
  461. error:
  462. VariantClear(&vOldValue);
  463. VariantClear(&vNewValue);
  464. RRETURN(hr);
  465. }
  466. HRESULT
  467. VarFindEntry(
  468. LPWSTR pszNDSPathName,
  469. VARIANT varMembers
  470. )
  471. {
  472. HRESULT hr = S_OK;
  473. DWORD dwSLBound = 0;
  474. DWORD dwSUBound = 0;
  475. DWORD i = 0;
  476. VARIANT v;
  477. if (!(V_VT(&varMembers) == (VT_VARIANT|VT_ARRAY))) {
  478. return(E_FAIL);
  479. }
  480. //
  481. // Check that there is only one dimension in this array
  482. //
  483. if ((V_ARRAY(&varMembers))->cDims != 1) {
  484. hr = E_FAIL;
  485. BAIL_ON_FAILURE(hr);
  486. }
  487. //
  488. // Check that there is atleast one element in this array
  489. //
  490. if ((V_ARRAY(&varMembers))->rgsabound[0].cElements == 0){
  491. hr = E_FAIL;
  492. BAIL_ON_FAILURE(hr);
  493. }
  494. //
  495. // We know that this is a valid single dimension array
  496. //
  497. hr = SafeArrayGetLBound(V_ARRAY(&varMembers),
  498. 1,
  499. (long FAR *)&dwSLBound
  500. );
  501. BAIL_ON_FAILURE(hr);
  502. hr = SafeArrayGetUBound(V_ARRAY(&varMembers),
  503. 1,
  504. (long FAR *)&dwSUBound
  505. );
  506. BAIL_ON_FAILURE(hr);
  507. for (i = dwSLBound; i <= dwSUBound; i++) {
  508. VariantInit(&v);
  509. hr = SafeArrayGetElement(V_ARRAY(&varMembers),
  510. (long FAR *)&i,
  511. &v
  512. );
  513. if (!_wcsicmp(V_BSTR(&v), pszNDSPathName)) {
  514. VariantClear(&v);
  515. RRETURN(S_OK);
  516. }
  517. VariantClear(&v);
  518. }
  519. error:
  520. RRETURN(E_FAIL);
  521. }
  522. HRESULT
  523. VarMultipleAddEntry(
  524. LPWSTR pszNDSPathName,
  525. VARIANT varMembers,
  526. VARIANT * pvarNewMembers
  527. )
  528. { SAFEARRAYBOUND sabNewArray;
  529. SAFEARRAY * pFilter = NULL;
  530. HRESULT hr = S_OK;
  531. DWORD dwSLBound = 0;
  532. DWORD dwSUBound = 0;
  533. DWORD i = 0;
  534. VARIANT v;
  535. VariantInit(pvarNewMembers);
  536. if (!(V_VT(&varMembers) == (VT_VARIANT|VT_ARRAY))) {
  537. return(E_FAIL);
  538. }
  539. //
  540. // Check that there is only one dimension in this array
  541. //
  542. if ((V_ARRAY(&varMembers))->cDims != 1) {
  543. hr = E_FAIL;
  544. BAIL_ON_FAILURE(hr);
  545. }
  546. //
  547. // Check that there is atleast one element in this array
  548. //
  549. if ((V_ARRAY(&varMembers))->rgsabound[0].cElements == 0){
  550. hr = E_FAIL;
  551. BAIL_ON_FAILURE(hr);
  552. }
  553. //
  554. // We know that this is a valid single dimension array
  555. //
  556. hr = SafeArrayGetLBound(V_ARRAY(&varMembers),
  557. 1,
  558. (long FAR *)&dwSLBound
  559. );
  560. BAIL_ON_FAILURE(hr);
  561. hr = SafeArrayGetUBound(V_ARRAY(&varMembers),
  562. 1,
  563. (long FAR *)&dwSUBound
  564. );
  565. BAIL_ON_FAILURE(hr);
  566. sabNewArray.cElements = (dwSUBound - dwSLBound + 1) + 1;
  567. sabNewArray.lLbound = dwSLBound;
  568. pFilter = SafeArrayCreate(
  569. VT_VARIANT,
  570. 1,
  571. &sabNewArray
  572. );
  573. if (!pFilter) {
  574. hr = E_OUTOFMEMORY;
  575. BAIL_ON_FAILURE(hr);
  576. }
  577. for (i = dwSLBound; i <= dwSUBound; i++) {
  578. VariantInit(&v);
  579. hr = SafeArrayGetElement(
  580. V_ARRAY(&varMembers),
  581. (long FAR *)&i,
  582. &v
  583. );
  584. BAIL_ON_FAILURE(hr);
  585. hr = SafeArrayPutElement(
  586. pFilter,
  587. (long*)&i,
  588. (void *)&v
  589. );
  590. VariantClear(&v);
  591. BAIL_ON_FAILURE(hr);
  592. }
  593. VariantInit(&v);
  594. V_VT(&v) = VT_BSTR;
  595. V_BSTR(&v) = SysAllocString(pszNDSPathName);
  596. hr = SafeArrayPutElement(
  597. pFilter,
  598. (long *)&i,
  599. (void *)&v
  600. );
  601. VariantClear(&v);
  602. BAIL_ON_FAILURE(hr);
  603. V_VT(pvarNewMembers) = VT_ARRAY | VT_VARIANT;
  604. V_ARRAY(pvarNewMembers) = pFilter;
  605. RRETURN(S_OK);
  606. error:
  607. if (pFilter) {
  608. SafeArrayDestroy(pFilter);
  609. }
  610. RRETURN(hr);
  611. }
  612. HRESULT
  613. VarMultipleRemoveEntry(
  614. LPWSTR pszNDSPathName,
  615. VARIANT varMembers,
  616. VARIANT * pvarNewMembers
  617. )
  618. { SAFEARRAYBOUND sabNewArray;
  619. SAFEARRAY * pFilter = NULL;
  620. HRESULT hr = S_OK;
  621. DWORD dwSLBound = 0;
  622. DWORD dwSUBound = 0;
  623. DWORD i = 0;
  624. DWORD dwNewCount = 0;
  625. VARIANT v;
  626. VariantInit(pvarNewMembers);
  627. if(!(V_VT(&varMembers) == (VT_VARIANT|VT_ARRAY))){
  628. return(E_FAIL);
  629. }
  630. //
  631. // Check that there is only one dimension in this array
  632. //
  633. if ((V_ARRAY(&varMembers))->cDims != 1) {
  634. hr = E_FAIL;
  635. BAIL_ON_FAILURE(hr);
  636. }
  637. //
  638. // Check that there is atleast one element in this array
  639. //
  640. if ((V_ARRAY(&varMembers))->rgsabound[0].cElements == 0){
  641. hr = E_FAIL;
  642. BAIL_ON_FAILURE(hr);
  643. }
  644. //
  645. // We know that this is a valid single dimension array
  646. //
  647. hr = SafeArrayGetLBound(V_ARRAY(&varMembers),
  648. 1,
  649. (long FAR *)&dwSLBound
  650. );
  651. BAIL_ON_FAILURE(hr);
  652. hr = SafeArrayGetUBound(V_ARRAY(&varMembers),
  653. 1,
  654. (long FAR *)&dwSUBound
  655. );
  656. BAIL_ON_FAILURE(hr);
  657. sabNewArray.cElements = (dwSUBound - dwSLBound);
  658. sabNewArray.lLbound = dwSLBound;
  659. pFilter = SafeArrayCreate(
  660. VT_VARIANT,
  661. 1,
  662. &sabNewArray
  663. );
  664. if (!pFilter) {
  665. hr = E_OUTOFMEMORY;
  666. BAIL_ON_FAILURE(hr);
  667. }
  668. for (i = dwSLBound, dwNewCount = dwSLBound; i <= dwSUBound; i++) {
  669. VariantInit(&v);
  670. hr = SafeArrayGetElement(
  671. V_ARRAY(&varMembers),
  672. (long FAR *)&i,
  673. &v
  674. );
  675. if (!_wcsicmp(V_BSTR(&v), pszNDSPathName)) {
  676. VariantClear(&v);
  677. //
  678. // skip this entry
  679. //
  680. continue;
  681. }
  682. hr = SafeArrayPutElement(
  683. pFilter,
  684. (long*)&dwNewCount,
  685. (void *)&v
  686. );
  687. VariantClear(&v);
  688. BAIL_ON_FAILURE(hr);
  689. dwNewCount++;
  690. }
  691. V_VT(pvarNewMembers) = VT_ARRAY | VT_VARIANT;
  692. V_ARRAY(pvarNewMembers) = pFilter;
  693. RRETURN(S_OK);
  694. error:
  695. if (pFilter) {
  696. SafeArrayDestroy(pFilter);
  697. }
  698. RRETURN(hr);
  699. }
  700. HRESULT
  701. VarSingleAddEntry(
  702. LPWSTR pszNDSPathName,
  703. VARIANT varMembers,
  704. VARIANT * pvarNewMembers
  705. )
  706. { SAFEARRAYBOUND sabNewArray;
  707. SAFEARRAY * pFilter = NULL;
  708. HRESULT hr = S_OK;
  709. DWORD dwSLBound = 0;
  710. DWORD dwSUBound = 0;
  711. DWORD i = 0;
  712. VARIANT v;
  713. VariantInit(pvarNewMembers);
  714. if(!((V_VT(&varMembers) & VT_TYPEMASK) == VT_BSTR)){
  715. return(E_FAIL);
  716. }
  717. sabNewArray.cElements = (1) + 1;
  718. sabNewArray.lLbound = 0;
  719. pFilter = SafeArrayCreate(
  720. VT_VARIANT,
  721. 1,
  722. &sabNewArray
  723. );
  724. if (!pFilter) {
  725. hr = E_OUTOFMEMORY;
  726. BAIL_ON_FAILURE(hr);
  727. }
  728. i = 0;
  729. hr = SafeArrayPutElement(
  730. pFilter,
  731. (long *)&i,
  732. (void *)&varMembers
  733. );
  734. BAIL_ON_FAILURE(hr);
  735. i++;
  736. VariantInit(&v);
  737. V_VT(&v) = VT_BSTR;
  738. V_BSTR(&v) = SysAllocString(pszNDSPathName);
  739. hr = SafeArrayPutElement(
  740. pFilter,
  741. (long *)&i,
  742. (void *)&v
  743. );
  744. VariantClear(&v);
  745. BAIL_ON_FAILURE(hr);
  746. V_VT(pvarNewMembers) = VT_ARRAY | VT_VARIANT;
  747. V_ARRAY(pvarNewMembers) = pFilter;
  748. RRETURN(S_OK);
  749. error:
  750. if (pFilter) {
  751. SafeArrayDestroy(pFilter);
  752. }
  753. RRETURN(hr);
  754. }
  755. HRESULT
  756. VarSingleRemoveEntry(
  757. LPWSTR pszNDSPathName,
  758. VARIANT varMembers,
  759. VARIANT * pvarNewMembers
  760. )
  761. {
  762. HRESULT hr = S_OK;
  763. VariantInit(pvarNewMembers);
  764. if(!((V_VT(&varMembers) & VT_TYPEMASK) == VT_BSTR)){
  765. return(E_FAIL);
  766. }
  767. V_VT(pvarNewMembers) = VT_EMPTY;
  768. V_BSTR(pvarNewMembers) = NULL;
  769. RRETURN(hr);
  770. }
  771. HRESULT
  772. VarRemoveEntry(
  773. LPWSTR pszNDSPathName,
  774. VARIANT varMembers,
  775. VARIANT * pvarNewMembers
  776. )
  777. {
  778. HRESULT hr = S_OK;
  779. if (V_VT(&varMembers) == (VT_VARIANT|VT_ARRAY)) {
  780. hr = VarMultipleRemoveEntry(
  781. pszNDSPathName,
  782. varMembers,
  783. pvarNewMembers
  784. );
  785. RRETURN(hr);
  786. }else if (V_VT(&varMembers) == VT_BSTR){
  787. hr = VarSingleRemoveEntry(
  788. pszNDSPathName,
  789. varMembers,
  790. pvarNewMembers
  791. );
  792. RRETURN(hr);
  793. }else {
  794. RRETURN(E_FAIL);
  795. }
  796. }
  797. HRESULT
  798. VarAddEntry(
  799. LPWSTR pszNDSPathName,
  800. VARIANT varMembers,
  801. VARIANT * pvarNewMembers
  802. )
  803. {
  804. HRESULT hr = S_OK;
  805. if (V_VT(&varMembers) == (VT_VARIANT|VT_ARRAY)){
  806. hr = VarMultipleAddEntry(
  807. pszNDSPathName,
  808. varMembers,
  809. pvarNewMembers
  810. );
  811. RRETURN(hr);
  812. }else if ((V_VT(&varMembers) & VT_TYPEMASK) == VT_BSTR){
  813. hr = VarSingleAddEntry(
  814. pszNDSPathName,
  815. varMembers,
  816. pvarNewMembers
  817. );
  818. RRETURN(hr);
  819. }else {
  820. RRETURN(E_FAIL);
  821. }
  822. }