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.

1183 lines
26 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 NW
  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-1996 KrishnaG Created.
  21. // cloned off NDS property cache code
  22. //
  23. //
  24. //----------------------------------------------------------------------------
  25. #include "nwcompat.hxx"
  26. #pragma hdrstop
  27. //+------------------------------------------------------------------------
  28. //
  29. // Function: CPropertyCache::addproperty
  30. //
  31. // Synopsis:
  32. //
  33. //
  34. //
  35. // Arguments: [szPropertyName] --
  36. // [vt] --
  37. // [vaData] --
  38. //
  39. //
  40. //-------------------------------------------------------------------------
  41. HRESULT
  42. CPropertyCache::
  43. addproperty(
  44. LPWSTR szPropertyName,
  45. DWORD dwSyntaxId,
  46. DWORD dwNumValues,
  47. PNTOBJECT pNtObject
  48. )
  49. {
  50. HRESULT hr = S_OK;
  51. PPROPERTY pNewProperty = NULL;
  52. LPWSTR tempString = NULL;
  53. //
  54. // Allocate the string first
  55. //
  56. tempString = AllocADsStr(szPropertyName);
  57. if (!tempString)
  58. BAIL_ON_FAILURE(hr=E_OUTOFMEMORY);
  59. //
  60. // extend the property cache by adding a new property entry
  61. //
  62. _pProperties = (PPROPERTY)ReallocADsMem(
  63. _pProperties,
  64. _cb,
  65. _cb + sizeof(PROPERTY)
  66. );
  67. if (!_pProperties) {
  68. hr = E_OUTOFMEMORY;
  69. BAIL_ON_FAILURE(hr);
  70. }
  71. pNewProperty = (PPROPERTY)((LPBYTE)_pProperties + _cb);
  72. if (pNewProperty->szPropertyName) {
  73. FreeADsStr(pNewProperty->szPropertyName);
  74. pNewProperty->szPropertyName = NULL;
  75. }
  76. //
  77. // Since the memory has already been allocated in tempString
  78. // just set the value/pointer now.
  79. //
  80. pNewProperty->szPropertyName = tempString;
  81. //
  82. // BugBug - add in the NDSOBJECT code
  83. //
  84. //
  85. // Update the index
  86. //
  87. _dwMaxProperties++;
  88. _cb += sizeof(PROPERTY);
  89. RRETURN(hr);
  90. error:
  91. if (tempString)
  92. FreeADsStr(tempString);
  93. NW_RRETURN_EXP_IF_ERR(hr);
  94. }
  95. //+------------------------------------------------------------------------
  96. //
  97. // Function: CPropertyCache::updateproperty
  98. //
  99. // Synopsis:
  100. //
  101. //
  102. //
  103. // Arguments: [szPropertyName] --
  104. // [vaData] --
  105. //
  106. //-------------------------------------------------------------------------
  107. HRESULT
  108. CPropertyCache::updateproperty(
  109. LPWSTR szPropertyName,
  110. DWORD dwSyntaxId,
  111. DWORD dwNumValues,
  112. PNTOBJECT pNtObject,
  113. BOOL fExplicit
  114. )
  115. {
  116. HRESULT hr;
  117. DWORD dwIndex;
  118. PNTOBJECT pNtTempObject = NULL;
  119. PPROPERTY pThisProperty = NULL;
  120. hr = findproperty(
  121. szPropertyName,
  122. &dwIndex
  123. );
  124. BAIL_ON_FAILURE(hr);
  125. pThisProperty = _pProperties + dwIndex;
  126. if (!fExplicit) {
  127. if (PROPERTY_IS_MODIFIED(pThisProperty)) {
  128. hr = S_OK;
  129. goto error;
  130. }
  131. }
  132. //
  133. // Factor in cases where object state is necessary to
  134. // decide on update.
  135. //
  136. if (PROPERTY_NTOBJECT(pThisProperty)) {
  137. NTTypeFreeNTObjects(
  138. PROPERTY_NTOBJECT(pThisProperty),
  139. PROPERTY_NUMVALUES(pThisProperty)
  140. );
  141. PROPERTY_NTOBJECT(pThisProperty) = NULL;
  142. }
  143. PROPERTY_SYNTAX(pThisProperty) = dwSyntaxId;
  144. PROPERTY_NUMVALUES(pThisProperty) = dwNumValues;
  145. hr = NtTypeCopyConstruct(
  146. pNtObject,
  147. dwNumValues,
  148. &pNtTempObject
  149. );
  150. BAIL_ON_FAILURE(hr);
  151. PROPERTY_NTOBJECT(pThisProperty) = pNtTempObject;
  152. PROPERTY_FLAGS(pThisProperty) &= ~CACHE_PROPERTY_MODIFIED;
  153. error:
  154. NW_RRETURN_EXP_IF_ERR(hr);
  155. }
  156. //+------------------------------------------------------------------------
  157. //
  158. // Function: CPropertyCache::findproperty
  159. //
  160. // Synopsis:
  161. //
  162. //
  163. //
  164. // Arguments: [szPropertyName] --
  165. // [pdwIndex] --
  166. //
  167. //-------------------------------------------------------------------------
  168. HRESULT
  169. CPropertyCache::findproperty(
  170. LPWSTR szPropertyName,
  171. PDWORD pdwIndex
  172. )
  173. {
  174. DWORD i = 0;
  175. PPROPERTY pThisProperty = NULL;
  176. for (i = 0; i < _dwMaxProperties; i++) {
  177. pThisProperty = _pProperties + i;
  178. if (!_wcsicmp(pThisProperty->szPropertyName, szPropertyName)) {
  179. *pdwIndex = i;
  180. RRETURN(S_OK);
  181. }
  182. }
  183. *pdwIndex = 0;
  184. NW_RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_FOUND);
  185. }
  186. //+------------------------------------------------------------------------
  187. //
  188. // Function: CPropertyCache::getproperty
  189. //
  190. // Synopsis:
  191. //
  192. //
  193. //
  194. // Arguments: [szPropertyName] -- Property to retrieve from the cache
  195. // [pvaData] -- Data returned in a variant
  196. //
  197. //-------------------------------------------------------------------------
  198. HRESULT
  199. CPropertyCache::
  200. getproperty(
  201. LPWSTR szPropertyName,
  202. PDWORD pdwSyntaxId,
  203. PDWORD pdwNumValues,
  204. PNTOBJECT * ppNtObject
  205. )
  206. {
  207. HRESULT hr;
  208. DWORD dwIndex = 0L;
  209. PPROPERTY pThisProperty = NULL;
  210. DWORD dwResult;
  211. DWORD dwInfoLevel = 0;
  212. hr = findproperty(
  213. szPropertyName,
  214. &dwIndex
  215. );
  216. if (hr == E_ADS_PROPERTY_NOT_FOUND) {
  217. hr = GetPropertyInfoLevel(
  218. szPropertyName,
  219. _pSchemaClassProps,
  220. _dwNumProperties,
  221. &dwInfoLevel
  222. );
  223. BAIL_ON_FAILURE(hr);
  224. //
  225. // Now call the GetInfo function
  226. //
  227. hr = _pCoreADsObject->GetInfo(
  228. dwInfoLevel,
  229. FALSE
  230. );
  231. BAIL_ON_FAILURE(hr);
  232. hr = findproperty(
  233. szPropertyName,
  234. &dwIndex
  235. );
  236. }
  237. BAIL_ON_FAILURE(hr);
  238. pThisProperty = _pProperties + dwIndex;
  239. if (PROPERTY_NTOBJECT(pThisProperty)) {
  240. *pdwSyntaxId = (DWORD)PROPERTY_SYNTAX(pThisProperty);
  241. *pdwNumValues = (DWORD)PROPERTY_NUMVALUES(pThisProperty);
  242. hr = NtTypeCopyConstruct(PROPERTY_NTOBJECT(pThisProperty),
  243. PROPERTY_NUMVALUES(pThisProperty),
  244. ppNtObject );
  245. BAIL_ON_FAILURE(hr);
  246. }else {
  247. *ppNtObject = NULL;
  248. *pdwNumValues = 0;
  249. *pdwSyntaxId = 0;
  250. hr = E_FAIL;
  251. }
  252. error:
  253. NW_RRETURN_EXP_IF_ERR(hr);
  254. }
  255. //+------------------------------------------------------------------------
  256. //
  257. // Function: CPropertyCache::marshallgetproperty
  258. //
  259. // Synopsis:
  260. //
  261. //
  262. //
  263. // Arguments: [szPropertyName] -- Property to retrieve from the cache
  264. // [pvaData] -- Data returned in a variant
  265. //
  266. //-------------------------------------------------------------------------
  267. HRESULT
  268. CPropertyCache::
  269. marshallgetproperty(
  270. LPWSTR szPropertyName,
  271. PDWORD pdwSyntaxId,
  272. PDWORD pdwNumValues,
  273. PNTOBJECT * ppNtObject
  274. )
  275. {
  276. HRESULT hr;
  277. DWORD dwIndex = 0L;
  278. PPROPERTY pThisProperty = NULL;
  279. DWORD dwResult;
  280. DWORD dwInfoLevel = 0;
  281. hr = findproperty(
  282. szPropertyName,
  283. &dwIndex
  284. );
  285. BAIL_ON_FAILURE(hr);
  286. pThisProperty = _pProperties + dwIndex;
  287. if (PROPERTY_NTOBJECT(pThisProperty)) {
  288. *pdwSyntaxId = (DWORD)PROPERTY_SYNTAX(pThisProperty);
  289. *pdwNumValues = (DWORD)PROPERTY_NUMVALUES(pThisProperty);
  290. hr = NtTypeCopyConstruct(PROPERTY_NTOBJECT(pThisProperty),
  291. PROPERTY_NUMVALUES(pThisProperty),
  292. ppNtObject );
  293. BAIL_ON_FAILURE(hr);
  294. }else {
  295. *ppNtObject = NULL;
  296. *pdwNumValues = 0;
  297. *pdwSyntaxId = 0;
  298. hr = E_FAIL;
  299. }
  300. error:
  301. NW_RRETURN_EXP_IF_ERR(hr);
  302. }
  303. //+------------------------------------------------------------------------
  304. //
  305. // Function: CPropertyCache::putproperty
  306. //
  307. // Synopsis:
  308. //
  309. //
  310. //
  311. // Arguments: [szPropertyName] -- Clsid index
  312. // [vaData] -- Matching clsid returned in *pclsid
  313. //
  314. //-------------------------------------------------------------------------
  315. HRESULT
  316. CPropertyCache::putproperty(
  317. LPWSTR szPropertyName,
  318. DWORD dwSyntaxId,
  319. DWORD dwNumValues,
  320. PNTOBJECT pNtObject
  321. )
  322. {
  323. HRESULT hr;
  324. DWORD dwIndex = 0L;
  325. PNTOBJECT pNtTempObject = NULL;
  326. PPROPERTY pThisProperty = NULL;
  327. hr = findproperty(
  328. szPropertyName,
  329. &dwIndex
  330. );
  331. BAIL_ON_FAILURE(hr);
  332. pThisProperty = _pProperties + dwIndex;
  333. //
  334. // AccountLocked is "half writable" -> need special care
  335. //
  336. if (_wcsicmp(szPropertyName, TEXT("IsAccountLocked"))==0 ) {
  337. if (pNtObject->NTType != NT_SYNTAX_ID_BOOL) {
  338. hr = E_ADS_BAD_PARAMETER;
  339. BAIL_ON_FAILURE(hr);
  340. }
  341. //
  342. // canNOT just disallow user to set cache to TRUE since
  343. // user may have accidentally set cache to FALSE (unlock) and
  344. // want to set the cache back to TRUE (do not unlock) without
  345. // GetInfo to affect other changes in cache. It will be a major
  346. // mistake if cuser cannot set the cache back to TRUE after
  347. // changing it to FALSE accidentally and thus unlocking the
  348. // account even if the user does not want to.
  349. //
  350. // If cache value on IsAccountLocked is changed from FALSE to TRUE,
  351. // cached value will be automatically changed back to FALSE upon
  352. // SetInfo since user cannot lock an account thru' ADSI. (NW server
  353. // wont' allow. Ref: SysCon)
  354. //
  355. // Should: If new value == value already in cache, do nothing.
  356. // That is, do not try to set the cache_property_modified flag.
  357. // This is to prevent
  358. // 1) the side effect of setting BadLogins to 0 when a
  359. // user set the cached property IsAccountLocked
  360. // from FALSE to FALSE (no change really) and call SetInfo.
  361. // 2) the side effect of changing the cache value to 0 (not
  362. // consistent with server or original cached value) when
  363. // a user set the cache property IsAccontLocked
  364. // from TRUE to TRUE (no change really) and call SetInfo.
  365. //
  366. // If user set IsAccountLocked from FALSE to TRUE and then
  367. // back to FALSE, or from TRUE to FALSE and then back to TURE,
  368. // side effect 1) or 2) will happen.
  369. // Both side effect not critical.
  370. //
  371. // We first check whether the object has been set previously, if not,
  372. // NTOBJECT will be NULL
  373. //
  374. if (PROPERTY_NTOBJECT(pThisProperty) &&
  375. (pNtObject->NTValue.fValue==
  376. PROPERTY_NTOBJECT(pThisProperty)->NTValue.fValue)) {
  377. RRETURN(S_OK);
  378. }
  379. }
  380. if (PROPERTY_NTOBJECT(pThisProperty)) {
  381. NTTypeFreeNTObjects(
  382. PROPERTY_NTOBJECT(pThisProperty),
  383. PROPERTY_NUMVALUES(pThisProperty)
  384. );
  385. PROPERTY_NTOBJECT(pThisProperty) = NULL;
  386. }
  387. PROPERTY_SYNTAX(pThisProperty) = dwSyntaxId;
  388. PROPERTY_NUMVALUES(pThisProperty) = dwNumValues;
  389. hr = NtTypeCopyConstruct(
  390. pNtObject,
  391. dwNumValues,
  392. &pNtTempObject
  393. );
  394. BAIL_ON_FAILURE(hr);
  395. PROPERTY_NTOBJECT(pThisProperty) = pNtTempObject;
  396. PROPERTY_FLAGS(pThisProperty) |= CACHE_PROPERTY_MODIFIED;
  397. error:
  398. NW_RRETURN_EXP_IF_ERR(hr);
  399. }
  400. //+------------------------------------------------------------------------
  401. //
  402. // Function: CPropertyCache
  403. //
  404. // Synopsis:
  405. //
  406. //
  407. //
  408. // Arguments:
  409. //
  410. //
  411. //-------------------------------------------------------------------------
  412. CPropertyCache::CPropertyCache():
  413. _pCoreADsObject(NULL),
  414. _pSchemaClassProps(NULL),
  415. _dwMaxProperties(0),
  416. _pProperties(NULL),
  417. _dwCurrentIndex(0),
  418. _cb(0)
  419. {
  420. }
  421. //+------------------------------------------------------------------------
  422. //
  423. // Function: ~CPropertyCache
  424. //
  425. // Synopsis:
  426. //
  427. //
  428. //
  429. // Arguments:
  430. //
  431. //
  432. //-------------------------------------------------------------------------
  433. CPropertyCache::
  434. ~CPropertyCache()
  435. {
  436. DWORD i = 0;
  437. PPROPERTY pThisProperty = NULL;
  438. if (_pProperties) {
  439. for (i = 0; i < _dwMaxProperties; i++) {
  440. pThisProperty = _pProperties + i;
  441. if (pThisProperty->szPropertyName) {
  442. FreeADsStr(pThisProperty->szPropertyName);
  443. pThisProperty->szPropertyName = NULL;
  444. }
  445. if (PROPERTY_NTOBJECT(pThisProperty)) {
  446. NTTypeFreeNTObjects(
  447. PROPERTY_NTOBJECT(pThisProperty),
  448. PROPERTY_NUMVALUES(pThisProperty)
  449. );
  450. PROPERTY_NTOBJECT(pThisProperty) = NULL;
  451. }
  452. }
  453. FreeADsMem(_pProperties);
  454. }
  455. }
  456. //+------------------------------------------------------------------------
  457. //
  458. // Function:
  459. //
  460. // Synopsis:
  461. //
  462. //
  463. //
  464. // Arguments:
  465. //
  466. //
  467. //-------------------------------------------------------------------------
  468. HRESULT
  469. CPropertyCache::
  470. createpropertycache(
  471. PPROPERTYINFO pSchemaClassProps,
  472. DWORD dwNumProperties,
  473. CCoreADsObject FAR * pCoreADsObject,
  474. CPropertyCache FAR *FAR * ppPropertyCache
  475. )
  476. {
  477. CPropertyCache FAR * pPropertyCache = NULL;
  478. pPropertyCache = new CPropertyCache();
  479. if (!pPropertyCache) {
  480. NW_RRETURN_EXP_IF_ERR(E_OUTOFMEMORY);
  481. }
  482. pPropertyCache->_pCoreADsObject = pCoreADsObject;
  483. pPropertyCache->_pSchemaClassProps = pSchemaClassProps;
  484. pPropertyCache->_dwNumProperties = dwNumProperties;
  485. *ppPropertyCache = pPropertyCache;
  486. RRETURN(S_OK);
  487. }
  488. //+------------------------------------------------------------------------
  489. //
  490. // Function:
  491. //
  492. // Synopsis:
  493. //
  494. //
  495. //
  496. // Arguments:
  497. //
  498. //
  499. //-------------------------------------------------------------------------
  500. HRESULT
  501. CPropertyCache::
  502. unmarshallproperty(
  503. LPWSTR szPropertyName,
  504. LPBYTE lpValue,
  505. DWORD dwNumValues,
  506. DWORD dwSyntaxId,
  507. BOOL fExplicit
  508. )
  509. {
  510. DWORD dwIndex = 0;
  511. HRESULT hr = S_OK;
  512. PNTOBJECT pNTObject = NULL;
  513. hr = UnMarshallNTToNTSynId(
  514. dwSyntaxId,
  515. dwNumValues,
  516. lpValue,
  517. &pNTObject
  518. );
  519. BAIL_ON_FAILURE(hr);
  520. //
  521. // Find this property in the cache
  522. //
  523. hr = findproperty(
  524. szPropertyName,
  525. &dwIndex
  526. );
  527. //
  528. // If this property does not exist in the
  529. // cache, add this property into the cache.
  530. //
  531. if (FAILED(hr)) {
  532. hr = addproperty(
  533. szPropertyName,
  534. dwSyntaxId,
  535. dwNumValues,
  536. pNTObject
  537. );
  538. //
  539. // If the operation fails for some reason
  540. // move on to the next property
  541. //
  542. BAIL_ON_FAILURE(hr);
  543. }
  544. //
  545. // Now update the property in the cache
  546. //
  547. hr = updateproperty(
  548. szPropertyName,
  549. dwSyntaxId,
  550. dwNumValues,
  551. pNTObject,
  552. fExplicit
  553. );
  554. BAIL_ON_FAILURE(hr);
  555. if (pNTObject) {
  556. NTTypeFreeNTObjects(
  557. pNTObject,
  558. dwNumValues
  559. );
  560. }
  561. error:
  562. NW_RRETURN_EXP_IF_ERR(hr);
  563. }
  564. HRESULT
  565. ValidatePropertyinSchemaClass(
  566. PPROPERTYINFO pSchemaClassProps,
  567. DWORD dwNumProperties,
  568. LPWSTR pszPropName,
  569. PDWORD pdwSyntaxId
  570. )
  571. {
  572. DWORD i = 0;
  573. PPROPERTYINFO pThisSchProperty = NULL;
  574. for (i = 0; i < dwNumProperties; i++) {
  575. pThisSchProperty = (pSchemaClassProps + i);
  576. if (!_wcsicmp(pszPropName, pThisSchProperty->szPropertyName)) {
  577. *pdwSyntaxId = pThisSchProperty->dwSyntaxId;
  578. RRETURN (S_OK);
  579. }
  580. }
  581. RRETURN(E_ADS_SCHEMA_VIOLATION);
  582. }
  583. HRESULT
  584. ValidateIfWriteableProperty(
  585. PPROPERTYINFO pSchemaClassProps,
  586. DWORD dwNumProperties,
  587. LPWSTR pszPropName
  588. )
  589. {
  590. DWORD i = 0;
  591. PPROPERTYINFO pThisSchProperty = NULL;
  592. for (i = 0; i < dwNumProperties; i++) {
  593. pThisSchProperty = (pSchemaClassProps + i);
  594. if (!_wcsicmp(pszPropName, pThisSchProperty->szPropertyName)) {
  595. RRETURN((pThisSchProperty->dwFlags & PROPERTY_WRITEABLE)
  596. ? S_OK : E_ADS_SCHEMA_VIOLATION);
  597. }
  598. }
  599. RRETURN(E_ADS_SCHEMA_VIOLATION);
  600. // for winnt & nw312, return E_ADS_SCHEMA_VIOLATION if not ok even
  601. // attempt to write to cache only
  602. }
  603. HRESULT
  604. GetPropertyInfoLevel(
  605. LPWSTR pszPropName,
  606. PPROPERTYINFO pSchemaClassProps,
  607. DWORD dwNumProperties,
  608. PDWORD pdwInfoLevel
  609. )
  610. {
  611. DWORD i = 0;
  612. PPROPERTYINFO pThisSchProperty = NULL;
  613. for (i = 0; i < dwNumProperties; i++) {
  614. pThisSchProperty = (pSchemaClassProps + i);
  615. if (!_wcsicmp(pszPropName, pThisSchProperty->szPropertyName)) {
  616. *pdwInfoLevel = pThisSchProperty->dwInfoLevel;
  617. RRETURN(S_OK);
  618. }
  619. }
  620. //
  621. // Returning E_ADS_PROPERTY_NOT_FOUND so that implicit
  622. // GetInfo fails gracefully
  623. //
  624. NW_RRETURN_EXP_IF_ERR(E_ADS_PROPERTY_NOT_FOUND);
  625. }
  626. //+------------------------------------------------------------------------
  627. //
  628. // Function: ~CPropertyCache
  629. //
  630. // Synopsis:
  631. //
  632. //
  633. //
  634. // Arguments:
  635. //
  636. //
  637. //-------------------------------------------------------------------------
  638. void
  639. CPropertyCache::
  640. flushpropcache()
  641. {
  642. DWORD i = 0;
  643. PPROPERTY pThisProperty = NULL;
  644. if (_pProperties) {
  645. for (i = 0; i < _dwMaxProperties; i++) {
  646. pThisProperty = _pProperties + i;
  647. if (pThisProperty->szPropertyName) {
  648. FreeADsStr(pThisProperty->szPropertyName);
  649. pThisProperty->szPropertyName = NULL;
  650. }
  651. if (PROPERTY_NTOBJECT(pThisProperty)) {
  652. NTTypeFreeNTObjects(
  653. PROPERTY_NTOBJECT(pThisProperty),
  654. PROPERTY_NUMVALUES(pThisProperty)
  655. );
  656. PROPERTY_NTOBJECT(pThisProperty) = NULL;
  657. }
  658. }
  659. FreeADsMem(_pProperties);
  660. }
  661. //
  662. // Reset the property cache
  663. //
  664. _pProperties = NULL;
  665. _dwMaxProperties = 0;
  666. _cb = 0;
  667. }
  668. //+------------------------------------------------------------------------
  669. //
  670. // Function: CPropertyCache::getproperty
  671. //
  672. // Synopsis:
  673. //
  674. //
  675. //
  676. // Arguments: [szPropertyName] -- Property to retrieve from the cache
  677. // [pvaData] -- Data returned in a variant
  678. //
  679. //-------------------------------------------------------------------------
  680. HRESULT
  681. CPropertyCache::
  682. unboundgetproperty(
  683. LPWSTR szPropertyName,
  684. PDWORD pdwSyntaxId,
  685. PDWORD pdwNumValues,
  686. PNTOBJECT * ppNtObject
  687. )
  688. {
  689. HRESULT hr;
  690. DWORD dwIndex = 0L;
  691. PPROPERTY pThisProperty = NULL;
  692. hr = findproperty(
  693. szPropertyName,
  694. &dwIndex
  695. );
  696. BAIL_ON_FAILURE(hr);
  697. pThisProperty = _pProperties + dwIndex;
  698. if (PROPERTY_NTOBJECT(pThisProperty)) {
  699. *pdwSyntaxId = (DWORD)PROPERTY_SYNTAX(pThisProperty);
  700. *pdwNumValues = (DWORD)PROPERTY_NUMVALUES(pThisProperty);
  701. hr = NtTypeCopyConstruct(
  702. PROPERTY_NTOBJECT(pThisProperty),
  703. PROPERTY_NUMVALUES(pThisProperty),
  704. ppNtObject
  705. );
  706. BAIL_ON_FAILURE(hr);
  707. }else {
  708. *ppNtObject = NULL;
  709. *pdwNumValues = 0;
  710. *pdwSyntaxId = 0;
  711. hr = E_FAIL;
  712. }
  713. error:
  714. NW_RRETURN_EXP_IF_ERR(hr);
  715. }
  716. //+------------------------------------------------------------------------
  717. //
  718. // Function: CPropertyCache::getproperty
  719. //
  720. // Synopsis:
  721. //
  722. //
  723. //
  724. // Arguments: [szPropertyName] -- Property to retrieve from the cache
  725. // [pvaData] -- Data returned in a variant
  726. //
  727. //-------------------------------------------------------------------------
  728. HRESULT
  729. CPropertyCache::
  730. unboundgetproperty(
  731. DWORD dwIndex,
  732. PDWORD pdwSyntaxId,
  733. PDWORD pdwNumValues,
  734. PNTOBJECT * ppNtObject
  735. )
  736. {
  737. HRESULT hr;
  738. PPROPERTY pThisProperty = NULL;
  739. if (!index_valid(dwIndex)) {
  740. RRETURN(E_ADS_BAD_PARAMETER); // better if E_ADS_INDEX or sth
  741. }
  742. pThisProperty = _pProperties + dwIndex;
  743. if (PROPERTY_NTOBJECT(pThisProperty)) {
  744. *pdwSyntaxId = (DWORD)PROPERTY_SYNTAX(pThisProperty);
  745. *pdwNumValues = (DWORD)PROPERTY_NUMVALUES(pThisProperty);
  746. hr = NtTypeCopyConstruct(
  747. PROPERTY_NTOBJECT(pThisProperty),
  748. PROPERTY_NUMVALUES(pThisProperty),
  749. ppNtObject
  750. );
  751. BAIL_ON_FAILURE(hr);
  752. }else {
  753. *ppNtObject = NULL;
  754. *pdwNumValues = 0;
  755. *pdwSyntaxId = 0;
  756. hr = E_FAIL;
  757. }
  758. error:
  759. NW_RRETURN_EXP_IF_ERR(hr);
  760. }
  761. BOOL
  762. CPropertyCache::
  763. index_valid(
  764. )
  765. {
  766. // _dwMaxProperties =0 -> dwMaxProperties -1 = -1 -> converted to
  767. // unsigned during comparision with unsigned _dwCurrentIndex ->
  768. // comparision does not work. So need to check if _dwMaxProperties==0 1st
  769. if (_dwMaxProperties ==0)
  770. return (FALSE);
  771. if (_dwCurrentIndex < 0 || _dwCurrentIndex > _dwMaxProperties - 1)
  772. return(FALSE);
  773. else
  774. return(TRUE);
  775. }
  776. BOOL
  777. CPropertyCache::
  778. index_valid(
  779. DWORD dwIndex
  780. )
  781. {
  782. // _dwMaxProperties =0 -> dwMaxProperties -1 = -1 -> converted to
  783. // unsigned during comparision with unsigned _dwCurrentIndex ->
  784. // comparision does not work. So need to check if _dwMaxProperties==0 1st
  785. if (_dwMaxProperties ==0)
  786. return (FALSE);
  787. if (dwIndex < 0 || dwIndex > _dwMaxProperties - 1)
  788. return(FALSE);
  789. else
  790. return(TRUE);
  791. }
  792. void
  793. CPropertyCache::
  794. reset_propindex(
  795. )
  796. {
  797. _dwCurrentIndex = 0;
  798. }
  799. HRESULT
  800. CPropertyCache::
  801. skip_propindex(
  802. DWORD dwElements
  803. )
  804. {
  805. DWORD newIndex = _dwCurrentIndex + dwElements;
  806. if (!index_valid() || !_dwMaxProperties)
  807. NW_RRETURN_EXP_IF_ERR(E_FAIL);
  808. //
  809. // BugBug it will be better to return IndexOutOfRange or something like that
  810. //
  811. if (_dwCurrentIndex < 0 || _dwCurrentIndex > _dwMaxProperties-1)
  812. NW_RRETURN_EXP_IF_ERR(E_FAIL);
  813. if ( newIndex < 0 || newIndex > _dwMaxProperties )
  814. NW_RRETURN_EXP_IF_ERR(E_FAIL);
  815. _dwCurrentIndex = newIndex;
  816. RRETURN(S_OK);
  817. }
  818. HRESULT
  819. CPropertyCache::
  820. get_PropertyCount(
  821. PDWORD pdwMaxProperties
  822. )
  823. {
  824. *pdwMaxProperties = _dwMaxProperties;
  825. RRETURN(S_OK);
  826. }
  827. DWORD
  828. CPropertyCache::
  829. get_CurrentIndex(
  830. )
  831. {
  832. return(_dwCurrentIndex);
  833. }
  834. LPWSTR
  835. CPropertyCache::
  836. get_CurrentPropName(
  837. )
  838. {
  839. PPROPERTY pThisProperty = NULL;
  840. if (!index_valid())
  841. return(PROPERTY_NAME(pThisProperty));
  842. pThisProperty = _pProperties + _dwCurrentIndex;
  843. return(PROPERTY_NAME(pThisProperty));
  844. }
  845. LPWSTR
  846. CPropertyCache::
  847. get_PropName(
  848. DWORD dwIndex
  849. )
  850. {
  851. PPROPERTY pThisProperty = NULL;
  852. if (!index_valid(dwIndex))
  853. return(NULL);
  854. pThisProperty = _pProperties + dwIndex;
  855. return(PROPERTY_NAME(pThisProperty));
  856. }
  857. HRESULT
  858. CPropertyCache::
  859. deleteproperty(
  860. DWORD dwIndex
  861. )
  862. {
  863. HRESULT hr = S_OK;
  864. PPROPERTY pNewProperties = NULL;
  865. PPROPERTY pThisProperty = _pProperties + dwIndex;
  866. if (!index_valid(dwIndex)) {
  867. RRETURN(E_ADS_BAD_PARAMETER);
  868. }
  869. if (_dwMaxProperties == 1) {
  870. //
  871. // Deleting everything
  872. //
  873. if (PROPERTY_NTOBJECT(pThisProperty)) {
  874. NTTypeFreeNTObjects(
  875. PROPERTY_NTOBJECT(pThisProperty),
  876. PROPERTY_NUMVALUES(pThisProperty)
  877. );
  878. PROPERTY_NTOBJECT(pThisProperty) = NULL;
  879. }
  880. FreeADsMem(_pProperties);
  881. _pProperties = NULL;
  882. _dwMaxProperties = 0;
  883. _cb = 0;
  884. RRETURN(hr);
  885. }
  886. pNewProperties = (PPROPERTY)AllocADsMem(
  887. _cb - sizeof(PROPERTY)
  888. );
  889. if (!pNewProperties) {
  890. hr = E_OUTOFMEMORY;
  891. BAIL_ON_FAILURE(hr);
  892. }
  893. //
  894. // Copying the memory before the deleted item
  895. //
  896. if (dwIndex != 0) {
  897. memcpy( pNewProperties,
  898. _pProperties,
  899. dwIndex * sizeof(PROPERTY));
  900. }
  901. //
  902. // Copying the memory following the deleted item
  903. //
  904. if (dwIndex != (_dwMaxProperties-1)) {
  905. memcpy( pNewProperties + dwIndex,
  906. _pProperties + dwIndex + 1,
  907. (_dwMaxProperties - dwIndex - 1) * sizeof(PROPERTY));
  908. }
  909. if (PROPERTY_NTOBJECT(pThisProperty)) {
  910. NTTypeFreeNTObjects(
  911. PROPERTY_NTOBJECT(pThisProperty),
  912. PROPERTY_NUMVALUES(pThisProperty)
  913. );
  914. PROPERTY_NTOBJECT(pThisProperty) = NULL;
  915. }
  916. FreeADsMem(_pProperties);
  917. _pProperties = pNewProperties;
  918. _dwMaxProperties--;
  919. _cb -= sizeof(PROPERTY);
  920. error:
  921. NW_RRETURN_EXP_IF_ERR(hr);
  922. }
  923. HRESULT
  924. CPropertyCache::
  925. propertyismodified(
  926. LPWSTR szPropertyName,
  927. BOOL * pfModified
  928. )
  929. {
  930. HRESULT hr;
  931. DWORD dwIndex = 0L;
  932. PPROPERTY pThisProperty = NULL;
  933. if (!szPropertyName || !pfModified) {
  934. RRETURN(E_ADS_BAD_PARAMETER);
  935. }
  936. hr = findproperty(
  937. szPropertyName,
  938. &dwIndex
  939. );
  940. BAIL_ON_FAILURE(hr);
  941. pThisProperty = _pProperties + dwIndex;
  942. *pfModified=PROPERTY_IS_MODIFIED(pThisProperty);
  943. error:
  944. RRETURN(hr);
  945. }