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.

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