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.

1118 lines
24 KiB

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