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.

1863 lines
47 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000-2002 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. // Maintained By:
  13. // Galen Barbee (GalenB) 13-JUL-2001
  14. //
  15. //////////////////////////////////////////////////////////////////////////////
  16. #include "Pch.h"
  17. #include <clusrtl.h>
  18. #include <PropList.h>
  19. #include <StatusReports.h>
  20. #include <CommonStrings.h>
  21. #include <ClusRPC.h>
  22. #include <ClusVerp.h>
  23. #include <initguid.h>
  24. #define STACK_ARRAY_SIZE 256
  25. // {DD1C1DE0-F39D-46ee-BFD1-07ABF7566705}
  26. DEFINE_GUID( TASKID_Minor_HrCheckJoiningNodeVersion_RpcStringBindingComposeW,
  27. 0xdd1c1de0, 0xf39d, 0x46ee, 0xbf, 0xd1, 0x7, 0xab, 0xf7, 0x56, 0x67, 0x5);
  28. // {62AF0964-4B32-4067-8BF1-8903FEC95A82}
  29. DEFINE_GUID( TASKID_Minor_HrCheckJoiningNodeVersion_RpcBindingFromStringBindingW,
  30. 0x62af0964, 0x4b32, 0x4067, 0x8b, 0xf1, 0x89, 0x3, 0xfe, 0xc9, 0x5a, 0x82);
  31. // {D8C0BA67-D079-45ca-A28C-C4C389DB389A}
  32. DEFINE_GUID( TASKID_Minor_HrCheckJoiningNodeVersion_RpcBindingSetAuthInfoW,
  33. 0xd8c0ba67, 0xd079, 0x45ca, 0xa2, 0x8c, 0xc4, 0xc3, 0x89, 0xdb, 0x38, 0x9a);
  34. // {110E29E4-2072-4916-BE66-BED556F12A7B}
  35. DEFINE_GUID( TASKID_Minor_HrCheckJoiningNodeVersion_CsRpcGetJoinVersionData_Log,
  36. 0x110e29e4, 0x2072, 0x4916, 0xbe, 0x66, 0xbe, 0xd5, 0x56, 0xf1, 0x2a, 0x7b);
  37. // {5EB1F008-1B49-4cf0-9FE1-B1BC8F76454A}
  38. DEFINE_GUID( TASKID_Minor_HrCheckJoiningNodeVersion_CsRpcGetJoinVersionData,
  39. 0x5eb1f008, 0x1b49, 0x4cf0, 0x9f, 0xe1, 0xb1, 0xbc, 0x8f, 0x76, 0x45, 0x4a);
  40. //////////////////////////////////////////////////////////////////////////////
  41. //++
  42. //
  43. // HrSeparateDomainAndName
  44. //
  45. // Description:
  46. //
  47. //
  48. // Arguments:
  49. // bstrNameIn
  50. // pbstrDomainOut
  51. // pbstrNameOut
  52. //
  53. // Return Value:
  54. // S_OK - Success.
  55. // E_INVALIDARG - Required input argument not specified.
  56. // E_OUTOFMEMORY - Couldn't allocate memory.
  57. // Other HRESULTs.
  58. //
  59. //--
  60. //////////////////////////////////////////////////////////////////////////////
  61. HRESULT
  62. HrSeparateDomainAndName(
  63. BSTR bstrNameIn
  64. , BSTR * pbstrDomainOut
  65. , BSTR * pbstrNameOut
  66. )
  67. {
  68. TraceFunc( "" );
  69. Assert( bstrNameIn != NULL );
  70. Assert( ( pbstrDomainOut != NULL )
  71. || ( pbstrNameOut != NULL )
  72. );
  73. HRESULT hr = S_OK;
  74. WCHAR * psz = NULL;
  75. psz = wcschr( bstrNameIn, L'.' );
  76. if ( psz == NULL )
  77. {
  78. hr = THR( E_INVALIDARG );
  79. goto Cleanup;
  80. } // if:
  81. if ( pbstrDomainOut != NULL )
  82. {
  83. psz++; // skip the .
  84. *pbstrDomainOut = TraceSysAllocString( psz );
  85. if ( *pbstrDomainOut == NULL )
  86. {
  87. hr = THR( E_OUTOFMEMORY );
  88. goto Cleanup;
  89. } // if:
  90. psz--; // reset back to .
  91. } // if:
  92. if ( pbstrNameOut != NULL )
  93. {
  94. *pbstrNameOut = TraceSysAllocStringLen( bstrNameIn, (UINT) ( psz - bstrNameIn ) );
  95. if ( *pbstrNameOut == NULL )
  96. {
  97. hr = THR( E_OUTOFMEMORY );
  98. goto Cleanup;
  99. } // if:
  100. } // if:
  101. Cleanup:
  102. HRETURN ( hr );
  103. } //*** HrSeparateDomainAndName
  104. //////////////////////////////////////////////////////////////////////////////
  105. //++
  106. //
  107. // HrAppendDomainToName
  108. //
  109. // Description:
  110. //
  111. //
  112. // Arguments:
  113. // bstrNameIn
  114. // bstrDomainIn
  115. // pbstrDomainNameOut
  116. //
  117. // Return Value:
  118. // S_OK - Success.
  119. // E_OUTOFMEMORY - Couldn't allocate memory.
  120. // Other HRESULTs.
  121. //
  122. //--
  123. //////////////////////////////////////////////////////////////////////////////
  124. HRESULT
  125. HrAppendDomainToName(
  126. BSTR bstrNameIn
  127. , BSTR bstrDomainIn
  128. , BSTR * pbstrDomainNameOut
  129. )
  130. {
  131. TraceFunc( "" );
  132. Assert( bstrNameIn != NULL );
  133. Assert( pbstrDomainNameOut != NULL );
  134. HRESULT hr = S_OK;
  135. size_t cchName = 0;
  136. // Create a fully qualified node name
  137. if ( bstrDomainIn != NULL )
  138. {
  139. cchName = wcslen( bstrNameIn ) + wcslen( bstrDomainIn ) + 1 + 1;
  140. Assert( cchName <= MAXDWORD );
  141. *pbstrDomainNameOut = TraceSysAllocStringLen( NULL, (UINT) cchName );
  142. if ( *pbstrDomainNameOut == NULL )
  143. {
  144. hr = THR( E_OUTOFMEMORY );
  145. goto Cleanup;
  146. } // if:
  147. hr = THR( StringCchPrintfW( *pbstrDomainNameOut, cchName, L"%ws.%ws", bstrNameIn, bstrDomainIn ) );
  148. } // if:
  149. else
  150. {
  151. *pbstrDomainNameOut = TraceSysAllocString( bstrNameIn );
  152. if ( *pbstrDomainNameOut == NULL )
  153. {
  154. hr = THR( E_OUTOFMEMORY );
  155. goto Cleanup;
  156. } // if:
  157. hr = S_FALSE;
  158. } // else:
  159. Cleanup:
  160. HRETURN( hr );
  161. } //*** HrAppendDomainToName
  162. //////////////////////////////////////////////////////////////////////////////
  163. //++
  164. //
  165. // HrIsCoreResource
  166. //
  167. // Description:
  168. // Determines whether the resource is a core resource.
  169. //
  170. // Arguments:
  171. // hResourceIn
  172. //
  173. // Return Value:
  174. // S_OK - Resource is a core resource.
  175. // S_FALSE - Resource is not a core resource.
  176. // Other HRESULTs.
  177. //
  178. //--
  179. //////////////////////////////////////////////////////////////////////////////
  180. HRESULT
  181. HrIsCoreResource( HRESOURCE hResourceIn )
  182. {
  183. TraceFunc( "" );
  184. Assert( hResourceIn );
  185. HRESULT hr = S_FALSE;
  186. DWORD sc;
  187. DWORD dwFlags = 0;
  188. DWORD cb;
  189. sc = TW32( ClusterResourceControl( hResourceIn, NULL, CLUSCTL_RESOURCE_GET_FLAGS, NULL, 0, &dwFlags, sizeof( dwFlags ), &cb ) );
  190. if ( sc != ERROR_SUCCESS )
  191. {
  192. hr = HRESULT_FROM_WIN32( sc );
  193. goto Cleanup;
  194. } // if:
  195. if ( dwFlags & CLUS_FLAG_CORE )
  196. {
  197. hr = S_OK;
  198. } // if:
  199. Cleanup:
  200. HRETURN( hr );
  201. } //*** HrIsCoreResource
  202. //////////////////////////////////////////////////////////////////////////////
  203. //++
  204. //
  205. // HrIsResourceOfType
  206. //
  207. // Description:
  208. // Find out if a resource if of a specific type.
  209. //
  210. // Arguments:
  211. // hResourceIn - Handle to the resource to check.
  212. // pszResourceTypeIn - Resource type name.
  213. //
  214. // Return Value:
  215. // S_OK - Resource is of specified type.
  216. // S_FALSE - Resource is not of specified type.
  217. // Other HRESULTs.
  218. //
  219. //--
  220. //////////////////////////////////////////////////////////////////////////////
  221. HRESULT
  222. HrIsResourceOfType(
  223. HRESOURCE hResourceIn
  224. , const WCHAR * pszResourceTypeIn
  225. )
  226. {
  227. TraceFunc( "" );
  228. Assert( hResourceIn != NULL );
  229. Assert( pszResourceTypeIn != NULL );
  230. HRESULT hr = S_OK;
  231. DWORD sc;
  232. WCHAR * pszBuf = NULL;
  233. size_t cchBuf = 65;
  234. DWORD cb;
  235. int idx;
  236. pszBuf = new WCHAR [ cchBuf ];
  237. if ( pszBuf == NULL )
  238. {
  239. hr = THR( E_OUTOFMEMORY );
  240. goto Cleanup;
  241. } // if:
  242. for ( idx = 0; idx < 2; idx++ )
  243. {
  244. sc = ClusterResourceControl( hResourceIn, NULL, CLUSCTL_RESOURCE_GET_RESOURCE_TYPE, NULL, 0, pszBuf, (DWORD)( cchBuf * sizeof( WCHAR ) ), &cb );
  245. if ( sc == ERROR_MORE_DATA )
  246. {
  247. delete [] pszBuf;
  248. pszBuf = NULL;
  249. cchBuf = ( cb / sizeof( WCHAR ) ) + 1; // add one in case cb is an odd size...
  250. pszBuf = new WCHAR [ cchBuf ];
  251. if ( pszBuf == NULL )
  252. {
  253. hr = THR( E_OUTOFMEMORY );
  254. goto Cleanup;
  255. } // if:
  256. continue;
  257. } // if:
  258. if ( sc != ERROR_SUCCESS )
  259. {
  260. hr = HRESULT_FROM_WIN32( TW32( sc ) );
  261. goto Cleanup;
  262. } // if:
  263. break;
  264. } // for:
  265. if ( wcsncmp( pszBuf, pszResourceTypeIn, cchBuf ) == 0 )
  266. {
  267. hr = S_OK;
  268. } // if:
  269. else
  270. {
  271. hr = S_FALSE;
  272. } // else:
  273. Cleanup:
  274. delete [] pszBuf;
  275. HRETURN( hr );
  276. } //*** HrIsResourceOfType
  277. //////////////////////////////////////////////////////////////////////////////
  278. //++
  279. //
  280. // HrGetIPAddressInfo
  281. //
  282. // Description:
  283. //
  284. //
  285. // Arguments:
  286. // hResourceIn
  287. // pulIPAddress
  288. // pulSubnetMask
  289. // pbstrNetworkName
  290. //
  291. // Return Value:
  292. // S_OK - Success.
  293. // E_OUTOFMEMORY - Couldn't allocate memory.
  294. // Other HRESULTs.
  295. //
  296. //--
  297. //////////////////////////////////////////////////////////////////////////////
  298. HRESULT
  299. HrGetIPAddressInfo(
  300. HRESOURCE hResourceIn
  301. , ULONG * pulIPAddress
  302. , ULONG * pulSubnetMask
  303. , BSTR * pbstrNetworkName
  304. )
  305. {
  306. TraceFunc( "" );
  307. Assert( hResourceIn != NULL );
  308. Assert( pulIPAddress != NULL );
  309. Assert( pulSubnetMask != NULL );
  310. Assert( pbstrNetworkName != NULL );
  311. HRESULT hr = S_OK;
  312. DWORD sc;
  313. CClusPropList cpl;
  314. CLUSPROP_BUFFER_HELPER cpbh;
  315. sc = TW32( cpl.ScGetResourceProperties( hResourceIn, CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES ) );
  316. if ( sc != ERROR_SUCCESS )
  317. {
  318. hr = HRESULT_FROM_WIN32( sc );
  319. goto Cleanup;
  320. } // if:
  321. sc = TW32( cpl.ScMoveToPropertyByName( L"Address" ) );
  322. if ( sc != ERROR_SUCCESS )
  323. {
  324. hr = HRESULT_FROM_WIN32( sc );
  325. goto Cleanup;
  326. } // if:
  327. cpbh = cpl.CbhCurrentValue();
  328. Assert( cpbh.pSyntax->dw == CLUSPROP_SYNTAX_LIST_VALUE_SZ );
  329. sc = TW32( ClRtlTcpipStringToAddress( cpbh.pStringValue->sz, pulIPAddress ) );
  330. if ( sc != ERROR_SUCCESS )
  331. {
  332. hr = HRESULT_FROM_WIN32( sc );
  333. goto Cleanup;
  334. } // if:
  335. sc = TW32( cpl.ScMoveToPropertyByName( L"SubnetMask" ) );
  336. if ( sc != ERROR_SUCCESS )
  337. {
  338. hr = HRESULT_FROM_WIN32( sc );
  339. goto Cleanup;
  340. } // if:
  341. cpbh = cpl.CbhCurrentValue();
  342. Assert( cpbh.pSyntax->dw == CLUSPROP_SYNTAX_LIST_VALUE_SZ );
  343. sc = TW32( ClRtlTcpipStringToAddress( cpbh.pStringValue->sz, pulSubnetMask ) );
  344. if ( sc != ERROR_SUCCESS )
  345. {
  346. hr = HRESULT_FROM_WIN32( sc );
  347. goto Cleanup;
  348. } // if:
  349. if ( pbstrNetworkName != NULL )
  350. {
  351. sc = TW32( cpl.ScMoveToPropertyByName( L"Network" ) );
  352. if ( sc != ERROR_SUCCESS )
  353. {
  354. hr = HRESULT_FROM_WIN32( sc );
  355. goto Cleanup;
  356. } // if:
  357. cpbh = cpl.CbhCurrentValue();
  358. Assert( cpbh.pSyntax->dw == CLUSPROP_SYNTAX_LIST_VALUE_SZ );
  359. *pbstrNetworkName = TraceSysAllocString( cpbh.pStringValue->sz );
  360. if( *pbstrNetworkName == NULL )
  361. {
  362. hr = THR( E_OUTOFMEMORY );
  363. goto Cleanup;
  364. }
  365. } // if: caller wants the network name
  366. Cleanup:
  367. HRETURN( hr );
  368. } //*** HrGetIPAddressInfo
  369. //////////////////////////////////////////////////////////////////////////////
  370. //++
  371. //
  372. // HrLoadCredentials
  373. //
  374. // Description:
  375. // Set credentials for the cluscfg session from an existing cluster
  376. // service.
  377. //
  378. // Arguments:
  379. // bstrMachine
  380. // piCCSC
  381. //
  382. // Return Value:
  383. // S_OK - Success.
  384. // S_FALSE -
  385. // E_OUTOFMEMORY - Couldn't allocate memory.
  386. // Other HRESULTs.
  387. //
  388. //--
  389. //////////////////////////////////////////////////////////////////////////////
  390. HRESULT
  391. HrLoadCredentials(
  392. BSTR bstrMachine
  393. , IClusCfgSetCredentials * piCCSC
  394. )
  395. {
  396. TraceFunc( "" );
  397. Assert( bstrMachine != NULL );
  398. Assert( piCCSC != NULL );
  399. HRESULT hr = S_FALSE;
  400. SC_HANDLE schSCM = NULL;
  401. SC_HANDLE schClusSvc = NULL;
  402. DWORD sc;
  403. DWORD cbpqsc = 128;
  404. DWORD cbRequired;
  405. QUERY_SERVICE_CONFIG * pqsc = NULL;
  406. schSCM = OpenSCManager( bstrMachine, NULL, GENERIC_READ );
  407. if ( schSCM == NULL )
  408. {
  409. sc = TW32( GetLastError() );
  410. hr = HRESULT_FROM_WIN32( hr );
  411. goto CleanUp;
  412. } // if:
  413. schClusSvc = OpenService( schSCM, L"ClusSvc", GENERIC_READ );
  414. if ( schClusSvc == NULL )
  415. {
  416. sc = TW32( GetLastError() );
  417. hr = HRESULT_FROM_WIN32( hr );
  418. goto CleanUp;
  419. } // if:
  420. for ( ; ; )
  421. {
  422. pqsc = (QUERY_SERVICE_CONFIG *) TraceAlloc( 0, cbpqsc );
  423. if ( pqsc == NULL )
  424. {
  425. hr = THR( E_OUTOFMEMORY );
  426. goto CleanUp;
  427. } // if:
  428. if ( ! QueryServiceConfig( schClusSvc, pqsc, cbpqsc, &cbRequired ) )
  429. {
  430. sc = GetLastError();
  431. if ( sc == ERROR_INSUFFICIENT_BUFFER )
  432. {
  433. TraceFree( pqsc );
  434. pqsc = NULL;
  435. cbpqsc = cbRequired;
  436. continue;
  437. } // if:
  438. else
  439. {
  440. TW32( sc );
  441. hr = HRESULT_FROM_WIN32( sc );
  442. goto CleanUp;
  443. } // else:
  444. } // if:
  445. else
  446. {
  447. break;
  448. } // else:
  449. } // for:
  450. hr = THR( piCCSC->SetDomainCredentials( pqsc->lpServiceStartName ) );
  451. CleanUp:
  452. if ( schClusSvc != NULL )
  453. {
  454. CloseServiceHandle( schClusSvc );
  455. } // if:
  456. if ( schSCM != NULL )
  457. {
  458. CloseServiceHandle( schSCM );
  459. } // if:
  460. TraceFree( pqsc );
  461. HRETURN( hr );
  462. } //*** HrLoadCredentials
  463. //////////////////////////////////////////////////////////////////////////////
  464. //++
  465. //
  466. // HrGetNodeNameHostingResource
  467. //
  468. // Description:
  469. // Get the name of the node hosting the cluster resource.
  470. //
  471. // Arguments:
  472. // hClusterIn
  473. // pbstrNodeName
  474. //
  475. // Return Value:
  476. // S_OK - Success.
  477. // S_FALSE -
  478. // E_OUTOFMEMORY - Couldn't allocate memory.
  479. // Other HRESULTs.
  480. //
  481. //--
  482. //////////////////////////////////////////////////////////////////////////////
  483. HRESULT
  484. HrGetNodeNameHostingResource(
  485. HCLUSTER hClusterIn
  486. , HRESOURCE hResourceIn
  487. , BSTR * pbstrNameOut
  488. )
  489. {
  490. TraceFunc( "" );
  491. Assert( hClusterIn != NULL );
  492. Assert( hResourceIn != NULL );
  493. Assert( pbstrNameOut != NULL );
  494. HRESULT hr = S_FALSE;
  495. WCHAR * pszNodeBuffer = NULL;
  496. DWORD cchNodeNameLen;
  497. DWORD scLastError;
  498. //
  499. // Get the length of the node name.
  500. //
  501. cchNodeNameLen = 0;
  502. GetClusterResourceState( hResourceIn, NULL, &cchNodeNameLen, NULL, NULL ); // Ignore the returned state.
  503. scLastError = GetLastError();
  504. if ( scLastError != ERROR_SUCCESS )
  505. {
  506. hr = HRESULT_FROM_WIN32( TW32( scLastError ) );
  507. goto Cleanup;
  508. }
  509. cchNodeNameLen++; // Increment for NULL.
  510. pszNodeBuffer = new WCHAR[ cchNodeNameLen ];
  511. if ( pszNodeBuffer == NULL )
  512. {
  513. hr = THR( E_OUTOFMEMORY );
  514. goto Cleanup;
  515. }
  516. //
  517. // Try it again, this time we should get the actual node name.
  518. //
  519. GetClusterResourceState( hResourceIn, pszNodeBuffer, &cchNodeNameLen, NULL, NULL ); // Ignore the returned state.
  520. scLastError = GetLastError();
  521. if ( scLastError != ERROR_SUCCESS )
  522. {
  523. hr = HRESULT_FROM_WIN32( TW32( scLastError ) );
  524. goto Cleanup;
  525. }
  526. //
  527. // Alloc & assign a copy of the node name to the out arg.
  528. //
  529. *pbstrNameOut = TraceSysAllocString( pszNodeBuffer );
  530. if ( pbstrNameOut == NULL )
  531. {
  532. hr = THR( E_OUTOFMEMORY );
  533. goto Cleanup;
  534. }
  535. hr = S_OK;
  536. Cleanup:
  537. delete [] pszNodeBuffer;
  538. HRETURN( hr );
  539. } //*** HrGetNodeNameHostingResource
  540. //////////////////////////////////////////////////////////////////////////////
  541. //++
  542. //
  543. // HrGetNodeNameHostingCluster
  544. //
  545. // Description:
  546. // Get the name of the node hosting the cluster service...
  547. //
  548. // Arguments:
  549. // hClusterIn
  550. // pbstrNodeName
  551. //
  552. // Return Value:
  553. // S_OK - Success.
  554. // E_OUTOFMEMORY - Couldn't allocate memory.
  555. // Other HRESULTs.
  556. //
  557. //--
  558. //////////////////////////////////////////////////////////////////////////////
  559. HRESULT
  560. HrGetNodeNameHostingCluster(
  561. HCLUSTER hClusterIn
  562. , BSTR * pbstrNodeName
  563. )
  564. {
  565. TraceFunc( "" );
  566. Assert( hClusterIn );
  567. HRESULT hr = S_OK;
  568. DWORD sc;
  569. HCLUSENUM hEnum = NULL;
  570. DWORD idx;
  571. DWORD dwType;
  572. WCHAR * psz = NULL;
  573. DWORD cchpsz = 33;
  574. HRESOURCE hRes = NULL;
  575. hEnum = ClusterOpenEnum( hClusterIn, CLUSTER_ENUM_RESOURCE );
  576. if ( hEnum == NULL )
  577. {
  578. sc = TW32( GetLastError() );
  579. hr = HRESULT_FROM_WIN32( sc );
  580. goto CleanUp;
  581. } // if:
  582. psz = new WCHAR [ cchpsz ];
  583. if ( psz == NULL )
  584. {
  585. goto OutOfMemory;
  586. } // if:
  587. for ( idx = 0; ; )
  588. {
  589. sc = ClusterEnum( hEnum, idx, &dwType, psz, &cchpsz );
  590. if ( sc == ERROR_MORE_DATA )
  591. {
  592. delete [] psz;
  593. psz = NULL;
  594. cchpsz++;
  595. psz = new WCHAR [ cchpsz ];
  596. if ( psz == NULL )
  597. {
  598. goto OutOfMemory;
  599. } // if:
  600. continue;
  601. } // if:
  602. if ( sc == ERROR_SUCCESS )
  603. {
  604. hRes = OpenClusterResource( hClusterIn, psz );
  605. if ( hRes == NULL )
  606. {
  607. sc = TW32( GetLastError() );
  608. hr = HRESULT_FROM_WIN32( sc );
  609. goto CleanUp;
  610. } // if:
  611. hr = STHR( HrIsResourceOfType( hRes, L"Network Name" ) );
  612. if ( FAILED( hr ) )
  613. {
  614. break;
  615. } // if:
  616. if ( hr == S_OK )
  617. {
  618. hr = THR( HrIsCoreResource( hRes ) );
  619. if ( FAILED( hr ) )
  620. {
  621. break;
  622. } // if:
  623. if ( hr == S_OK )
  624. {
  625. hr = THR( HrGetNodeNameHostingResource( hClusterIn, hRes, pbstrNodeName ) );
  626. if ( FAILED( hr ) )
  627. {
  628. break;
  629. } // if:
  630. else if( hr == S_OK )
  631. {
  632. goto CleanUp;
  633. }
  634. } // if:
  635. } // if:
  636. CloseClusterResource( hRes );
  637. hRes = NULL;
  638. idx++;
  639. continue;
  640. } // if:
  641. if ( sc == ERROR_NO_MORE_ITEMS )
  642. {
  643. hr = S_OK;
  644. break;
  645. } // if:
  646. TW32( sc );
  647. hr = HRESULT_FROM_WIN32( sc );
  648. break;
  649. } // for:
  650. goto CleanUp;
  651. OutOfMemory:
  652. hr = THR( E_OUTOFMEMORY );
  653. CleanUp:
  654. delete [] psz;
  655. if ( hRes != NULL )
  656. {
  657. CloseClusterResource( hRes );
  658. } // if:
  659. if ( hEnum != NULL )
  660. {
  661. ClusterCloseEnum( hEnum );
  662. } // if:
  663. HRETURN( hr );
  664. } //*** HrGetNodeNameHostingCluster
  665. //////////////////////////////////////////////////////////////////////////////
  666. //++
  667. //
  668. // HrGetSCSIInfo
  669. //
  670. // Description:
  671. // Get the name of the node hosting the cluster service...
  672. //
  673. // Arguments:
  674. // hResourceIn
  675. // pCSAOut
  676. // pdwSignatureOut
  677. // pdwDiskNumberOut
  678. //
  679. // Return Value:
  680. // S_OK - Success.
  681. // Other HRESULTs.
  682. //
  683. //--
  684. //////////////////////////////////////////////////////////////////////////////
  685. HRESULT
  686. HrGetSCSIInfo(
  687. HRESOURCE hResourceIn
  688. , CLUS_SCSI_ADDRESS * pCSAOut
  689. , DWORD * pdwSignatureOut
  690. , DWORD * pdwDiskNumberOut
  691. )
  692. {
  693. TraceFunc( "" );
  694. Assert( hResourceIn != NULL );
  695. HRESULT hr = S_OK;
  696. DWORD sc;
  697. CClusPropValueList cpvl;
  698. CLUSPROP_BUFFER_HELPER cpbh;
  699. sc = TW32( cpvl.ScGetResourceValueList( hResourceIn, CLUSCTL_RESOURCE_STORAGE_GET_DISK_INFO ) );
  700. if ( sc != ERROR_SUCCESS )
  701. {
  702. hr = HRESULT_FROM_WIN32( sc );
  703. goto Cleanup;
  704. } // if:
  705. // loop through all the properties.
  706. sc = TW32( cpvl.ScMoveToFirstValue() );
  707. if ( sc != ERROR_SUCCESS )
  708. {
  709. hr = HRESULT_FROM_WIN32( sc );
  710. goto Cleanup;
  711. } // if:
  712. do
  713. {
  714. if ( sc != ERROR_SUCCESS )
  715. {
  716. hr = HRESULT_FROM_WIN32( sc );
  717. goto Cleanup;
  718. } // if:
  719. cpbh = cpvl;
  720. switch ( cpbh.pSyntax->dw )
  721. {
  722. case CLUSPROP_SYNTAX_PARTITION_INFO :
  723. {
  724. break;
  725. } // case: CLUSPROP_SYNTAX_PARTITION_INFO
  726. case CLUSPROP_SYNTAX_DISK_SIGNATURE :
  727. {
  728. *pdwSignatureOut = cpbh.pDiskSignatureValue->dw;
  729. break;
  730. } // case: CLUSPROP_SYNTAX_DISK_SIGNATURE
  731. case CLUSPROP_SYNTAX_SCSI_ADDRESS :
  732. {
  733. pCSAOut->dw = cpbh.pScsiAddressValue->dw;
  734. break;
  735. } // case: CLUSPROP_SYNTAX_SCSI_ADDRESS
  736. case CLUSPROP_SYNTAX_DISK_NUMBER :
  737. {
  738. *pdwDiskNumberOut = cpbh.pDiskNumberValue->dw;
  739. break;
  740. } // case:
  741. } // switch:
  742. // Move to the next item.
  743. sc = cpvl.ScCheckIfAtLastValue();
  744. if ( sc == ERROR_NO_MORE_ITEMS )
  745. {
  746. break;
  747. }
  748. sc = cpvl.ScMoveToNextValue();
  749. } while ( sc == ERROR_SUCCESS );
  750. hr = S_OK;
  751. Cleanup:
  752. HRETURN( hr );
  753. } //*** HrGetSCSIInfo
  754. //////////////////////////////////////////////////////////////////////////////
  755. //++
  756. //
  757. // HrGetClusterInformation
  758. //
  759. // Description:
  760. // Get the cluster information. This includes the name and the version
  761. // info.
  762. //
  763. // Arguments:
  764. // hClusterIn
  765. // pbstrClusterNameOut
  766. // pcviOut
  767. //
  768. // Return Value:
  769. // S_OK - Success.
  770. // E_OUTOFMEMORY - Couldn't allocate memory.
  771. // Other HRESULTs.
  772. //
  773. //--
  774. //////////////////////////////////////////////////////////////////////////////
  775. HRESULT
  776. HrGetClusterInformation(
  777. HCLUSTER hClusterIn,
  778. BSTR * pbstrClusterNameOut,
  779. CLUSTERVERSIONINFO * pcviOut
  780. )
  781. {
  782. TraceFunc( "" );
  783. Assert( hClusterIn != NULL );
  784. Assert( pbstrClusterNameOut != NULL );
  785. HRESULT hr = S_OK;
  786. DWORD sc;
  787. WCHAR * psz = NULL;
  788. DWORD cch = 33;
  789. CLUSTERVERSIONINFO cvi;
  790. cvi.dwVersionInfoSize = sizeof( cvi );
  791. if ( pcviOut == NULL )
  792. {
  793. pcviOut = &cvi;
  794. } // if:
  795. psz = new WCHAR[ cch ];
  796. if ( psz == NULL )
  797. {
  798. goto OutOfMemory;
  799. } // if:
  800. sc = GetClusterInformation( hClusterIn, psz, &cch, pcviOut );
  801. if ( sc == ERROR_MORE_DATA )
  802. {
  803. delete [] psz;
  804. psz = NULL;
  805. psz = new WCHAR[ ++cch ];
  806. if ( psz == NULL )
  807. {
  808. goto OutOfMemory;
  809. } // if:
  810. sc = GetClusterInformation( hClusterIn, psz, &cch, pcviOut );
  811. } // if:
  812. if ( sc != ERROR_SUCCESS )
  813. {
  814. hr = THR( HRESULT_FROM_WIN32( sc ) );
  815. LogMsg( __FUNCTION__ ": GetClusterInformation() failed (hr = 0x%08x).", hr );
  816. goto Cleanup;
  817. } // if:
  818. *pbstrClusterNameOut = TraceSysAllocString( psz );
  819. if ( *pbstrClusterNameOut == NULL )
  820. {
  821. goto OutOfMemory;
  822. } // if:
  823. goto Cleanup;
  824. OutOfMemory:
  825. hr = THR( E_OUTOFMEMORY );
  826. Cleanup:
  827. delete [] psz;
  828. HRETURN( hr );
  829. } //*** HrGetClusterInformation
  830. /////////////////////////////////////////////////////////////////////////////
  831. //++
  832. //
  833. // HrGetClusterResourceState
  834. //
  835. // Description:
  836. //
  837. // Arguments:
  838. // hResourceIn
  839. // pbstrNodeNameOut
  840. // pbstrGroupNameOut
  841. // pcrsStateOut
  842. //
  843. // Return Values:
  844. // S_OK - Success.
  845. // E_OUTOFMEMORY - Couldn't allocate memory.
  846. // Other HRESULTs.
  847. //
  848. //--
  849. /////////////////////////////////////////////////////////////////////////////
  850. HRESULT
  851. HrGetClusterResourceState(
  852. HRESOURCE hResourceIn
  853. , BSTR * pbstrNodeNameOut
  854. , BSTR * pbstrGroupNameOut
  855. , CLUSTER_RESOURCE_STATE * pcrsStateOut
  856. )
  857. {
  858. TraceFunc( "" );
  859. Assert( hResourceIn != NULL );
  860. HRESULT hr = S_OK;
  861. CLUSTER_RESOURCE_STATE crsState = ClusterResourceStateUnknown;
  862. WCHAR * pszNodeName = NULL;
  863. DWORD cchNodeName = 33;
  864. WCHAR * pszGroupName = NULL;
  865. DWORD cchGroupName = 33;
  866. pszNodeName = new WCHAR[ cchNodeName ];
  867. if ( pszNodeName == NULL )
  868. {
  869. goto OutOfMemory;
  870. } // if:
  871. pszGroupName = new WCHAR[ cchGroupName ];
  872. if ( pszGroupName == NULL )
  873. {
  874. goto OutOfMemory;
  875. } // if:
  876. crsState = GetClusterResourceState( hResourceIn, pszNodeName, &cchNodeName, pszGroupName, &cchGroupName );
  877. if ( GetLastError() == ERROR_MORE_DATA )
  878. {
  879. crsState = ClusterResourceStateUnknown; // reset to error condition
  880. delete [] pszNodeName;
  881. pszNodeName = NULL;
  882. cchNodeName++;
  883. delete [] pszGroupName;
  884. pszGroupName = NULL;
  885. cchGroupName++;
  886. pszNodeName = new WCHAR[ cchNodeName ];
  887. if ( pszNodeName == NULL )
  888. {
  889. goto OutOfMemory;
  890. } // if:
  891. pszGroupName = new WCHAR[ cchGroupName ];
  892. if ( pszGroupName == NULL )
  893. {
  894. goto OutOfMemory;
  895. } // if:
  896. crsState = GetClusterResourceState( hResourceIn, pszNodeName, &cchNodeName, pszGroupName, &cchGroupName );
  897. if ( crsState == ClusterResourceStateUnknown )
  898. {
  899. DWORD sc;
  900. sc = TW32( GetLastError() );
  901. hr = HRESULT_FROM_WIN32( sc );
  902. goto Cleanup;
  903. } // if:
  904. } // if: more data
  905. if ( pbstrNodeNameOut != NULL )
  906. {
  907. *pbstrNodeNameOut = TraceSysAllocString( pszNodeName );
  908. if ( *pbstrNodeNameOut == NULL )
  909. {
  910. goto OutOfMemory;
  911. } // if:
  912. } // if:
  913. if ( pbstrGroupNameOut != NULL )
  914. {
  915. *pbstrGroupNameOut = TraceSysAllocString( pszGroupName );
  916. if ( *pbstrGroupNameOut == NULL )
  917. {
  918. goto OutOfMemory;
  919. } // if:
  920. } // if:
  921. if ( pcrsStateOut != NULL )
  922. {
  923. *pcrsStateOut = crsState;
  924. } // if:
  925. goto Cleanup;
  926. OutOfMemory:
  927. hr = THR( E_OUTOFMEMORY );
  928. Cleanup:
  929. delete [] pszNodeName;
  930. delete [] pszGroupName;
  931. HRETURN( hr );
  932. } //*** HrGetClusterResourceState
  933. /////////////////////////////////////////////////////////////////////////////
  934. //++
  935. //
  936. // HrGetClusterQuorumResource
  937. //
  938. // Description:
  939. // Get the information about the quorum resource.
  940. //
  941. // Arguments:
  942. // hClusterIn
  943. // pbstrResourceNameOut
  944. // pbstrDeviceNameOut
  945. // pdwMaxQuorumLogSizeOut
  946. //
  947. // Return Value.:
  948. // S_OK - Success.
  949. // E_INVALIDARG - An input argument was not specified.
  950. // E_OUTOFMEMORY - Couldn't allocate memory.
  951. // Other HRESULTs.
  952. //
  953. //--
  954. //////////////////////////////////////////////////////////////////////////////
  955. HRESULT
  956. HrGetClusterQuorumResource(
  957. HCLUSTER hClusterIn
  958. , BSTR * pbstrResourceNameOut
  959. , BSTR * pbstrDeviceNameOut
  960. , DWORD * pdwMaxQuorumLogSizeOut
  961. )
  962. {
  963. TraceFunc( "" );
  964. Assert( hClusterIn != NULL );
  965. Assert( ( pbstrResourceNameOut != NULL )
  966. || ( pbstrDeviceNameOut != NULL )
  967. || ( pdwMaxQuorumLogSizeOut != NULL )
  968. );
  969. HRESULT hr = S_OK;
  970. DWORD sc;
  971. LPWSTR pszResourceName = NULL;
  972. DWORD cchResourceName = 128;
  973. DWORD cchTempResourceName = cchResourceName;
  974. LPWSTR pszDeviceName = NULL;
  975. DWORD cchDeviceName = 128;
  976. DWORD cchTempDeviceName = cchDeviceName;
  977. DWORD dwMaxQuorumLogSize = 0;
  978. // Allocate the resource name buffer
  979. pszResourceName = new WCHAR[ cchResourceName ];
  980. if ( pszResourceName == NULL )
  981. {
  982. goto OutOfMemory;
  983. } // if:
  984. // Allocate the device name buffer
  985. pszDeviceName = new WCHAR[ cchDeviceName ];
  986. if ( pszDeviceName == NULL )
  987. {
  988. goto OutOfMemory;
  989. } // if:
  990. sc = GetClusterQuorumResource(
  991. hClusterIn
  992. , pszResourceName
  993. , &cchTempResourceName
  994. , pszDeviceName
  995. , &cchTempDeviceName
  996. , &dwMaxQuorumLogSize
  997. );
  998. if ( sc == ERROR_MORE_DATA )
  999. {
  1000. delete [] pszResourceName;
  1001. pszResourceName = NULL;
  1002. cchResourceName = ++cchTempResourceName;
  1003. // Allocate the resource name buffer
  1004. pszResourceName = new WCHAR[ cchResourceName ];
  1005. if ( pszResourceName == NULL )
  1006. {
  1007. goto OutOfMemory;
  1008. } // if:
  1009. delete [] pszDeviceName;
  1010. pszDeviceName = NULL;
  1011. cchDeviceName = ++cchTempDeviceName;
  1012. // Allocate the device name buffer
  1013. pszDeviceName = new WCHAR[ cchDeviceName ];
  1014. if ( pszDeviceName == NULL )
  1015. {
  1016. goto OutOfMemory;
  1017. } // if:
  1018. sc = GetClusterQuorumResource(
  1019. hClusterIn
  1020. , pszResourceName
  1021. , &cchTempResourceName
  1022. , pszDeviceName
  1023. , &cchTempDeviceName
  1024. , &dwMaxQuorumLogSize
  1025. );
  1026. } // if:
  1027. if ( sc != ERROR_SUCCESS )
  1028. {
  1029. TW32( sc );
  1030. hr = HRESULT_FROM_WIN32( sc );
  1031. goto Cleanup;
  1032. } // if:
  1033. if ( pbstrResourceNameOut != NULL )
  1034. {
  1035. *pbstrResourceNameOut = TraceSysAllocString( pszResourceName );
  1036. if ( *pbstrResourceNameOut == NULL )
  1037. {
  1038. goto OutOfMemory;
  1039. } // if:
  1040. } // if:
  1041. if ( pbstrDeviceNameOut != NULL )
  1042. {
  1043. *pbstrDeviceNameOut = TraceSysAllocString( pszDeviceName );
  1044. if ( *pbstrDeviceNameOut == NULL )
  1045. {
  1046. goto OutOfMemory;
  1047. } // if:
  1048. } // if:
  1049. if ( pdwMaxQuorumLogSizeOut != NULL )
  1050. {
  1051. *pdwMaxQuorumLogSizeOut = dwMaxQuorumLogSize;
  1052. } // if:
  1053. goto Cleanup;
  1054. OutOfMemory:
  1055. hr = THR( E_OUTOFMEMORY );
  1056. Cleanup:
  1057. delete [] pszResourceName;
  1058. delete [] pszDeviceName;
  1059. HRETURN( hr );
  1060. } //*** HrGetClusterQuorumResource
  1061. //////////////////////////////////////////////////////////////////////////////
  1062. //++
  1063. //
  1064. // HrReplaceTokens
  1065. //
  1066. // Description:
  1067. // Replaces all instances of the search tokens with a replacement token.
  1068. //
  1069. // Arguments:
  1070. // pwszStringInout - The string in which to perform replacements.
  1071. // pwszSearchTokenIn - The string of tokens to search for that will be replaced.
  1072. // chReplaceTokenIn - What the search tokens will be replaced with.
  1073. // pcReplacementsOut - [optional] The number of replacements performed.
  1074. //
  1075. // Return Values:
  1076. // S_OK - Success.
  1077. // Other HRESULTs.
  1078. //
  1079. //--
  1080. //////////////////////////////////////////////////////////////////////////////
  1081. HRESULT
  1082. HrReplaceTokens(
  1083. LPWSTR pwszStringInout
  1084. , LPCWSTR pwszSearchTokensIn
  1085. , WCHAR chReplaceTokenIn
  1086. , DWORD * pcReplacementsOut
  1087. )
  1088. {
  1089. TraceFunc3(
  1090. "pwszString = '%ws', pwszSearchToken: '%ws%', chReplaceToken: '%ws%'"
  1091. , ( pwszStringInout != NULL ? pwszStringInout: L"<null>" )
  1092. , pwszSearchTokensIn
  1093. , chReplaceTokenIn
  1094. );
  1095. HRESULT hr = S_OK;
  1096. DWORD cReps = 0;
  1097. WCHAR * pwszStr = NULL;
  1098. WCHAR * pwszTok = NULL;
  1099. Assert( pwszStringInout != NULL );
  1100. Assert( pwszSearchTokensIn != NULL );
  1101. //
  1102. // For each character in pwszStringInout check it against every character in
  1103. // pwszSearchTokensIn and if we find a match replace the character in
  1104. // pwszStringInout with the chReplaceTokenIn character.
  1105. //
  1106. for( pwszStr = pwszStringInout; *pwszStr != L'\0'; pwszStr++ )
  1107. {
  1108. for( pwszTok = (WCHAR *) pwszSearchTokensIn; *pwszTok != L'\0'; pwszTok++ )
  1109. {
  1110. if ( *pwszStr == *pwszTok )
  1111. {
  1112. *pwszStr = chReplaceTokenIn;
  1113. cReps++;
  1114. break;
  1115. } // if: match
  1116. } // for: each search token
  1117. } // for: each string element
  1118. if ( pcReplacementsOut != NULL )
  1119. {
  1120. *pcReplacementsOut = cReps;
  1121. }
  1122. HRETURN( hr );
  1123. } //*** HrReplaceTokens
  1124. /////////////////////////////////////////////////////////////////////////////
  1125. //++
  1126. //
  1127. // HrGetMaxNodeCount
  1128. //
  1129. // Description:
  1130. // Get the maximum node count supported by the cluster. This value
  1131. // could be based upon the product suite, or it could be overridden
  1132. // by an entry in the cluster hive.
  1133. //
  1134. // Arguments:
  1135. // pcMaxNodesOut
  1136. //
  1137. // Return Value:
  1138. // S_OK - Success.
  1139. // S_FALSE -
  1140. // E_POINTER - An output argument was not specified.
  1141. // Other HRESULTs.
  1142. //
  1143. // Note:
  1144. // THIS ROUTINE IS NOT FUNCIONTAL AT THE MOMENT.
  1145. //
  1146. //--
  1147. //////////////////////////////////////////////////////////////////////////////
  1148. HRESULT
  1149. HrGetMaxNodeCount(
  1150. DWORD * pcMaxNodesOut
  1151. )
  1152. {
  1153. TraceFunc( "" );
  1154. HRESULT hr = S_FALSE;
  1155. if ( pcMaxNodesOut == NULL )
  1156. {
  1157. hr = THR( E_POINTER );
  1158. goto Cleanup;
  1159. } // if:
  1160. //
  1161. // TODO: 11-OCT-2001 GalenB
  1162. //
  1163. // Need to finish this!
  1164. //
  1165. Cleanup:
  1166. HRETURN( hr );
  1167. } //*** HrGetMaxNodeCount
  1168. /////////////////////////////////////////////////////////////////////////////
  1169. //++
  1170. //
  1171. // HrGetReferenceStringFromHResult
  1172. //
  1173. // Description:
  1174. // Return if the specified HRESULT is in our list.
  1175. //
  1176. // Arguments:
  1177. // hrIn
  1178. // pbstrReferenceStringOut
  1179. //
  1180. // Return Value:
  1181. // S_OK - Success - HRESULT is in our list.
  1182. // S_FALSE - HRESULT is not in our list.
  1183. // E_POINTER - An output argument was not specified.
  1184. // Other HRESULTs.
  1185. //
  1186. //--
  1187. //////////////////////////////////////////////////////////////////////////////
  1188. HRESULT
  1189. HrGetReferenceStringFromHResult(
  1190. HRESULT hrIn
  1191. , BSTR * pbstrReferenceStringOut
  1192. )
  1193. {
  1194. TraceFunc( "" );
  1195. Assert( pbstrReferenceStringOut != NULL );
  1196. HRESULT hr = S_FALSE;
  1197. UINT idx;
  1198. struct MapHResultToStringId
  1199. {
  1200. HRESULT hr;
  1201. UINT ids;
  1202. };
  1203. static MapHResultToStringId s_rgmhrtsi[] =
  1204. {
  1205. { HRESULT_FROM_WIN32( ERROR_CLUSTER_IPADDR_IN_USE ), IDS_ERROR_IP_ADDRESS_IN_USE_REF }
  1206. , { HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY ), IDS_ERROR_OUTOFMEMORY_REF }
  1207. };
  1208. for ( idx = 0 ; idx < ARRAYSIZE( s_rgmhrtsi ) ; idx++ )
  1209. {
  1210. if ( hrIn == s_rgmhrtsi[ idx ].hr )
  1211. {
  1212. hr = THR( HrLoadStringIntoBSTR( g_hInstance, s_rgmhrtsi[ idx ].ids, pbstrReferenceStringOut ) );
  1213. if ( FAILED( hr ) )
  1214. {
  1215. goto Cleanup;
  1216. }
  1217. break;
  1218. } // if: found a match
  1219. } // for: each entry in the array
  1220. Cleanup:
  1221. HRETURN( hr );
  1222. } //*** HrGetReferenceStringFromHResult
  1223. /////////////////////////////////////////////////////////////////////////////
  1224. //++
  1225. //
  1226. // CClusterUtils:HrIsClusterServiceRunning
  1227. //
  1228. // Description:
  1229. // Is cluster service running?
  1230. //
  1231. // Arguments:
  1232. // None.
  1233. //
  1234. // Return Value:
  1235. // S_OK - The cluster service is running.
  1236. // S_FALSE - The cluster service is NOT running.
  1237. // HRESULT - Something failed.
  1238. //
  1239. //--
  1240. //////////////////////////////////////////////////////////////////////////////
  1241. HRESULT
  1242. HrIsClusterServiceRunning( void )
  1243. {
  1244. TraceFunc( "" );
  1245. HRESULT hr = S_FALSE;
  1246. DWORD sc;
  1247. DWORD dwClusterState;
  1248. //
  1249. // Get the cluster state of the node.
  1250. //
  1251. sc = GetNodeClusterState( NULL, &dwClusterState );
  1252. if ( ( sc != ERROR_SUCCESS ) && ( sc != ERROR_SERVICE_DOES_NOT_EXIST ) )
  1253. {
  1254. hr = HRESULT_FROM_WIN32( TW32( sc ) );
  1255. goto Cleanup;
  1256. } // if : GetClusterState() failed
  1257. if ( dwClusterState == ClusterStateRunning )
  1258. {
  1259. hr = S_OK;
  1260. } // if:
  1261. Cleanup:
  1262. HRETURN( hr );
  1263. } //*** HrIsClusterServiceRunning
  1264. /////////////////////////////////////////////////////////////////////////////
  1265. //++
  1266. //
  1267. // HrCheckJoiningNodeVersion
  1268. //
  1269. // Check a joining node's version information against that of the cluster.
  1270. //
  1271. // Arguments:
  1272. // pcwszClusterNameIn - can be null, which means to use local machine.
  1273. // dwNodeHighestVersionIn
  1274. // dwNodeLowestVersionIn
  1275. // pcccbIn - for status reporting.
  1276. //
  1277. // Return Value:
  1278. // S_OK
  1279. // The joining node is compatible.
  1280. //
  1281. // HRESULT_FROM_WIN32( ERROR_CLUSTER_INCOMPATIBLE_VERSIONS )
  1282. // The joining node is NOT compatible.
  1283. //
  1284. // Other HRESULT errors.
  1285. //
  1286. // Remarks:
  1287. //
  1288. // Get and verify the sponsor version
  1289. //
  1290. //
  1291. // From Whistler onwards, CsRpcGetJoinVersionData() will return a failure code in its last parameter
  1292. // if the version of this node is not compatible with the sponsor version. Prior to this, the last
  1293. // parameter always contained a success value and the cluster versions had to be compared subsequent to this
  1294. // call. This will, however, still have to be done as long as interoperability with Win2K
  1295. // is a requirement, since Win2K sponsors do not return an error in the last parameter.
  1296. //
  1297. //--
  1298. //////////////////////////////////////////////////////////////////////////////
  1299. HRESULT
  1300. HrCheckJoiningNodeVersion(
  1301. PCWSTR pcwszClusterNameIn
  1302. , DWORD dwNodeHighestVersionIn
  1303. , DWORD dwNodeLowestVersionIn
  1304. , IClusCfgCallback * pcccbIn
  1305. )
  1306. {
  1307. TraceFunc( "" );
  1308. HRESULT hr = S_OK;
  1309. RPC_STATUS rpcs = RPC_S_OK;
  1310. RPC_BINDING_HANDLE hRPCBinding = NULL;
  1311. PWSTR pwszBindingString = NULL;
  1312. DWORD scJoinStatus = ERROR_SUCCESS;
  1313. DWORD dwSponsorNode = 0;
  1314. DWORD dwClusterHighestVersion = 0;
  1315. DWORD dwClusterLowestVersion = 0;
  1316. DWORD scRPC = ERROR_SUCCESS;
  1317. //
  1318. // Connect to this cluster with RPC.
  1319. // The parameters and logic imitate OpenCluster,
  1320. // but the RPC interface (identified by the first parameter to RpcStringBindingComposeW) is different.
  1321. //
  1322. rpcs = TW32( RpcStringBindingComposeW(
  1323. L"6e17aaa0-1a47-11d1-98bd-0000f875292e" // Special interface for CsRpcGetJoinVersionData.
  1324. , ( pcwszClusterNameIn == NULL? L"ncalrpc": L"ncadg_ip_udp" )
  1325. , const_cast< WCHAR* >( pcwszClusterNameIn )
  1326. , NULL
  1327. , NULL
  1328. , &pwszBindingString
  1329. ) );
  1330. if ( rpcs != RPC_S_OK )
  1331. {
  1332. hr = HRESULT_FROM_WIN32( rpcs );
  1333. THR( HrSendStatusReport(
  1334. pcccbIn
  1335. , TASKID_Major_Client_And_Server_Log
  1336. , TASKID_Minor_HrCheckJoiningNodeVersion_RpcStringBindingComposeW
  1337. , 1
  1338. , 1
  1339. , 1
  1340. , hr
  1341. , L"HrCheckJoiningNodeVersion() RpcStringBindingComposeW() failed."
  1342. ) );
  1343. goto Cleanup;
  1344. } // if
  1345. rpcs = TW32( RpcBindingFromStringBindingW( pwszBindingString, &hRPCBinding ) );
  1346. if ( rpcs != RPC_S_OK )
  1347. {
  1348. hr = HRESULT_FROM_WIN32( rpcs );
  1349. THR( HrSendStatusReport(
  1350. pcccbIn
  1351. , TASKID_Major_Client_And_Server_Log
  1352. , TASKID_Minor_HrCheckJoiningNodeVersion_RpcBindingFromStringBindingW
  1353. , 1
  1354. , 1
  1355. , 1
  1356. , hr
  1357. , L"HrCheckJoiningNodeVersion() RpcBindingFromStringBindingW() failed."
  1358. ) );
  1359. goto Cleanup;
  1360. } // if
  1361. // Parameters to RpcBindingSetAuthInfoW copied from OpenCluster.
  1362. rpcs = TW32( RpcBindingSetAuthInfoW(
  1363. hRPCBinding
  1364. , NULL
  1365. , RPC_C_AUTHN_LEVEL_CONNECT
  1366. , RPC_C_AUTHN_WINNT
  1367. , NULL
  1368. , RPC_C_AUTHZ_NAME
  1369. ) );
  1370. if ( rpcs != RPC_S_OK )
  1371. {
  1372. hr = HRESULT_FROM_WIN32( rpcs );
  1373. THR( HrSendStatusReport(
  1374. pcccbIn
  1375. , TASKID_Major_Client_And_Server_Log
  1376. , TASKID_Minor_HrCheckJoiningNodeVersion_RpcBindingSetAuthInfoW
  1377. , 1
  1378. , 1
  1379. , 1
  1380. , hr
  1381. , L"HrCheckJoiningNodeVersion() RpcBindingSetAuthInfoW() failed."
  1382. ) );
  1383. goto Cleanup;
  1384. } // if
  1385. // Now, perform the check this function advertises.
  1386. scRPC = TW32( CsRpcGetJoinVersionData(
  1387. hRPCBinding
  1388. , 0
  1389. , dwNodeHighestVersionIn
  1390. , dwNodeLowestVersionIn
  1391. , &dwSponsorNode
  1392. , &dwClusterHighestVersion
  1393. , &dwClusterLowestVersion
  1394. , &scJoinStatus
  1395. ) );
  1396. hr = HRESULT_FROM_WIN32( scRPC );
  1397. THR( HrFormatDescriptionAndSendStatusReport(
  1398. pcccbIn
  1399. , pcwszClusterNameIn
  1400. , TASKID_Major_Client_And_Server_Log
  1401. , TASKID_Minor_HrCheckJoiningNodeVersion_CsRpcGetJoinVersionData_Log
  1402. , 1
  1403. , 1
  1404. , 1
  1405. , hr
  1406. , L"( Node Highest, Node Lowest ) == ( %1!#08x!, %2!#08x! ), ( Cluster Highest, Cluster Lowest ) == ( %3!#08x!, %4!#08x! )."
  1407. , dwNodeHighestVersionIn
  1408. , dwNodeLowestVersionIn
  1409. , dwClusterHighestVersion
  1410. , dwClusterLowestVersion
  1411. ) );
  1412. if ( scRPC != ERROR_SUCCESS )
  1413. {
  1414. THR( HrSendStatusReport(
  1415. pcccbIn
  1416. , TASKID_Major_Client_And_Server_Log
  1417. , TASKID_Minor_HrCheckJoiningNodeVersion_CsRpcGetJoinVersionData
  1418. , 1
  1419. , 1
  1420. , 1
  1421. , hr
  1422. , L"HrCheckJoiningNodeVersion() CsRpcGetJoinVersionData() failed."
  1423. ) );
  1424. goto Cleanup;
  1425. } // if
  1426. if ( scJoinStatus == ERROR_SUCCESS )
  1427. {
  1428. DWORD dwClusterMajorVersion = CLUSTER_GET_MAJOR_VERSION( dwClusterHighestVersion );
  1429. Assert( dwClusterMajorVersion >= ( CLUSTER_INTERNAL_CURRENT_MAJOR_VERSION - 1 ) );
  1430. //
  1431. // Only want to join clusters that are no more than one version back.
  1432. //
  1433. if ( dwClusterMajorVersion < ( CLUSTER_INTERNAL_CURRENT_MAJOR_VERSION - 1 ) )
  1434. {
  1435. hr = THR( HRESULT_FROM_WIN32( ERROR_CLUSTER_INCOMPATIBLE_VERSIONS ) );
  1436. } // if
  1437. } // if
  1438. else
  1439. {
  1440. hr = THR( HRESULT_FROM_WIN32( ERROR_CLUSTER_INCOMPATIBLE_VERSIONS ) );
  1441. } // else
  1442. Cleanup:
  1443. if ( hRPCBinding != NULL )
  1444. {
  1445. RpcBindingFree( &hRPCBinding );
  1446. } // if
  1447. if ( pwszBindingString != NULL )
  1448. {
  1449. RpcStringFree( &pwszBindingString );
  1450. } // if
  1451. HRETURN( hr );
  1452. } //*** HrCheckJoiningNodeVersion
  1453. //////////////////////////////////////////////////////////////////////////////
  1454. //++
  1455. //
  1456. // HrGetNodeNames
  1457. //
  1458. // Description:
  1459. // Retrieve the names of the nodes currently in a cluster.
  1460. //
  1461. // Parameters:
  1462. // hClusterIn
  1463. // A handle to the cluster of interest. Must NOT be null.
  1464. //
  1465. // pnCountOut
  1466. // On success, *pnCountOut returns the number of nodes in the cluster.
  1467. //
  1468. // prgbstrNodeNamesOut
  1469. // On success, an array of BSTRs containing the node names.
  1470. // The caller must free each BSTR with SysFreeString, and free
  1471. // the array with CoTaskMemFree.
  1472. //
  1473. // Return Values:
  1474. // S_OK
  1475. // The out parameters contain valid information and the caller
  1476. // must free the array and the BSTRs it contains.
  1477. //
  1478. // E_OUTOFMEMORY, and other failures are possible.
  1479. //
  1480. //--
  1481. //////////////////////////////////////////////////////////////////////////////
  1482. HRESULT
  1483. HrGetNodeNames(
  1484. HCLUSTER hClusterIn
  1485. , long * pnCountOut
  1486. , BSTR ** prgbstrNodeNamesOut
  1487. )
  1488. {
  1489. TraceFunc( "" );
  1490. HRESULT hr = S_OK;
  1491. BSTR * prgbstrNodeNames = NULL;
  1492. long idxNode = 0;
  1493. HCLUSENUM hClusEnum = NULL;
  1494. long cNodes = 0;
  1495. if ( pnCountOut != NULL )
  1496. {
  1497. *pnCountOut = 0;
  1498. } // if
  1499. if ( prgbstrNodeNamesOut != NULL )
  1500. {
  1501. *prgbstrNodeNamesOut = NULL;
  1502. } // if
  1503. if ( ( pnCountOut == NULL ) || ( prgbstrNodeNamesOut == NULL ) )
  1504. {
  1505. hr = THR( E_POINTER );
  1506. goto Cleanup;
  1507. } // if
  1508. hClusEnum = ClusterOpenEnum( hClusterIn, CLUSTER_ENUM_NODE );
  1509. if ( hClusEnum == NULL )
  1510. {
  1511. DWORD scLastError = TW32( GetLastError() );
  1512. hr = HRESULT_FROM_WIN32( scLastError );
  1513. goto Cleanup;
  1514. } // if
  1515. cNodes = ClusterGetEnumCount( hClusEnum );
  1516. if ( cNodes > 0 )
  1517. {
  1518. //
  1519. // Set up local copy of name array.
  1520. //
  1521. prgbstrNodeNames = reinterpret_cast< BSTR* >( CoTaskMemAlloc( cNodes * sizeof( BSTR ) ) );
  1522. if ( prgbstrNodeNames == NULL )
  1523. {
  1524. hr = THR( E_OUTOFMEMORY );
  1525. goto Cleanup;
  1526. } // if
  1527. ZeroMemory( prgbstrNodeNames, cNodes * sizeof( BSTR ) );
  1528. for ( idxNode = 0; idxNode < cNodes; idxNode += 1 )
  1529. {
  1530. DWORD dwNodeType = 0;
  1531. WCHAR wszNodeName[ DNS_MAX_NAME_BUFFER_LENGTH ];
  1532. DWORD cchNodeName = RTL_NUMBER_OF( wszNodeName );
  1533. DWORD scEnum = ERROR_SUCCESS;
  1534. scEnum = TW32( ClusterEnum( hClusEnum, idxNode, &dwNodeType, wszNodeName, &cchNodeName ) );
  1535. if ( scEnum != ERROR_SUCCESS )
  1536. {
  1537. hr = HRESULT_FROM_WIN32( scEnum );
  1538. goto Cleanup;
  1539. } // if
  1540. prgbstrNodeNames[ idxNode ] = SysAllocString( wszNodeName );
  1541. if ( prgbstrNodeNames[ idxNode ] == NULL )
  1542. {
  1543. hr = THR( E_OUTOFMEMORY );
  1544. goto Cleanup;
  1545. } // if
  1546. } // for each node in the cluster
  1547. //
  1548. // Copy succeeded, so transfer ownership to caller.
  1549. //
  1550. *pnCountOut = cNodes;
  1551. *prgbstrNodeNamesOut = prgbstrNodeNames;
  1552. prgbstrNodeNames = NULL;
  1553. } // if cluster has at least one node
  1554. Cleanup:
  1555. if ( hClusEnum != NULL )
  1556. {
  1557. ClusterCloseEnum( hClusEnum );
  1558. } // if
  1559. if ( prgbstrNodeNames != NULL )
  1560. {
  1561. //
  1562. // Making local copy of array must have failed midway, so
  1563. // clean up whatever parts of it exist.
  1564. //
  1565. for ( idxNode = 0; idxNode < cNodes; ++idxNode )
  1566. {
  1567. SysFreeString( prgbstrNodeNames[ idxNode ] );
  1568. } // for
  1569. CoTaskMemFree( prgbstrNodeNames );
  1570. } // if still own local copy of array.
  1571. HRETURN( hr );
  1572. } //*** HrGetNodeNames