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.

2757 lines
83 KiB

  1. /////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // PropList.cpp
  7. //
  8. // Description:
  9. // Implementation of the CClusPropList class.
  10. //
  11. // Author:
  12. // <name> (<e-mail name>) Mmmm DD, 2002
  13. //
  14. // Revision History:
  15. //
  16. // Notes:
  17. //
  18. /////////////////////////////////////////////////////////////////////////////
  19. #include "stdafx.h"
  20. #include "PropList.h"
  21. #ifdef _DEBUG
  22. #ifdef __AFX_H__
  23. #define new DEBUG_NEW
  24. #undef THIS_FILE
  25. static char THIS_FILE[] = __FILE__;
  26. #endif // __AFX_H__
  27. #endif
  28. #ifndef __AFX_H__
  29. class CMemoryException
  30. {
  31. public:
  32. void Delete( void ) { }
  33. }; //*** class CMemoryException
  34. #endif // __AFX_H__
  35. /////////////////////////////////////////////////////////////////////////////
  36. // Constant Definitions
  37. /////////////////////////////////////////////////////////////////////////////
  38. const int BUFFER_GROWTH_FACTOR = 256;
  39. /////////////////////////////////////////////////////////////////////////////
  40. //++
  41. //
  42. // CchMultiSz
  43. //
  44. // Description:
  45. // Length of all of the substrings of a multisz string minus the final NULL.
  46. //
  47. // (i.e., includes the nulls of the substrings, excludes the final null)
  48. // multiszlen( "abcd\0efgh\0\0" => 5 + 5 = 10
  49. //
  50. // Arguments:
  51. // psz [IN] The string to get the length of.
  52. //
  53. // Return Value:
  54. // Count of characters in the multisz or 0 if empty.
  55. //
  56. //--
  57. /////////////////////////////////////////////////////////////////////////////
  58. static DWORD CchMultiSz(
  59. IN LPCWSTR psz
  60. )
  61. {
  62. ASSERT( psz != NULL );
  63. DWORD _cchTotal = 0;
  64. DWORD _cchChars;
  65. while ( *psz != _T( '\0' ) )
  66. {
  67. _cchChars = lstrlenW( psz ) + 1;
  68. _cchTotal += _cchChars;
  69. psz += _cchChars;
  70. } // while: pointer not stopped on EOS
  71. return _cchTotal;
  72. } //*** CchMultiSz
  73. /////////////////////////////////////////////////////////////////////////////
  74. //++
  75. //
  76. // NCompareMultiSz
  77. //
  78. // Description:
  79. // Compare two MULTI_SZ buffers.
  80. //
  81. // Arguments:
  82. // pszSource [IN] The source string.
  83. // pszTarget [IN] The target string.
  84. //
  85. // Return Value:
  86. // If the string pointed to by pszSource is less than the string pointed
  87. // to by pszTarget, the return value is negative. If the string pointed
  88. // to by pszSource is greater than the string pointed to by pszTarget,
  89. // the return value is positive. If the strings are equal, the return value
  90. // is zero.
  91. //
  92. //--
  93. /////////////////////////////////////////////////////////////////////////////
  94. static int NCompareMultiSz(
  95. IN LPCWSTR pszSource,
  96. IN LPCWSTR pszTarget
  97. )
  98. {
  99. ASSERT( pszSource != NULL );
  100. ASSERT( pszTarget != NULL );
  101. while ( ( *pszSource != L'\0' ) && ( *pszTarget != L'\0') )
  102. {
  103. //
  104. // Move to end of strings.
  105. //
  106. while ( ( *pszSource != L'\0' ) && ( *pszTarget != L'\0') && ( *pszSource == *pszTarget ) )
  107. {
  108. ++pszSource;
  109. ++pszTarget;
  110. } // while: pointer not stopped on EOS
  111. //
  112. // If strings are the same, skip past terminating NUL.
  113. // Otherwise exit the loop.
  114. if ( ( *pszSource == L'\0' ) && ( *pszTarget == L'\0') )
  115. {
  116. ++pszSource;
  117. ++pszTarget;
  118. } // if: both stopped on EOS
  119. else
  120. {
  121. break;
  122. } // else: stopped because something is not equal -- wr are done.
  123. } // while: pointer not stopped on EOS
  124. return *pszSource - *pszTarget;
  125. } //*** NCompareMultiSz()
  126. //*************************************************************************//
  127. /////////////////////////////////////////////////////////////////////////////
  128. // CClusPropValueList class
  129. /////////////////////////////////////////////////////////////////////////////
  130. #ifdef __AFX_H__
  131. IMPLEMENT_DYNAMIC( CClusPropValueList, CObject );
  132. #endif // __AFX_H__
  133. /////////////////////////////////////////////////////////////////////////////
  134. //++
  135. //
  136. // CClusPropValueList::ScMoveToFirstValue
  137. //
  138. // Description:
  139. // Move the cursor to the first value in the value list.
  140. //
  141. // Arguments:
  142. // None.
  143. //
  144. // Return Value:
  145. // ERROR_SUCCESS Position moved to the first value successfully.
  146. //
  147. //--
  148. /////////////////////////////////////////////////////////////////////////////
  149. DWORD CClusPropValueList::ScMoveToFirstValue( void )
  150. {
  151. ASSERT( m_cbhValueList.pb != NULL );
  152. DWORD _sc;
  153. m_cbhCurrentValue = m_cbhValueList;
  154. m_cbDataLeft = m_cbDataSize;
  155. m_bAtEnd = FALSE;
  156. if ( m_cbhCurrentValue.pSyntax->dw == CLUSPROP_SYNTAX_ENDMARK )
  157. {
  158. _sc = ERROR_NO_MORE_ITEMS;
  159. } // if: no items in the value list
  160. else
  161. {
  162. _sc = ERROR_SUCCESS;
  163. } // else: items exist in the value list
  164. return _sc;
  165. } //*** CClusPropValueList::ScMoveToFirstValue()
  166. /////////////////////////////////////////////////////////////////////////////
  167. //++
  168. //
  169. // CClusPropValueList::ScMoveToNextValue
  170. //
  171. // Description:
  172. // Move the cursor to the next value in the list.
  173. //
  174. // Arguments:
  175. // None.
  176. //
  177. // Return Value:
  178. // ERROR_SUCCESS Position moved to the next value successfully.
  179. // ERROR_NO_MORE_ITEMS Already at the end of the list.
  180. // ERROR_INVALID_DATA Not enough data in the buffer.
  181. //
  182. //--
  183. /////////////////////////////////////////////////////////////////////////////
  184. DWORD CClusPropValueList::ScMoveToNextValue( void )
  185. {
  186. ASSERT( m_cbhCurrentValue.pb != NULL );
  187. DWORD _sc = ERROR_NO_MORE_ITEMS;
  188. DWORD _cbDataSize;
  189. CLUSPROP_BUFFER_HELPER _cbhCurrentValue;
  190. _cbhCurrentValue = m_cbhCurrentValue;
  191. do
  192. {
  193. //
  194. // Don't try to move if we're already at the end.
  195. //
  196. if ( m_bAtEnd )
  197. {
  198. break;
  199. } // if: already at the end of the list
  200. //
  201. // Make sure the buffer is big enough for the value header.
  202. //
  203. if ( m_cbDataLeft < sizeof( *_cbhCurrentValue.pValue ) )
  204. {
  205. _sc = ERROR_INVALID_DATA;
  206. break;
  207. } // if: not enough data left
  208. //
  209. // Calculate how much to advance buffer pointer.
  210. //
  211. _cbDataSize = sizeof( *_cbhCurrentValue.pValue )
  212. + ALIGN_CLUSPROP( _cbhCurrentValue.pValue->cbLength );
  213. //
  214. // Make sure the buffer is big enough for the value header,
  215. // the data itself, and the endmark.
  216. //
  217. if ( m_cbDataLeft < _cbDataSize + sizeof( CLUSPROP_SYNTAX ) )
  218. {
  219. _sc = ERROR_INVALID_DATA;
  220. break;
  221. } // if: not enough data left
  222. //
  223. // Move past the current value to the next value's syntax.
  224. //
  225. _cbhCurrentValue.pb += _cbDataSize;
  226. //
  227. // This test will ensure that the value is always valid since we won't
  228. // advance if the next thing is the endmark.
  229. //
  230. if ( _cbhCurrentValue.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK )
  231. {
  232. m_cbhCurrentValue = _cbhCurrentValue;
  233. m_cbDataLeft -= _cbDataSize;
  234. _sc = ERROR_SUCCESS;
  235. } // if: next value's syntax is not the endmark
  236. else
  237. {
  238. m_bAtEnd = TRUE;
  239. } // else: next value's syntax is the endmark
  240. } while ( 0 );
  241. return _sc;
  242. } //*** CClusPropValueList::ScMoveToNextValue()
  243. /////////////////////////////////////////////////////////////////////////////
  244. //++
  245. //
  246. // CClusPropValueList::ScCheckIfAtLastValue
  247. //
  248. // Description:
  249. // Indicate whether we are on the last value in the list or not.
  250. //
  251. // Arguments:
  252. // None.
  253. //
  254. // Return Value:
  255. // ERROR_SUCCESS Not currently at the last value in the list.
  256. // ERROR_NO_MORE_ITEMS Currently at the last value in the list.
  257. // ERROR_INVALID_DATA Not enough data in the buffer.
  258. //
  259. //--
  260. /////////////////////////////////////////////////////////////////////////////
  261. DWORD CClusPropValueList::ScCheckIfAtLastValue( void )
  262. {
  263. ASSERT( m_cbhCurrentValue.pb != NULL );
  264. DWORD _sc = ERROR_SUCCESS;
  265. CLUSPROP_BUFFER_HELPER _cbhCurrentValue;
  266. DWORD _cbDataSize;
  267. _cbhCurrentValue = m_cbhCurrentValue;
  268. do
  269. {
  270. //
  271. // Don't try to recalculate if we already know
  272. // we're at the end of the list.
  273. //
  274. if ( m_bAtEnd )
  275. {
  276. break;
  277. } // if: already at the end of the list
  278. //
  279. // Make sure the buffer is big enough for the value header.
  280. //
  281. if ( m_cbDataLeft < sizeof( *_cbhCurrentValue.pValue ) )
  282. {
  283. _sc = ERROR_INVALID_DATA;
  284. break;
  285. } // if: not enough data left
  286. //
  287. // Calculate how much to advance buffer pointer.
  288. //
  289. _cbDataSize = sizeof( *_cbhCurrentValue.pValue )
  290. + ALIGN_CLUSPROP( _cbhCurrentValue.pValue->cbLength );
  291. //
  292. // Make sure the buffer is big enough for the value header,
  293. // the data itself, and the endmark.
  294. //
  295. if ( m_cbDataLeft < _cbDataSize + sizeof( CLUSPROP_SYNTAX ) )
  296. {
  297. _sc = ERROR_INVALID_DATA;
  298. break;
  299. } // if: not enough data left
  300. //
  301. // Move past the current value to the next value's syntax.
  302. //
  303. _cbhCurrentValue.pb += _cbDataSize;
  304. //
  305. // We are on the last value if the next thing after this value
  306. // is an endmark.
  307. //
  308. if ( _cbhCurrentValue.pSyntax->dw == CLUSPROP_SYNTAX_ENDMARK )
  309. {
  310. _sc = ERROR_NO_MORE_ITEMS;
  311. } // if: next value's syntax is the endmark
  312. } while ( 0 );
  313. return _sc;
  314. } //*** CClusPropValueList::ScCheckIfAtLastValue()
  315. /////////////////////////////////////////////////////////////////////////////
  316. //++
  317. //
  318. // CClusPropValueList::ScAllocValueList
  319. //
  320. // Description:
  321. // Allocate a value list buffer that's big enough to hold the next
  322. // value.
  323. //
  324. // Arguments:
  325. // cbMinimum [IN] Minimum size of the value list.
  326. //
  327. // Return Value:
  328. // None.
  329. //
  330. // Exceptions Thrown:
  331. // Any exceptions thrown by new. By default, no exceptions are thrown.
  332. //
  333. //--
  334. /////////////////////////////////////////////////////////////////////////////
  335. DWORD CClusPropValueList::ScAllocValueList( IN DWORD cbMinimum )
  336. {
  337. ASSERT( cbMinimum > 0 );
  338. DWORD _sc = ERROR_SUCCESS;
  339. DWORD _cbTotal = 0;
  340. //
  341. // Add the size of the item count and final endmark.
  342. //
  343. cbMinimum += sizeof( CLUSPROP_VALUE );
  344. _cbTotal = m_cbDataSize + cbMinimum;
  345. if ( m_cbBufferSize < _cbTotal )
  346. {
  347. PBYTE _pbNewValuelist = NULL;
  348. cbMinimum = max( BUFFER_GROWTH_FACTOR, cbMinimum );
  349. _cbTotal = m_cbDataSize + cbMinimum;
  350. //
  351. // Allocate and zero a new buffer.
  352. //
  353. _pbNewValuelist = new BYTE[ _cbTotal ];
  354. if ( _pbNewValuelist != NULL )
  355. {
  356. ZeroMemory( _pbNewValuelist, _cbTotal );
  357. //
  358. // If there was a previous buffer, copy it and the delete it.
  359. //
  360. if ( m_cbhValueList.pb != NULL )
  361. {
  362. if ( m_cbDataSize != 0 )
  363. {
  364. CopyMemory( _pbNewValuelist, m_cbhValueList.pb, m_cbDataSize );
  365. } // if: data already exists in buffer
  366. delete [] m_cbhValueList.pb;
  367. m_cbhCurrentValue.pb = _pbNewValuelist + (m_cbhCurrentValue.pb - m_cbhValueList.pb);
  368. } // if: there was a previous buffer
  369. else
  370. {
  371. m_cbhCurrentValue.pb = _pbNewValuelist + sizeof( DWORD ); // move past prop count
  372. } // else: no previous buffer
  373. //
  374. // Save the new buffer.
  375. //
  376. m_cbhValueList.pb = _pbNewValuelist;
  377. m_cbBufferSize = _cbTotal;
  378. } // if: allocation succeeded
  379. else
  380. {
  381. _sc = ERROR_NOT_ENOUGH_MEMORY;
  382. } // else: allocation failed
  383. } // if: buffer isn't big enough
  384. return _sc;
  385. } //*** CClusPropValueList::ScAllocValueList()
  386. /////////////////////////////////////////////////////////////////////////////
  387. //++
  388. //
  389. // CClusPropValueList::ScGetResourceValueList
  390. //
  391. // Description:
  392. // Get value list of a resource.
  393. //
  394. // Arguments:
  395. // hResource [IN] Handle for the resource to get properties from.
  396. // dwControlCode [IN] Control code for the request.
  397. // hHostNode [IN] Handle for the node to direct this request to.
  398. // Defaults to NULL.
  399. // lpInBuffer [IN] Input buffer for the request. Defaults to NULL.
  400. // cbInBufferSize [IN] Size of the input buffer. Defaults to 0.
  401. //
  402. // Return Value:
  403. // None.
  404. //
  405. // Exceptions Thrown:
  406. // Any exceptions CClusPropValueList::ScAllocValueList().
  407. //
  408. //--
  409. /////////////////////////////////////////////////////////////////////////////
  410. DWORD CClusPropValueList::ScGetResourceValueList(
  411. IN HRESOURCE hResource,
  412. IN DWORD dwControlCode,
  413. IN HNODE hHostNode,
  414. IN LPVOID lpInBuffer,
  415. IN DWORD cbInBufferSize
  416. )
  417. {
  418. ASSERT( hResource != NULL );
  419. ASSERT( (dwControlCode & (CLUSCTL_OBJECT_MASK << CLUSCTL_OBJECT_SHIFT))
  420. == (CLUS_OBJECT_RESOURCE << CLUSCTL_OBJECT_SHIFT) );
  421. DWORD _sc = ERROR_SUCCESS;
  422. DWORD _cb = 512;
  423. //
  424. // Overwrite anything that may be in the buffer.
  425. // Allows this class instance to be reused.
  426. //
  427. m_cbDataSize = 0;
  428. //
  429. // Get values.
  430. //
  431. _sc = ScAllocValueList( _cb );
  432. if ( _sc == ERROR_SUCCESS )
  433. {
  434. _sc = ClusterResourceControl(
  435. hResource,
  436. hHostNode,
  437. dwControlCode,
  438. lpInBuffer,
  439. cbInBufferSize,
  440. m_cbhValueList.pb,
  441. m_cbBufferSize,
  442. &_cb
  443. );
  444. if ( _sc == ERROR_MORE_DATA )
  445. {
  446. _sc = ScAllocValueList( _cb );
  447. if ( _sc == ERROR_SUCCESS )
  448. {
  449. _sc = ClusterResourceControl(
  450. hResource,
  451. hHostNode,
  452. dwControlCode,
  453. lpInBuffer,
  454. cbInBufferSize,
  455. m_cbhValueList.pb,
  456. m_cbBufferSize,
  457. &_cb
  458. );
  459. } // if: ScAllocValueList succeeded
  460. } // if: buffer too small
  461. } // if: ScAllocValueList succeeded
  462. if ( _sc != ERROR_SUCCESS )
  463. {
  464. DeleteValueList();
  465. } // if: error getting properties.
  466. else
  467. {
  468. m_cbDataSize = _cb;
  469. m_cbDataLeft = _cb;
  470. } // else: no errors
  471. return _sc;
  472. } //*** CClusPropValueList::ScGetResourceValueList()
  473. /////////////////////////////////////////////////////////////////////////////
  474. //++
  475. //
  476. // CClusPropValueList::ScGetResourceTypeValueList
  477. //
  478. // Description:
  479. // Get value list of a resource type.
  480. //
  481. // Arguments:
  482. // hCluster [IN] Handle for the cluster in which the resource
  483. // type resides.
  484. // pwszResTypeName [IN] Name of the resource type.
  485. // dwControlCode [IN] Control code for the request.
  486. // hHostNode [IN] Handle for the node to direct this request to.
  487. // Defaults to NULL.
  488. // lpInBuffer [IN] Input buffer for the request. Defaults to NULL.
  489. // cbInBufferSize [IN] Size of the input buffer. Defaults to 0.
  490. //
  491. // Return Value:
  492. // None.
  493. //
  494. // Exceptions Thrown:
  495. // Any exceptions CClusPropValueList::ScAllocValueList().
  496. //
  497. //--
  498. /////////////////////////////////////////////////////////////////////////////
  499. DWORD CClusPropValueList::ScGetResourceTypeValueList(
  500. IN HCLUSTER hCluster,
  501. IN LPCWSTR pwszResTypeName,
  502. IN DWORD dwControlCode,
  503. IN HNODE hHostNode,
  504. IN LPVOID lpInBuffer,
  505. IN DWORD cbInBufferSize
  506. )
  507. {
  508. ASSERT( hCluster != NULL );
  509. ASSERT( pwszResTypeName != NULL );
  510. ASSERT( *pwszResTypeName != L'\0' );
  511. ASSERT( (dwControlCode & (CLUSCTL_OBJECT_MASK << CLUSCTL_OBJECT_SHIFT))
  512. == (CLUS_OBJECT_RESOURCE_TYPE << CLUSCTL_OBJECT_SHIFT) );
  513. DWORD _sc = ERROR_SUCCESS;
  514. DWORD _cb = 512;
  515. //
  516. // Overwrite anything that may be in the buffer.
  517. // Allows this class instance to be reused.
  518. //
  519. m_cbDataSize = 0;
  520. //
  521. // Get values.
  522. //
  523. _sc = ScAllocValueList( _cb );
  524. if ( _sc == ERROR_SUCCESS )
  525. {
  526. _sc = ClusterResourceTypeControl(
  527. hCluster,
  528. pwszResTypeName,
  529. hHostNode,
  530. dwControlCode,
  531. lpInBuffer,
  532. cbInBufferSize,
  533. m_cbhValueList.pb,
  534. m_cbBufferSize,
  535. &_cb
  536. );
  537. if ( _sc == ERROR_MORE_DATA )
  538. {
  539. _sc = ScAllocValueList( _cb );
  540. if ( _sc == ERROR_SUCCESS )
  541. {
  542. _sc = ClusterResourceTypeControl(
  543. hCluster,
  544. pwszResTypeName,
  545. hHostNode,
  546. dwControlCode,
  547. lpInBuffer,
  548. cbInBufferSize,
  549. m_cbhValueList.pb,
  550. m_cbBufferSize,
  551. &_cb
  552. );
  553. } // if: ScAllocValueList succeeded
  554. } // if: buffer too small
  555. } // if: ScAllocValueList succeeded
  556. if ( _sc != ERROR_SUCCESS )
  557. {
  558. DeleteValueList();
  559. } // if: error getting properties.
  560. else
  561. {
  562. m_cbDataSize = _cb;
  563. m_cbDataLeft = _cb;
  564. } // else: no errors
  565. return _sc;
  566. } //*** CClusPropValueList::ScGetResourceTypeValueList()
  567. //*************************************************************************//
  568. /////////////////////////////////////////////////////////////////////////////
  569. // CClusPropList class
  570. /////////////////////////////////////////////////////////////////////////////
  571. #ifdef __AFX_H__
  572. IMPLEMENT_DYNAMIC( CClusPropList, CObject );
  573. #endif // __AFX_H__
  574. /////////////////////////////////////////////////////////////////////////////
  575. //++
  576. //
  577. // CClusPropList::ScCopy
  578. //
  579. // Description:
  580. // Copy a property list. This function is equivalent to an assignment
  581. // operator. Since this operation can fail, no assignment operator is
  582. // provided.
  583. //
  584. // Arguments:
  585. // pcplPropList [IN] The proplist to copy into this instance.
  586. // cbListSize [IN] The total size of the prop list.
  587. //
  588. // Return Value:
  589. // Win32 status code.
  590. //
  591. //--
  592. /////////////////////////////////////////////////////////////////////////////
  593. DWORD CClusPropList::ScCopy(
  594. IN const PCLUSPROP_LIST pcplPropList,
  595. IN DWORD cbListSize
  596. )
  597. {
  598. ASSERT( pcplPropList != NULL );
  599. DWORD _sc = ERROR_SUCCESS;
  600. //
  601. // Clean up any vestiges of a previous prop list.
  602. //
  603. if ( m_cbhPropList.pb != NULL )
  604. {
  605. DeletePropList();
  606. } // if: the current list is not empty
  607. //
  608. // Allocate the new property list buffer. If successful,
  609. // copy the source list.
  610. //
  611. m_cbhPropList.pb = new BYTE[ cbListSize ];
  612. if ( m_cbhPropList.pb != NULL )
  613. {
  614. CopyMemory( m_cbhPropList.pList, pcplPropList, cbListSize );
  615. m_cbBufferSize = cbListSize;
  616. m_cbDataSize = cbListSize;
  617. m_cbDataLeft = cbListSize;
  618. _sc = ScMoveToFirstProperty();
  619. } // if: new succeeded
  620. else
  621. {
  622. _sc = ERROR_NOT_ENOUGH_MEMORY;
  623. } // else:
  624. return _sc;
  625. } //*** CClusPropList::ScCopy()
  626. ////////////////////////////////////////////////////////////////////////////
  627. //++
  628. //
  629. // CClusPropList::ScMoveToFirstProperty
  630. //
  631. // Description:
  632. // Move the cursor to the first propery in the list.
  633. //
  634. // Arguments:
  635. // None.
  636. //
  637. // Return Value:
  638. // ERROR_SUCCESS Position moved to the first property successfully.
  639. // ERROR_NO_MORE_ITEMS There are no properties in the list.
  640. // ERROR_INVALID_DATA Not enough data in the buffer.
  641. //
  642. //--
  643. /////////////////////////////////////////////////////////////////////////////
  644. DWORD CClusPropList::ScMoveToFirstProperty( void )
  645. {
  646. ASSERT( m_cbhPropList.pb != NULL );
  647. ASSERT( m_cbDataSize >= sizeof( m_cbhPropList.pList->nPropertyCount ) );
  648. DWORD _sc;
  649. DWORD _cbDataLeft;
  650. DWORD _cbDataSize;
  651. CLUSPROP_BUFFER_HELPER _cbhCurrentValue;
  652. do
  653. {
  654. //
  655. // Make sure the buffer is big enough for the list header.
  656. //
  657. if ( m_cbDataSize < sizeof( m_cbhPropList.pList->nPropertyCount ) )
  658. {
  659. _sc = ERROR_INVALID_DATA;
  660. break;
  661. } // if: not enough data
  662. //
  663. // Set the property counter to the number of properties in the list.
  664. //
  665. m_nPropsRemaining = m_cbhPropList.pList->nPropertyCount;
  666. //
  667. // Point the name pointer to the first name in the list.
  668. //
  669. m_cbhCurrentPropName.pName = &m_cbhPropList.pList->PropertyName;
  670. m_cbDataLeft = m_cbDataSize - sizeof( m_cbhPropList.pList->nPropertyCount );
  671. //
  672. // Check to see if there are any properties in the list.
  673. //
  674. if ( m_nPropsRemaining == 0 )
  675. {
  676. _sc = ERROR_NO_MORE_ITEMS;
  677. break;
  678. } // if: no properties in the list
  679. //
  680. // Make sure the buffer is big enough for the first property name.
  681. //
  682. if ( m_cbDataLeft < sizeof( *m_cbhCurrentPropName.pName ) )
  683. {
  684. _sc = ERROR_INVALID_DATA;
  685. break;
  686. } // if: not enough data left
  687. //
  688. // Calculate how much to advance the buffer pointer.
  689. //
  690. _cbDataSize = sizeof( *m_cbhCurrentPropName.pName )
  691. + ALIGN_CLUSPROP( m_cbhCurrentPropName.pName->cbLength );
  692. //
  693. // Make sure the buffer is big enough for the name header
  694. // and the data itself.
  695. //
  696. if ( m_cbDataLeft < _cbDataSize )
  697. {
  698. _sc = ERROR_INVALID_DATA;
  699. break;
  700. } // if: not enough data left
  701. //
  702. // Point the value buffer to the first value in the list.
  703. //
  704. _cbhCurrentValue.pb = m_cbhCurrentPropName.pb + _cbDataSize;
  705. _cbDataLeft = m_cbDataLeft - _cbDataSize;
  706. m_pvlValues.Init( _cbhCurrentValue, _cbDataLeft );
  707. //
  708. // Indicate we are successful.
  709. //
  710. _sc = ERROR_SUCCESS;
  711. } while ( 0 );
  712. return _sc;
  713. } //*** CClusPropList::ScMoveToFirstProperty
  714. /////////////////////////////////////////////////////////////////////////////
  715. //++
  716. //
  717. // CClusPropList::ScMoveToNextProperty
  718. //
  719. // Description:
  720. // Move the cursor to the next property in the list.
  721. //
  722. // Arguments:
  723. // None.
  724. //
  725. // Return Value:
  726. // ERROR_SUCCESS Position moved to the next property successfully.
  727. // ERROR_NO_MORE_ITEMS Already at the end of the list.
  728. // ERROR_INVALID_DATA Not enough data in the buffer.
  729. //
  730. //--
  731. /////////////////////////////////////////////////////////////////////////////
  732. DWORD CClusPropList::ScMoveToNextProperty( void )
  733. {
  734. ASSERT( m_cbhPropList.pb != NULL );
  735. ASSERT( m_pvlValues.CbhValueList().pb != NULL );
  736. DWORD _sc;
  737. DWORD _cbNameSize;
  738. DWORD _cbDataLeft;
  739. DWORD _cbDataSize;
  740. CLUSPROP_BUFFER_HELPER _cbhCurrentValue;
  741. CLUSPROP_BUFFER_HELPER _cbhPropName;
  742. _cbhCurrentValue = m_pvlValues;
  743. _cbDataLeft = m_pvlValues.CbDataLeft();
  744. //
  745. // If we aren't already at the last property, attempt to move to the next one.
  746. //
  747. _sc = ScCheckIfAtLastProperty();
  748. if ( _sc == ERROR_SUCCESS )
  749. {
  750. do
  751. {
  752. //
  753. // Make sure the buffer is big enough for the value header.
  754. //
  755. if ( _cbDataLeft < sizeof( *_cbhCurrentValue.pValue ) )
  756. {
  757. _sc = ERROR_INVALID_DATA;
  758. break;
  759. } // if: not enough data left
  760. //
  761. // Careful! Add offset only to cbhCurrentValue.pb. Otherwise
  762. // pointer arithmetic will give undesirable results.
  763. //
  764. while ( _cbhCurrentValue.pSyntax->dw != CLUSPROP_SYNTAX_ENDMARK )
  765. {
  766. //
  767. // Make sure the buffer is big enough for the value
  768. // and an endmark.
  769. //
  770. _cbDataSize = sizeof( *_cbhCurrentValue.pValue )
  771. + ALIGN_CLUSPROP( _cbhCurrentValue.pValue->cbLength );
  772. if ( _cbDataLeft < _cbDataSize + sizeof( *_cbhCurrentValue.pSyntax ) )
  773. {
  774. _sc = ERROR_INVALID_DATA;
  775. break;
  776. } // if: not enough data left
  777. //
  778. // Advance past the value.
  779. //
  780. _cbhCurrentValue.pb += _cbDataSize;
  781. _cbDataLeft -= _cbDataSize;
  782. } // while: not at endmark
  783. if ( _sc != ERROR_SUCCESS )
  784. {
  785. break;
  786. } // if: error occurred in loop
  787. //
  788. // Advanced past the endmark.
  789. // Size check already performed in above loop.
  790. //
  791. _cbDataSize = sizeof( *_cbhCurrentValue.pSyntax );
  792. _cbhCurrentValue.pb += _cbDataSize;
  793. _cbDataLeft -= _cbDataSize;
  794. //
  795. // Point the name pointer to the next name in the list.
  796. //
  797. _cbhPropName = _cbhCurrentValue;
  798. ASSERT( _cbDataLeft == m_cbDataSize - (_cbhPropName.pb - m_cbhPropList.pb) );
  799. //
  800. // Calculate the size of the name with header.
  801. // Make sure the buffer is big enough for the name and an endmark.
  802. //
  803. if ( _cbDataLeft < sizeof( *_cbhPropName.pName ) )
  804. {
  805. _sc = ERROR_INVALID_DATA;
  806. break;
  807. } // if: not enough data
  808. _cbNameSize = sizeof( *_cbhPropName.pName )
  809. + ALIGN_CLUSPROP( _cbhPropName.pName->cbLength );
  810. if ( _cbDataLeft < _cbNameSize + sizeof( CLUSPROP_SYNTAX ) )
  811. {
  812. _sc = ERROR_INVALID_DATA;
  813. break;
  814. } // if: not enough data
  815. //
  816. // Point the value buffer to the first value in the list.
  817. //
  818. _cbhCurrentValue.pb = _cbhPropName.pb + _cbNameSize;
  819. m_cbhCurrentPropName = _cbhPropName;
  820. m_cbDataLeft = _cbDataLeft - _cbNameSize;
  821. m_pvlValues.Init( _cbhCurrentValue, m_cbDataLeft );
  822. //
  823. // We've successfully advanced to the next property,
  824. // so there is now one fewer property remaining.
  825. //
  826. --m_nPropsRemaining;
  827. ASSERT( m_nPropsRemaining >= 1 );
  828. _sc = ERROR_SUCCESS;
  829. } while ( 0 );
  830. } // if: not at last property
  831. return _sc;
  832. } //*** CClusPropList::ScMoveToNextProperty()
  833. /////////////////////////////////////////////////////////////////////////////
  834. //++
  835. //
  836. // CClusPropList::ScMoveToPropertyByName
  837. //
  838. // Description:
  839. // Find the passed in property name in the proplist. Note that the
  840. // cursor is reset to the beginning at the beginning of the routine and
  841. // the current state of the cursor is lost.
  842. //
  843. // Arguments:
  844. // pwszPropName [IN] Name of the property
  845. //
  846. // Return Value:
  847. // TRUE if the property was found, FALSE if not.
  848. //
  849. //--
  850. /////////////////////////////////////////////////////////////////////////////
  851. DWORD CClusPropList::ScMoveToPropertyByName( IN LPCWSTR pwszPropName )
  852. {
  853. ASSERT( m_cbhPropList.pb != NULL );
  854. DWORD _sc;
  855. _sc = ScMoveToFirstProperty();
  856. if ( _sc == ERROR_SUCCESS )
  857. {
  858. do
  859. {
  860. //
  861. // See if this is the specified property. If so, we're done.
  862. //
  863. if ( lstrcmpiW( m_cbhCurrentPropName.pName->sz, pwszPropName ) == 0 )
  864. {
  865. break;
  866. } // if: property found
  867. //
  868. // Advance to the next property.
  869. //
  870. _sc = ScMoveToNextProperty();
  871. } while ( _sc == ERROR_SUCCESS ); // do-while: not end of list
  872. } // if: successfully moved to the first property
  873. return _sc;
  874. } //*** ClusPropList::ScMoveToPropertyByName( LPCWSTR )
  875. /////////////////////////////////////////////////////////////////////////////
  876. //++
  877. //
  878. // CClusPropList::ScAllocPropList
  879. //
  880. // Description:
  881. // Allocate a property list buffer that's big enough to hold the next
  882. // property.
  883. //
  884. // Arguments:
  885. // cbMinimum [IN] Minimum size of the property list.
  886. //
  887. // Return Value:
  888. // None.
  889. //
  890. // Exceptions Thrown:
  891. // Any exceptions thrown by new. By default, no exceptions are thrown.
  892. //
  893. //--
  894. /////////////////////////////////////////////////////////////////////////////
  895. DWORD CClusPropList::ScAllocPropList( IN DWORD cbMinimum )
  896. {
  897. ASSERT( cbMinimum > 0 );
  898. DWORD _sc = ERROR_SUCCESS;
  899. DWORD _cbTotal = 0;
  900. //
  901. // Add the size of the item count and final endmark.
  902. //
  903. cbMinimum += sizeof( CLUSPROP_VALUE );
  904. _cbTotal = m_cbDataSize + cbMinimum;
  905. if ( m_cbBufferSize < _cbTotal )
  906. {
  907. PBYTE _pbNewProplist = NULL;
  908. cbMinimum = max( BUFFER_GROWTH_FACTOR, cbMinimum );
  909. _cbTotal = m_cbDataSize + cbMinimum;
  910. //
  911. // Allocate and zero a new buffer.
  912. //
  913. _pbNewProplist = new BYTE[ _cbTotal ];
  914. if ( _pbNewProplist != NULL )
  915. {
  916. ZeroMemory( _pbNewProplist, _cbTotal );
  917. //
  918. // If there was a previous buffer, copy it and the delete it.
  919. //
  920. if ( m_cbhPropList.pb != NULL )
  921. {
  922. if ( m_cbDataSize != 0 )
  923. {
  924. CopyMemory( _pbNewProplist, m_cbhPropList.pb, m_cbDataSize );
  925. } // if: data already exists in buffer
  926. delete [] m_cbhPropList.pb;
  927. m_cbhCurrentProp.pb = _pbNewProplist + (m_cbhCurrentProp.pb - m_cbhPropList.pb);
  928. } // if: there was a previous buffer
  929. else
  930. {
  931. m_cbhCurrentProp.pb = _pbNewProplist + sizeof( DWORD ); // move past prop count
  932. } // else: no previous buffer
  933. //
  934. // Save the new buffer.
  935. //
  936. m_cbhPropList.pb = _pbNewProplist;
  937. m_cbBufferSize = _cbTotal;
  938. } // if: allocation succeeded
  939. else
  940. {
  941. _sc = ERROR_NOT_ENOUGH_MEMORY;
  942. } // else: allocation failed
  943. } // if: buffer isn't big enough
  944. return _sc;
  945. } //*** CClusPropList::ScAllocPropList()
  946. /////////////////////////////////////////////////////////////////////////////
  947. //++
  948. //
  949. // CClusPropList::ScAddProp
  950. //
  951. // Description:
  952. // Add a string property to a property list if it has changed.
  953. //
  954. // Arguments:
  955. // pwszName [IN] Name of the property.
  956. // pwszValue [IN] Value of the property to set in the list.
  957. // pwszPrevValue [IN] Previous value of the property.
  958. //
  959. // Return Value:
  960. // ERROR_SUCCESS or other Win32 error code.
  961. //
  962. //--
  963. /////////////////////////////////////////////////////////////////////////////
  964. DWORD CClusPropList::ScAddProp(
  965. IN LPCWSTR pwszName,
  966. IN LPCWSTR pwszValue,
  967. IN LPCWSTR pwszPrevValue
  968. )
  969. {
  970. ASSERT( pwszName != NULL );
  971. DWORD _sc = ERROR_SUCCESS;
  972. BOOL _bValuesDifferent = TRUE;
  973. PCLUSPROP_PROPERTY_NAME _pName;
  974. PCLUSPROP_SZ _pValue;
  975. if (( pwszPrevValue != NULL ) && ( lstrcmpW( pwszValue, pwszPrevValue ) == 0 ))
  976. {
  977. _bValuesDifferent = FALSE;
  978. } // if: we have a prev value and the values are the same
  979. //
  980. // If we should always add, or if the new value and the previous value
  981. // are not equal, add the property to the property list.
  982. //
  983. if ( m_bAlwaysAddProp || _bValuesDifferent )
  984. {
  985. DWORD _cbNameSize;
  986. DWORD _cbDataSize;
  987. DWORD _cbValueSize;
  988. //
  989. // Calculate sizes and make sure we have a property list.
  990. //
  991. _cbNameSize = sizeof( CLUSPROP_PROPERTY_NAME )
  992. + ALIGN_CLUSPROP( (lstrlenW( pwszName ) + 1) * sizeof( WCHAR ) );
  993. _cbDataSize = (lstrlenW( pwszValue ) + 1) * sizeof( WCHAR );
  994. _cbValueSize = sizeof( CLUSPROP_SZ )
  995. + ALIGN_CLUSPROP( _cbDataSize )
  996. + sizeof( CLUSPROP_SYNTAX ); // value list endmark
  997. _sc = ScAllocPropList( _cbNameSize + _cbValueSize );
  998. if ( _sc == ERROR_SUCCESS )
  999. {
  1000. //
  1001. // Set the property name.
  1002. //
  1003. _pName = m_cbhCurrentProp.pName;
  1004. CopyProp( _pName, CLUSPROP_TYPE_NAME, pwszName );
  1005. m_cbhCurrentProp.pb += _cbNameSize;
  1006. //
  1007. // Set the property value.
  1008. //
  1009. _pValue = m_cbhCurrentProp.pStringValue;
  1010. CopyProp( _pValue, CLUSPROP_TYPE_LIST_VALUE, pwszValue, _cbDataSize );
  1011. m_cbhCurrentProp.pb += _cbValueSize;
  1012. //
  1013. // Increment the property count and buffer size.
  1014. //
  1015. m_cbhPropList.pList->nPropertyCount++;
  1016. m_cbDataSize += _cbNameSize + _cbValueSize;
  1017. } // if: ScAllocPropList successfully grew the proplist
  1018. } // if: the value has changed
  1019. return _sc;
  1020. } //*** CClusPropList::ScAddProp( LPCWSTR )
  1021. /////////////////////////////////////////////////////////////////////////////
  1022. //++
  1023. //
  1024. // CClusPropList::ScAddMultiSzProp
  1025. //
  1026. // Description:
  1027. // Add a string property to a property list if it has changed.
  1028. //
  1029. // Arguments:
  1030. // pwszName [IN] Name of the property.
  1031. // pwszValue [IN] Value of the property to set in the list.
  1032. // pwszPrevValue [IN] Previous value of the property.
  1033. //
  1034. // Return Value:
  1035. // ERROR_SUCCESS or other Win32 error code.
  1036. //
  1037. //--
  1038. /////////////////////////////////////////////////////////////////////////////
  1039. DWORD CClusPropList::ScAddMultiSzProp(
  1040. IN LPCWSTR pwszName,
  1041. IN LPCWSTR pwszValue,
  1042. IN LPCWSTR pwszPrevValue
  1043. )
  1044. {
  1045. ASSERT( pwszName != NULL );
  1046. DWORD _sc = ERROR_SUCCESS;
  1047. BOOL _bValuesDifferent = TRUE;
  1048. PCLUSPROP_PROPERTY_NAME _pName;
  1049. PCLUSPROP_MULTI_SZ _pValue;
  1050. if ( ( pwszPrevValue != NULL ) && ( NCompareMultiSz( pwszValue, pwszPrevValue ) == 0 ) )
  1051. {
  1052. _bValuesDifferent = FALSE;
  1053. } // if: we have a prev value and the values are the same
  1054. //
  1055. // If we should always add, or if the new value and the previous value
  1056. // are not equal, add the property to the property list.
  1057. //
  1058. if ( m_bAlwaysAddProp || _bValuesDifferent )
  1059. {
  1060. DWORD _cbNameSize;
  1061. DWORD _cbDataSize;
  1062. DWORD _cbValueSize;
  1063. //
  1064. // Calculate sizes and make sure we have a property list.
  1065. //
  1066. _cbNameSize = sizeof( CLUSPROP_PROPERTY_NAME )
  1067. + ALIGN_CLUSPROP( (lstrlenW( pwszName ) + 1) * sizeof( WCHAR ) );
  1068. _cbDataSize = (CchMultiSz( pwszValue ) + 1) * sizeof( WCHAR );
  1069. _cbValueSize = sizeof( CLUSPROP_SZ )
  1070. + ALIGN_CLUSPROP( _cbDataSize )
  1071. + sizeof( CLUSPROP_SYNTAX ); // value list endmark
  1072. _sc = ScAllocPropList( _cbNameSize + _cbValueSize );
  1073. if ( _sc == ERROR_SUCCESS )
  1074. {
  1075. //
  1076. // Set the property name.
  1077. //
  1078. _pName = m_cbhCurrentProp.pName;
  1079. CopyProp( _pName, CLUSPROP_TYPE_NAME, pwszName );
  1080. m_cbhCurrentProp.pb += _cbNameSize;
  1081. //
  1082. // Set the property value.
  1083. //
  1084. _pValue = m_cbhCurrentProp.pMultiSzValue;
  1085. CopyMultiSzProp( _pValue, CLUSPROP_TYPE_LIST_VALUE, pwszValue, _cbDataSize );
  1086. m_cbhCurrentProp.pb += _cbValueSize;
  1087. //
  1088. // Increment the property count and buffer size.
  1089. //
  1090. m_cbhPropList.pList->nPropertyCount++;
  1091. m_cbDataSize += _cbNameSize + _cbValueSize;
  1092. } // if: ScAllocPropList successfully grew the proplist
  1093. } // if: the value has changed
  1094. return _sc;
  1095. } //*** CClusPropList::ScAddMultiSzProp( LPCWSTR )
  1096. /////////////////////////////////////////////////////////////////////////////
  1097. //++
  1098. //
  1099. // CClusPropList::ScAddExpandSzProp
  1100. //
  1101. // Description:
  1102. // Add an EXPAND_SZ string property to a property list if it has changed.
  1103. //
  1104. // Arguments:
  1105. // pwszName [IN] Name of the property.
  1106. // pwszValue [IN] Value of the property to set in the list.
  1107. // pwszPrevValue [IN] Previous value of the property.
  1108. //
  1109. // Return Value:
  1110. // None.
  1111. //
  1112. //--
  1113. /////////////////////////////////////////////////////////////////////////////
  1114. DWORD CClusPropList::ScAddExpandSzProp(
  1115. IN LPCWSTR pwszName,
  1116. IN LPCWSTR pwszValue,
  1117. IN LPCWSTR pwszPrevValue
  1118. )
  1119. {
  1120. ASSERT( pwszName != NULL );
  1121. DWORD _sc = ERROR_SUCCESS;
  1122. BOOL _bValuesDifferent = TRUE;
  1123. PCLUSPROP_PROPERTY_NAME _pName;
  1124. PCLUSPROP_SZ _pValue;
  1125. if ( ( pwszPrevValue != NULL ) && ( lstrcmpW( pwszValue, pwszPrevValue ) == 0 ) )
  1126. {
  1127. _bValuesDifferent = FALSE;
  1128. } // if: we have a prev value and the values are the same
  1129. //
  1130. // If we should always add, or if the new value and the previous value
  1131. // are not equal, add the property to the property list.
  1132. //
  1133. if ( m_bAlwaysAddProp || _bValuesDifferent )
  1134. {
  1135. DWORD _cbNameSize;
  1136. DWORD _cbDataSize;
  1137. DWORD _cbValueSize;
  1138. //
  1139. // Calculate sizes and make sure we have a property list.
  1140. //
  1141. _cbNameSize = sizeof( CLUSPROP_PROPERTY_NAME )
  1142. + ALIGN_CLUSPROP( (lstrlenW( pwszName ) + 1) * sizeof( WCHAR ) );
  1143. _cbDataSize = (lstrlenW( pwszValue ) + 1) * sizeof( WCHAR );
  1144. _cbValueSize = sizeof( CLUSPROP_SZ )
  1145. + ALIGN_CLUSPROP( _cbDataSize )
  1146. + sizeof( CLUSPROP_SYNTAX ); // value list endmark
  1147. _sc = ScAllocPropList( _cbNameSize + _cbValueSize );
  1148. if ( _sc == ERROR_SUCCESS )
  1149. {
  1150. //
  1151. // Set the property name.
  1152. //
  1153. _pName = m_cbhCurrentProp.pName;
  1154. CopyProp( _pName, CLUSPROP_TYPE_NAME, pwszName );
  1155. m_cbhCurrentProp.pb += _cbNameSize;
  1156. //
  1157. // Set the property value.
  1158. //
  1159. _pValue = m_cbhCurrentProp.pStringValue;
  1160. CopyExpandSzProp( _pValue, CLUSPROP_TYPE_LIST_VALUE, pwszValue, _cbDataSize );
  1161. m_cbhCurrentProp.pb += _cbValueSize;
  1162. //
  1163. // Increment the property count and buffer size.
  1164. //
  1165. m_cbhPropList.pList->nPropertyCount++;
  1166. m_cbDataSize += _cbNameSize + _cbValueSize;
  1167. } // if: ScAllocPropList successfully grew the proplist
  1168. } // if: the value has changed
  1169. return _sc;
  1170. } //*** CClusPropList::ScAddExpandSzProp( LPCWSTR )
  1171. /////////////////////////////////////////////////////////////////////////////
  1172. //++
  1173. //
  1174. // CClusPropList::ScAddProp
  1175. //
  1176. // Description:
  1177. // Add a DWORD property to a property list if it has changed.
  1178. //
  1179. // Arguments:
  1180. // pwszName [IN] Name of the property.
  1181. // nValue [IN] Value of the property to set in the list.
  1182. // nPrevValue [IN] Previous value of the property.
  1183. //
  1184. // Return Value:
  1185. // None.
  1186. //
  1187. //--
  1188. /////////////////////////////////////////////////////////////////////////////
  1189. DWORD CClusPropList::ScAddProp(
  1190. IN LPCWSTR pwszName,
  1191. IN DWORD nValue,
  1192. IN DWORD nPrevValue
  1193. )
  1194. {
  1195. ASSERT( pwszName != NULL );
  1196. DWORD _sc = ERROR_SUCCESS;
  1197. PCLUSPROP_PROPERTY_NAME _pName;
  1198. PCLUSPROP_DWORD _pValue;
  1199. if ( m_bAlwaysAddProp || ( nValue != nPrevValue ) )
  1200. {
  1201. DWORD _cbNameSize;
  1202. DWORD _cbValueSize;
  1203. //
  1204. // Calculate sizes and make sure we have a property list.
  1205. //
  1206. _cbNameSize = sizeof( CLUSPROP_PROPERTY_NAME )
  1207. + ALIGN_CLUSPROP( (lstrlenW( pwszName ) + 1) * sizeof( WCHAR ) );
  1208. _cbValueSize = sizeof( CLUSPROP_DWORD )
  1209. + sizeof( CLUSPROP_SYNTAX ); // value list endmark
  1210. _sc = ScAllocPropList( _cbNameSize + _cbValueSize );
  1211. if ( _sc == ERROR_SUCCESS )
  1212. {
  1213. //
  1214. // Set the property name.
  1215. //
  1216. _pName = m_cbhCurrentProp.pName;
  1217. CopyProp( _pName, CLUSPROP_TYPE_NAME, pwszName );
  1218. m_cbhCurrentProp.pb += _cbNameSize;
  1219. //
  1220. // Set the property value.
  1221. //
  1222. _pValue = m_cbhCurrentProp.pDwordValue;
  1223. CopyProp( _pValue, CLUSPROP_TYPE_LIST_VALUE, nValue );
  1224. m_cbhCurrentProp.pb += _cbValueSize;
  1225. //
  1226. // Increment the property count and buffer size.
  1227. //
  1228. m_cbhPropList.pList->nPropertyCount++;
  1229. m_cbDataSize += _cbNameSize + _cbValueSize;
  1230. } // if: ScAllocPropList successfully grew the proplist
  1231. } // if: the value has changed
  1232. return _sc;
  1233. } //*** CClusPropList::ScAddProp( DWORD )
  1234. #if CLUSAPI_VERSION >= 0x0500
  1235. /////////////////////////////////////////////////////////////////////////////
  1236. //++
  1237. //
  1238. // CClusPropList::ScAddProp
  1239. //
  1240. // Description:
  1241. // Add a LONG property to a property list if it has changed.
  1242. //
  1243. // Arguments:
  1244. // pwszName [IN] Name of the property.
  1245. // nValue [IN] Value of the property to set in the list.
  1246. // nPrevValue [IN] Previous value of the property.
  1247. //
  1248. // Return Value:
  1249. // None.
  1250. //
  1251. //--
  1252. /////////////////////////////////////////////////////////////////////////////
  1253. DWORD CClusPropList::ScAddProp(
  1254. IN LPCWSTR pwszName,
  1255. IN LONG nValue,
  1256. IN LONG nPrevValue
  1257. )
  1258. {
  1259. ASSERT( pwszName != NULL );
  1260. DWORD _sc = ERROR_SUCCESS;
  1261. PCLUSPROP_PROPERTY_NAME _pName;
  1262. PCLUSPROP_LONG _pValue;
  1263. if ( m_bAlwaysAddProp || ( nValue != nPrevValue ) )
  1264. {
  1265. DWORD _cbNameSize;
  1266. DWORD _cbValueSize;
  1267. //
  1268. // Calculate sizes and make sure we have a property list.
  1269. //
  1270. _cbNameSize = sizeof( CLUSPROP_PROPERTY_NAME )
  1271. + ALIGN_CLUSPROP( (lstrlenW( pwszName ) + 1) * sizeof( WCHAR ) );
  1272. _cbValueSize = sizeof( CLUSPROP_LONG )
  1273. + sizeof( CLUSPROP_SYNTAX ); // value list endmark
  1274. _sc = ScAllocPropList( _cbNameSize + _cbValueSize );
  1275. if ( _sc == ERROR_SUCCESS )
  1276. {
  1277. //
  1278. // Set the property name.
  1279. //
  1280. _pName = m_cbhCurrentProp.pName;
  1281. CopyProp( _pName, CLUSPROP_TYPE_NAME, pwszName );
  1282. m_cbhCurrentProp.pb += _cbNameSize;
  1283. //
  1284. // Set the property value.
  1285. //
  1286. _pValue = m_cbhCurrentProp.pLongValue;
  1287. CopyProp( _pValue, CLUSPROP_TYPE_LIST_VALUE, nValue );
  1288. m_cbhCurrentProp.pb += _cbValueSize;
  1289. //
  1290. // Increment the property count and buffer size.
  1291. //
  1292. m_cbhPropList.pList->nPropertyCount++;
  1293. m_cbDataSize += _cbNameSize + _cbValueSize;
  1294. } // if: ScAllocPropList successfully grew the proplist
  1295. } // if: the value has changed
  1296. return _sc;
  1297. } //*** CClusPropList::ScAddProp( LONG )
  1298. #endif // CLUSAPI_VERSION >= 0x0500
  1299. /////////////////////////////////////////////////////////////////////////////
  1300. //++
  1301. //
  1302. // CClusPropList::ScAddProp
  1303. //
  1304. // Description:
  1305. // Add a binary property to a property list if it has changed.
  1306. //
  1307. // Arguments:
  1308. // pwszName [IN] Name of the property.
  1309. // pbValue [IN] Value of the property to set in the list.
  1310. // cbValue [IN] Count of bytes in pbValue.
  1311. // pbPrevValue [IN] Previous value of the property.
  1312. // cbPrevValue [IN] Count of bytes in pbPrevValue.
  1313. //
  1314. // Return Value:
  1315. // None.
  1316. //
  1317. //--
  1318. /////////////////////////////////////////////////////////////////////////////
  1319. DWORD CClusPropList::ScAddProp(
  1320. IN LPCWSTR pwszName,
  1321. IN const PBYTE pbValue,
  1322. IN DWORD cbValue,
  1323. IN const PBYTE pbPrevValue,
  1324. IN DWORD cbPrevValue
  1325. )
  1326. {
  1327. ASSERT( pwszName != NULL );
  1328. DWORD _sc = ERROR_SUCCESS;
  1329. BOOL _bChanged = FALSE;
  1330. PCLUSPROP_PROPERTY_NAME _pName;
  1331. PCLUSPROP_BINARY _pValue;
  1332. //
  1333. // Determine if the buffer has changed.
  1334. //
  1335. if ( m_bAlwaysAddProp || (cbValue != cbPrevValue) )
  1336. {
  1337. _bChanged = TRUE;
  1338. } // if: always adding the property or the value size changed
  1339. else if ( ( cbValue != 0 ) && ( cbPrevValue != 0 ) )
  1340. {
  1341. _bChanged = memcmp( pbValue, pbPrevValue, cbValue ) != 0;
  1342. } // else if: value length changed
  1343. if ( _bChanged )
  1344. {
  1345. DWORD _cbNameSize;
  1346. DWORD _cbValueSize;
  1347. //
  1348. // Calculate sizes and make sure we have a property list.
  1349. //
  1350. _cbNameSize = sizeof( CLUSPROP_PROPERTY_NAME )
  1351. + ALIGN_CLUSPROP( (lstrlenW( pwszName ) + 1) * sizeof( WCHAR ) );
  1352. _cbValueSize = sizeof( CLUSPROP_BINARY )
  1353. + ALIGN_CLUSPROP( cbValue )
  1354. + sizeof( CLUSPROP_SYNTAX ); // value list endmark
  1355. _sc = ScAllocPropList( _cbNameSize + _cbValueSize );
  1356. if ( _sc == ERROR_SUCCESS )
  1357. {
  1358. //
  1359. // Set the property name.
  1360. //
  1361. _pName = m_cbhCurrentProp.pName;
  1362. CopyProp( _pName, CLUSPROP_TYPE_NAME, pwszName );
  1363. m_cbhCurrentProp.pb += _cbNameSize;
  1364. //
  1365. // Set the property value.
  1366. //
  1367. _pValue = m_cbhCurrentProp.pBinaryValue;
  1368. CopyProp( _pValue, CLUSPROP_TYPE_LIST_VALUE, pbValue, cbValue );
  1369. m_cbhCurrentProp.pb += _cbValueSize;
  1370. //
  1371. // Increment the property count and buffer size.
  1372. //
  1373. m_cbhPropList.pList->nPropertyCount++;
  1374. m_cbDataSize += _cbNameSize + _cbValueSize;
  1375. } // if: ScAllocPropList successfully grew the proplist
  1376. } // if: the value has changed
  1377. return _sc;
  1378. } //*** CClusPropList::ScAddProp( PBYTE )
  1379. /////////////////////////////////////////////////////////////////////////////
  1380. //++
  1381. //
  1382. // CClusPropList::ScAddProp
  1383. //
  1384. // Routine Description:
  1385. // Add a ULONGLONG property to a property list if it has changed.
  1386. //
  1387. // Arguments:
  1388. // pwszName [IN] Name of the property.
  1389. // ullValue [IN] Value of the property to set in the list.
  1390. // ullPrevValue [IN] Previous value of the property.
  1391. //
  1392. // Return Value:
  1393. // None.
  1394. //
  1395. //--
  1396. /////////////////////////////////////////////////////////////////////////////
  1397. DWORD CClusPropList::ScAddProp(
  1398. IN LPCWSTR pwszName,
  1399. IN ULONGLONG ullValue,
  1400. IN ULONGLONG ullPrevValue
  1401. )
  1402. {
  1403. ASSERT( pwszName != NULL );
  1404. DWORD _sc = ERROR_SUCCESS;
  1405. PCLUSPROP_PROPERTY_NAME _pName;
  1406. PCLUSPROP_ULARGE_INTEGER _pValue;
  1407. if ( m_bAlwaysAddProp || ( ullValue != ullPrevValue ) )
  1408. {
  1409. DWORD _cbNameSize;
  1410. DWORD _cbValueSize;
  1411. //
  1412. // Calculate sizes and make sure we have a property list.
  1413. //
  1414. _cbNameSize = sizeof( CLUSPROP_PROPERTY_NAME )
  1415. + ALIGN_CLUSPROP( (lstrlenW( pwszName ) + 1) * sizeof( WCHAR ) );
  1416. _cbValueSize = sizeof( CLUSPROP_ULARGE_INTEGER )
  1417. + sizeof( CLUSPROP_SYNTAX ); // value list endmark
  1418. _sc = ScAllocPropList( _cbNameSize + _cbValueSize );
  1419. if ( _sc == ERROR_SUCCESS )
  1420. {
  1421. //
  1422. // Set the property name.
  1423. //
  1424. _pName = m_cbhCurrentProp.pName;
  1425. CopyProp( _pName, CLUSPROP_TYPE_NAME, pwszName );
  1426. m_cbhCurrentProp.pb += _cbNameSize;
  1427. //
  1428. // Set the property value.
  1429. //
  1430. _pValue = m_cbhCurrentProp.pULargeIntegerValue;
  1431. CopyProp( _pValue, CLUSPROP_TYPE_LIST_VALUE, ullValue );
  1432. m_cbhCurrentProp.pb += _cbValueSize;
  1433. //
  1434. // Increment the property count and buffer size.
  1435. //
  1436. m_cbhPropList.pList->nPropertyCount++;
  1437. m_cbDataSize += _cbNameSize + _cbValueSize;
  1438. } // if: ScAllocPropList successfully grew the proplist
  1439. } // if: the value has changed
  1440. return _sc;
  1441. } //*** CClusPropList::ScAddProp( ULONGLONG )
  1442. /////////////////////////////////////////////////////////////////////////////
  1443. //++
  1444. //
  1445. // CClusPropList::ScSetPropToDefault
  1446. //
  1447. // Description:
  1448. // Add a property to the property list so that it will revert to its
  1449. // default value.
  1450. //
  1451. // Arguments:
  1452. // pwszName [IN] Name of the property.
  1453. // cpfPropFmt [IN] Format of property
  1454. //
  1455. // Return Value:
  1456. // None.
  1457. //
  1458. //--
  1459. /////////////////////////////////////////////////////////////////////////////
  1460. DWORD CClusPropList::ScSetPropToDefault(
  1461. IN LPCWSTR pwszName,
  1462. IN CLUSTER_PROPERTY_FORMAT cpfPropFmt
  1463. )
  1464. {
  1465. ASSERT( pwszName != NULL );
  1466. DWORD _sc = ERROR_SUCCESS;
  1467. DWORD _cbNameSize;
  1468. DWORD _cbValueSize;
  1469. PCLUSPROP_PROPERTY_NAME _pName;
  1470. PCLUSPROP_VALUE _pValue;
  1471. // Calculate sizes and make sure we have a property list.
  1472. _cbNameSize = sizeof( CLUSPROP_PROPERTY_NAME )
  1473. + ALIGN_CLUSPROP( (lstrlenW( pwszName ) + 1) * sizeof( WCHAR ) );
  1474. _cbValueSize = sizeof( CLUSPROP_BINARY )
  1475. + sizeof( CLUSPROP_SYNTAX ); // value list endmark
  1476. _sc = ScAllocPropList( _cbNameSize + _cbValueSize );
  1477. if ( _sc == ERROR_SUCCESS )
  1478. {
  1479. //
  1480. // Set the property name.
  1481. //
  1482. _pName = m_cbhCurrentProp.pName;
  1483. CopyProp( _pName, CLUSPROP_TYPE_NAME, pwszName );
  1484. m_cbhCurrentProp.pb += _cbNameSize;
  1485. //
  1486. // Set the property value.
  1487. //
  1488. _pValue = m_cbhCurrentProp.pValue;
  1489. CopyEmptyProp( _pValue, CLUSPROP_TYPE_LIST_VALUE, cpfPropFmt );
  1490. m_cbhCurrentProp.pb += _cbValueSize;
  1491. //
  1492. // Increment the property count and buffer size.
  1493. //
  1494. m_cbhPropList.pList->nPropertyCount++;
  1495. m_cbDataSize += _cbNameSize + _cbValueSize;
  1496. } // if:
  1497. return _sc;
  1498. } //*** CClusPropList::ScSetPropToDefault()
  1499. /////////////////////////////////////////////////////////////////////////////
  1500. //++
  1501. //
  1502. // CClusPropList::CopyProp
  1503. //
  1504. // Description:
  1505. // Copy a string property to a property structure.
  1506. //
  1507. // Arguments:
  1508. // pprop [OUT] Property structure to fill.
  1509. // cptPropType [IN] Type of string.
  1510. // psz [IN] String to copy.
  1511. // cbsz [IN] Count of bytes in pwsz string. If specified as 0,
  1512. // the the length will be determined by a call to strlen.
  1513. //
  1514. // Return Value:
  1515. // None.
  1516. //
  1517. //--
  1518. /////////////////////////////////////////////////////////////////////////////
  1519. void CClusPropList::CopyProp(
  1520. OUT PCLUSPROP_SZ pprop,
  1521. IN CLUSTER_PROPERTY_TYPE cptPropType,
  1522. IN LPCWSTR psz,
  1523. IN DWORD cbsz // = 0
  1524. )
  1525. {
  1526. ASSERT( pprop != NULL );
  1527. ASSERT( psz != NULL );
  1528. CLUSPROP_BUFFER_HELPER _cbhProps;
  1529. pprop->Syntax.wFormat = CLUSPROP_FORMAT_SZ;
  1530. pprop->Syntax.wType = static_cast< WORD >( cptPropType );
  1531. if ( cbsz == 0 )
  1532. {
  1533. cbsz = (lstrlenW( psz ) + 1) * sizeof( WCHAR );
  1534. } // if: zero size specified
  1535. ASSERT( cbsz == (lstrlenW( psz ) + 1) * sizeof( WCHAR ) );
  1536. pprop->cbLength = cbsz;
  1537. lstrcpyW( pprop->sz, psz );
  1538. //
  1539. // Set an endmark.
  1540. //
  1541. _cbhProps.pStringValue = pprop;
  1542. _cbhProps.pb += sizeof( *_cbhProps.pStringValue ) + ALIGN_CLUSPROP( cbsz );
  1543. _cbhProps.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  1544. } //*** CClusPropList::CopyProp()
  1545. /////////////////////////////////////////////////////////////////////////////
  1546. //++
  1547. //
  1548. // CClusPropList::CopyMultiSzProp
  1549. //
  1550. // Description:
  1551. // Copy a MULTI_SZ string property to a property structure.
  1552. //
  1553. // Arguments:
  1554. // pprop [OUT] Property structure to fill.
  1555. // cptPropType [IN] Type of string.
  1556. // psz [IN] String to copy.
  1557. // cbsz [IN] Count of bytes in psz string. If specified as 0,
  1558. // the the length will be determined by calls to strlen.
  1559. //
  1560. // Return Value:
  1561. // None.
  1562. //
  1563. //--
  1564. /////////////////////////////////////////////////////////////////////////////
  1565. void CClusPropList::CopyMultiSzProp(
  1566. OUT PCLUSPROP_MULTI_SZ pprop,
  1567. IN CLUSTER_PROPERTY_TYPE cptPropType,
  1568. IN LPCWSTR psz,
  1569. IN DWORD cbsz
  1570. )
  1571. {
  1572. ASSERT( pprop != NULL );
  1573. ASSERT( psz != NULL );
  1574. CLUSPROP_BUFFER_HELPER _cbhProps;
  1575. pprop->Syntax.wFormat = CLUSPROP_FORMAT_MULTI_SZ;
  1576. pprop->Syntax.wType = static_cast< WORD >( cptPropType );
  1577. if ( cbsz == 0 )
  1578. {
  1579. cbsz = (CchMultiSz( psz ) + 1) * sizeof( WCHAR );
  1580. } // if: zero size specified
  1581. ASSERT( cbsz == (CchMultiSz( psz ) + 1) * sizeof( WCHAR ) );
  1582. pprop->cbLength = cbsz;
  1583. CopyMemory( pprop->sz, psz, cbsz );
  1584. //
  1585. // Set an endmark.
  1586. //
  1587. _cbhProps.pMultiSzValue = pprop;
  1588. _cbhProps.pb += sizeof( *_cbhProps.pMultiSzValue ) + ALIGN_CLUSPROP( cbsz );
  1589. _cbhProps.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  1590. } //*** CClusPropList::CopyMultiSzProp()
  1591. /////////////////////////////////////////////////////////////////////////////
  1592. //++
  1593. //
  1594. // CClusPropList::CopyExpandSzProp
  1595. //
  1596. // Description:
  1597. // Copy an EXPAND_SZ string property to a property structure.
  1598. //
  1599. // Arguments:
  1600. // pprop [OUT] Property structure to fill.
  1601. // cptPropType [IN] Type of string.
  1602. // psz [IN] String to copy.
  1603. // cbsz [IN] Count of bytes in psz string.
  1604. //
  1605. // Return Value:
  1606. // None.
  1607. //
  1608. //--
  1609. /////////////////////////////////////////////////////////////////////////////
  1610. void CClusPropList::CopyExpandSzProp(
  1611. OUT PCLUSPROP_SZ pprop,
  1612. IN CLUSTER_PROPERTY_TYPE cptPropType,
  1613. IN LPCWSTR psz,
  1614. IN DWORD cbsz
  1615. )
  1616. {
  1617. ASSERT( pprop != NULL );
  1618. ASSERT( psz != NULL );
  1619. CLUSPROP_BUFFER_HELPER _cbhProps;
  1620. pprop->Syntax.wFormat = CLUSPROP_FORMAT_EXPAND_SZ;
  1621. pprop->Syntax.wType = static_cast< WORD >( cptPropType );
  1622. if ( cbsz == 0 )
  1623. {
  1624. cbsz = (lstrlenW( psz ) + 1) * sizeof( WCHAR );
  1625. } // if: cbsz == 0
  1626. ASSERT( cbsz == (lstrlenW( psz ) + 1) * sizeof( WCHAR ) );
  1627. pprop->cbLength = cbsz;
  1628. lstrcpyW( pprop->sz, psz );
  1629. //
  1630. // Set an endmark.
  1631. //
  1632. _cbhProps.pStringValue = pprop;
  1633. _cbhProps.pb += sizeof( *_cbhProps.pStringValue ) + ALIGN_CLUSPROP( cbsz );
  1634. _cbhProps.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  1635. } //*** CClusPropList::CopyExpandSzProp()
  1636. /////////////////////////////////////////////////////////////////////////////
  1637. //++
  1638. //
  1639. // CClusPropList::CopyProp
  1640. //
  1641. // Description:
  1642. // Copy a DWORD property to a property structure.
  1643. //
  1644. // Arguments:
  1645. // pprop [OUT] Property structure to fill.
  1646. // cptPropType [IN] Type of DWORD.
  1647. // nValue [IN] Property value to copy.
  1648. //
  1649. // Return Value:
  1650. // None.
  1651. //
  1652. //--
  1653. /////////////////////////////////////////////////////////////////////////////
  1654. void CClusPropList::CopyProp(
  1655. OUT PCLUSPROP_DWORD pprop,
  1656. IN CLUSTER_PROPERTY_TYPE cptPropType,
  1657. IN DWORD nValue
  1658. )
  1659. {
  1660. ASSERT( pprop != NULL );
  1661. CLUSPROP_BUFFER_HELPER _cbhProps;
  1662. pprop->Syntax.wFormat = CLUSPROP_FORMAT_DWORD;
  1663. pprop->Syntax.wType = static_cast< WORD >( cptPropType );
  1664. pprop->cbLength = sizeof( DWORD );
  1665. pprop->dw = nValue;
  1666. //
  1667. // Set an endmark.
  1668. //
  1669. _cbhProps.pDwordValue = pprop;
  1670. _cbhProps.pb += sizeof( *_cbhProps.pDwordValue );
  1671. _cbhProps.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  1672. } //*** CClusPropList::CopyProp( DWORD )
  1673. #if CLUSAPI_VERSION >= 0x0500
  1674. /////////////////////////////////////////////////////////////////////////////
  1675. //++
  1676. //
  1677. // CClusPropList::CopyProp
  1678. //
  1679. // Description:
  1680. // Copy a LONG property to a property structure.
  1681. //
  1682. // Arguments:
  1683. // pprop [OUT] Property structure to fill.
  1684. // cptPropType [IN] Type of LONG.
  1685. // nValue [IN] Property value to copy.
  1686. //
  1687. // Return Value:
  1688. // None.
  1689. //
  1690. //--
  1691. /////////////////////////////////////////////////////////////////////////////
  1692. void CClusPropList::CopyProp(
  1693. OUT PCLUSPROP_LONG pprop,
  1694. IN CLUSTER_PROPERTY_TYPE cptPropType,
  1695. IN LONG nValue
  1696. )
  1697. {
  1698. ASSERT( pprop != NULL );
  1699. CLUSPROP_BUFFER_HELPER _cbhProps;
  1700. pprop->Syntax.wFormat = CLUSPROP_FORMAT_LONG;
  1701. pprop->Syntax.wType = static_cast< WORD >( cptPropType );
  1702. pprop->cbLength = sizeof( LONG );
  1703. pprop->l = nValue;
  1704. //
  1705. // Set an endmark.
  1706. //
  1707. _cbhProps.pLongValue = pprop;
  1708. _cbhProps.pb += sizeof( *_cbhProps.pLongValue );
  1709. _cbhProps.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  1710. } //*** CClusPropList::CopyProp( LONG )
  1711. #endif // CLUSAPI_VERSION >= 0x0500
  1712. /////////////////////////////////////////////////////////////////////////////
  1713. //++
  1714. //
  1715. // CClusPropList::CopyProp
  1716. //
  1717. // Description:
  1718. // Copy a ULONGLONG property to a property structure.
  1719. //
  1720. // Arguments:
  1721. // pprop [OUT] Property structure to fill.
  1722. // proptype [IN] Type of LONG.
  1723. // nValue [IN] Property value to copy.
  1724. //
  1725. // Return Value:
  1726. // None.
  1727. //
  1728. //--
  1729. /////////////////////////////////////////////////////////////////////////////
  1730. void CClusPropList::CopyProp(
  1731. OUT PCLUSPROP_ULARGE_INTEGER pprop,
  1732. IN CLUSTER_PROPERTY_TYPE proptype,
  1733. IN ULONGLONG nValue
  1734. )
  1735. {
  1736. ASSERT( pprop != NULL );
  1737. CLUSPROP_BUFFER_HELPER _cbhProps;
  1738. pprop->Syntax.wFormat = CLUSPROP_FORMAT_ULARGE_INTEGER;
  1739. pprop->Syntax.wType = static_cast< WORD >( proptype );
  1740. pprop->cbLength = sizeof( ULONGLONG );
  1741. pprop->li.QuadPart = nValue;
  1742. //
  1743. // Set an endmark.
  1744. //
  1745. _cbhProps.pULargeIntegerValue = pprop;
  1746. _cbhProps.pb += sizeof( *_cbhProps.pULargeIntegerValue );
  1747. _cbhProps.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  1748. } //*** CClusPropList::CopyProp( ULONGLONG )
  1749. /////////////////////////////////////////////////////////////////////////////
  1750. //++
  1751. //
  1752. // CClusPropList::CopyProp
  1753. //
  1754. // Description:
  1755. // Copy a binary property to a property structure.
  1756. //
  1757. // Arguments:
  1758. // pprop [OUT] Property structure to fill.
  1759. // cptPropType [IN] Type of string.
  1760. // pb [IN] Block to copy.
  1761. // cbsz [IN] Count of bytes in pb buffer.
  1762. //
  1763. // Return Value:
  1764. // None.
  1765. //
  1766. //--
  1767. /////////////////////////////////////////////////////////////////////////////
  1768. void CClusPropList::CopyProp(
  1769. OUT PCLUSPROP_BINARY pprop,
  1770. IN CLUSTER_PROPERTY_TYPE cptPropType,
  1771. IN const PBYTE pb,
  1772. IN DWORD cb
  1773. )
  1774. {
  1775. ASSERT( pprop != NULL );
  1776. CLUSPROP_BUFFER_HELPER _cbhProps;
  1777. pprop->Syntax.wFormat = CLUSPROP_FORMAT_BINARY;
  1778. pprop->Syntax.wType = static_cast< WORD >( cptPropType );
  1779. pprop->cbLength = cb;
  1780. if ( cb > 0 )
  1781. {
  1782. CopyMemory( pprop->rgb, pb, cb );
  1783. } // if: non-zero data length
  1784. //
  1785. // Set an endmark.
  1786. //
  1787. _cbhProps.pBinaryValue = pprop;
  1788. _cbhProps.pb += sizeof( *_cbhProps.pStringValue ) + ALIGN_CLUSPROP( cb );
  1789. _cbhProps.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  1790. } //*** CClusPropList::CopyProp( PBYTE )
  1791. /////////////////////////////////////////////////////////////////////////////
  1792. //++
  1793. //
  1794. // CClusPropList::CopyEmptyProp
  1795. //
  1796. // Description:
  1797. // Copy an empty property to a property structure.
  1798. //
  1799. // Arguments:
  1800. // pprop [OUT] Property structure to fill.
  1801. // cptPropType [IN] Type of property.
  1802. // cpfPropFmt [IN] Format of property.
  1803. //
  1804. // Return Value:
  1805. // None.
  1806. //
  1807. //--
  1808. /////////////////////////////////////////////////////////////////////////////
  1809. void CClusPropList::CopyEmptyProp(
  1810. OUT PCLUSPROP_VALUE pprop,
  1811. IN CLUSTER_PROPERTY_TYPE cptPropType,
  1812. IN CLUSTER_PROPERTY_FORMAT cptPropFmt
  1813. )
  1814. {
  1815. ASSERT( pprop != NULL );
  1816. CLUSPROP_BUFFER_HELPER _cbhProps;
  1817. pprop->Syntax.wFormat = static_cast< WORD >( cptPropFmt );
  1818. pprop->Syntax.wType = static_cast< WORD >( cptPropType );
  1819. pprop->cbLength = 0;
  1820. //
  1821. // Set an endmark.
  1822. //
  1823. _cbhProps.pValue = pprop;
  1824. _cbhProps.pb += sizeof( *_cbhProps.pValue );
  1825. _cbhProps.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  1826. } //*** CClusPropList::CopyEmptyProp()
  1827. /////////////////////////////////////////////////////////////////////////////
  1828. //++
  1829. //
  1830. // CClusPropList::ScGetNodeProperties
  1831. //
  1832. // Description:
  1833. // Get properties on a node.
  1834. //
  1835. // Arguments:
  1836. // hNode [IN] Handle for the node to get properties from.
  1837. // dwControlCode [IN] Control code for the request.
  1838. // hHostNode [IN] Handle for the node to direct this request to.
  1839. // Defaults to NULL.
  1840. // lpInBuffer [IN] Input buffer for the request. Defaults to NULL.
  1841. // cbInBufferSize [IN] Size of the input buffer. Defaults to 0.
  1842. //
  1843. // Return Value:
  1844. // None.
  1845. //
  1846. // Exceptions Thrown:
  1847. // Any exceptions CClusPropList::ScAllocPropList().
  1848. //
  1849. //--
  1850. /////////////////////////////////////////////////////////////////////////////
  1851. DWORD CClusPropList::ScGetNodeProperties(
  1852. IN HNODE hNode,
  1853. IN DWORD dwControlCode,
  1854. IN HNODE hHostNode,
  1855. IN LPVOID lpInBuffer,
  1856. IN DWORD cbInBufferSize
  1857. )
  1858. {
  1859. ASSERT( hNode != NULL );
  1860. ASSERT( (dwControlCode & (CLUSCTL_OBJECT_MASK << CLUSCTL_OBJECT_SHIFT))
  1861. == (CLUS_OBJECT_NODE << CLUSCTL_OBJECT_SHIFT) );
  1862. DWORD _sc = ERROR_SUCCESS;
  1863. DWORD _cbProps = 256;
  1864. //
  1865. // Overwrite anything that may be in the buffer.
  1866. // Allows this class instance to be reused.
  1867. //
  1868. m_cbDataSize = 0;
  1869. //
  1870. // Get properties.
  1871. //
  1872. _sc = ScAllocPropList( _cbProps );
  1873. if ( _sc == ERROR_SUCCESS )
  1874. {
  1875. _sc = ClusterNodeControl(
  1876. hNode,
  1877. hHostNode,
  1878. dwControlCode,
  1879. lpInBuffer,
  1880. cbInBufferSize,
  1881. m_cbhPropList.pb,
  1882. m_cbBufferSize,
  1883. &_cbProps
  1884. );
  1885. if ( _sc == ERROR_MORE_DATA )
  1886. {
  1887. _sc = ScAllocPropList( _cbProps );
  1888. if ( _sc == ERROR_SUCCESS )
  1889. {
  1890. _sc = ClusterNodeControl(
  1891. hNode,
  1892. hHostNode,
  1893. dwControlCode,
  1894. lpInBuffer,
  1895. cbInBufferSize,
  1896. m_cbhPropList.pb,
  1897. m_cbBufferSize,
  1898. &_cbProps
  1899. );
  1900. } // if: ScAllocPropList succeeded
  1901. } // if: buffer too small
  1902. } // if: ScAllocPropList succeeded
  1903. if ( _sc != ERROR_SUCCESS )
  1904. {
  1905. DeletePropList();
  1906. } // if: error getting properties.
  1907. else
  1908. {
  1909. m_cbDataSize = _cbProps;
  1910. m_cbDataLeft = _cbProps;
  1911. } // else: no errors
  1912. return _sc;
  1913. } //*** CClusPropList::ScGetNodeProperties()
  1914. /////////////////////////////////////////////////////////////////////////////
  1915. //++
  1916. //
  1917. // CClusPropList::ScGetGroupProperties
  1918. //
  1919. // Description:
  1920. // Get properties on a group.
  1921. //
  1922. // Arguments:
  1923. // hGroup [IN] Handle for the group to get properties from.
  1924. // dwControlCode [IN] Control code for the request.
  1925. // hHostNode [IN] Handle for the node to direct this request to.
  1926. // Defaults to NULL.
  1927. // lpInBuffer [IN] Input buffer for the request. Defaults to NULL.
  1928. // cbInBufferSize [IN] Size of the input buffer. Defaults to 0.
  1929. //
  1930. // Return Value:
  1931. // None.
  1932. //
  1933. // Exceptions Thrown:
  1934. // Any exceptions CClusPropList::ScAllocPropList().
  1935. //
  1936. //--
  1937. /////////////////////////////////////////////////////////////////////////////
  1938. DWORD CClusPropList::ScGetGroupProperties(
  1939. IN HGROUP hGroup,
  1940. IN DWORD dwControlCode,
  1941. IN HNODE hHostNode,
  1942. IN LPVOID lpInBuffer,
  1943. IN DWORD cbInBufferSize
  1944. )
  1945. {
  1946. ASSERT( hGroup != NULL );
  1947. ASSERT( (dwControlCode & (CLUSCTL_OBJECT_MASK << CLUSCTL_OBJECT_SHIFT))
  1948. == (CLUS_OBJECT_GROUP << CLUSCTL_OBJECT_SHIFT) );
  1949. DWORD _sc = ERROR_SUCCESS;
  1950. DWORD _cbProps = 256;
  1951. //
  1952. // Overwrite anything that may be in the buffer.
  1953. // Allows this class instance to be reused.
  1954. //
  1955. m_cbDataSize = 0;
  1956. //
  1957. // Get properties.
  1958. //
  1959. _sc = ScAllocPropList( _cbProps );
  1960. if ( _sc == ERROR_SUCCESS )
  1961. {
  1962. _sc = ClusterGroupControl(
  1963. hGroup,
  1964. hHostNode,
  1965. dwControlCode,
  1966. lpInBuffer,
  1967. cbInBufferSize,
  1968. m_cbhPropList.pb,
  1969. m_cbBufferSize,
  1970. &_cbProps
  1971. );
  1972. if ( _sc == ERROR_MORE_DATA )
  1973. {
  1974. _sc = ScAllocPropList( _cbProps );
  1975. if ( _sc == ERROR_SUCCESS )
  1976. {
  1977. _sc = ClusterGroupControl(
  1978. hGroup,
  1979. hHostNode,
  1980. dwControlCode,
  1981. lpInBuffer,
  1982. cbInBufferSize,
  1983. m_cbhPropList.pb,
  1984. m_cbBufferSize,
  1985. &_cbProps
  1986. );
  1987. } // if: ScAllocPropList succeeded
  1988. } // if: buffer too small
  1989. } // if: ScAllocPropList succeeded
  1990. if ( _sc != ERROR_SUCCESS )
  1991. {
  1992. DeletePropList();
  1993. } // if: error getting properties.
  1994. else
  1995. {
  1996. m_cbDataSize = _cbProps;
  1997. m_cbDataLeft = _cbProps;
  1998. } // else: no errors
  1999. return _sc;
  2000. } //*** CClusPropList::ScGetGroupProperties()
  2001. /////////////////////////////////////////////////////////////////////////////
  2002. //++
  2003. //
  2004. // CClusPropList::ScGetResourceProperties
  2005. //
  2006. // Description:
  2007. // Get properties on a resource.
  2008. //
  2009. // Arguments:
  2010. // hResource [IN] Handle for the resource to get properties from.
  2011. // dwControlCode [IN] Control code for the request.
  2012. // hHostNode [IN] Handle for the node to direct this request to.
  2013. // Defaults to NULL.
  2014. // lpInBuffer [IN] Input buffer for the request. Defaults to NULL.
  2015. // cbInBufferSize [IN] Size of the input buffer. Defaults to 0.
  2016. //
  2017. // Return Value:
  2018. // None.
  2019. //
  2020. // Exceptions Thrown:
  2021. // Any exceptions CClusPropList::ScAllocPropList().
  2022. //
  2023. //--
  2024. /////////////////////////////////////////////////////////////////////////////
  2025. DWORD CClusPropList::ScGetResourceProperties(
  2026. IN HRESOURCE hResource,
  2027. IN DWORD dwControlCode,
  2028. IN HNODE hHostNode,
  2029. IN LPVOID lpInBuffer,
  2030. IN DWORD cbInBufferSize
  2031. )
  2032. {
  2033. ASSERT( hResource != NULL );
  2034. ASSERT( (dwControlCode & (CLUSCTL_OBJECT_MASK << CLUSCTL_OBJECT_SHIFT))
  2035. == (CLUS_OBJECT_RESOURCE << CLUSCTL_OBJECT_SHIFT) );
  2036. DWORD _sc = ERROR_SUCCESS;
  2037. DWORD _cbProps = 256;
  2038. //
  2039. // Overwrite anything that may be in the buffer.
  2040. // Allows this class instance to be reused.
  2041. //
  2042. m_cbDataSize = 0;
  2043. //
  2044. // Get properties.
  2045. //
  2046. _sc = ScAllocPropList( _cbProps );
  2047. if ( _sc == ERROR_SUCCESS )
  2048. {
  2049. _sc = ClusterResourceControl(
  2050. hResource,
  2051. hHostNode,
  2052. dwControlCode,
  2053. lpInBuffer,
  2054. cbInBufferSize,
  2055. m_cbhPropList.pb,
  2056. m_cbBufferSize,
  2057. &_cbProps
  2058. );
  2059. if ( _sc == ERROR_MORE_DATA )
  2060. {
  2061. _sc = ScAllocPropList( _cbProps );
  2062. if ( _sc == ERROR_SUCCESS )
  2063. {
  2064. _sc = ClusterResourceControl(
  2065. hResource,
  2066. hHostNode,
  2067. dwControlCode,
  2068. lpInBuffer,
  2069. cbInBufferSize,
  2070. m_cbhPropList.pb,
  2071. m_cbBufferSize,
  2072. &_cbProps
  2073. );
  2074. } // if: ScAllocPropList succeeded
  2075. } // if: buffer too small
  2076. } // if: ScAllocPropList succeeded
  2077. if ( _sc != ERROR_SUCCESS )
  2078. {
  2079. DeletePropList();
  2080. } // if: error getting properties.
  2081. else
  2082. {
  2083. m_cbDataSize = _cbProps;
  2084. m_cbDataLeft = _cbProps;
  2085. } // else: no errors
  2086. return _sc;
  2087. } //*** CClusPropList::ScGetResourceProperties()
  2088. /////////////////////////////////////////////////////////////////////////////
  2089. //++
  2090. //
  2091. // CClusPropList::ScGetResourceTypeProperties
  2092. //
  2093. // Description:
  2094. // Get properties on a resource type.
  2095. //
  2096. // Arguments:
  2097. // hCluster [IN] Handle for the cluster in which the resource
  2098. // type resides.
  2099. // pwszResTypeName [IN] Name of the resource type.
  2100. // dwControlCode [IN] Control code for the request.
  2101. // hHostNode [IN] Handle for the node to direct this request to.
  2102. // Defaults to NULL.
  2103. // lpInBuffer [IN] Input buffer for the request. Defaults to NULL.
  2104. // cbInBufferSize [IN] Size of the input buffer. Defaults to 0.
  2105. //
  2106. // Return Value:
  2107. // None.
  2108. //
  2109. // Exceptions Thrown:
  2110. // Any exceptions CClusPropList::ScAllocPropList().
  2111. //
  2112. //--
  2113. /////////////////////////////////////////////////////////////////////////////
  2114. DWORD CClusPropList::ScGetResourceTypeProperties(
  2115. IN HCLUSTER hCluster,
  2116. IN LPCWSTR pwszResTypeName,
  2117. IN DWORD dwControlCode,
  2118. IN HNODE hHostNode,
  2119. IN LPVOID lpInBuffer,
  2120. IN DWORD cbInBufferSize
  2121. )
  2122. {
  2123. ASSERT( hCluster != NULL );
  2124. ASSERT( pwszResTypeName != NULL );
  2125. ASSERT( *pwszResTypeName != L'\0' );
  2126. ASSERT( (dwControlCode & (CLUSCTL_OBJECT_MASK << CLUSCTL_OBJECT_SHIFT))
  2127. == (CLUS_OBJECT_RESOURCE_TYPE << CLUSCTL_OBJECT_SHIFT) );
  2128. DWORD _sc = ERROR_SUCCESS;
  2129. DWORD _cbProps = 256;
  2130. //
  2131. // Overwrite anything that may be in the buffer.
  2132. // Allows this class instance to be reused.
  2133. //
  2134. m_cbDataSize = 0;
  2135. //
  2136. // Get properties.
  2137. //
  2138. _sc = ScAllocPropList( _cbProps );
  2139. if ( _sc == ERROR_SUCCESS )
  2140. {
  2141. _sc = ClusterResourceTypeControl(
  2142. hCluster,
  2143. pwszResTypeName,
  2144. hHostNode,
  2145. dwControlCode,
  2146. lpInBuffer,
  2147. cbInBufferSize,
  2148. m_cbhPropList.pb,
  2149. m_cbBufferSize,
  2150. &_cbProps
  2151. );
  2152. if ( _sc == ERROR_MORE_DATA )
  2153. {
  2154. _sc = ScAllocPropList( _cbProps );
  2155. if ( _sc == ERROR_SUCCESS )
  2156. {
  2157. _sc = ClusterResourceTypeControl(
  2158. hCluster,
  2159. pwszResTypeName,
  2160. hHostNode,
  2161. dwControlCode,
  2162. lpInBuffer,
  2163. cbInBufferSize,
  2164. m_cbhPropList.pb,
  2165. m_cbBufferSize,
  2166. &_cbProps
  2167. );
  2168. } // if: ScAllocPropList succeeded
  2169. } // if: buffer too small
  2170. } // if: ScAllocPropList succeeded
  2171. if ( _sc != ERROR_SUCCESS )
  2172. {
  2173. DeletePropList();
  2174. } // if: error getting properties.
  2175. else
  2176. {
  2177. m_cbDataSize = _cbProps;
  2178. m_cbDataLeft = _cbProps;
  2179. } // else: no errors
  2180. return _sc;
  2181. } //*** CClusPropList::ScGetResourceTypeProperties()
  2182. /////////////////////////////////////////////////////////////////////////////
  2183. //++
  2184. //
  2185. // CClusPropList::ScGetNetworkProperties
  2186. //
  2187. // Description:
  2188. // Get properties on a network.
  2189. //
  2190. // Arguments:
  2191. // hNetwork [IN] Handle for the network to get properties from.
  2192. // dwControlCode [IN] Control code for the request.
  2193. // hHostNode [IN] Handle for the node to direct this request to.
  2194. // Defaults to NULL.
  2195. // lpInBuffer [IN] Input buffer for the request. Defaults to NULL.
  2196. // cbInBufferSize [IN] Size of the input buffer. Defaults to 0.
  2197. //
  2198. // Return Value:
  2199. // None.
  2200. //
  2201. // Exceptions Thrown:
  2202. // Any exceptions CClusPropList::ScAllocPropList().
  2203. //
  2204. //--
  2205. /////////////////////////////////////////////////////////////////////////////
  2206. DWORD CClusPropList::ScGetNetworkProperties(
  2207. IN HNETWORK hNetwork,
  2208. IN DWORD dwControlCode,
  2209. IN HNODE hHostNode,
  2210. IN LPVOID lpInBuffer,
  2211. IN DWORD cbInBufferSize
  2212. )
  2213. {
  2214. ASSERT( hNetwork != NULL );
  2215. ASSERT( (dwControlCode & (CLUSCTL_OBJECT_MASK << CLUSCTL_OBJECT_SHIFT))
  2216. == (CLUS_OBJECT_NETWORK << CLUSCTL_OBJECT_SHIFT) );
  2217. DWORD _sc = ERROR_SUCCESS;
  2218. DWORD _cbProps = 256;
  2219. //
  2220. // Overwrite anything that may be in the buffer.
  2221. // Allows this class instance to be reused.
  2222. //
  2223. m_cbDataSize = 0;
  2224. //
  2225. // Get properties.
  2226. //
  2227. _sc = ScAllocPropList( _cbProps );
  2228. if ( _sc == ERROR_SUCCESS )
  2229. {
  2230. _sc = ClusterNetworkControl(
  2231. hNetwork,
  2232. hHostNode,
  2233. dwControlCode,
  2234. lpInBuffer,
  2235. cbInBufferSize,
  2236. m_cbhPropList.pb,
  2237. m_cbBufferSize,
  2238. &_cbProps
  2239. );
  2240. if ( _sc == ERROR_MORE_DATA )
  2241. {
  2242. _sc = ScAllocPropList( _cbProps );
  2243. if ( _sc == ERROR_SUCCESS )
  2244. {
  2245. _sc = ClusterNetworkControl(
  2246. hNetwork,
  2247. hHostNode,
  2248. dwControlCode,
  2249. lpInBuffer,
  2250. cbInBufferSize,
  2251. m_cbhPropList.pb,
  2252. m_cbBufferSize,
  2253. &_cbProps
  2254. );
  2255. } // if: ScAllocPropList succeeded
  2256. } // if: buffer too small
  2257. } // if: ScAllocPropList succeeded
  2258. if ( _sc != ERROR_SUCCESS )
  2259. {
  2260. DeletePropList();
  2261. } // if: error getting private properties.
  2262. else
  2263. {
  2264. m_cbDataSize = _cbProps;
  2265. m_cbDataLeft = _cbProps;
  2266. } // else: no errors
  2267. return _sc;
  2268. } //*** CClusPropList::ScGetNetworkProperties()
  2269. /////////////////////////////////////////////////////////////////////////////
  2270. //++
  2271. //
  2272. // CClusPropList::ScGetNetInterfaceProperties
  2273. //
  2274. // Description:
  2275. // Get properties on a network interface.
  2276. //
  2277. // Arguments:
  2278. // hNetInterface [IN] Handle for the network interface to get properties from.
  2279. // dwControlCode [IN] Control code for the request.
  2280. // hHostNode [IN] Handle for the node to direct this request to.
  2281. // Defaults to NULL.
  2282. // lpInBuffer [IN] Input buffer for the request. Defaults to NULL.
  2283. // cbInBufferSize [IN] Size of the input buffer. Defaults to 0.
  2284. //
  2285. // Return Value:
  2286. // None.
  2287. //
  2288. // Exceptions Thrown:
  2289. // Any exceptions CClusPropList::ScAllocPropList().
  2290. //
  2291. //--
  2292. /////////////////////////////////////////////////////////////////////////////
  2293. DWORD CClusPropList::ScGetNetInterfaceProperties(
  2294. IN HNETINTERFACE hNetInterface,
  2295. IN DWORD dwControlCode,
  2296. IN HNODE hHostNode,
  2297. IN LPVOID lpInBuffer,
  2298. IN DWORD cbInBufferSize
  2299. )
  2300. {
  2301. ASSERT( hNetInterface != NULL );
  2302. ASSERT( (dwControlCode & (CLUSCTL_OBJECT_MASK << CLUSCTL_OBJECT_SHIFT))
  2303. == (CLUS_OBJECT_NETINTERFACE << CLUSCTL_OBJECT_SHIFT) );
  2304. DWORD _sc= ERROR_SUCCESS;
  2305. DWORD _cbProps = 256;
  2306. //
  2307. // Overwrite anything that may be in the buffer.
  2308. // Allows this class instance to be reused.
  2309. //
  2310. m_cbDataSize = 0;
  2311. //
  2312. // Get properties.
  2313. //
  2314. _sc = ScAllocPropList( _cbProps );
  2315. if ( _sc == ERROR_SUCCESS )
  2316. {
  2317. _sc = ClusterNetInterfaceControl(
  2318. hNetInterface,
  2319. hHostNode,
  2320. dwControlCode,
  2321. lpInBuffer,
  2322. cbInBufferSize,
  2323. m_cbhPropList.pb,
  2324. m_cbBufferSize,
  2325. &_cbProps
  2326. );
  2327. if ( _sc == ERROR_MORE_DATA )
  2328. {
  2329. _sc = ScAllocPropList( _cbProps );
  2330. if ( _sc == ERROR_SUCCESS )
  2331. {
  2332. _sc = ClusterNetInterfaceControl(
  2333. hNetInterface,
  2334. hHostNode,
  2335. dwControlCode,
  2336. lpInBuffer,
  2337. cbInBufferSize,
  2338. m_cbhPropList.pb,
  2339. m_cbBufferSize,
  2340. &_cbProps
  2341. );
  2342. } // if: ScAllocPropList succeeded
  2343. } // if: buffer too small
  2344. } // if: ScAllocPropList succeeded
  2345. if ( _sc != ERROR_SUCCESS )
  2346. {
  2347. DeletePropList();
  2348. } // if: error getting private properties.
  2349. else
  2350. {
  2351. m_cbDataSize = _cbProps;
  2352. m_cbDataLeft = _cbProps;
  2353. } // else: no errors
  2354. return _sc;
  2355. } //*** CClusPropList::ScGetNetInterfaceProperties()
  2356. #if CLUSAPI_VERSION >= 0x0500
  2357. /////////////////////////////////////////////////////////////////////////////
  2358. //++
  2359. //
  2360. // CClusPropList::ScGetClusterProperties
  2361. //
  2362. // Description:
  2363. // Get properties on a cluster.
  2364. //
  2365. // Arguments:
  2366. // hCluster [IN] Handle for the cluster to get properties from.
  2367. // dwControlCode [IN] Control code for the request.
  2368. // hHostNode [IN] Handle for the node to direct this request to.
  2369. // Defaults to NULL.
  2370. // lpInBuffer [IN] Input buffer for the request. Defaults to NULL.
  2371. // cbInBufferSize [IN] Size of the input buffer. Defaults to 0.
  2372. //
  2373. // Return Value:
  2374. // None.
  2375. //
  2376. // Exceptions Thrown:
  2377. // Any exceptions CClusPropList::ScAllocPropList().
  2378. //
  2379. //--
  2380. /////////////////////////////////////////////////////////////////////////////
  2381. DWORD CClusPropList::ScGetClusterProperties(
  2382. IN HCLUSTER hCluster,
  2383. IN DWORD dwControlCode,
  2384. IN HNODE hHostNode,
  2385. IN LPVOID lpInBuffer,
  2386. IN DWORD cbInBufferSize
  2387. )
  2388. {
  2389. ASSERT( hCluster != NULL );
  2390. ASSERT( (dwControlCode & (CLUSCTL_OBJECT_MASK << CLUSCTL_OBJECT_SHIFT))
  2391. == (CLUS_OBJECT_CLUSTER << CLUSCTL_OBJECT_SHIFT) );
  2392. ASSERT( dwControlCode == CLUSCTL_CLUSTER_GET_COMMON_PROPERTIES );
  2393. DWORD _sc= ERROR_SUCCESS;
  2394. DWORD _cbProps = 256;
  2395. //
  2396. // Overwrite anything that may be in the buffer.
  2397. // Allows this class instance to be reused.
  2398. //
  2399. m_cbDataSize = 0;
  2400. //
  2401. // Get properties.
  2402. //
  2403. _sc = ScAllocPropList( _cbProps );
  2404. if ( _sc == ERROR_SUCCESS )
  2405. {
  2406. _sc = ClusterControl(
  2407. hCluster,
  2408. hHostNode,
  2409. dwControlCode,
  2410. lpInBuffer,
  2411. cbInBufferSize,
  2412. m_cbhPropList.pb,
  2413. m_cbBufferSize,
  2414. &_cbProps
  2415. );
  2416. if ( _sc == ERROR_MORE_DATA )
  2417. {
  2418. _sc = ScAllocPropList( _cbProps );
  2419. if ( _sc == ERROR_SUCCESS )
  2420. {
  2421. _sc = ClusterControl(
  2422. hCluster,
  2423. hHostNode,
  2424. dwControlCode,
  2425. lpInBuffer,
  2426. cbInBufferSize,
  2427. m_cbhPropList.pb,
  2428. m_cbBufferSize,
  2429. &_cbProps
  2430. );
  2431. } // if: ScAllocPropList succeeded
  2432. } // if: buffer too small
  2433. } // if: ScAllocPropList succeeded
  2434. if ( _sc != ERROR_SUCCESS )
  2435. {
  2436. DeletePropList();
  2437. } // if: error getting private properties.
  2438. else
  2439. {
  2440. m_cbDataSize = _cbProps;
  2441. m_cbDataLeft = _cbProps;
  2442. } // else: no errors
  2443. return _sc;
  2444. } //*** CClusPropList::ScGetClusterProperties()
  2445. #endif // CLUSAPI_VERSION >= 0x0500