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.

1597 lines
34 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2001 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // ClusterUtils.h
  7. //
  8. // Description:
  9. // This file contains the implementations of the ClusterUtils
  10. // functions.
  11. //
  12. //
  13. // Documentation:
  14. //
  15. // Maintained By:
  16. //
  17. //////////////////////////////////////////////////////////////////////////////
  18. #include "pch.h"
  19. #include <clusrtl.h>
  20. #include "CBaseInfo.h"
  21. #include "CBasePropList.h"
  22. #include "ClusterUtils.h"
  23. #define STACK_ARRAY_SIZE 256
  24. //////////////////////////////////////////////////////////////////////////////
  25. //++
  26. //
  27. // HrSeparateDomainAndName()
  28. //
  29. // Description:
  30. //
  31. //
  32. // Arguments:
  33. //
  34. //
  35. // Return Value:
  36. //
  37. // Remarks:
  38. // None.
  39. //
  40. //--
  41. //////////////////////////////////////////////////////////////////////////////
  42. HRESULT
  43. HrSeparateDomainAndName(
  44. BSTR bstrNameIn,
  45. BSTR * pbstrDomainOut,
  46. BSTR * pbstrNameOut
  47. )
  48. {
  49. TraceFunc( "" );
  50. HRESULT hr = S_OK;
  51. WCHAR * psz = NULL;
  52. if ( bstrNameIn == NULL )
  53. {
  54. hr = THR( E_INVALIDARG );
  55. goto Exit;
  56. } // if:
  57. psz = wcschr( bstrNameIn, L'.' );
  58. if ( psz == NULL )
  59. {
  60. hr = THR( E_INVALIDARG );
  61. goto Exit;
  62. } // if:
  63. if ( pbstrDomainOut != NULL )
  64. {
  65. psz++; // skip the .
  66. *pbstrDomainOut = TraceSysAllocString( psz );
  67. if ( *pbstrDomainOut == NULL )
  68. {
  69. hr = THR( E_OUTOFMEMORY );
  70. goto Exit;
  71. } // if:
  72. psz--; // reset back to .
  73. } // if:
  74. if ( pbstrNameOut != NULL )
  75. {
  76. *pbstrNameOut = TraceSysAllocStringLen( NULL, (UINT)( psz - bstrNameIn ) );
  77. if ( *pbstrNameOut == NULL )
  78. {
  79. hr = THR( E_OUTOFMEMORY );
  80. goto Exit;
  81. } // if:
  82. wcsncpy( *pbstrNameOut, bstrNameIn, ( psz - bstrNameIn) );
  83. } // if:
  84. Exit:
  85. HRETURN ( hr );
  86. } //*** HrSeparateDomainAndName()
  87. //////////////////////////////////////////////////////////////////////////////
  88. //++
  89. //
  90. // HrAppendDomainToName()
  91. //
  92. // Description:
  93. //
  94. //
  95. // Arguments:
  96. //
  97. //
  98. // Return Value:
  99. // S_OK = TRUE
  100. // S_FALSE = FALSE
  101. //
  102. // Remarks:
  103. // None.
  104. //
  105. //--
  106. //////////////////////////////////////////////////////////////////////////////
  107. HRESULT
  108. HrAppendDomainToName(
  109. BSTR bstrNameIn,
  110. BSTR bstrDomainIn,
  111. BSTR * pbstrDomainNameOut
  112. )
  113. {
  114. TraceFunc( "" );
  115. Assert( bstrNameIn != NULL );
  116. Assert( pbstrDomainNameOut != NULL );
  117. HRESULT hr = S_OK;
  118. size_t cchName = 0;
  119. if ( pbstrDomainNameOut == NULL )
  120. {
  121. hr = THR( E_POINTER );
  122. goto Exit;
  123. } // if:
  124. if ( bstrNameIn == NULL )
  125. {
  126. hr = THR( E_INVALIDARG );
  127. goto Exit;
  128. } // if:
  129. // Create a fully qualified node name
  130. if ( bstrDomainIn != NULL )
  131. {
  132. cchName = wcslen( bstrNameIn ) + wcslen( bstrDomainIn ) + 1;
  133. Assert( cchName <= MAXDWORD );
  134. *pbstrDomainNameOut = TraceSysAllocStringLen( NULL, (UINT) cchName );
  135. if ( *pbstrDomainNameOut == NULL )
  136. {
  137. hr = THR( E_OUTOFMEMORY );
  138. goto Exit;
  139. } // if:
  140. wcscpy( *pbstrDomainNameOut, bstrNameIn );
  141. wcscat( *pbstrDomainNameOut, L"." );
  142. wcscat( *pbstrDomainNameOut, bstrDomainIn );
  143. hr = S_OK;
  144. } // if:
  145. else
  146. {
  147. *pbstrDomainNameOut = TraceSysAllocString( bstrNameIn );
  148. if ( *pbstrDomainNameOut == NULL )
  149. {
  150. hr = THR( E_OUTOFMEMORY );
  151. goto Exit;
  152. } // if:
  153. hr = S_FALSE;
  154. } // else:
  155. Exit:
  156. HRETURN( hr );
  157. } //*** HrAppendDomainToName()
  158. //////////////////////////////////////////////////////////////////////////////
  159. //++
  160. //
  161. // HrIsCoreResource()
  162. //
  163. // Description:
  164. // Determines whether the resource is a core resource.
  165. //
  166. // Arguments:
  167. //
  168. //
  169. // Return Value:
  170. // S_OK = TRUE
  171. // S_FALSE = FALSE
  172. //
  173. // Remarks:
  174. // None.
  175. //
  176. //--
  177. //////////////////////////////////////////////////////////////////////////////
  178. HRESULT
  179. HrIsCoreResource( HRESOURCE hResIn )
  180. {
  181. TraceFunc( "" );
  182. HRESULT hr = S_FALSE;
  183. DWORD sc;
  184. DWORD dwFlags = 0;
  185. DWORD cb;
  186. sc = TW32( ClusterResourceControl( hResIn, NULL, CLUSCTL_RESOURCE_GET_FLAGS, NULL, 0, &dwFlags, sizeof( dwFlags ), &cb ) );
  187. if ( sc != ERROR_SUCCESS )
  188. {
  189. hr = HRESULT_FROM_WIN32( sc );
  190. goto Exit;
  191. } // if:
  192. if ( dwFlags & CLUS_FLAG_CORE )
  193. {
  194. hr = S_OK;
  195. } // if:
  196. Exit:
  197. HRETURN( hr );
  198. } //*** HrIsCoreResource()
  199. //////////////////////////////////////////////////////////////////////////////
  200. //++
  201. //
  202. // HrIsResourceOfType()
  203. //
  204. // Description:
  205. //
  206. //
  207. // Arguments:
  208. //
  209. //
  210. // Return Value:
  211. // S_OK = TRUE
  212. // S_FALSE = FALSE
  213. //
  214. // Remarks:
  215. // None.
  216. //
  217. //--
  218. //////////////////////////////////////////////////////////////////////////////
  219. HRESULT
  220. HrIsResourceOfType(
  221. HRESOURCE hResIn,
  222. const WCHAR * pszResourceTypeIn
  223. )
  224. {
  225. TraceFunc( "" );
  226. HRESULT hr = S_OK;
  227. DWORD sc;
  228. WCHAR * psz = NULL;
  229. DWORD cbpsz = 33;
  230. DWORD cb;
  231. int idx;
  232. psz = new WCHAR [ cbpsz * sizeof( WCHAR ) ];
  233. if ( psz == NULL )
  234. {
  235. goto OutOfMemory;
  236. } // if:
  237. for ( idx = 0; ; idx++ )
  238. {
  239. Assert( idx < 2 );
  240. sc = ClusterResourceControl( hResIn, NULL, CLUSCTL_RESOURCE_GET_RESOURCE_TYPE, NULL, 0, psz, cbpsz, &cb );
  241. if ( sc == ERROR_MORE_DATA )
  242. {
  243. delete [] psz;
  244. psz = NULL;
  245. cbpsz = cb + 1;
  246. psz = new WCHAR [ cbpsz * sizeof( WCHAR ) ];
  247. if ( psz == NULL )
  248. {
  249. goto OutOfMemory;
  250. } // if:
  251. continue;
  252. } // if:
  253. if ( sc != ERROR_SUCCESS )
  254. {
  255. hr = HRESULT_FROM_WIN32( TW32( sc ) );
  256. goto CleanUp;
  257. } // if:
  258. break;
  259. } // for:
  260. if ( wcscmp( psz, pszResourceTypeIn ) == 0 )
  261. {
  262. hr = S_OK;
  263. } // if:
  264. else
  265. {
  266. hr = S_FALSE;
  267. } // else:
  268. goto CleanUp;
  269. OutOfMemory:
  270. hr = THR( E_OUTOFMEMORY );
  271. CleanUp:
  272. delete [] psz;
  273. HRETURN( hr );
  274. } //*** HrIsResourceOfType()
  275. //////////////////////////////////////////////////////////////////////////////
  276. //++
  277. //
  278. // HrGetIPAddressInfo()
  279. //
  280. // Description:
  281. //
  282. //
  283. // Arguments:
  284. //
  285. //
  286. // Return Value:
  287. //
  288. //
  289. // Remarks:
  290. // None.
  291. //
  292. //--
  293. //////////////////////////////////////////////////////////////////////////////
  294. HRESULT
  295. HrGetIPAddressInfo( HRESOURCE hResIn, ULONG * pulIPAddress, ULONG * pulSubnetMask, BSTR * pbstrNetworkName )
  296. {
  297. TraceFunc( "" );
  298. HRESULT hr = S_OK;
  299. DWORD sc;
  300. CBasePropList cpl;
  301. CBaseClusterResourceInfo cbri;
  302. CLUSPROP_BUFFER_HELPER cpbh;
  303. cbri.m_hResource = hResIn;
  304. sc = TW32( cpl.ScGetProperties( cbri, cbri.ToCode( CONTROL_GET_PRIVATE_PROPERTIES ) ) );
  305. if ( sc != ERROR_SUCCESS )
  306. {
  307. goto MakeHr;
  308. } // if:
  309. sc = TW32( cpl.ScMoveToPropertyByName( L"Address" ) );
  310. if ( sc != ERROR_SUCCESS )
  311. {
  312. goto MakeHr;
  313. } // if:
  314. cpbh = cpl.CbhCurrentValue();
  315. Assert( cpbh.pSyntax->dw == CLUSPROP_SYNTAX_LIST_VALUE_SZ );
  316. sc = ClRtlTcpipStringToAddress( cpbh.pStringValue->sz, pulIPAddress );
  317. if ( sc != ERROR_SUCCESS )
  318. {
  319. goto MakeHr;
  320. } // if:
  321. sc = TW32( cpl.ScMoveToPropertyByName( L"SubnetMask" ) );
  322. if ( sc != ERROR_SUCCESS )
  323. {
  324. goto MakeHr;
  325. } // if:
  326. cpbh = cpl.CbhCurrentValue();
  327. Assert( cpbh.pSyntax->dw == CLUSPROP_SYNTAX_LIST_VALUE_SZ );
  328. sc = ClRtlTcpipStringToAddress( cpbh.pStringValue->sz, pulSubnetMask );
  329. if ( sc != ERROR_SUCCESS )
  330. {
  331. goto MakeHr;
  332. } // if:
  333. if( pbstrNetworkName )
  334. {
  335. sc = TW32( cpl.ScMoveToPropertyByName( L"Network" ) );
  336. if ( sc != ERROR_SUCCESS )
  337. {
  338. goto MakeHr;
  339. } // if:
  340. cpbh = cpl.CbhCurrentValue();
  341. Assert( cpbh.pSyntax->dw == CLUSPROP_SYNTAX_LIST_VALUE_SZ );
  342. *pbstrNetworkName = TraceSysAllocString( cpbh.pStringValue->sz );
  343. if( *pbstrNetworkName == NULL )
  344. {
  345. hr = E_OUTOFMEMORY;
  346. goto CleanUp;
  347. }
  348. }
  349. goto CleanUp;
  350. MakeHr:
  351. hr = HRESULT_FROM_WIN32( sc );
  352. CleanUp:
  353. cbri.m_hResource = NULL;
  354. HRETURN( hr );
  355. } //*** HrGetIPAddressInfo()
  356. //////////////////////////////////////////////////////////////////////////////
  357. //++
  358. //
  359. // HrLoadCredentials()
  360. //
  361. // Description:
  362. //
  363. //
  364. // Arguments:
  365. //
  366. //
  367. // Return Value:
  368. //
  369. //
  370. // Remarks:
  371. // None.
  372. //
  373. //--
  374. //////////////////////////////////////////////////////////////////////////////
  375. HRESULT
  376. HrLoadCredentials( BSTR bstrMachine, IClusCfgSetCredentials * piCCSC )
  377. {
  378. TraceFunc( "" );
  379. HRESULT hr = S_FALSE;
  380. SC_HANDLE schSCM = NULL;
  381. SC_HANDLE schClusSvc = NULL;
  382. DWORD sc;
  383. DWORD cbpqsc = 128;
  384. DWORD cbRequired;
  385. QUERY_SERVICE_CONFIG * pqsc = NULL;
  386. schSCM = OpenSCManager( bstrMachine, NULL, GENERIC_READ );
  387. if ( schSCM == NULL )
  388. {
  389. sc = TW32( GetLastError() );
  390. hr = HRESULT_FROM_WIN32( hr );
  391. goto CleanUp;
  392. } // if:
  393. schClusSvc = OpenService( schSCM, L"ClusSvc", GENERIC_READ );
  394. if ( schClusSvc == NULL )
  395. {
  396. sc = TW32( GetLastError() );
  397. hr = HRESULT_FROM_WIN32( hr );
  398. goto CleanUp;
  399. } // if:
  400. for ( ; ; )
  401. {
  402. pqsc = (QUERY_SERVICE_CONFIG *) TraceAlloc( 0, cbpqsc );
  403. if ( pqsc == NULL )
  404. {
  405. hr = THR( E_OUTOFMEMORY );
  406. goto CleanUp;
  407. } // if:
  408. if ( !QueryServiceConfig( schClusSvc, pqsc, cbpqsc, &cbRequired ) )
  409. {
  410. sc = GetLastError();
  411. if ( sc == ERROR_INSUFFICIENT_BUFFER )
  412. {
  413. TraceFree( pqsc );
  414. pqsc = NULL;
  415. cbpqsc = cbRequired;
  416. continue;
  417. } // if:
  418. else
  419. {
  420. TW32( sc );
  421. hr = HRESULT_FROM_WIN32( sc );
  422. goto CleanUp;
  423. } // else:
  424. } // if:
  425. else
  426. {
  427. break;
  428. } // else:
  429. } // for:
  430. hr = THR( piCCSC->SetDomainCredentials( pqsc->lpServiceStartName ) );
  431. CleanUp:
  432. if ( schClusSvc != NULL )
  433. {
  434. CloseServiceHandle( schClusSvc );
  435. } // if:
  436. if ( schSCM != NULL )
  437. {
  438. CloseServiceHandle( schSCM );
  439. } // if:
  440. if ( pqsc != NULL )
  441. {
  442. TraceFree( pqsc );
  443. } // if:
  444. HRETURN( hr );
  445. } //*** HrLoadCredentials()
  446. //////////////////////////////////////////////////////////////////////////////
  447. //++
  448. //
  449. // HRESULT
  450. // HrGetNodeNameHostingResource(
  451. // HCLUSTER hCluster,
  452. // HRESOURCE hRes,
  453. // BSTR * pbstrNameOut
  454. // )
  455. //
  456. //--
  457. //////////////////////////////////////////////////////////////////////////////
  458. HRESULT
  459. HrGetNodeNameHostingResource(
  460. HCLUSTER hClusterIn,
  461. HRESOURCE hResIn,
  462. BSTR * pbstrNameOut
  463. )
  464. {
  465. TraceFunc( "" );
  466. WCHAR pszNodeBuffer[STACK_ARRAY_SIZE];
  467. WCHAR pszGroupBuffer[STACK_ARRAY_SIZE];
  468. DWORD sc;
  469. HRESULT hr = S_OK;
  470. BSTR bstrGroupName = NULL;
  471. BSTR bstrNodeName = NULL;
  472. DWORD dwNodeNameLen;
  473. DWORD dwGroupNameLen;
  474. HGROUP hGroup = NULL;
  475. Assert( hClusterIn != NULL );
  476. // Get the name and the group of the cluster.
  477. dwNodeNameLen = STACK_ARRAY_SIZE;
  478. dwGroupNameLen = STACK_ARRAY_SIZE;
  479. sc = GetClusterResourceState( hResIn, pszNodeBuffer, &dwNodeNameLen, pszGroupBuffer, &dwGroupNameLen );
  480. // Check to see if they were available and fit into the memory we allocated.
  481. if( dwNodeNameLen == 0 && dwGroupNameLen == 0)
  482. {
  483. hr = E_FAIL;
  484. goto Cleanup;
  485. }
  486. if ( dwNodeNameLen != 0 && dwNodeNameLen < STACK_ARRAY_SIZE )
  487. {
  488. bstrNodeName = TraceSysAllocString( pszNodeBuffer );
  489. if( bstrNodeName == NULL)
  490. goto OutOfMemory;
  491. goto Success;
  492. }
  493. if ( dwGroupNameLen != 0 && dwGroupNameLen < STACK_ARRAY_SIZE )
  494. {
  495. bstrGroupName = TraceSysAllocString( pszGroupBuffer );
  496. if( bstrGroupName == NULL)
  497. goto OutOfMemory;
  498. }
  499. // Allocate memory and try again.
  500. if( bstrNodeName == NULL )
  501. {
  502. bstrNodeName = TraceSysAllocStringByteLen( NULL, sizeof(WCHAR) * ( dwNodeNameLen + 2 ) );
  503. if( bstrNodeName == NULL)
  504. goto OutOfMemory;
  505. }
  506. if( bstrGroupName == NULL )
  507. {
  508. bstrGroupName = TraceSysAllocStringByteLen( NULL, sizeof(WCHAR) * ( dwGroupNameLen + 2 ) );
  509. if( bstrGroupName == NULL)
  510. goto OutOfMemory;
  511. }
  512. //
  513. // Retrieve a second time.
  514. //
  515. dwNodeNameLen = SysStringLen( bstrNodeName );
  516. dwGroupNameLen = SysStringLen( bstrGroupName );
  517. sc = GetClusterResourceState( hResIn, pszNodeBuffer, &dwNodeNameLen, pszGroupBuffer, &dwGroupNameLen );
  518. if( dwNodeNameLen != 0 )
  519. goto Success;
  520. if( dwGroupNameLen == 0 )
  521. goto Cleanup;
  522. //
  523. // If we don't have the name yet, we have to look up the
  524. // group name and figure out where it lives.
  525. //
  526. hGroup = OpenClusterGroup( hClusterIn, bstrGroupName );
  527. if( hGroup == NULL )
  528. goto Win32Error;
  529. dwNodeNameLen = STACK_ARRAY_SIZE;
  530. sc = GetClusterGroupState( hGroup, pszNodeBuffer, &dwNodeNameLen );
  531. if( dwNodeNameLen == 0 )
  532. {
  533. if( sc == ClusterGroupStateUnknown )
  534. goto Win32Error;
  535. hr = E_FAIL;
  536. goto Cleanup;
  537. }
  538. else if( dwNodeNameLen < STACK_ARRAY_SIZE )
  539. {
  540. bstrNodeName = TraceSysAllocString( pszNodeBuffer );
  541. if( bstrNodeName == NULL)
  542. goto OutOfMemory;
  543. }
  544. else
  545. {
  546. bstrNodeName = TraceSysAllocStringByteLen( NULL, sizeof(WCHAR) * ( dwNodeNameLen + 2 ) );
  547. dwNodeNameLen = SysStringLen( bstrNodeName );
  548. if( bstrNodeName == NULL)
  549. goto OutOfMemory;
  550. sc = GetClusterGroupState( hGroup, bstrNodeName, &dwNodeNameLen );
  551. if( dwNodeNameLen == 0 )
  552. {
  553. if( sc == ClusterGroupStateUnknown )
  554. goto Win32Error;
  555. hr = E_FAIL;
  556. goto Cleanup;
  557. }
  558. }
  559. Success:
  560. hr = S_OK;
  561. *pbstrNameOut = bstrNodeName;
  562. bstrNodeName = NULL;
  563. Cleanup:
  564. if( hGroup != NULL )
  565. {
  566. CloseClusterGroup( hGroup );
  567. }
  568. if( bstrGroupName )
  569. {
  570. TraceSysFreeString( bstrGroupName );
  571. }
  572. if( bstrNodeName )
  573. {
  574. TraceSysFreeString( bstrNodeName );
  575. }
  576. HRETURN( hr );
  577. OutOfMemory:
  578. hr = E_OUTOFMEMORY;
  579. goto Cleanup;
  580. Win32Error:
  581. hr = HRESULT_FROM_WIN32( GetLastError() );
  582. goto Cleanup;
  583. } //*** HrGetNodeNameHostingResource()
  584. //////////////////////////////////////////////////////////////////////////////
  585. //++
  586. //
  587. // HRESULT
  588. // HrGetDependentIPAddressInfo(
  589. // HCLUSTER hClusterIn,
  590. // ULONG * pulIPAddress,
  591. // ULONG * pulSubnetMask
  592. // )
  593. //
  594. //--
  595. //////////////////////////////////////////////////////////////////////////////
  596. HRESULT
  597. HrGetDependentIPAddressInfo(
  598. HCLUSTER hClusterIn,
  599. HRESOURCE hResIn,
  600. ULONG * pulIPAddress,
  601. ULONG * pulSubnetMask,
  602. BSTR * pbstrNetworkName
  603. )
  604. {
  605. TraceFunc( "" );
  606. HRESULT hr = S_FALSE;
  607. DWORD sc;
  608. HRESENUM hEnum = NULL;
  609. DWORD idx;
  610. WCHAR * psz = NULL;
  611. DWORD cchpsz = 33;
  612. DWORD dwType;
  613. HRESOURCE hRes = NULL;
  614. hEnum = ClusterResourceOpenEnum( hResIn, CLUSTER_RESOURCE_ENUM_DEPENDS );
  615. if ( hEnum == NULL )
  616. {
  617. sc = TW32( GetLastError() );
  618. hr = HRESULT_FROM_WIN32( sc );
  619. goto CleanUp;
  620. } // if:
  621. psz = new WCHAR [ cchpsz ];
  622. if ( psz == NULL )
  623. {
  624. goto OutOfMemory;
  625. } // if:
  626. for ( idx = 0; ; )
  627. {
  628. sc = TW32( ClusterResourceEnum( hEnum, idx, &dwType, psz, &cchpsz ) );
  629. if ( sc == ERROR_NO_MORE_ITEMS )
  630. {
  631. break;
  632. } // if:
  633. if ( sc == ERROR_MORE_DATA )
  634. {
  635. delete [] psz;
  636. psz = NULL;
  637. cchpsz++;
  638. psz = new WCHAR [ cchpsz ];
  639. if ( psz == NULL )
  640. {
  641. goto OutOfMemory;
  642. } // if:
  643. continue;
  644. } // if:
  645. if ( sc == ERROR_SUCCESS )
  646. {
  647. hRes = OpenClusterResource( hClusterIn, psz );
  648. if ( hRes == NULL )
  649. {
  650. sc = TW32( GetLastError() );
  651. hr = HRESULT_FROM_WIN32( sc );
  652. goto CleanUp;
  653. } // if:
  654. hr = THR( HrIsResourceOfType( hRes, L"IP Address" ) );
  655. if ( SUCCEEDED( hr ) )
  656. {
  657. hr = THR( HrGetIPAddressInfo( hRes, pulIPAddress, pulSubnetMask, pbstrNetworkName ) ); // not recursive!
  658. goto CleanUp;
  659. } // if:
  660. CloseClusterResource( hRes );
  661. hRes = NULL;
  662. idx++;
  663. continue;
  664. } // if:
  665. hr = THR( HRESULT_FROM_WIN32( sc ) ); // must be an error!
  666. goto CleanUp;
  667. } // for:
  668. goto CleanUp;
  669. OutOfMemory:
  670. hr = THR( E_OUTOFMEMORY );
  671. CleanUp:
  672. delete [] psz;
  673. if ( hRes != NULL )
  674. {
  675. CloseClusterResource( hRes );
  676. } // if:
  677. if ( hEnum != NULL )
  678. {
  679. ClusterResourceCloseEnum( hEnum );
  680. } // if:
  681. HRETURN( hr );
  682. } //*** HrGetDependentIPAddressInfo()
  683. //////////////////////////////////////////////////////////////////////////////
  684. //++
  685. //
  686. // HRESULT
  687. // HrGetIPAddressOfCluster(
  688. // HCLUSTER hClusterIn,
  689. // ULONG * pulIPAddress,
  690. // ULONG * pulSubnetMask
  691. // )
  692. //
  693. //--
  694. //////////////////////////////////////////////////////////////////////////////
  695. HRESULT
  696. HrGetIPAddressOfCluster( HCLUSTER hClusterIn, ULONG * pulIPAddress, ULONG * pulSubnetMask, BSTR * pbstrNetworkName )
  697. {
  698. TraceFunc( "" );
  699. HRESULT hr = S_OK;
  700. DWORD sc;
  701. HCLUSENUM hEnum = NULL;
  702. DWORD idx;
  703. DWORD dwType;
  704. WCHAR * psz = NULL;
  705. DWORD cchpsz = 33;
  706. HRESOURCE hRes = NULL;
  707. hEnum = ClusterOpenEnum( hClusterIn, CLUSTER_ENUM_RESOURCE );
  708. if ( hEnum == NULL )
  709. {
  710. sc = TW32( GetLastError() );
  711. hr = HRESULT_FROM_WIN32( sc );
  712. goto CleanUp;
  713. } // if:
  714. psz = new WCHAR [ cchpsz ];
  715. if ( psz == NULL )
  716. {
  717. goto OutOfMemory;
  718. } // if:
  719. for ( idx = 0; ; )
  720. {
  721. sc = ClusterEnum( hEnum, idx, &dwType, psz, &cchpsz );
  722. if ( sc == ERROR_MORE_DATA )
  723. {
  724. delete [] psz;
  725. psz = NULL;
  726. cchpsz++;
  727. psz = new WCHAR [ cchpsz ];
  728. if ( psz == NULL )
  729. {
  730. goto OutOfMemory;
  731. } // if:
  732. continue;
  733. } // if:
  734. if ( sc == ERROR_SUCCESS )
  735. {
  736. hRes = OpenClusterResource( hClusterIn, psz );
  737. if ( hRes == NULL )
  738. {
  739. sc = TW32( GetLastError() );
  740. hr = HRESULT_FROM_WIN32( sc );
  741. goto CleanUp;
  742. } // if:
  743. hr = STHR( HrIsResourceOfType( hRes, L"Network Name" ) );
  744. if ( FAILED( hr ) )
  745. {
  746. break;
  747. } // if:
  748. if ( hr == S_OK )
  749. {
  750. hr = STHR( HrIsCoreResource( hRes ) );
  751. if ( FAILED( hr ) )
  752. {
  753. break;
  754. } // if:
  755. if ( hr == S_OK )
  756. {
  757. hr = THR( HrGetDependentIPAddressInfo( hClusterIn, hRes, pulIPAddress, pulSubnetMask, pbstrNetworkName ) );
  758. if ( FAILED( hr ) )
  759. {
  760. break;
  761. } // if:
  762. } // if:
  763. } // if:
  764. CloseClusterResource( hRes );
  765. hRes = NULL;
  766. idx++;
  767. continue;
  768. } // if:
  769. if ( sc == ERROR_NO_MORE_ITEMS )
  770. {
  771. hr = S_OK;
  772. break;
  773. } // if:
  774. TW32( sc );
  775. hr = HRESULT_FROM_WIN32( sc );
  776. break;
  777. } // for:
  778. goto CleanUp;
  779. OutOfMemory:
  780. hr = THR( E_OUTOFMEMORY );
  781. CleanUp:
  782. delete [] psz;
  783. if ( hRes != NULL )
  784. {
  785. CloseClusterResource( hRes );
  786. } // if:
  787. if ( hEnum != NULL )
  788. {
  789. ClusterCloseEnum( hEnum );
  790. } // if:
  791. HRETURN( hr );
  792. } //*** HrGetIPAddressOfCluster()
  793. //////////////////////////////////////////////////////////////////////////////
  794. //++
  795. //
  796. // HrGetNodeNameHostingCluster()
  797. //
  798. // Description:
  799. // Get the name of the node hosting the cluster service...
  800. //
  801. // Arguments:
  802. //
  803. //
  804. // Return Value:
  805. //
  806. //
  807. // Remarks:
  808. // None.
  809. //
  810. //--
  811. //////////////////////////////////////////////////////////////////////////////
  812. HRESULT
  813. HrGetNodeNameHostingCluster( HCLUSTER hClusterIn, BSTR * pbstrNodeName )
  814. {
  815. TraceFunc( "" );
  816. HRESULT hr = S_OK;
  817. DWORD sc;
  818. HCLUSENUM hEnum = NULL;
  819. DWORD idx;
  820. DWORD dwType;
  821. WCHAR * psz = NULL;
  822. DWORD cchpsz = 33;
  823. HRESOURCE hRes = NULL;
  824. hEnum = ClusterOpenEnum( hClusterIn, CLUSTER_ENUM_RESOURCE );
  825. if ( hEnum == NULL )
  826. {
  827. sc = TW32( GetLastError() );
  828. hr = HRESULT_FROM_WIN32( sc );
  829. goto CleanUp;
  830. } // if:
  831. psz = new WCHAR [ cchpsz ];
  832. if ( psz == NULL )
  833. {
  834. goto OutOfMemory;
  835. } // if:
  836. for ( idx = 0; ; )
  837. {
  838. sc = ClusterEnum( hEnum, idx, &dwType, psz, &cchpsz );
  839. if ( sc == ERROR_MORE_DATA )
  840. {
  841. delete [] psz;
  842. psz = NULL;
  843. cchpsz++;
  844. psz = new WCHAR [ cchpsz ];
  845. if ( psz == NULL )
  846. {
  847. goto OutOfMemory;
  848. } // if:
  849. continue;
  850. } // if:
  851. if ( sc == ERROR_SUCCESS )
  852. {
  853. hRes = OpenClusterResource( hClusterIn, psz );
  854. if ( hRes == NULL )
  855. {
  856. sc = TW32( GetLastError() );
  857. hr = HRESULT_FROM_WIN32( sc );
  858. goto CleanUp;
  859. } // if:
  860. hr = STHR( HrIsResourceOfType( hRes, L"Network Name" ) );
  861. if ( FAILED( hr ) )
  862. {
  863. break;
  864. } // if:
  865. if ( hr == S_OK )
  866. {
  867. hr = THR( HrIsCoreResource( hRes ) );
  868. if ( FAILED( hr ) )
  869. {
  870. break;
  871. } // if:
  872. if ( hr == S_OK )
  873. {
  874. hr = THR( HrGetNodeNameHostingResource( hClusterIn, hRes, pbstrNodeName ) );
  875. if ( FAILED( hr ) )
  876. {
  877. break;
  878. } // if:
  879. else if( hr == S_OK )
  880. {
  881. goto CleanUp;
  882. }
  883. } // if:
  884. } // if:
  885. CloseClusterResource( hRes );
  886. hRes = NULL;
  887. idx++;
  888. continue;
  889. } // if:
  890. if ( sc == ERROR_NO_MORE_ITEMS )
  891. {
  892. hr = S_OK;
  893. break;
  894. } // if:
  895. TW32( sc );
  896. hr = HRESULT_FROM_WIN32( sc );
  897. break;
  898. } // for:
  899. goto CleanUp;
  900. OutOfMemory:
  901. hr = THR( E_OUTOFMEMORY );
  902. CleanUp:
  903. delete [] psz;
  904. if ( hRes != NULL )
  905. {
  906. CloseClusterResource( hRes );
  907. } // if:
  908. if ( hEnum != NULL )
  909. {
  910. ClusterCloseEnum( hEnum );
  911. } // if:
  912. HRETURN( hr );
  913. } //*** HrGetNodeNameHostingCluster()
  914. //////////////////////////////////////////////////////////////////////////////
  915. //++
  916. //
  917. // HrGetSCSIInfo()
  918. //
  919. // Description:
  920. // Get the name of the node hosting the cluster service...
  921. //
  922. // Arguments:
  923. //
  924. //
  925. // Return Value:
  926. //
  927. //
  928. //--
  929. //////////////////////////////////////////////////////////////////////////////
  930. HRESULT
  931. HrGetSCSIInfo(
  932. HRESOURCE hResIn,
  933. CLUS_SCSI_ADDRESS * pCSAOut,
  934. DWORD * pdwSignatureOut,
  935. DWORD * pdwDiskNumberOut
  936. )
  937. {
  938. TraceFunc( "" );
  939. HRESULT hr = S_OK;
  940. DWORD sc;
  941. CBasePropValueList cpvl;
  942. CBaseClusterResourceInfo cbri;
  943. CLUSPROP_BUFFER_HELPER cpbh;
  944. cbri.m_hResource = hResIn;
  945. sc = TW32( cpvl.ScGetValueList( cbri, CLUSCTL_RESOURCE_STORAGE_GET_DISK_INFO ) );
  946. if ( sc != ERROR_SUCCESS )
  947. {
  948. goto MakeHr;
  949. } // if:
  950. // loop through all the properties.
  951. sc = cpvl.ScMoveToFirstValue();
  952. if ( sc != ERROR_SUCCESS )
  953. {
  954. goto MakeHr;
  955. } // if:
  956. do
  957. {
  958. if( sc != ERROR_SUCCESS )
  959. goto MakeHr;
  960. cpbh = cpvl;
  961. switch ( cpbh.pSyntax->dw )
  962. {
  963. case CLUSPROP_SYNTAX_PARTITION_INFO :
  964. {
  965. break;
  966. } // case: CLUSPROP_SYNTAX_PARTITION_INFO
  967. case CLUSPROP_SYNTAX_DISK_SIGNATURE :
  968. {
  969. *pdwSignatureOut = cpbh.pDiskSignatureValue->dw;
  970. break;
  971. } // case: CLUSPROP_SYNTAX_DISK_SIGNATURE
  972. case CLUSPROP_SYNTAX_SCSI_ADDRESS :
  973. {
  974. pCSAOut->dw = cpbh.pScsiAddressValue->dw;
  975. break;
  976. } // case: CLUSPROP_SYNTAX_SCSI_ADDRESS
  977. case CLUSPROP_SYNTAX_DISK_NUMBER :
  978. {
  979. *pdwDiskNumberOut = cpbh.pDiskNumberValue->dw;
  980. break;
  981. } // case:
  982. } // switch:
  983. // Move to the next item.
  984. sc = cpvl.ScCheckIfAtLastValue();
  985. if( sc == ERROR_NO_MORE_ITEMS )
  986. break;
  987. sc = cpvl.ScMoveToNextValue();
  988. } while( sc == ERROR_SUCCESS );
  989. hr = S_OK;
  990. Cleanup:
  991. cbri.m_hResource = NULL;
  992. HRETURN( hr );
  993. MakeHr:
  994. sc = GetLastError();
  995. hr = HRESULT_FROM_WIN32( sc );
  996. goto Cleanup;
  997. } //*** HrGetSCSIInfo()
  998. //////////////////////////////////////////////////////////////////////////////
  999. //++
  1000. //
  1001. // HrGetClusterInformation()
  1002. //
  1003. // Description:
  1004. // Get the cluster information. This includes the name and the version
  1005. // info.
  1006. //
  1007. // Arguments:
  1008. //
  1009. //
  1010. // Return Value:
  1011. //
  1012. //
  1013. //--
  1014. //////////////////////////////////////////////////////////////////////////////
  1015. HRESULT
  1016. HrGetClusterInformation(
  1017. HCLUSTER hClusterIn,
  1018. BSTR * pbstrClusterNameOut,
  1019. CLUSTERVERSIONINFO * pcviOut
  1020. )
  1021. {
  1022. TraceFunc( "" );
  1023. HRESULT hr = S_OK;
  1024. DWORD sc;
  1025. WCHAR * psz = NULL;
  1026. DWORD cch = 33;
  1027. CLUSTERVERSIONINFO cvi;
  1028. if ( pbstrClusterNameOut == NULL )
  1029. {
  1030. goto Pointer;
  1031. } // if:
  1032. cvi.dwVersionInfoSize = sizeof( cvi );
  1033. if ( pcviOut == NULL )
  1034. {
  1035. pcviOut = &cvi;
  1036. } // if:
  1037. psz = new WCHAR[ cch ];
  1038. if ( psz == NULL )
  1039. {
  1040. goto OutOfMemory;
  1041. } // if:
  1042. sc = GetClusterInformation( hClusterIn, psz, &cch, pcviOut );
  1043. if ( sc == ERROR_MORE_DATA )
  1044. {
  1045. delete [] psz;
  1046. psz = NULL;
  1047. psz = new WCHAR[ ++cch ];
  1048. if ( psz == NULL )
  1049. {
  1050. goto OutOfMemory;
  1051. } // if:
  1052. sc = GetClusterInformation( hClusterIn, psz, &cch, pcviOut );
  1053. } // if:
  1054. if ( sc != ERROR_SUCCESS )
  1055. {
  1056. hr = THR( HRESULT_FROM_WIN32( sc ) );
  1057. LogMsg( __FUNCTION__ ": GetClusterInformation() failed (hr = 0x%08x).", hr );
  1058. goto Cleanup;
  1059. } // if:
  1060. *pbstrClusterNameOut = TraceSysAllocString( psz );
  1061. if ( *pbstrClusterNameOut == NULL )
  1062. {
  1063. goto OutOfMemory;
  1064. } // if:
  1065. goto Cleanup;
  1066. Pointer:
  1067. hr = THR( E_POINTER );
  1068. goto Cleanup;
  1069. OutOfMemory:
  1070. hr = THR( E_OUTOFMEMORY );
  1071. Cleanup:
  1072. delete [] psz;
  1073. HRETURN( hr );
  1074. } //*** HrGetClusterInformation()
  1075. /////////////////////////////////////////////////////////////////////////////
  1076. //++
  1077. //
  1078. // HrGetClusterResourceState
  1079. //
  1080. // Description:
  1081. //
  1082. // Arguments:
  1083. //
  1084. //
  1085. // Return Value:
  1086. //
  1087. //
  1088. //--
  1089. /////////////////////////////////////////////////////////////////////////////
  1090. HRESULT
  1091. HrGetClusterResourceState(
  1092. HRESOURCE hResourceIn
  1093. , BSTR * pbstrNodeNameOut
  1094. , BSTR * pbstrGroupNameOut
  1095. , CLUSTER_RESOURCE_STATE * pcrsStateOut
  1096. )
  1097. {
  1098. TraceFunc( "" );
  1099. Assert( hResourceIn != NULL );
  1100. HRESULT hr = S_OK;
  1101. CLUSTER_RESOURCE_STATE crsState = ClusterResourceStateUnknown;
  1102. WCHAR * pszNodeName = NULL;
  1103. DWORD cchNodeName = 33;
  1104. WCHAR * pszGroupName = NULL;
  1105. DWORD cchGroupName = 33;
  1106. pszNodeName = new WCHAR[ cchNodeName ];
  1107. if ( pszNodeName == NULL )
  1108. {
  1109. goto OutOfMemory;
  1110. } // if:
  1111. pszGroupName = new WCHAR[ cchGroupName ];
  1112. if ( pszGroupName == NULL )
  1113. {
  1114. goto OutOfMemory;
  1115. } // if:
  1116. crsState = GetClusterResourceState( hResourceIn, pszNodeName, &cchNodeName, pszGroupName, &cchGroupName );
  1117. if ( GetLastError() == ERROR_MORE_DATA )
  1118. {
  1119. crsState = ClusterResourceStateUnknown; // reset to error condition
  1120. delete [] pszNodeName;
  1121. pszNodeName = NULL;
  1122. cchNodeName++;
  1123. delete [] pszGroupName;
  1124. pszGroupName = NULL;
  1125. cchGroupName++;
  1126. pszNodeName = new WCHAR[ cchNodeName ];
  1127. if ( pszNodeName == NULL )
  1128. {
  1129. goto OutOfMemory;
  1130. } // if:
  1131. pszGroupName = new WCHAR[ cchGroupName ];
  1132. if ( pszGroupName == NULL )
  1133. {
  1134. goto OutOfMemory;
  1135. } // if:
  1136. crsState = GetClusterResourceState( hResourceIn, pszNodeName, &cchNodeName, pszGroupName, &cchGroupName );
  1137. if ( crsState == ClusterResourceStateUnknown )
  1138. {
  1139. DWORD sc;
  1140. sc = TW32( GetLastError() );
  1141. hr = HRESULT_FROM_WIN32( sc );
  1142. goto Cleanup;
  1143. } // if:
  1144. } // if: more data
  1145. if ( pbstrNodeNameOut != NULL )
  1146. {
  1147. *pbstrNodeNameOut = TraceSysAllocString( pszNodeName );
  1148. if ( *pbstrNodeNameOut == NULL )
  1149. {
  1150. goto OutOfMemory;
  1151. } // if:
  1152. } // if:
  1153. if ( pbstrGroupNameOut != NULL )
  1154. {
  1155. *pbstrGroupNameOut = TraceSysAllocString( pszGroupName );
  1156. if ( *pbstrGroupNameOut == NULL )
  1157. {
  1158. goto OutOfMemory;
  1159. } // if:
  1160. } // if:
  1161. if ( pcrsStateOut != NULL )
  1162. {
  1163. *pcrsStateOut = crsState;
  1164. } // if:
  1165. goto Cleanup;
  1166. OutOfMemory:
  1167. hr = THR( E_OUTOFMEMORY );
  1168. Cleanup:
  1169. delete [] pszNodeName;
  1170. delete [] pszGroupName;
  1171. HRETURN( hr );
  1172. } //*** HrGetClusterResourceState
  1173. /////////////////////////////////////////////////////////////////////////////
  1174. //++
  1175. //
  1176. // HrGetClusterQuorumResource()
  1177. //
  1178. // Description:
  1179. // Get the information about the quorum resource.
  1180. //
  1181. // Arguments:
  1182. //
  1183. //
  1184. // Return Value:
  1185. // S_OK
  1186. // Success.
  1187. //
  1188. // Other HRESULT error codes.
  1189. //
  1190. // Remarks:
  1191. // None.
  1192. //
  1193. //--
  1194. //////////////////////////////////////////////////////////////////////////////
  1195. HRESULT
  1196. HrGetClusterQuorumResource(
  1197. HCLUSTER hClusterIn
  1198. , BSTR * pbstrResourceNameOut
  1199. , BSTR * pbstrDeviceNameOut
  1200. , DWORD * pdwMaxQuorumLogSizeOut
  1201. )
  1202. {
  1203. TraceFunc( "" );
  1204. HRESULT hr = S_OK;
  1205. DWORD sc;
  1206. LPWSTR pszResourceName = NULL;
  1207. DWORD cchResourceName = 128;
  1208. DWORD cchTempResourceName = cchResourceName;
  1209. LPWSTR pszDeviceName = NULL;
  1210. DWORD cchDeviceName = 128;
  1211. DWORD cchTempDeviceName = cchDeviceName;
  1212. DWORD dwMaxQuorumLogSize = 0;
  1213. if ( hClusterIn == NULL )
  1214. {
  1215. hr = THR( E_INVALIDARG );
  1216. goto Cleanup;
  1217. } // if:
  1218. // Allocate the resource name buffer
  1219. pszResourceName = new WCHAR[ cchResourceName ];
  1220. if ( pszResourceName == NULL )
  1221. {
  1222. goto OutOfMemory;
  1223. } // if:
  1224. // Allocate the device name buffer
  1225. pszDeviceName = new WCHAR[ cchDeviceName ];
  1226. if ( pszDeviceName == NULL )
  1227. {
  1228. goto OutOfMemory;
  1229. } // if:
  1230. sc = GetClusterQuorumResource(
  1231. hClusterIn
  1232. , pszResourceName
  1233. , &cchTempResourceName
  1234. , pszDeviceName
  1235. , &cchTempDeviceName
  1236. , &dwMaxQuorumLogSize
  1237. );
  1238. if ( sc == ERROR_MORE_DATA )
  1239. {
  1240. delete [] pszResourceName;
  1241. pszResourceName = NULL;
  1242. cchResourceName = ++cchTempResourceName;
  1243. // Allocate the resource name buffer
  1244. pszResourceName = new WCHAR[ cchResourceName ];
  1245. if ( pszResourceName == NULL )
  1246. {
  1247. goto OutOfMemory;
  1248. } // if:
  1249. delete [] pszDeviceName;
  1250. pszDeviceName = NULL;
  1251. cchDeviceName = ++cchTempDeviceName;
  1252. // Allocate the device name buffer
  1253. pszDeviceName = new WCHAR[ cchDeviceName ];
  1254. if ( pszDeviceName == NULL )
  1255. {
  1256. goto OutOfMemory;
  1257. } // if:
  1258. sc = GetClusterQuorumResource(
  1259. hClusterIn
  1260. , pszResourceName
  1261. , &cchTempResourceName
  1262. , pszDeviceName
  1263. , &cchTempDeviceName
  1264. , &dwMaxQuorumLogSize
  1265. );
  1266. } // if:
  1267. if ( sc != ERROR_SUCCESS )
  1268. {
  1269. TW32( sc );
  1270. hr = HRESULT_FROM_WIN32( sc );
  1271. goto Cleanup;
  1272. } // if:
  1273. if ( pbstrResourceNameOut != NULL )
  1274. {
  1275. *pbstrResourceNameOut = TraceSysAllocString( pszResourceName );
  1276. if ( *pbstrResourceNameOut == NULL )
  1277. {
  1278. goto OutOfMemory;
  1279. } // if:
  1280. } // if:
  1281. if ( pbstrDeviceNameOut != NULL )
  1282. {
  1283. *pbstrDeviceNameOut = TraceSysAllocString( pszDeviceName );
  1284. if ( *pbstrDeviceNameOut == NULL )
  1285. {
  1286. goto OutOfMemory;
  1287. } // if:
  1288. } // if:
  1289. if ( pdwMaxQuorumLogSizeOut != NULL )
  1290. {
  1291. *pdwMaxQuorumLogSizeOut = dwMaxQuorumLogSize;
  1292. } // if:
  1293. goto Cleanup;
  1294. OutOfMemory:
  1295. hr = THR( E_OUTOFMEMORY );
  1296. Cleanup:
  1297. delete [] pszResourceName;
  1298. delete [] pszDeviceName;
  1299. HRETURN( hr );
  1300. } //*** HrGetClusterQuorumResource()