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.

1614 lines
36 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1992 - 1995.
  5. //
  6. // File: cprops.cxx
  7. //
  8. // Contents: Property Cache functionality for IIS
  9. //
  10. // Functions:
  11. // CPropertyCache::addproperty
  12. // CPropertyCache::updateproperty
  13. // CPropertyCache::findproperty
  14. // CPropertyCache::getproperty
  15. // CPropertyCache::putproperty
  16. // CProperyCache::CPropertyCache
  17. // CPropertyCache::~CPropertyCache
  18. // CPropertyCache::createpropertycache
  19. //
  20. // History: 17-June-1997 sophiac Created.
  21. // cloned off NT property cache code
  22. //
  23. //
  24. //----------------------------------------------------------------------------
  25. #include "iis.hxx"
  26. #pragma hdrstop
  27. #if DBG
  28. DECLARE_INFOLEVEL(IISMarshall);
  29. DECLARE_DEBUG(IISMarshall);
  30. #define IISMarshallDebugOut(x) IISMarshallInlineDebugOut x
  31. #endif
  32. //+------------------------------------------------------------------------
  33. //
  34. // Function: CPropertyCache::addproperty
  35. //
  36. // Synopsis:
  37. //
  38. //
  39. //
  40. // Arguments: [szPropertyName] --
  41. // [vt] --
  42. // [vaData] --
  43. //
  44. //
  45. //-------------------------------------------------------------------------
  46. HRESULT
  47. CPropertyCache::
  48. addproperty(
  49. LPWSTR szPropertyName,
  50. DWORD dwSyntaxId,
  51. DWORD dwNumValues,
  52. PIISOBJECT pIISObject
  53. )
  54. {
  55. HRESULT hr = S_OK;
  56. PPROPERTY pNewProperty = NULL;
  57. //
  58. // extend the property cache by adding a new property entry
  59. //
  60. PPROPERTY pOrigProperties = _pProperties;
  61. _pProperties = (PPROPERTY)ReallocADsMem(
  62. _pProperties,
  63. _cb,
  64. _cb + sizeof(PROPERTY)
  65. );
  66. if (!_pProperties) {
  67. _pProperties = pOrigProperties;
  68. hr = E_OUTOFMEMORY;
  69. BAIL_ON_FAILURE(hr);
  70. }
  71. pNewProperty = (PPROPERTY)((LPBYTE)_pProperties + _cb);
  72. wcscpy(pNewProperty->szPropertyName, szPropertyName);
  73. //
  74. // Update the index
  75. //
  76. _dwMaxProperties++;
  77. _cb += sizeof(PROPERTY);
  78. error:
  79. RRETURN(hr);
  80. }
  81. //+------------------------------------------------------------------------
  82. //
  83. // Function: CPropertyCache::updateproperty
  84. //
  85. // Synopsis:
  86. //
  87. //
  88. //
  89. // Arguments: [szPropertyName] --
  90. // [vaData] --
  91. //
  92. //-------------------------------------------------------------------------
  93. HRESULT
  94. CPropertyCache::updateproperty(
  95. LPWSTR szPropertyName,
  96. DWORD dwSyntaxId,
  97. DWORD dwNumValues,
  98. PIISOBJECT pIISObject,
  99. BOOL fExplicit
  100. )
  101. {
  102. HRESULT hr;
  103. DWORD dwIndex;
  104. DWORD dwMetaId;
  105. PIISOBJECT pIISTempObject = NULL;
  106. PPROPERTY pThisProperty = NULL;
  107. hr = LoadSchema();
  108. BAIL_ON_FAILURE(hr);
  109. hr = findproperty(
  110. szPropertyName,
  111. &dwIndex
  112. );
  113. BAIL_ON_FAILURE(hr);
  114. pThisProperty = _pProperties + dwIndex;
  115. if (!fExplicit) {
  116. if ((PROPERTY_FLAGS(pThisProperty) == CACHE_PROPERTY_MODIFIED) ||
  117. (PROPERTY_FLAGS(pThisProperty) == CACHE_PROPERTY_CLEARED)) {
  118. hr = S_OK;
  119. goto error;
  120. }
  121. }
  122. //
  123. // Factor in cases where object state is necessary to
  124. // decide on update.
  125. //
  126. if (PROPERTY_IISOBJECT(pThisProperty)) {
  127. IISTypeFreeIISObjects(
  128. PROPERTY_IISOBJECT(pThisProperty),
  129. PROPERTY_NUMVALUES(pThisProperty)
  130. );
  131. PROPERTY_IISOBJECT(pThisProperty) = NULL;
  132. }
  133. PROPERTY_SYNTAX(pThisProperty) = dwSyntaxId;
  134. PROPERTY_NUMVALUES(pThisProperty) = dwNumValues;
  135. _pSchema->ConvertPropName_To_ID(szPropertyName, &dwMetaId);
  136. PROPERTY_METAID(pThisProperty) = dwMetaId;
  137. hr = IISTypeCopyConstruct(
  138. pIISObject,
  139. dwNumValues,
  140. &pIISTempObject
  141. );
  142. BAIL_ON_FAILURE(hr);
  143. PROPERTY_IISOBJECT(pThisProperty) = pIISTempObject;
  144. PROPERTY_FLAGS(pThisProperty) = CACHE_PROPERTY_INITIALIZED;
  145. error:
  146. RRETURN(hr);
  147. }
  148. //+------------------------------------------------------------------------
  149. //
  150. // Function: CPropertyCache::findproperty
  151. //
  152. // Synopsis:
  153. //
  154. //
  155. //
  156. // Arguments: [szPropertyName] --
  157. // [pdwIndex] --
  158. //
  159. //-------------------------------------------------------------------------
  160. HRESULT
  161. CPropertyCache::findproperty(
  162. LPWSTR szPropertyName,
  163. PDWORD pdwIndex
  164. )
  165. {
  166. DWORD i = 0;
  167. PPROPERTY pThisProperty = NULL;
  168. for (i = 0; i < _dwMaxProperties; i++) {
  169. pThisProperty = _pProperties + i;
  170. ASSERT(pThisProperty);
  171. if (!_wcsicmp(pThisProperty->szPropertyName, szPropertyName)) {
  172. *pdwIndex = i;
  173. RRETURN(S_OK);
  174. }
  175. }
  176. *pdwIndex = 0;
  177. RRETURN(E_ADS_PROPERTY_NOT_FOUND);
  178. }
  179. //+------------------------------------------------------------------------
  180. //
  181. // Function: CPropertyCache::getproperty
  182. //
  183. // Synopsis:
  184. //
  185. //
  186. //
  187. // Arguments: [szPropertyName] -- Property to retrieve from the cache
  188. // [pvaData] -- Data returned in a variant
  189. //
  190. //-------------------------------------------------------------------------
  191. HRESULT
  192. CPropertyCache::
  193. getproperty(
  194. LPWSTR szPropertyName,
  195. PDWORD pdwSyntaxId,
  196. PDWORD pdwNumValues,
  197. PIISOBJECT * ppIISObject
  198. )
  199. {
  200. HRESULT hr;
  201. DWORD dwIndex = 0L;
  202. PPROPERTY pThisProperty = NULL;
  203. DWORD dwInfoLevel = 0;
  204. hr = LoadSchema();
  205. BAIL_ON_FAILURE(hr);
  206. hr = findproperty(
  207. szPropertyName,
  208. &dwIndex
  209. );
  210. if (hr == E_ADS_PROPERTY_NOT_FOUND) {
  211. //
  212. // Now call the GetInfo function
  213. //
  214. if (!_bPropsLoaded) {
  215. hr = _pCoreADsObject->GetInfo(FALSE);
  216. if (FAILED(hr) && hr != E_ADS_OBJECT_UNBOUND) {
  217. BAIL_ON_FAILURE(hr);
  218. }
  219. hr = findproperty(
  220. szPropertyName,
  221. &dwIndex
  222. );
  223. }
  224. }
  225. if (hr == E_ADS_PROPERTY_NOT_FOUND) {
  226. LPBYTE propvalue;
  227. DWORD dwSyntax;
  228. DWORD dwNumValues;
  229. hr = _pSchema->GetDefaultProperty(szPropertyName, &dwNumValues,
  230. &dwSyntax, &propvalue);
  231. BAIL_ON_FAILURE(hr);
  232. hr = unmarshallproperty(
  233. szPropertyName,
  234. propvalue,
  235. dwNumValues,
  236. dwSyntax,
  237. 0
  238. );
  239. BAIL_ON_FAILURE(hr);
  240. hr = findproperty (szPropertyName,
  241. &dwIndex
  242. );
  243. }
  244. BAIL_ON_FAILURE(hr);
  245. pThisProperty = _pProperties + dwIndex;
  246. if (PROPERTY_IISOBJECT(pThisProperty)) {
  247. *pdwSyntaxId = (DWORD)PROPERTY_SYNTAX(pThisProperty);
  248. *pdwNumValues = (DWORD)PROPERTY_NUMVALUES(pThisProperty);
  249. hr = IISTypeCopyConstruct(PROPERTY_IISOBJECT(pThisProperty),
  250. PROPERTY_NUMVALUES(pThisProperty),
  251. ppIISObject );
  252. BAIL_ON_FAILURE(hr);
  253. }else {
  254. *ppIISObject = NULL;
  255. *pdwNumValues = 0;
  256. *pdwSyntaxId = 0;
  257. hr = E_ADS_PROPERTY_NOT_SET;
  258. }
  259. error:
  260. RRETURN(hr);
  261. }
  262. //+------------------------------------------------------------------------
  263. //
  264. // Function: CPropertyCache::putproperty
  265. //
  266. // Synopsis:
  267. //
  268. //
  269. //
  270. // Arguments: [szPropertyName] -- Clsid index
  271. // [vaData] -- Matching clsid returned in *pclsid
  272. //
  273. //-------------------------------------------------------------------------
  274. HRESULT
  275. CPropertyCache::putproperty(
  276. LPWSTR szPropertyName,
  277. DWORD dwFlags,
  278. DWORD dwSyntaxId,
  279. DWORD dwNumValues,
  280. PIISOBJECT pIISObject
  281. )
  282. {
  283. HRESULT hr;
  284. DWORD dwIndex = 0L;
  285. DWORD dwMetaId = 0;
  286. PIISOBJECT pIISTempObject = NULL;
  287. PPROPERTY pThisProperty = NULL;
  288. hr = LoadSchema();
  289. BAIL_ON_FAILURE(hr);
  290. hr = findproperty(
  291. szPropertyName,
  292. &dwIndex
  293. );
  294. BAIL_ON_FAILURE(hr);
  295. pThisProperty = _pProperties + dwIndex;
  296. if (PROPERTY_IISOBJECT(pThisProperty)) {
  297. IISTypeFreeIISObjects(
  298. PROPERTY_IISOBJECT(pThisProperty),
  299. PROPERTY_NUMVALUES(pThisProperty)
  300. );
  301. PROPERTY_IISOBJECT(pThisProperty) = NULL;
  302. }
  303. _pSchema->ConvertPropName_To_ID(szPropertyName, &dwMetaId);
  304. switch (dwFlags) {
  305. case CACHE_PROPERTY_MODIFIED:
  306. PROPERTY_SYNTAX(pThisProperty) = dwSyntaxId;
  307. PROPERTY_NUMVALUES(pThisProperty) = dwNumValues;
  308. PROPERTY_METAID(pThisProperty) = dwMetaId;
  309. hr = IISTypeCopyConstruct(
  310. pIISObject,
  311. dwNumValues,
  312. &pIISTempObject
  313. );
  314. BAIL_ON_FAILURE(hr);
  315. PROPERTY_IISOBJECT(pThisProperty) = pIISTempObject;
  316. PROPERTY_FLAGS(pThisProperty) = CACHE_PROPERTY_MODIFIED;
  317. break;
  318. case CACHE_PROPERTY_CLEARED:
  319. PROPERTY_SYNTAX(pThisProperty) = dwSyntaxId;
  320. PROPERTY_NUMVALUES(pThisProperty) = 0;
  321. PROPERTY_IISOBJECT(pThisProperty) = NULL;
  322. PROPERTY_FLAGS(pThisProperty) = CACHE_PROPERTY_CLEARED;
  323. break;
  324. }
  325. error:
  326. RRETURN(hr);
  327. }
  328. //+------------------------------------------------------------------------
  329. //
  330. // Function: CPropertyCache
  331. //
  332. // Synopsis:
  333. //
  334. //
  335. //
  336. // Arguments:
  337. //
  338. //
  339. //-------------------------------------------------------------------------
  340. CPropertyCache::CPropertyCache():
  341. _pCoreADsObject(NULL),
  342. _pSchema(NULL),
  343. _bPropsLoaded(FALSE),
  344. _dwMaxProperties(0),
  345. _dwCurrentIndex(0),
  346. _pProperties(NULL),
  347. _cb(0),
  348. _pDispProperties(NULL),
  349. _dwDispMaxProperties(0),
  350. _cbDisp(0),
  351. _bstrServerName(NULL)
  352. {
  353. }
  354. //+------------------------------------------------------------------------
  355. //
  356. // Function: ~CPropertyCache
  357. //
  358. // Synopsis:
  359. //
  360. //
  361. //
  362. // Arguments:
  363. //
  364. //
  365. //-------------------------------------------------------------------------
  366. CPropertyCache::
  367. ~CPropertyCache()
  368. {
  369. DWORD i = 0;
  370. PPROPERTY pThisProperty = NULL;
  371. PDISPPROPERTY pThisDispProperty = NULL;
  372. if (_pProperties) {
  373. for (i = 0; i < _dwMaxProperties; i++) {
  374. pThisProperty = _pProperties + i;
  375. if (PROPERTY_IISOBJECT(pThisProperty)) {
  376. IISTypeFreeIISObjects(
  377. PROPERTY_IISOBJECT(pThisProperty),
  378. PROPERTY_NUMVALUES(pThisProperty)
  379. );
  380. PROPERTY_IISOBJECT(pThisProperty) = NULL;
  381. }
  382. }
  383. FreeADsMem(_pProperties);
  384. }
  385. //
  386. // Free Dynamic Dispid Table
  387. //
  388. if (_pDispProperties) {
  389. FreeADsMem(_pDispProperties);
  390. }
  391. if( _bstrServerName )
  392. {
  393. ADsFreeString( _bstrServerName );
  394. }
  395. }
  396. //+------------------------------------------------------------------------
  397. //
  398. // Function:
  399. //
  400. // Synopsis:
  401. //
  402. //
  403. //
  404. // Arguments:
  405. //
  406. //
  407. //-------------------------------------------------------------------------
  408. HRESULT
  409. CPropertyCache::createpropertycache(
  410. CCoreADsObject FAR * pCoreADsObject,
  411. CPropertyCache FAR *FAR * ppPropertyCache
  412. )
  413. {
  414. CPropertyCache FAR * pPropertyCache = NULL;
  415. BSTR serverName=NULL;
  416. HRESULT hr;
  417. hr = pCoreADsObject->get_CoreName(&serverName);
  418. BAIL_ON_FAILURE(hr);
  419. pPropertyCache = new CPropertyCache();
  420. if (!pPropertyCache) {
  421. RRETURN(E_OUTOFMEMORY);
  422. }
  423. pPropertyCache->_pCoreADsObject = pCoreADsObject;
  424. *ppPropertyCache = pPropertyCache;
  425. RRETURN(S_OK);
  426. error :
  427. RRETURN(hr);
  428. }
  429. //+------------------------------------------------------------------------
  430. //
  431. // Function:
  432. //
  433. // Synopsis:
  434. //
  435. //
  436. //
  437. // Arguments:
  438. //
  439. //
  440. //-------------------------------------------------------------------------
  441. HRESULT
  442. CPropertyCache::
  443. unmarshallproperty(
  444. LPWSTR szPropertyName,
  445. LPBYTE lpValue,
  446. DWORD dwNumValues,
  447. DWORD dwSyntaxId,
  448. BOOL fExplicit
  449. )
  450. {
  451. DWORD dwIndex = 0;
  452. HRESULT hr = S_OK;
  453. PIISOBJECT pIISObject = NULL;
  454. hr = UnMarshallIISToIISSynId(
  455. dwSyntaxId,
  456. dwNumValues,
  457. lpValue,
  458. &pIISObject
  459. );
  460. BAIL_ON_FAILURE(hr);
  461. //
  462. // Find this property in the cache
  463. //
  464. hr = findproperty(
  465. szPropertyName,
  466. &dwIndex
  467. );
  468. //
  469. // If this property does not exist in the
  470. // cache, add this property into the cache.
  471. //
  472. if (FAILED(hr)) {
  473. hr = addproperty(
  474. szPropertyName,
  475. dwSyntaxId,
  476. dwNumValues,
  477. pIISObject
  478. );
  479. //
  480. // If the operation fails for some reason
  481. // move on to the next property
  482. //
  483. BAIL_ON_FAILURE(hr);
  484. }
  485. //
  486. // Now update the property in the cache
  487. //
  488. hr = updateproperty(
  489. szPropertyName,
  490. dwSyntaxId,
  491. dwNumValues,
  492. pIISObject,
  493. fExplicit
  494. );
  495. BAIL_ON_FAILURE(hr);
  496. error:
  497. if (pIISObject) {
  498. IISTypeFreeIISObjects(
  499. pIISObject,
  500. dwNumValues
  501. );
  502. }
  503. RRETURN(hr);
  504. }
  505. HRESULT
  506. CPropertyCache::
  507. IISUnMarshallProperties(
  508. LPBYTE pBase,
  509. LPBYTE pBuffer,
  510. DWORD dwMDNumDataEntries,
  511. BOOL fExplicit
  512. )
  513. {
  514. HRESULT hr = S_OK;
  515. PMETADATA_GETALL_RECORD pmdgarData = NULL, pTemp = NULL;
  516. DWORD i = 0;
  517. WCHAR szPropertyName[MAX_PATH];
  518. DWORD dwSyntaxID;
  519. DWORD dwNumValues;
  520. ZeroMemory(szPropertyName, MAX_PATH);
  521. hr = LoadSchema();
  522. BAIL_ON_FAILURE(hr);
  523. _bPropsLoaded = TRUE;
  524. pmdgarData = (PMETADATA_GETALL_RECORD)pBuffer;
  525. for (i = 0; i < dwMDNumDataEntries; i++) {
  526. //
  527. // unmarshall this property into the
  528. // property cache
  529. //
  530. pTemp = pmdgarData + i;
  531. hr = _pSchema->ConvertID_To_PropName(pTemp->dwMDIdentifier,
  532. szPropertyName);
  533. CONTINUE_ON_FAILURE(hr);
  534. hr = _pSchema->LookupSyntaxID(szPropertyName, &dwSyntaxID);
  535. CONTINUE_ON_FAILURE(hr);
  536. //
  537. // find out number of strings within the multi-sz string
  538. //
  539. if (pTemp->dwMDDataType == MULTISZ_METADATA) {
  540. LPWSTR pszStr = (LPWSTR) (pBase + pTemp->dwMDDataOffset);
  541. if (*pszStr == 0) {
  542. dwNumValues = 1;
  543. }
  544. else {
  545. dwNumValues = 0;
  546. }
  547. while (*pszStr != L'\0') {
  548. while (*pszStr != L'\0') {
  549. pszStr++;
  550. }
  551. dwNumValues++;
  552. pszStr++;
  553. }
  554. }
  555. else if (pTemp->dwMDDataType == BINARY_METADATA) {
  556. //
  557. // if DataType == BINARY, pass the length to dwNumValues
  558. //
  559. dwNumValues = pTemp->dwMDDataLen;
  560. }
  561. else {
  562. dwNumValues = 1;
  563. }
  564. hr = unmarshallproperty(
  565. szPropertyName,
  566. pBase + pTemp->dwMDDataOffset,
  567. dwNumValues,
  568. dwSyntaxID,
  569. fExplicit
  570. );
  571. CONTINUE_ON_FAILURE(hr);
  572. }
  573. error:
  574. RRETURN(hr);
  575. }
  576. HRESULT
  577. CPropertyCache::
  578. IISMarshallProperties(
  579. PMETADATA_RECORD * ppMetaDataRecords,
  580. PDWORD pdwMDNumDataEntries
  581. )
  582. {
  583. HRESULT hr = S_OK;
  584. DWORD i = 0;
  585. PPROPERTY pThisProperty = NULL;
  586. PMETADATA_RECORD pMetaDataArray = NULL;
  587. DWORD dwCount = 0;
  588. hr = LoadSchema();
  589. BAIL_ON_FAILURE(hr);
  590. pMetaDataArray = (PMETADATA_RECORD) AllocADsMem(
  591. _dwMaxProperties * sizeof(METADATA_RECORD));
  592. if (!pMetaDataArray ) {
  593. hr = E_OUTOFMEMORY;
  594. BAIL_ON_FAILURE(hr);
  595. }
  596. *ppMetaDataRecords = pMetaDataArray;
  597. for (i = 0; i < _dwMaxProperties ; i++) {
  598. pThisProperty = _pProperties + i;
  599. //
  600. // Bypass any property that has not been
  601. // modified
  602. //
  603. if (PROPERTY_FLAGS(pThisProperty) == 0 ||
  604. PROPERTY_FLAGS(pThisProperty) == CACHE_PROPERTY_CLEARED) {
  605. continue;
  606. }
  607. hr = MarshallIISSynIdToIIS(
  608. _pSchema,
  609. PROPERTY_SYNTAX(pThisProperty),
  610. PROPERTY_METAID(pThisProperty),
  611. PROPERTY_IISOBJECT(pThisProperty),
  612. PROPERTY_NUMVALUES(pThisProperty),
  613. pMetaDataArray
  614. );
  615. CONTINUE_ON_FAILURE(hr);
  616. pMetaDataArray++;
  617. dwCount++;
  618. }
  619. *pdwMDNumDataEntries = dwCount;
  620. error:
  621. RRETURN(hr);
  622. }
  623. //+------------------------------------------------------------------------
  624. //
  625. // Function: ~CPropertyCache
  626. //
  627. // Synopsis:
  628. //
  629. //
  630. //
  631. // Arguments:
  632. //
  633. //
  634. //-------------------------------------------------------------------------
  635. void
  636. CPropertyCache::
  637. flushpropcache()
  638. {
  639. DWORD i = 0;
  640. PPROPERTY pThisProperty = NULL;
  641. if (_pProperties) {
  642. for (i = 0; i < _dwMaxProperties; i++) {
  643. pThisProperty = _pProperties + i;
  644. if (PROPERTY_IISOBJECT(pThisProperty)) {
  645. IISTypeFreeIISObjects(
  646. PROPERTY_IISOBJECT(pThisProperty),
  647. PROPERTY_NUMVALUES(pThisProperty)
  648. );
  649. PROPERTY_IISOBJECT(pThisProperty) = NULL;
  650. }
  651. }
  652. FreeADsMem(_pProperties);
  653. }
  654. //
  655. // Reset the property cache
  656. //
  657. _pProperties = NULL;
  658. _dwMaxProperties = 0;
  659. _cb = 0;
  660. }
  661. BOOL
  662. CPropertyCache::
  663. index_valid(
  664. )
  665. {
  666. //
  667. // need to check separately since a negative DWORD is equal to +ve large #
  668. //
  669. if (_dwMaxProperties==0)
  670. return(FALSE);
  671. if (_dwCurrentIndex > _dwMaxProperties - 1)
  672. return(FALSE);
  673. else
  674. return(TRUE);
  675. }
  676. BOOL
  677. CPropertyCache::
  678. index_valid(
  679. DWORD dwIndex
  680. )
  681. {
  682. //
  683. // need to check separately since a negative DWORD is equal to +ve large #
  684. //
  685. if (_dwMaxProperties==0)
  686. return(FALSE);
  687. if (dwIndex > _dwMaxProperties - 1)
  688. return(FALSE);
  689. else
  690. return(TRUE);
  691. }
  692. void
  693. CPropertyCache::
  694. reset_propindex(
  695. )
  696. {
  697. _dwCurrentIndex = 0;
  698. }
  699. HRESULT
  700. CPropertyCache::
  701. skip_propindex(
  702. DWORD dwElements
  703. )
  704. {
  705. DWORD newIndex = _dwCurrentIndex + dwElements;
  706. if (!index_valid())
  707. RRETURN(E_ADS_BAD_PARAMETER);
  708. if (newIndex > _dwMaxProperties) {
  709. RRETURN(E_ADS_BAD_PARAMETER);
  710. }
  711. _dwCurrentIndex = newIndex;
  712. RRETURN(S_OK);
  713. }
  714. HRESULT
  715. CPropertyCache::
  716. get_PropertyCount(
  717. PDWORD pdwMaxProperties
  718. )
  719. {
  720. *pdwMaxProperties = _dwMaxProperties;
  721. RRETURN(S_OK);
  722. }
  723. DWORD
  724. CPropertyCache::
  725. get_CurrentIndex(
  726. )
  727. {
  728. return(_dwCurrentIndex);
  729. }
  730. LPWSTR
  731. CPropertyCache::
  732. get_CurrentPropName(
  733. )
  734. {
  735. PPROPERTY pThisProperty = NULL;
  736. if (!_dwMaxProperties) // if !_dwMaxProperties, pThisProperty=NULL, AV
  737. return NULL; // in PROPERTY_NAME(pThisProperty)
  738. if (!index_valid())
  739. return(PROPERTY_NAME(pThisProperty));
  740. pThisProperty = _pProperties + _dwCurrentIndex;
  741. return(PROPERTY_NAME(pThisProperty));
  742. }
  743. LPWSTR
  744. CPropertyCache::
  745. get_PropName(
  746. DWORD dwIndex
  747. )
  748. {
  749. PPROPERTY pThisProperty = NULL;
  750. if (!index_valid(dwIndex))
  751. return(NULL);
  752. pThisProperty = _pProperties + dwIndex;
  753. return(PROPERTY_NAME(pThisProperty));
  754. }
  755. HRESULT
  756. CPropertyCache::
  757. deleteproperty(
  758. DWORD dwIndex
  759. )
  760. {
  761. HRESULT hr = S_OK;
  762. PPROPERTY pNewProperties = NULL;
  763. PPROPERTY pThisProperty = _pProperties + dwIndex;
  764. if (!index_valid(dwIndex)) {
  765. hr = E_FAIL;
  766. BAIL_ON_FAILURE(hr);
  767. }
  768. if (_dwMaxProperties == 1) {
  769. //
  770. // Deleting everything
  771. //
  772. if (PROPERTY_IISOBJECT(pThisProperty)) {
  773. IISTypeFreeIISObjects(
  774. PROPERTY_IISOBJECT(pThisProperty),
  775. PROPERTY_NUMVALUES(pThisProperty)
  776. );
  777. PROPERTY_IISOBJECT(pThisProperty) = NULL;
  778. }
  779. FreeADsMem(_pProperties);
  780. _pProperties = NULL;
  781. _dwMaxProperties = 0;
  782. _cb = 0;
  783. RRETURN(hr);
  784. }
  785. pNewProperties = (PPROPERTY)AllocADsMem(
  786. _cb - sizeof(PROPERTY)
  787. );
  788. if (!pNewProperties) {
  789. hr = E_OUTOFMEMORY;
  790. BAIL_ON_FAILURE(hr);
  791. }
  792. //
  793. // Copying the memory before the deleted item
  794. //
  795. if (dwIndex != 0) {
  796. memcpy( pNewProperties,
  797. _pProperties,
  798. dwIndex * sizeof(PROPERTY));
  799. }
  800. //
  801. // Copying the memory following the deleted item
  802. //
  803. if (dwIndex != (_dwMaxProperties-1)) {
  804. memcpy( pNewProperties + dwIndex,
  805. _pProperties + dwIndex + 1,
  806. (_dwMaxProperties - dwIndex - 1) * sizeof(PROPERTY));
  807. }
  808. if (PROPERTY_IISOBJECT(pThisProperty)) {
  809. IISTypeFreeIISObjects(
  810. PROPERTY_IISOBJECT(pThisProperty),
  811. PROPERTY_NUMVALUES(pThisProperty)
  812. );
  813. PROPERTY_IISOBJECT(pThisProperty) = NULL;
  814. }
  815. FreeADsMem(_pProperties);
  816. _pProperties = pNewProperties;
  817. _dwMaxProperties--;
  818. _cb -= sizeof(PROPERTY);
  819. error:
  820. RRETURN(hr);
  821. }
  822. ////////////////////////////////////////////////////////////////////////
  823. //
  824. // IPropertyCache
  825. //
  826. HRESULT
  827. CPropertyCache::
  828. locateproperty(
  829. LPWSTR szPropertyName,
  830. PDWORD pdwDispid
  831. )
  832. {
  833. HRESULT hr;
  834. hr = DispatchLocateProperty(
  835. szPropertyName,
  836. pdwDispid
  837. );
  838. RRETURN(hr);
  839. }
  840. HRESULT
  841. CPropertyCache::
  842. putproperty(
  843. DWORD dwDispid,
  844. VARIANT varValue
  845. )
  846. {
  847. HRESULT hr;
  848. hr = DispatchPutProperty(
  849. dwDispid,
  850. varValue
  851. );
  852. RRETURN(hr);
  853. }
  854. HRESULT
  855. CPropertyCache::
  856. getproperty(
  857. DWORD dwDispid,
  858. VARIANT * pvarValue
  859. )
  860. {
  861. HRESULT hr;
  862. hr = DispatchGetProperty(
  863. dwDispid,
  864. pvarValue
  865. );
  866. RRETURN(hr);
  867. }
  868. ////////////////////////////////////////////////////////////////////////
  869. //
  870. // Dynamic Dispid Table
  871. //
  872. HRESULT
  873. CPropertyCache::
  874. DispatchFindProperty(
  875. LPWSTR szPropertyName,
  876. PDWORD pdwDispid
  877. )
  878. {
  879. DWORD i = 0;
  880. PDISPPROPERTY pDispProp = NULL;
  881. //
  882. // use ADs Error codes since this funct'n does not go directly into
  883. // the dispatch interface
  884. //
  885. if (!pdwDispid || !szPropertyName)
  886. RRETURN(E_ADS_BAD_PARAMETER);
  887. for (i=0; i<_dwDispMaxProperties; i++) {
  888. pDispProp = _pDispProperties + i;
  889. if (!_wcsicmp(DISPATCH_NAME(pDispProp), szPropertyName)) {
  890. *pdwDispid=i;
  891. RRETURN(S_OK);
  892. }
  893. }
  894. *pdwDispid = (DWORD)-1;
  895. RRETURN(E_ADS_PROPERTY_NOT_FOUND);
  896. }
  897. HRESULT
  898. CPropertyCache::
  899. DispatchAddProperty(
  900. LPWSTR szPropertyName,
  901. PDWORD pdwDispid /* optional */
  902. )
  903. {
  904. HRESULT hr = E_FAIL;
  905. DWORD dwDispid = (DWORD)-1;
  906. PDISPPROPERTY pNewDispProps = NULL;
  907. //
  908. // use ADs Error codes since this funct'n does not go directly into
  909. // the dispatch interface
  910. //
  911. if (!szPropertyName)
  912. RRETURN(E_ADS_BAD_PARAMETER);
  913. hr = DispatchFindProperty(
  914. szPropertyName,
  915. &dwDispid
  916. );
  917. if (hr==E_ADS_PROPERTY_NOT_FOUND) {
  918. //
  919. // increase the size of Dynamic Dispid Table by 1 property
  920. //
  921. pNewDispProps = (PDISPPROPERTY) ReallocADsMem(
  922. _pDispProperties,
  923. _cbDisp,
  924. _cbDisp + sizeof(DISPPROPERTY)
  925. );
  926. if (!pNewDispProps)
  927. BAIL_ON_FAILURE(hr=E_OUTOFMEMORY);
  928. //
  929. // must succeeded at this pt. okay to change table & indexes
  930. //
  931. _pDispProperties = pNewDispProps;
  932. wcscpy((_pDispProperties+_dwDispMaxProperties)->szPropertyName,
  933. szPropertyName);
  934. dwDispid = _dwDispMaxProperties++;
  935. _cbDisp += sizeof(DISPPROPERTY);
  936. hr = S_OK;
  937. }
  938. //
  939. // return valid, or invalid (-1) in case of failure, dispid of
  940. // szProperty iff asked for
  941. //
  942. if (pdwDispid)
  943. *pdwDispid = dwDispid;
  944. error:
  945. RRETURN(hr);
  946. }
  947. HRESULT
  948. CPropertyCache::
  949. DispatchLocateProperty(
  950. LPWSTR szPropertyName,
  951. PDWORD pdwDispid
  952. )
  953. {
  954. HRESULT hr;
  955. BSTR bstrClassName = NULL;
  956. //
  957. // - pdwDispid not optional here
  958. // - Use DISP_E_ERROR codes since this function directly called by
  959. // the dispatch manager
  960. //
  961. if (!pdwDispid || !szPropertyName)
  962. RRETURN(DISP_E_PARAMNOTOPTIONAL);
  963. hr = LoadSchema();
  964. BAIL_ON_FAILURE(hr);
  965. //
  966. // return dispid of property if already in table;
  967. //
  968. hr = DispatchFindProperty(
  969. szPropertyName,
  970. pdwDispid
  971. );
  972. if (hr==E_ADS_PROPERTY_NOT_FOUND) {
  973. //
  974. // check if property in schema
  975. // - this is necessary; otherwise, property not in schema will
  976. // be allowed to be added to cache and will not be given the
  977. // chance to be handled by 3rd party extension.
  978. // - note that property not in schema but added to the cache
  979. // thru' IADsProperty list will not be handled by 3rd
  980. // party extension either.
  981. //
  982. hr = _pCoreADsObject->get_CoreADsClass(&bstrClassName);
  983. BAIL_ON_FAILURE(hr);
  984. hr = _pSchema->ValidateProperty(bstrClassName, szPropertyName);
  985. BAIL_ON_FAILURE(hr);
  986. //
  987. // Add property that is in the schema but not in the cache to
  988. // the dynamic dispid table. That is, property which is in the
  989. // schema will always be handled by the cache/server thur ADSI but
  990. // will NOT be handled by 3rd party extension.
  991. //
  992. if (SUCCEEDED(hr)) {
  993. hr = DispatchAddProperty(
  994. szPropertyName,
  995. pdwDispid
  996. );
  997. BAIL_ON_FAILURE(hr);
  998. }
  999. //
  1000. // Property Not in the schema will nto be added to the dynamic
  1001. // dispid table and could be handled by 3rd party extension.
  1002. //
  1003. else {
  1004. hr = DISP_E_MEMBERNOTFOUND;
  1005. BAIL_ON_FAILURE(hr);
  1006. }
  1007. }
  1008. if (bstrClassName) {
  1009. ADsFreeString(bstrClassName);
  1010. }
  1011. RRETURN(hr);
  1012. error:
  1013. if (bstrClassName) {
  1014. ADsFreeString(bstrClassName);
  1015. }
  1016. *pdwDispid = (DWORD)DISPID_UNKNOWN;
  1017. RRETURN(hr);
  1018. }
  1019. /* INTRINSA suppress=null_pointers, uninitialized */
  1020. HRESULT
  1021. CPropertyCache::
  1022. DispatchGetProperty(
  1023. DWORD dwDispid,
  1024. VARIANT * pvarVal
  1025. )
  1026. {
  1027. HRESULT hr;
  1028. LPWSTR szPropName = NULL;
  1029. DWORD dwSyntaxId = (DWORD)-1;
  1030. DWORD dwSyntax;
  1031. DWORD dwNumValues = (DWORD)0;
  1032. PIISOBJECT pIISObjs = NULL;
  1033. WCHAR wchName[MAX_PATH];
  1034. hr = LoadSchema();
  1035. BAIL_ON_FAILURE(hr);
  1036. //
  1037. // Use DISP_E_ERROR codes since this function directly called by
  1038. // the dispatch manager
  1039. //
  1040. if (!pvarVal)
  1041. RRETURN(DISP_E_PARAMNOTOPTIONAL);
  1042. if (!DISPATCH_INDEX_VALID(dwDispid))
  1043. RRETURN(DISP_E_MEMBERNOTFOUND);
  1044. szPropName = DISPATCH_PROPERTY_NAME(dwDispid);
  1045. //
  1046. // lookup ADSI IIS syntax Id
  1047. //
  1048. hr = _pSchema->LookupSyntaxID(szPropName, &dwSyntax);
  1049. BAIL_ON_FAILURE(hr);
  1050. //
  1051. // check if property is BITMASK type;
  1052. // if BITMASK type, get corresponding DWORD flag property
  1053. //
  1054. if (dwSyntax == IIS_SYNTAX_ID_BOOL_BITMASK || dwSyntax == IIS_SYNTAX_ID_BINARY) {
  1055. hr = _pSchema->LookupFlagPropName(szPropName, (LPWSTR)wchName);
  1056. BAIL_ON_FAILURE(hr);
  1057. }
  1058. //
  1059. // return value in cache for szPropName; retrieve value from server
  1060. // if not already in cache; fail if none on sever
  1061. //
  1062. if (dwSyntax == IIS_SYNTAX_ID_BOOL_BITMASK || dwSyntax == IIS_SYNTAX_ID_BINARY)
  1063. {
  1064. hr = getproperty(
  1065. wchName,
  1066. &dwSyntaxId,
  1067. &dwNumValues,
  1068. &pIISObjs
  1069. );
  1070. }
  1071. else
  1072. {
  1073. hr = getproperty(
  1074. szPropName,
  1075. &dwSyntaxId,
  1076. &dwNumValues,
  1077. &pIISObjs
  1078. );
  1079. }
  1080. BAIL_ON_FAILURE(hr);
  1081. //
  1082. // reset it to its syntax id if BITMASK type
  1083. //
  1084. pIISObjs->IISType = dwSyntax;
  1085. //
  1086. // translate IIS objects into variants
  1087. //
  1088. //
  1089. // always return an array for multisz type
  1090. //
  1091. if (dwSyntax == IIS_SYNTAX_ID_BINARY)
  1092. {
  1093. hr = IISTypeToVarTypeCopy(
  1094. _pSchema,
  1095. szPropName,
  1096. pIISObjs,
  1097. pvarVal,
  1098. TRUE
  1099. );
  1100. }
  1101. else if (dwNumValues == 1 && dwSyntax != IIS_SYNTAX_ID_MULTISZ &&
  1102. dwSyntax != IIS_SYNTAX_ID_MIMEMAP ) {
  1103. hr = IISTypeToVarTypeCopy(
  1104. _pSchema,
  1105. szPropName,
  1106. pIISObjs,
  1107. pvarVal,
  1108. FALSE
  1109. );
  1110. } else {
  1111. hr = IISTypeToVarTypeCopyConstruct(
  1112. _pSchema,
  1113. szPropName,
  1114. pIISObjs,
  1115. dwNumValues,
  1116. pvarVal,
  1117. FALSE
  1118. );
  1119. }
  1120. BAIL_ON_FAILURE(hr);
  1121. error:
  1122. if (pIISObjs) {
  1123. IISTypeFreeIISObjects(
  1124. pIISObjs,
  1125. dwNumValues
  1126. );
  1127. }
  1128. if (FAILED(hr)) {
  1129. V_VT(pvarVal) = VT_ERROR;
  1130. }
  1131. RRETURN(hr);
  1132. }
  1133. HRESULT
  1134. CPropertyCache::
  1135. DispatchPutProperty(
  1136. DWORD dwDispid,
  1137. VARIANT& varVal
  1138. )
  1139. {
  1140. HRESULT hr;
  1141. DWORD dwSyntaxId = (DWORD)-1;
  1142. DWORD dwIndex = (DWORD)-1;
  1143. LPIISOBJECT pIISObjs = NULL;
  1144. DWORD dwNumValues = (DWORD)0;
  1145. VARIANT * pVarArray = NULL; // to be freed
  1146. VARIANT * pvProp = NULL; // do not free
  1147. VARIANT vVar;
  1148. WCHAR wchName[MAX_PATH];
  1149. LPWSTR szPropName = NULL;
  1150. hr = LoadSchema();
  1151. BAIL_ON_FAILURE(hr);
  1152. //
  1153. // Use DISP_E_ERROR codes since this function directly called by
  1154. // the dispatch manager
  1155. //
  1156. if (!DISPATCH_INDEX_VALID(dwDispid))
  1157. RRETURN(DISP_E_MEMBERNOTFOUND);
  1158. //
  1159. // retreive property name from Dynamic Dispatch Table
  1160. //
  1161. szPropName = DISPATCH_PROPERTY_NAME(dwDispid);
  1162. //
  1163. // lookup its syntax ID
  1164. //
  1165. hr = _pSchema->LookupSyntaxID(szPropName, &dwSyntaxId);
  1166. BAIL_ON_FAILURE(hr);
  1167. //
  1168. // Issue: How do we handle multi-valued support
  1169. //
  1170. VariantInit(&vVar);
  1171. hr = VariantCopyInd(&vVar, &varVal);
  1172. BAIL_ON_FAILURE(hr);
  1173. if (V_VT(&vVar) == VT_DISPATCH)
  1174. {
  1175. hr = ConvertDispatchToVariantArray(
  1176. vVar,
  1177. &pVarArray,
  1178. &dwNumValues
  1179. );
  1180. if (S_OK == hr) {
  1181. pvProp = pVarArray;
  1182. }
  1183. else {
  1184. // something went wrong converting to a variant array
  1185. // don't bail - just stuff it in as is
  1186. dwNumValues = 1;
  1187. pvProp = &vVar;
  1188. hr = S_OK;
  1189. }
  1190. }
  1191. else if ((V_VT(&vVar) & VT_VARIANT) && V_ISARRAY(&vVar)) {
  1192. hr = ConvertArrayToVariantArray(
  1193. vVar,
  1194. &pVarArray,
  1195. &dwNumValues
  1196. );
  1197. BAIL_ON_FAILURE(hr);
  1198. pvProp = pVarArray;
  1199. }
  1200. else {
  1201. dwNumValues = 1;
  1202. pvProp = &vVar;
  1203. }
  1204. //
  1205. // Variant Array to IIS Objects
  1206. //
  1207. hr = VarTypeToIISTypeCopyConstruct(
  1208. dwSyntaxId,
  1209. pvProp,
  1210. dwNumValues,
  1211. &pIISObjs,
  1212. FALSE
  1213. );
  1214. BAIL_ON_FAILURE(hr);
  1215. //
  1216. // check if property is BITMASK type;
  1217. // if BITMASK type, get corresponding DWORD flag property
  1218. //
  1219. if (dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK) {
  1220. DWORD dwMask;
  1221. DWORD dwFlagValue;
  1222. DWORD Temp;
  1223. LPIISOBJECT pIISObject = NULL;
  1224. hr = _pSchema->LookupBitMask(szPropName, &dwMask);
  1225. BAIL_ON_FAILURE(hr);
  1226. //
  1227. // get its corresponding DWORD flag value
  1228. //
  1229. hr = _pSchema->LookupFlagPropName(szPropName, (LPWSTR)wchName);
  1230. BAIL_ON_FAILURE(hr);
  1231. hr = getproperty(wchName,
  1232. &Temp,
  1233. &Temp,
  1234. &pIISObject);
  1235. BAIL_ON_FAILURE(hr);
  1236. dwFlagValue = pIISObject->IISValue.value_1.dwDWORD;
  1237. if (pIISObjs->IISValue.value_1.dwDWORD) {
  1238. dwFlagValue |= dwMask;
  1239. }
  1240. else {
  1241. dwFlagValue &= ~dwMask;
  1242. }
  1243. pIISObjs->IISValue.value_1.dwDWORD = dwFlagValue;
  1244. pIISObjs->IISType = IIS_SYNTAX_ID_DWORD;
  1245. szPropName = wchName;
  1246. if (pIISObject) {
  1247. IISTypeFreeIISObjects(
  1248. pIISObject,
  1249. 1
  1250. );
  1251. }
  1252. }
  1253. if (dwSyntaxId == IIS_SYNTAX_ID_BINARY) {
  1254. hr = _pSchema->LookupFlagPropName(szPropName, (LPWSTR)wchName);
  1255. BAIL_ON_FAILURE(hr);
  1256. szPropName = wchName;
  1257. }
  1258. //
  1259. // add the property to cache if not already in since DispatchAddProperty
  1260. // does not addproperty
  1261. //
  1262. hr = findproperty(
  1263. szPropName,
  1264. &dwIndex
  1265. );
  1266. if (FAILED(hr)) {
  1267. hr = addproperty(
  1268. szPropName,
  1269. dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK ?
  1270. IIS_SYNTAX_ID_DWORD : dwSyntaxId,
  1271. dwNumValues,
  1272. pIISObjs
  1273. );
  1274. BAIL_ON_FAILURE(hr);
  1275. }
  1276. //
  1277. // update property value in cache
  1278. //
  1279. hr = putproperty(
  1280. szPropName,
  1281. CACHE_PROPERTY_MODIFIED,
  1282. dwSyntaxId == IIS_SYNTAX_ID_BOOL_BITMASK ?
  1283. IIS_SYNTAX_ID_DWORD : dwSyntaxId,
  1284. dwNumValues,
  1285. pIISObjs
  1286. );
  1287. BAIL_ON_FAILURE(hr);
  1288. error:
  1289. if (pIISObjs) {
  1290. IISTypeFreeIISObjects(
  1291. pIISObjs,
  1292. dwNumValues
  1293. );
  1294. }
  1295. if (pVarArray) {
  1296. DWORD i = 0;
  1297. for (i = 0; i < dwNumValues; i++) {
  1298. VariantClear(pVarArray + i);
  1299. }
  1300. FreeADsMem(pVarArray);
  1301. }
  1302. VariantClear(&vVar);
  1303. RRETURN(hr);
  1304. }