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.

2026 lines
50 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2001-2002 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CMajorityNodeSet.cpp
  7. //
  8. // Description:
  9. // This file contains the definition of the CMajorityNodeSet class.
  10. //
  11. // The class CMajorityNodeSet represents a cluster manageable
  12. // device. It implements the IClusCfgManagedResourceInfo interface.
  13. //
  14. // Maintained By:
  15. // Galen Barbee (GalenB) 13-MAR-2001
  16. //
  17. //////////////////////////////////////////////////////////////////////////////
  18. //////////////////////////////////////////////////////////////////////////////
  19. // Include Files
  20. //////////////////////////////////////////////////////////////////////////////
  21. #include "Pch.h"
  22. #include "CMajorityNodeSet.h"
  23. #include <clusrtl.h>
  24. //////////////////////////////////////////////////////////////////////////////
  25. // Constant Definitions
  26. //////////////////////////////////////////////////////////////////////////////
  27. DEFINE_THISCLASS( "CMajorityNodeSet" );
  28. #define SETUP_DIRECTORY_PREFIX L"\\cluster\\" MAJORITY_NODE_SET_DIRECTORY_PREFIX
  29. //*************************************************************************//
  30. /////////////////////////////////////////////////////////////////////////////
  31. // CMajorityNodeSet class
  32. /////////////////////////////////////////////////////////////////////////////
  33. //////////////////////////////////////////////////////////////////////////////
  34. //++
  35. //
  36. // CMajorityNodeSet::S_HrCreateInstance
  37. //
  38. // Description:
  39. // Create a CMajorityNodeSet instance.
  40. //
  41. // Arguments:
  42. // None.
  43. //
  44. // Return Values:
  45. // Pointer to CMajorityNodeSet instance.
  46. //
  47. //--
  48. //////////////////////////////////////////////////////////////////////////////
  49. HRESULT
  50. CMajorityNodeSet::S_HrCreateInstance( IUnknown ** ppunkOut )
  51. {
  52. TraceFunc( "" );
  53. HRESULT hr = S_OK;
  54. CMajorityNodeSet * pmns = NULL;
  55. if ( ppunkOut == NULL )
  56. {
  57. hr = THR( E_POINTER );
  58. goto Cleanup;
  59. } // if:
  60. pmns = new CMajorityNodeSet();
  61. if ( pmns == NULL )
  62. {
  63. hr = THR( E_OUTOFMEMORY );
  64. goto Cleanup;
  65. } // if: error allocating object
  66. hr = THR( pmns->HrInit() );
  67. if ( FAILED( hr ) )
  68. {
  69. goto Cleanup;
  70. } // if: HrInit() failed
  71. hr = THR( pmns->TypeSafeQI( IUnknown, ppunkOut ) );
  72. if ( FAILED( hr ) )
  73. {
  74. goto Cleanup;
  75. } // if: QI failed
  76. Cleanup:
  77. if ( FAILED( hr ) )
  78. {
  79. LogMsg( L"[SRV] CMajorityNodeSet::S_HrCreateInstance() failed. (hr = %#08x)", hr );
  80. } // if:
  81. if ( pmns != NULL )
  82. {
  83. pmns->Release();
  84. } // if:
  85. HRETURN( hr );
  86. } //*** CMajorityNodeSet::S_HrCreateInstance
  87. //*************************************************************************//
  88. /////////////////////////////////////////////////////////////////////////////
  89. // CMajorityNodeSet class -- Private Methods.
  90. /////////////////////////////////////////////////////////////////////////////
  91. //////////////////////////////////////////////////////////////////////////////
  92. //++
  93. //
  94. // CMajorityNodeSet::CMajorityNodeSet
  95. //
  96. // Description:
  97. // Constructor of the CMajorityNodeSet class. This initializes
  98. // the m_cRef variable to 1 instead of 0 to account of possible
  99. // QueryInterface failure in DllGetClassObject.
  100. //
  101. // Arguments:
  102. // None.
  103. //
  104. // Return Value:
  105. // None.
  106. //
  107. // Remarks:
  108. // None.
  109. //
  110. //--
  111. //////////////////////////////////////////////////////////////////////////////
  112. CMajorityNodeSet::CMajorityNodeSet( void )
  113. : m_cRef( 1 )
  114. , m_fIsQuorumCapable( TRUE )
  115. {
  116. TraceFunc( "" );
  117. // Increment the count of components in memory so the DLL hosting this
  118. // object cannot be unloaded.
  119. InterlockedIncrement( &g_cObjects );
  120. Assert( m_lcid == 0 );
  121. Assert( m_picccCallback == NULL );
  122. Assert( m_fIsQuorum == FALSE );
  123. Assert( m_fIsMultiNodeCapable == FALSE );
  124. Assert( m_fIsManaged == FALSE );
  125. Assert( m_fIsManagedByDefault == FALSE );
  126. Assert( m_bstrName == NULL );
  127. Assert( m_fAddedShare == FALSE );
  128. TraceFuncExit();
  129. } //*** CMajorityNodeSet::CMajorityNodeSet
  130. //////////////////////////////////////////////////////////////////////////////
  131. //++
  132. //
  133. // CMajorityNodeSet::~CMajorityNodeSet
  134. //
  135. // Description:
  136. // Desstructor of the CMajorityNodeSet class.
  137. //
  138. // Arguments:
  139. // None.
  140. //
  141. // Return Value:
  142. // None.
  143. //
  144. // Remarks:
  145. // None.
  146. //
  147. //--
  148. //////////////////////////////////////////////////////////////////////////////
  149. CMajorityNodeSet::~CMajorityNodeSet( void )
  150. {
  151. TraceFunc( "" );
  152. if ( m_picccCallback != NULL )
  153. {
  154. m_picccCallback->Release();
  155. } // if:
  156. TraceSysFreeString( m_bstrName );
  157. // There's going to be one less component in memory. Decrement component count.
  158. InterlockedDecrement( &g_cObjects );
  159. TraceFuncExit();
  160. } //*** CMajorityNodeSet::~CMajorityNodeSet
  161. //////////////////////////////////////////////////////////////////////////////
  162. //++
  163. //
  164. // CMajorityNodeSet::HrInit
  165. //
  166. // Description:
  167. // Initialize this component.
  168. //
  169. // Arguments:
  170. // None.
  171. //
  172. // Return Value:
  173. //
  174. //
  175. // Remarks:
  176. // None.
  177. //
  178. //--
  179. //////////////////////////////////////////////////////////////////////////////
  180. HRESULT
  181. CMajorityNodeSet::HrInit( void )
  182. {
  183. TraceFunc( "" );
  184. HRESULT hr = S_OK;
  185. // IUnknown
  186. Assert( m_cRef == 1 );
  187. //
  188. // BUGBUG: 16-MAR-2001 GalenB
  189. //
  190. // Make this device joinable by default. Need to figure how to do this
  191. // properly. Depending upon Majority Node Set this may be the right way to
  192. // do it...
  193. //
  194. m_fIsMultiNodeCapable = TRUE;
  195. //
  196. // Do not default to being manageable. Let our parent enum set this to true
  197. // if and only if there is an instance of MNS in the cluster.
  198. //
  199. //m_fIsManagedByDefault = TRUE;
  200. //
  201. // Load the display name for this resource
  202. //
  203. hr = THR( HrLoadStringIntoBSTR( g_hInstance, IDS_MAJORITY_NODE_SET, &m_bstrName ) );
  204. HRETURN( hr );
  205. } //*** CMajorityNodeSet::HrInit
  206. //////////////////////////////////////////////////////////////////////////////
  207. //++
  208. //
  209. // CMajorityNodeSet::HrSetupShare
  210. //
  211. // Description:
  212. // Setup the share for the MNS resource. Called from PrepareToHostQuorum.
  213. //
  214. // Arguments:
  215. // None.
  216. //
  217. // Return Value:
  218. // S_OK
  219. // Success.
  220. //
  221. // Other HRESULT
  222. // An error occurred.
  223. //
  224. // Remarks:
  225. // This duplicates the functionality found in SetupShare in resdll\ndquorum\setup.c.
  226. //
  227. //--
  228. //////////////////////////////////////////////////////////////////////////////
  229. HRESULT
  230. CMajorityNodeSet::HrSetupShare(
  231. LPCWSTR pcszGUIDIn
  232. )
  233. {
  234. TraceFunc( "" );
  235. HRESULT hr;
  236. DWORD sc;
  237. DWORD cch;
  238. WCHAR szPath[ MAX_PATH ];
  239. WCHAR szGUID[ MAX_PATH ];
  240. HANDLE hDir = NULL;
  241. SHARE_INFO_502 shareInfo;
  242. PBYTE pbBuffer = NULL;
  243. PSECURITY_DESCRIPTOR pSD = NULL;
  244. //
  245. // Both the directory and the share need to have '$' appended to them.
  246. //
  247. hr = THR( StringCchPrintfW( szGUID, ARRAYSIZE( szGUID ), L"%ws$", pcszGUIDIn ) );
  248. if ( FAILED( hr ) )
  249. {
  250. goto Cleanup;
  251. } // if:
  252. //
  253. // Retrieve the windows directory.
  254. //
  255. cch = GetWindowsDirectoryW( szPath, MAX_PATH );
  256. if ( cch == 0 )
  257. {
  258. sc = TW32( GetLastError() );
  259. LogMsg( L"[SRV] CMajorityNodeSet::SetupShare: GetWindowsDirectory failed: %d.", sc );
  260. hr = HRESULT_FROM_WIN32( sc );
  261. goto Cleanup;
  262. } // if: couldn't retrieve the Windows directory
  263. Assert( cch < MAX_PATH );
  264. Assert( wcslen( SETUP_DIRECTORY_PREFIX ) + wcslen( szGUID ) < MAX_PATH );
  265. // GetWindowsDirectory apparently doesn't null terminate the returned string.
  266. //szPath[ cch ] = L'\0';
  267. //
  268. // Construct the directory "<%systemroot%>\cluster\MNS.<GUID$>".
  269. //
  270. hr = THR( StringCchCatW( szPath, ARRAYSIZE( szPath ), SETUP_DIRECTORY_PREFIX ) );
  271. if ( FAILED( hr ) )
  272. {
  273. goto Cleanup;
  274. } // if:
  275. hr = THR( StringCchCatW( szPath, ARRAYSIZE( szPath ), szGUID ) );
  276. if ( FAILED( hr ) )
  277. {
  278. goto Cleanup;
  279. } // if:
  280. //
  281. // If the directory or share exists delete it. Should create it fresh.
  282. //
  283. hr = THR( HrDeleteShare( pcszGUIDIn ) );
  284. if ( FAILED( hr ) )
  285. {
  286. goto Cleanup;
  287. } // if:
  288. // Test
  289. LogMsg( L"[SRV] CMajorityNodeSet::SetupShare() share path=%ws share name=%ws.", szPath, szGUID );
  290. if ( FALSE == CreateDirectory( szPath, NULL ) )
  291. {
  292. sc = TW32( GetLastError() );
  293. if ( sc != ERROR_ALREADY_EXISTS )
  294. {
  295. LogMsg( L"[SRV] CMajorityNodeSet::SetupShare: Failed to create directory \'%ws\', %d.", szPath, sc );
  296. hr = HRESULT_FROM_WIN32( sc );
  297. goto Cleanup;
  298. } // if: CreateDirectory failed
  299. } // if: CreateDirectory failed - either we couldn't create it or it already exists.
  300. //
  301. // Open a handle to the new directory so that we can set permissions on it.
  302. //
  303. hDir = CreateFileW(
  304. szPath
  305. , GENERIC_READ | WRITE_DAC | READ_CONTROL
  306. , FILE_SHARE_READ | FILE_SHARE_WRITE
  307. , NULL
  308. , OPEN_ALWAYS
  309. , FILE_FLAG_BACKUP_SEMANTICS
  310. , NULL
  311. );
  312. if ( hDir == INVALID_HANDLE_VALUE )
  313. {
  314. sc = TW32( GetLastError() );
  315. LogMsg( L"[SRV] CMajorityNodeSet::SetupShare: Failed to open a handle to the directory 'w%s', %d.", szPath, sc );
  316. hr = HRESULT_FROM_WIN32( sc );
  317. goto Cleanup;
  318. } // if: we weren't able to open a handle to the new directory
  319. //
  320. // Set the security attributes for the file.
  321. //
  322. sc = TW32( ClRtlSetObjSecurityInfo( hDir, SE_FILE_OBJECT, GENERIC_ALL, GENERIC_ALL, 0 ) );
  323. if ( sc != ERROR_SUCCESS )
  324. {
  325. LogMsg( L"[SRV] CMajorityNodeSet::SetupShare: Error setting security on directory '%ws', %d.", szPath, sc );
  326. hr = HRESULT_FROM_WIN32( TW32( sc ) );
  327. goto Cleanup;
  328. } // if: failed to set the security on the object
  329. //
  330. // See if the share already exists.
  331. //
  332. pbBuffer = (PBYTE) &shareInfo;
  333. sc = TW32( NetShareGetInfo( NULL, (LPWSTR) szGUID, 502, (PBYTE *) &pbBuffer ) );
  334. if ( sc == NERR_Success )
  335. {
  336. NetApiBufferFree( pbBuffer );
  337. pbBuffer = NULL;
  338. hr = S_OK;
  339. goto Cleanup;
  340. } // if: NetShareGetInfo succeeded - the share exists already so we're done.
  341. //
  342. // We couldn't find the share, so try to create it.
  343. //
  344. sc = ConvertStringSecurityDescriptorToSecurityDescriptor(
  345. L"D:P(A;;GA;;;BA)(A;;GA;;;CO)"
  346. , SDDL_REVISION_1
  347. , &pSD
  348. , NULL
  349. );
  350. if ( sc == 0 ) // Zero indicates failure.
  351. {
  352. pSD = NULL;
  353. sc = TW32( GetLastError() );
  354. LogMsg( L"[SRV] CMajorityNodeSet::SetupShare: Unable to retrieve the security descriptor: %d.", sc );
  355. hr = HRESULT_FROM_WIN32( sc );
  356. goto Cleanup;
  357. } // if: Convert failed
  358. //
  359. // Now try to actually create it.
  360. //
  361. ZeroMemory( &shareInfo, sizeof( shareInfo ) );
  362. shareInfo.shi502_netname = (LPWSTR) szGUID;
  363. shareInfo.shi502_type = STYPE_DISKTREE;
  364. shareInfo.shi502_remark = L"";
  365. shareInfo.shi502_max_uses = (DWORD) -1;
  366. shareInfo.shi502_path = szPath;
  367. shareInfo.shi502_passwd = NULL;
  368. shareInfo.shi502_permissions = ACCESS_ALL;
  369. shareInfo.shi502_security_descriptor = pSD;
  370. sc = NetShareAdd( NULL, 502, (PBYTE) &shareInfo, NULL );
  371. if ( sc != NERR_Success && sc != NERR_DuplicateShare )
  372. {
  373. LogMsg( L"[SRV] CMajorityNodeSet::SetupShare: Unable to add share '%ws' to the local machine, %d.", szPath, sc );
  374. hr = THR( HRESULT_FROM_WIN32( sc ) );
  375. goto Cleanup;
  376. } // if: NetShareAdd failed
  377. m_fAddedShare = TRUE;
  378. hr = S_OK;
  379. Cleanup:
  380. if ( FAILED( hr ) )
  381. {
  382. STATUS_REPORT_STRING_REF(
  383. TASKID_Major_Check_Cluster_Feasibility
  384. , TASKID_Minor_MajorityNodeSet_HrSetupShare
  385. , IDS_ERROR_MNS_HRSETUPSHARE
  386. , szPath
  387. , IDS_ERROR_MNS_HRSETUPSHARE_REF
  388. , hr
  389. );
  390. } // if: we had an error
  391. if ( ( hDir != NULL ) && ( hDir != INVALID_HANDLE_VALUE ) )
  392. {
  393. CloseHandle( hDir );
  394. } // if:
  395. LocalFree( pSD );
  396. HRETURN( hr );
  397. } //*** CMajorityNodeSet::HrSetupShare
  398. //////////////////////////////////////////////////////////////////////////////
  399. //++
  400. //
  401. // CMajorityNodeSet::HrDeleteShare
  402. //
  403. // Description:
  404. // Delete the share that we setup for the MNS resource. Called from Cleanup.
  405. //
  406. // Arguments:
  407. // pcszGUIDIn - name of the GUID for this resource, used to figure out what
  408. // the share name and directory names are.
  409. //
  410. // Return Value:
  411. // S_OK
  412. // Success.
  413. //
  414. // Other HRESULT
  415. // An error occurred.
  416. //
  417. // Remarks:
  418. // This duplicates the functionality found in SetupDelete in resdll\ndquorum\setup.c.
  419. //
  420. //--
  421. //////////////////////////////////////////////////////////////////////////////
  422. HRESULT
  423. CMajorityNodeSet::HrDeleteShare(
  424. LPCWSTR pcszGUIDIn
  425. )
  426. {
  427. TraceFunc( "" );
  428. HRESULT hr;
  429. DWORD sc;
  430. DWORD cch;
  431. WCHAR szPath[ MAX_PATH ];
  432. WCHAR szGUID[ MAX_PATH ];
  433. //
  434. // Both the directory and the share have '$' appended to them.
  435. //
  436. hr = THR( StringCchPrintfW( szGUID, ARRAYSIZE( szGUID ), L"%ws$", pcszGUIDIn ) );
  437. if ( FAILED( hr ) )
  438. {
  439. goto Cleanup;
  440. } // if:
  441. sc = NetShareDel( NULL, szGUID, 0 );
  442. if ( ( sc != NERR_Success ) && ( sc != NERR_NetNameNotFound ) )
  443. {
  444. TW32( sc );
  445. LogMsg( L"[SRV] CMajorityNodeSet::Cleanup: NetShareDel failed: %d, '%ws'.", sc, szGUID );
  446. // Don't goto Cleanup yet. Try to delete the directory first.
  447. } // if: NetShareDel failed.
  448. LogMsg( L"CMajorityNodeSet::HrDeleteShare: share '%ws' deleted.", pcszGUIDIn );
  449. cch = GetWindowsDirectoryW( szPath, MAX_PATH );
  450. if ( cch == 0 )
  451. {
  452. sc = TW32( GetLastError() );
  453. LogMsg( L"[SRV] CMajorityNodeSet::Cleanup: GetWindowsDirectory failed: %d.", sc );
  454. hr = HRESULT_FROM_WIN32( sc );
  455. goto Cleanup;
  456. } // if: GetWindowsDirectory failed.
  457. hr = THR( StringCchCatW( szPath, ARRAYSIZE( szPath ), SETUP_DIRECTORY_PREFIX ) );
  458. if ( FAILED( hr ) )
  459. {
  460. goto Cleanup;
  461. } // if:
  462. hr = THR( StringCchCatW( szPath, ARRAYSIZE( szPath ), szGUID ) );
  463. if ( FAILED( hr ) )
  464. {
  465. goto Cleanup;
  466. } // if:
  467. sc = TW32( DwRemoveDirectory( szPath, 32 ) );
  468. if ( sc != ERROR_SUCCESS )
  469. {
  470. LogMsg( L"[SRV] CMajorityNodeSet::Cleanup: DwRemoveDirectory '%ws': %d.", szPath, sc );
  471. hr = HRESULT_FROM_WIN32( sc );
  472. goto Cleanup;
  473. } // if: unable to delete the directory structure
  474. hr = S_OK;
  475. Cleanup:
  476. HRETURN( hr );
  477. } //*** CMajorityNodeSet::HrDeleteShare
  478. //*************************************************************************//
  479. /////////////////////////////////////////////////////////////////////////////
  480. // CMajorityNodeSet -- IUknkown interface.
  481. /////////////////////////////////////////////////////////////////////////////
  482. //////////////////////////////////////////////////////////////////////////////
  483. //++
  484. //
  485. // CMajorityNodeSet::AddRef
  486. //
  487. // Description:
  488. // Increment the reference count of this object by one.
  489. //
  490. // Arguments:
  491. // None.
  492. //
  493. // Return Value:
  494. // The new reference count.
  495. //
  496. // Remarks:
  497. // None.
  498. //
  499. //--
  500. //////////////////////////////////////////////////////////////////////////////
  501. STDMETHODIMP_( ULONG )
  502. CMajorityNodeSet::AddRef( void )
  503. {
  504. TraceFunc( "[IUnknown]" );
  505. InterlockedIncrement( &m_cRef );
  506. CRETURN( m_cRef );
  507. } //*** CMajorityNodeSet::AddRef
  508. //////////////////////////////////////////////////////////////////////////////
  509. //++
  510. //
  511. // CMajorityNodeSet::Release
  512. //
  513. // Description:
  514. // Decrement the reference count of this object by one.
  515. //
  516. // Arguments:
  517. // None.
  518. //
  519. // Return Value:
  520. // The new reference count.
  521. //
  522. // Remarks:
  523. // None.
  524. //
  525. //--
  526. //////////////////////////////////////////////////////////////////////////////
  527. STDMETHODIMP_( ULONG )
  528. CMajorityNodeSet::Release( void )
  529. {
  530. TraceFunc( "[IUnknown]" );
  531. LONG cRef;
  532. cRef = InterlockedDecrement( &m_cRef );
  533. if ( cRef == 0 )
  534. {
  535. TraceDo( delete this );
  536. } // if: reference count equal to zero
  537. CRETURN( cRef );
  538. } //*** CMajorityNodeSet::Release
  539. //////////////////////////////////////////////////////////////////////////////
  540. //++
  541. //
  542. // CMajorityNodeSet::QueryInterface
  543. //
  544. // Description:
  545. // Query this object for the passed in interface.
  546. //
  547. // Arguments:
  548. // riidIn
  549. // Id of interface requested.
  550. //
  551. // ppvOut
  552. // Pointer to the requested interface.
  553. //
  554. // Return Value:
  555. // S_OK
  556. // If the interface is available on this object.
  557. //
  558. // E_NOINTERFACE
  559. // If the interface is not available.
  560. //
  561. // E_POINTER
  562. // ppvOut was NULL.
  563. //
  564. // Remarks:
  565. // None.
  566. //
  567. //--
  568. //////////////////////////////////////////////////////////////////////////////
  569. STDMETHODIMP
  570. CMajorityNodeSet::QueryInterface(
  571. REFIID riidIn
  572. , void ** ppvOut
  573. )
  574. {
  575. TraceQIFunc( riidIn, ppvOut );
  576. HRESULT hr = S_OK;
  577. //
  578. // Validate arguments.
  579. //
  580. Assert( ppvOut != NULL );
  581. if ( ppvOut == NULL )
  582. {
  583. hr = THR( E_POINTER );
  584. goto Cleanup;
  585. }
  586. //
  587. // Handle known interfaces.
  588. //
  589. if ( IsEqualIID( riidIn, IID_IUnknown ) )
  590. {
  591. *ppvOut = static_cast< IClusCfgManagedResourceInfo * >( this );
  592. } // if: IUnknown
  593. else if ( IsEqualIID( riidIn, IID_IClusCfgManagedResourceInfo ) )
  594. {
  595. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgManagedResourceInfo, this, 0 );
  596. } // else if: IClusCfgManagedResourceInfo
  597. else if ( IsEqualIID( riidIn, IID_IClusCfgInitialize ) )
  598. {
  599. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgInitialize, this, 0 );
  600. } // else if: IClusCfgInitialize
  601. else if ( IsEqualIID( riidIn, IID_IClusCfgManagedResourceCfg ) )
  602. {
  603. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgManagedResourceCfg, this, 0 );
  604. } // else if: IClusCfgManagedResourceCfg
  605. else if ( IsEqualIID( riidIn, IID_IClusCfgManagedResourceData ) )
  606. {
  607. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgManagedResourceData, this, 0 );
  608. } // else if: IClusCfgManagedResourceData
  609. else if ( IsEqualIID( riidIn, IID_IClusCfgVerifyQuorum ) )
  610. {
  611. *ppvOut = TraceInterface( __THISCLASS__, IClusCfgVerifyQuorum, this, 0 );
  612. } // else if: IClusCfgVerifyQuorum
  613. else
  614. {
  615. *ppvOut = NULL;
  616. hr = E_NOINTERFACE;
  617. }
  618. //
  619. // Add a reference to the interface if successful.
  620. //
  621. if ( SUCCEEDED( hr ) )
  622. {
  623. ((IUnknown *) *ppvOut)->AddRef();
  624. } // if: success
  625. Cleanup:
  626. QIRETURN_IGNORESTDMARSHALLING1( hr, riidIn, IID_IEnumClusCfgPartitions );
  627. } //*** CMajorityNodeSet::QueryInterface
  628. //*************************************************************************//
  629. /////////////////////////////////////////////////////////////////////////////
  630. // CMajorityNodeSet -- IClusCfgInitialize interface.
  631. /////////////////////////////////////////////////////////////////////////////
  632. //////////////////////////////////////////////////////////////////////////////
  633. //++
  634. //
  635. // CMajorityNodeSet::Initialize
  636. //
  637. // Description:
  638. // Initialize this component.
  639. //
  640. // Arguments:
  641. // IN IUknown * punkCallbackIn
  642. //
  643. // IN LCID lcidIn
  644. //
  645. // Return Value:
  646. // S_OK
  647. // Success
  648. //
  649. // Remarks:
  650. // None.
  651. //
  652. //--
  653. //////////////////////////////////////////////////////////////////////////////
  654. STDMETHODIMP
  655. CMajorityNodeSet::Initialize(
  656. IUnknown * punkCallbackIn,
  657. LCID lcidIn
  658. )
  659. {
  660. TraceFunc( "[IClusCfgInitialize]" );
  661. Assert( m_picccCallback == NULL );
  662. HRESULT hr = S_OK;
  663. m_lcid = lcidIn;
  664. if ( punkCallbackIn == NULL )
  665. {
  666. hr = THR( E_POINTER );
  667. goto Cleanup;
  668. } // if:
  669. hr = THR( punkCallbackIn->TypeSafeQI( IClusCfgCallback, &m_picccCallback ) );
  670. Cleanup:
  671. HRETURN( hr );
  672. } //*** CMajorityNodeSet::Initialize
  673. //*************************************************************************//
  674. /////////////////////////////////////////////////////////////////////////////
  675. // CMajorityNodeSet -- IClusCfgManagedResourceInfo interface.
  676. /////////////////////////////////////////////////////////////////////////////
  677. //////////////////////////////////////////////////////////////////////////////
  678. //++
  679. //
  680. // CMajorityNodeSet::GetUID
  681. //
  682. // Description:
  683. //
  684. // Arguments:
  685. //
  686. // Return Value:
  687. //
  688. // Remarks:
  689. // None.
  690. //
  691. //--
  692. //////////////////////////////////////////////////////////////////////////////
  693. STDMETHODIMP
  694. CMajorityNodeSet::GetUID( BSTR * pbstrUIDOut )
  695. {
  696. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  697. HRESULT hr = S_OK;
  698. if ( pbstrUIDOut == NULL )
  699. {
  700. hr = THR( E_POINTER );
  701. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_MajorityNodeSet_GetUID_Pointer, IDS_ERROR_NULL_POINTER, hr );
  702. goto Cleanup;
  703. } // if:
  704. *pbstrUIDOut = SysAllocString( CLUS_RESTYPE_NAME_MAJORITYNODESET );
  705. if ( *pbstrUIDOut == NULL )
  706. {
  707. hr = THR( E_OUTOFMEMORY );
  708. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_MajorityNodeSet_GetUID_Memory, IDS_ERROR_OUTOFMEMORY, hr );
  709. } // if:
  710. Cleanup:
  711. HRETURN( hr );
  712. } //*** CMajorityNodeSet::GetUID
  713. //////////////////////////////////////////////////////////////////////////////
  714. //++
  715. //
  716. // CMajorityNodeSet::GetName
  717. //
  718. // Description:
  719. //
  720. // Arguments:
  721. //
  722. // Return Value:
  723. //
  724. // Remarks:
  725. // None.
  726. //
  727. //--
  728. //////////////////////////////////////////////////////////////////////////////
  729. STDMETHODIMP
  730. CMajorityNodeSet::GetName( BSTR * pbstrNameOut )
  731. {
  732. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  733. HRESULT hr = S_OK;
  734. if ( pbstrNameOut == NULL )
  735. {
  736. hr = THR( E_POINTER );
  737. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_MajorityNodeSet_GetName_Pointer, IDS_ERROR_NULL_POINTER, hr );
  738. goto Cleanup;
  739. } // if:
  740. if ( m_bstrName == NULL )
  741. {
  742. hr = S_FALSE;
  743. goto Cleanup;
  744. } // if: m_bstrName is NULL
  745. *pbstrNameOut = SysAllocString( m_bstrName );
  746. if ( *pbstrNameOut == NULL )
  747. {
  748. hr = THR( E_OUTOFMEMORY );
  749. STATUS_REPORT( TASKID_Major_Find_Devices, TASKID_Minor_MajorityNodeSet_GetName_Memory, IDS_ERROR_OUTOFMEMORY, hr );
  750. } // if:
  751. Cleanup:
  752. HRETURN( hr );
  753. } //*** CMajorityNodeSet::GetName
  754. //////////////////////////////////////////////////////////////////////////////
  755. //++
  756. //
  757. // CMajorityNodeSet::SetName
  758. //
  759. // Description:
  760. //
  761. // Arguments:
  762. //
  763. // Return Value:
  764. //
  765. // Remarks:
  766. // None.
  767. //
  768. //--
  769. //////////////////////////////////////////////////////////////////////////////
  770. STDMETHODIMP
  771. CMajorityNodeSet::SetName( LPCWSTR pcszNameIn )
  772. {
  773. TraceFunc1( "[IClusCfgManagedResourceInfo] pcszNameIn = '%ls'", pcszNameIn == NULL ? L"<null>" : pcszNameIn );
  774. HRESULT hr = S_OK;
  775. BSTR bstr = NULL;
  776. if ( pcszNameIn == NULL )
  777. {
  778. hr = THR( E_INVALIDARG );
  779. goto Cleanup;
  780. } // if:
  781. bstr = TraceSysAllocString( pcszNameIn );
  782. if ( bstr == NULL )
  783. {
  784. hr = THR( E_OUTOFMEMORY );
  785. goto Cleanup;
  786. } // if:
  787. TraceSysFreeString( m_bstrName );
  788. m_bstrName = bstr;
  789. Cleanup:
  790. HRETURN( hr );
  791. } //*** CMajorityNodeSet::SetName
  792. //////////////////////////////////////////////////////////////////////////////
  793. //++
  794. //
  795. // CMajorityNodeSet::IsManaged
  796. //
  797. // Description:
  798. //
  799. // Arguments:
  800. //
  801. // Return Value:
  802. // S_OK
  803. // The device is managed.
  804. //
  805. // S_FALSE
  806. // The device is not managed.
  807. //
  808. // Win32 error as HRESULT when an error occurs.
  809. //
  810. // Remarks:
  811. // None.
  812. //
  813. //--
  814. //////////////////////////////////////////////////////////////////////////////
  815. STDMETHODIMP
  816. CMajorityNodeSet::IsManaged( void )
  817. {
  818. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  819. HRESULT hr = S_FALSE;
  820. if ( m_fIsManaged )
  821. {
  822. hr = S_OK;
  823. } // if:
  824. HRETURN( hr );
  825. } //*** CMajorityNodeSet::IsManaged
  826. //////////////////////////////////////////////////////////////////////////////
  827. //++
  828. //
  829. // CMajorityNodeSet::SetManaged
  830. //
  831. // Description:
  832. //
  833. // Arguments:
  834. //
  835. // Return Value:
  836. //
  837. // Remarks:
  838. // None.
  839. //
  840. //--
  841. //////////////////////////////////////////////////////////////////////////////
  842. STDMETHODIMP
  843. CMajorityNodeSet::SetManaged(
  844. BOOL fIsManagedIn
  845. )
  846. {
  847. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  848. m_fIsManaged = fIsManagedIn;
  849. HRETURN( S_OK );
  850. } //*** CMajorityNodeSet::SetManaged
  851. //////////////////////////////////////////////////////////////////////////////
  852. //++
  853. //
  854. // CMajorityNodeSet::IsQuorumResource
  855. //
  856. // Description:
  857. //
  858. // Arguments:
  859. //
  860. // Return Value:
  861. // S_OK
  862. // The device is the quorum device.
  863. //
  864. // S_FALSE
  865. // The device is not the quorum device.
  866. //
  867. // Win32 error as HRESULT when an error occurs.
  868. //
  869. // Remarks:
  870. // None.
  871. //
  872. //--
  873. //////////////////////////////////////////////////////////////////////////////
  874. STDMETHODIMP
  875. CMajorityNodeSet::IsQuorumResource( void )
  876. {
  877. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  878. HRESULT hr = S_FALSE;
  879. if ( m_fIsQuorum )
  880. {
  881. hr = S_OK;
  882. } // if:
  883. LOG_STATUS_REPORT_STRING(
  884. L"Majority Node Set '%1!ws!' the quorum device."
  885. , m_fIsQuorum ? L"is" : L"is not"
  886. , hr
  887. );
  888. HRETURN( hr );
  889. } //*** CMajorityNodeSet::IsQuorumResource
  890. //////////////////////////////////////////////////////////////////////////////
  891. //++
  892. //
  893. // CMajorityNodeSet::SetQuorumResource
  894. //
  895. // Description:
  896. //
  897. // Arguments:
  898. //
  899. // Return Value:
  900. //
  901. // Remarks:
  902. // None.
  903. //
  904. //--
  905. //////////////////////////////////////////////////////////////////////////////
  906. STDMETHODIMP
  907. CMajorityNodeSet::SetQuorumResource( BOOL fIsQuorumResourceIn )
  908. {
  909. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  910. HRESULT hr = S_OK;
  911. //
  912. // If we are not quorum capable then we should not allow ourself to be
  913. // made the quorum resource.
  914. //
  915. if ( ( fIsQuorumResourceIn ) && ( m_fIsQuorumCapable == FALSE ) )
  916. {
  917. hr = HRESULT_FROM_WIN32( ERROR_NOT_QUORUM_CAPABLE );
  918. goto Cleanup;
  919. } // if:
  920. m_fIsQuorum = fIsQuorumResourceIn;
  921. Cleanup:
  922. LOG_STATUS_REPORT_STRING(
  923. L"Setting Majority Node Set '%1!ws!' the quorum device."
  924. , m_fIsQuorum ? L"to be" : L"to not be"
  925. , hr
  926. );
  927. HRETURN( hr );
  928. } //*** CMajorityNodeSet::SetQuorumResource
  929. //////////////////////////////////////////////////////////////////////////////
  930. //++
  931. //
  932. // CMajorityNodeSet::IsQuorumCapable
  933. //
  934. // Description:
  935. //
  936. // Arguments:
  937. //
  938. // Return Value:
  939. // S_OK
  940. // The device is a quorum capable device.
  941. //
  942. // S_FALSE
  943. // The device is not a quorum capable device.
  944. //
  945. // Win32 error as HRESULT when an error occurs.
  946. //
  947. // Remarks:
  948. // None.
  949. //
  950. //--
  951. //////////////////////////////////////////////////////////////////////////////
  952. STDMETHODIMP
  953. CMajorityNodeSet::IsQuorumCapable( void )
  954. {
  955. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  956. HRESULT hr = S_FALSE;
  957. if ( m_fIsQuorumCapable )
  958. {
  959. hr = S_OK;
  960. } // if:
  961. HRETURN( hr );
  962. } //*** CMajorityNodeSet::IsQuorumCapable
  963. //////////////////////////////////////////////////////////////////////////
  964. //
  965. // CMajorityNodeSet::SetQuorumCapable
  966. //
  967. // Description:
  968. // Call this to set whether the resource is capable to be the quorum
  969. // resource or not.
  970. //
  971. // Parameter:
  972. // fIsQuorumCapableIn - If TRUE, the resource will be marked as quorum capable.
  973. //
  974. // Return Values:
  975. // S_OK
  976. // Call succeeded.
  977. //
  978. //////////////////////////////////////////////////////////////////////////
  979. STDMETHODIMP
  980. CMajorityNodeSet::SetQuorumCapable(
  981. BOOL fIsQuorumCapableIn
  982. )
  983. {
  984. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  985. HRESULT hr = S_OK;
  986. m_fIsQuorumCapable = fIsQuorumCapableIn;
  987. HRETURN( hr );
  988. } //*** CMajorityNodeSet::SetQuorumCapable
  989. //////////////////////////////////////////////////////////////////////////////
  990. //++
  991. //
  992. // CMajorityNodeSet::GetDriveLetterMappings
  993. //
  994. // Description:
  995. //
  996. // Arguments:
  997. //
  998. // Return Value:
  999. // S_FALSE
  1000. // There are not drive letters on this device.
  1001. //
  1002. // Remarks:
  1003. // None.
  1004. //
  1005. //--
  1006. //////////////////////////////////////////////////////////////////////////////
  1007. STDMETHODIMP
  1008. CMajorityNodeSet::GetDriveLetterMappings(
  1009. SDriveLetterMapping * pdlmDriveLetterMappingOut
  1010. )
  1011. {
  1012. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  1013. HRETURN( S_FALSE );
  1014. } //*** CMajorityNodeSet::GetDriveLetterMappings
  1015. //////////////////////////////////////////////////////////////////////////////
  1016. //++
  1017. //
  1018. // CMajorityNodeSet::SetDriveLetterMappings
  1019. //
  1020. // Description:
  1021. //
  1022. // Arguments:
  1023. //
  1024. // Return Value:
  1025. //
  1026. // Remarks:
  1027. // None.
  1028. //
  1029. //--
  1030. //////////////////////////////////////////////////////////////////////////////
  1031. STDMETHODIMP
  1032. CMajorityNodeSet::SetDriveLetterMappings(
  1033. SDriveLetterMapping dlmDriveLetterMappingIn
  1034. )
  1035. {
  1036. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  1037. HRETURN( THR( E_NOTIMPL ) );
  1038. } //*** CMajorityNodeSet::SetDriveLetterMappings
  1039. //////////////////////////////////////////////////////////////////////////////
  1040. //++
  1041. //
  1042. // CMajorityNodeSet::IsManagedByDefault
  1043. //
  1044. // Description:
  1045. // Should this resource be managed by the cluster by default?
  1046. //
  1047. // Arguments:
  1048. // None.
  1049. //
  1050. // Return Value:
  1051. // S_OK
  1052. // The device is managed by default.
  1053. //
  1054. // S_FALSE
  1055. // The device is not managed by default.
  1056. //
  1057. //
  1058. // Win32 error as HRESULT when an error occurs.
  1059. //
  1060. // Remarks:
  1061. // None.
  1062. //
  1063. //--
  1064. //////////////////////////////////////////////////////////////////////////////
  1065. STDMETHODIMP
  1066. CMajorityNodeSet::IsManagedByDefault( void )
  1067. {
  1068. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  1069. HRESULT hr = S_FALSE;
  1070. if ( m_fIsManagedByDefault )
  1071. {
  1072. hr = S_OK;
  1073. } // if:
  1074. HRETURN( hr );
  1075. } //*** CMajorityNodeSet::IsManagedByDefault
  1076. //////////////////////////////////////////////////////////////////////////////
  1077. //++
  1078. //
  1079. // CMajorityNodeSet::SetManagedByDefault
  1080. //
  1081. // Description:
  1082. //
  1083. // Arguments:
  1084. //
  1085. // Return Value:
  1086. //
  1087. // Remarks:
  1088. // None.
  1089. //
  1090. //--
  1091. //////////////////////////////////////////////////////////////////////////////
  1092. STDMETHODIMP
  1093. CMajorityNodeSet::SetManagedByDefault(
  1094. BOOL fIsManagedByDefaultIn
  1095. )
  1096. {
  1097. TraceFunc( "[IClusCfgManagedResourceInfo]" );
  1098. m_fIsManagedByDefault = fIsManagedByDefaultIn;
  1099. HRETURN( S_OK );
  1100. } //*** CMajorityNodeSet::SetManagedByDefault
  1101. //*************************************************************************//
  1102. /////////////////////////////////////////////////////////////////////////////
  1103. // CMajorityNodeSet class -- IClusCfgManagedResourceCfg
  1104. /////////////////////////////////////////////////////////////////////////////
  1105. //////////////////////////////////////////////////////////////////////////////
  1106. //++
  1107. //
  1108. // CMajorityNodeSet::PreCreate
  1109. //
  1110. // Description:
  1111. //
  1112. // Arguments:
  1113. //
  1114. // Return Value:
  1115. // S_OK
  1116. // Success
  1117. //
  1118. // Win32 error as HRESULT when an error occurs.
  1119. //
  1120. // Remarks:
  1121. // None.
  1122. //
  1123. //--
  1124. //////////////////////////////////////////////////////////////////////////////
  1125. STDMETHODIMP
  1126. CMajorityNodeSet::PreCreate( IUnknown * punkServicesIn )
  1127. {
  1128. TraceFunc( "[IClusCfgManagedResourceCfg]" );
  1129. HRESULT hr = S_OK;
  1130. IClusCfgResourcePreCreate * pccrpc = NULL;
  1131. hr = THR( punkServicesIn->TypeSafeQI( IClusCfgResourcePreCreate, &pccrpc ) );
  1132. if ( FAILED( hr ) )
  1133. {
  1134. goto Cleanup;
  1135. } // if:
  1136. hr = THR( pccrpc->SetType( (LPCLSID) &RESTYPE_MajorityNodeSet ) );
  1137. if ( FAILED( hr ) )
  1138. {
  1139. goto Cleanup;
  1140. } // if:
  1141. hr = THR( pccrpc->SetClassType( (LPCLSID) &RESCLASSTYPE_StorageDevice ) );
  1142. if ( FAILED( hr ) )
  1143. {
  1144. goto Cleanup;
  1145. } // if:
  1146. Cleanup:
  1147. STATUS_REPORT_STRING( TASKID_Major_Configure_Resources, TASKID_Minor_MNS_PreCreate, IDS_INFO_MNS_PRECREATE, m_bstrName, hr );
  1148. if ( pccrpc != NULL )
  1149. {
  1150. pccrpc->Release();
  1151. } // if:
  1152. HRETURN( hr );
  1153. } //*** CMajorityNodeSet::PreCreate
  1154. //////////////////////////////////////////////////////////////////////////////
  1155. //++
  1156. //
  1157. // CMajorityNodeSet::Create
  1158. //
  1159. // Description:
  1160. //
  1161. // Arguments:
  1162. //
  1163. // Return Value:
  1164. // S_OK
  1165. // Success
  1166. //
  1167. // Win32 error as HRESULT when an error occurs.
  1168. //
  1169. // Remarks:
  1170. // None.
  1171. //
  1172. //--
  1173. //////////////////////////////////////////////////////////////////////////////
  1174. STDMETHODIMP
  1175. CMajorityNodeSet::Create( IUnknown * punkServicesIn )
  1176. {
  1177. TraceFunc( "[IClusCfgManagedResourceCfg]" );
  1178. HRESULT hr = S_OK;
  1179. IClusCfgResourceCreate * pccrc = NULL;
  1180. hr = THR( punkServicesIn->TypeSafeQI( IClusCfgResourceCreate, &pccrc ) );
  1181. if ( FAILED( hr ) )
  1182. {
  1183. goto Cleanup;
  1184. } // if:
  1185. Cleanup:
  1186. STATUS_REPORT_STRING( TASKID_Major_Configure_Resources, TASKID_Minor_MNS_Create, IDS_INFO_MNS_CREATE, m_bstrName, hr );
  1187. if ( pccrc != NULL )
  1188. {
  1189. pccrc->Release();
  1190. } // if:
  1191. HRETURN( hr );
  1192. } //*** CMajorityNodeSet::Create
  1193. //////////////////////////////////////////////////////////////////////////////
  1194. //++
  1195. //
  1196. // CMajorityNodeSet::PostCreate
  1197. //
  1198. // Description:
  1199. //
  1200. // Arguments:
  1201. //
  1202. // Return Value:
  1203. // S_OK
  1204. // Success
  1205. //
  1206. // Remarks:
  1207. // This functions should do nothing but return S_OK.
  1208. //
  1209. //--
  1210. //////////////////////////////////////////////////////////////////////////////
  1211. STDMETHODIMP
  1212. CMajorityNodeSet::PostCreate( IUnknown * punkServicesIn )
  1213. {
  1214. TraceFunc( "[IClusCfgManagedResourceCfg]" );
  1215. HRETURN( S_OK );
  1216. } //*** CMajorityNodeSet::PostCreate
  1217. //////////////////////////////////////////////////////////////////////////////
  1218. //++
  1219. //
  1220. // CMajorityNodeSet::Evict
  1221. //
  1222. // Description:
  1223. //
  1224. // Arguments:
  1225. //
  1226. // Return Value:
  1227. // S_OK
  1228. // Success
  1229. //
  1230. // Win32 error as HRESULT when an error occurs.
  1231. //
  1232. // Remarks:
  1233. // This functions should do nothing but return S_OK.
  1234. //
  1235. //--
  1236. //////////////////////////////////////////////////////////////////////////////
  1237. STDMETHODIMP
  1238. CMajorityNodeSet::Evict( IUnknown * punkServicesIn )
  1239. {
  1240. TraceFunc( "[IClusCfgManagedResourceCfg]" );
  1241. HRETURN( S_OK );
  1242. } //*** CMajorityNodeSet::Evict
  1243. //*************************************************************************//
  1244. /////////////////////////////////////////////////////////////////////////////
  1245. // CMajorityNodeSet class -- IClusCfgManagedResourceData
  1246. /////////////////////////////////////////////////////////////////////////////
  1247. //////////////////////////////////////////////////////////////////////////////
  1248. //++
  1249. //
  1250. // CMajorityNodeSet::GetResourcePrivateData
  1251. //
  1252. // Description:
  1253. // Return the private data for this resource when it is hosted on the
  1254. // cluster.
  1255. //
  1256. // Arguments:
  1257. // pbBufferOut
  1258. //
  1259. // pcbBufferInout
  1260. //
  1261. // Return Value:
  1262. // S_OK
  1263. // Success
  1264. //
  1265. // S_FALSE
  1266. // No data available.
  1267. //
  1268. // ERROR_INSUFFICIENT_BUFFER as an HRESULT
  1269. // When the passed in buffer is too small to hold the data.
  1270. // pcbBufferOutIn will contain the size required.
  1271. //
  1272. //
  1273. // Win32 error as HRESULT when an error occurs.
  1274. //
  1275. //--
  1276. //////////////////////////////////////////////////////////////////////////////
  1277. STDMETHODIMP
  1278. CMajorityNodeSet::GetResourcePrivateData(
  1279. BYTE * pbBufferOut
  1280. , DWORD * pcbBufferInout
  1281. )
  1282. {
  1283. TraceFunc( "[IClusCfgManagedResourceData]" );
  1284. Assert( pcbBufferInout != NULL );
  1285. HRESULT hr = S_OK;
  1286. DWORD cb;
  1287. DWORD cbTemp;
  1288. HCLUSTER hCluster = NULL;
  1289. HRESOURCE hResource = NULL;
  1290. DWORD sc;
  1291. WCHAR * pszResourceId = NULL;
  1292. //
  1293. // Make sure we have a clean slate to start from.
  1294. //
  1295. m_cplPrivate.DeletePropList();
  1296. //
  1297. // Attempt to retrieve the resource id from the cluster resource if we're already on a
  1298. // clustered node.
  1299. //
  1300. hr = HrIsClusterServiceRunning();
  1301. if ( hr != S_OK )
  1302. {
  1303. // We must be on a node that is being added to a cluster.
  1304. // As such we don't have anything to contribute.
  1305. if ( FAILED( hr ) )
  1306. {
  1307. THR( hr );
  1308. LogMsg( L"[SRV] CMajorityNodeSet::GetResourcePrivateData(): HrIsClusterServiceRunning failed: 0x%08x.\n", hr );
  1309. } // if:
  1310. goto Cleanup;
  1311. } // if: cluster service is not running
  1312. hCluster = OpenCluster( NULL );
  1313. if ( hCluster == NULL )
  1314. {
  1315. sc = GetLastError();
  1316. if ( sc == RPC_S_SERVER_UNAVAILABLE )
  1317. {
  1318. //
  1319. // We must be on a node that is being added to a cluster.
  1320. // As such we don't have anything to contribute.
  1321. //
  1322. hr = S_FALSE;
  1323. LogMsg( L"[SRV] CMajorityNodeSet::GetResourcePrivateData(): This node is not clustered." );
  1324. } // if:
  1325. else
  1326. {
  1327. LogMsg( L"[SRV] CMajorityNodeSet::GetResourcePrivateData(): OpenCluster failed: %d.", sc );
  1328. hr = HRESULT_FROM_WIN32( TW32( sc ) );
  1329. } // else:
  1330. goto Cleanup;
  1331. } // if: hCluster == NULL
  1332. //
  1333. // Now, open the resource. If we're on a clustered node and there is no MNS resource by the
  1334. // name that we've been given then that means we're a dummy resource that exists so that
  1335. // the middle tier doesn't get confused. The resource doesn't actually exist, therefore we
  1336. // can't provide any private data for it. Note: the dummy resource is created by the enum.
  1337. //
  1338. hResource = OpenClusterResource( hCluster, m_bstrName );
  1339. if ( hResource == NULL )
  1340. {
  1341. sc = GetLastError();
  1342. LogMsg(
  1343. L"[SRV] CMajorityNodeSet::GetResourcePrivateData(): OpenClusterResource '%ws' failed: %d."
  1344. , ( m_bstrName == NULL ) ? L"<null>" : m_bstrName
  1345. , sc
  1346. );
  1347. if ( sc == ERROR_RESOURCE_NOT_FOUND )
  1348. {
  1349. hr = S_FALSE;
  1350. } // if:
  1351. else
  1352. {
  1353. hr = HRESULT_FROM_WIN32( TW32( sc ) );
  1354. } // else:
  1355. goto Cleanup;
  1356. } // if: OpenClusterResource failed
  1357. //
  1358. // Get the resource ID from the cluster resource. First try with a reasonable buffer size and then realloc
  1359. // and retry if the buffer wasn't big enough.
  1360. //
  1361. cb = 64 * sizeof( WCHAR );
  1362. pszResourceId = new WCHAR[ cb / sizeof( WCHAR ) ];
  1363. if ( pszResourceId == NULL )
  1364. {
  1365. hr = THR( E_OUTOFMEMORY );
  1366. goto Cleanup;
  1367. } // if: couldn't allocate more memory
  1368. sc = ClusterResourceControl( hResource, NULL, CLUSCTL_RESOURCE_GET_ID, NULL, 0, (VOID *) pszResourceId, cb, &cb );
  1369. if ( sc == ERROR_MORE_DATA )
  1370. {
  1371. // Reallocate and try again.
  1372. delete [] pszResourceId;
  1373. pszResourceId = new WCHAR[ cb / sizeof( WCHAR ) ];
  1374. if ( pszResourceId == NULL )
  1375. {
  1376. hr = THR( E_OUTOFMEMORY );
  1377. goto Cleanup;
  1378. } // if: couldn't allocate more memory
  1379. sc = TW32( ClusterResourceControl( hResource, NULL, CLUSCTL_RESOURCE_GET_ID, NULL, 0, (VOID *) pszResourceId, cb, &cb ) );
  1380. } // if: the buffer wasn't big enough
  1381. else
  1382. {
  1383. TW32( sc );
  1384. } // else:
  1385. if ( sc != ERROR_SUCCESS )
  1386. {
  1387. LogMsg( L"[SRV] CMajorityNodeSet::GetResourcePrivateData(): ClusterResourceControl failed: %d.", sc );
  1388. hr = HRESULT_FROM_WIN32( sc );
  1389. goto Cleanup;
  1390. } // if: ClusterResourceControl failed
  1391. //
  1392. // Now add the property to m_cplPrivate with the name "Resource ID".
  1393. //
  1394. sc = TW32( m_cplPrivate.ScAddProp( L"Resource ID", pszResourceId ) );
  1395. if ( sc != ERROR_SUCCESS )
  1396. {
  1397. LogMsg( L"[SRV] CMajorityNodeSet::GetResourcePrivateData(): ScAddProp failed: %d.", sc );
  1398. hr = HRESULT_FROM_WIN32( sc );
  1399. goto Cleanup;
  1400. } // if: ScAddProp failed
  1401. cb = static_cast< DWORD >( m_cplPrivate.CbPropList() );
  1402. cbTemp = *pcbBufferInout;
  1403. *pcbBufferInout = cb;
  1404. if ( cb > cbTemp )
  1405. {
  1406. hr = HRESULT_FROM_WIN32( TW32( ERROR_MORE_DATA ) );
  1407. goto Cleanup;
  1408. } // if:
  1409. Assert( pbBufferOut != NULL );
  1410. CopyMemory( pbBufferOut, m_cplPrivate.Plist(), cb );
  1411. hr = S_OK;
  1412. Cleanup:
  1413. delete [] pszResourceId;
  1414. if ( hResource != NULL )
  1415. {
  1416. CloseClusterResource( hResource );
  1417. } // if:
  1418. if ( hCluster != NULL )
  1419. {
  1420. CloseCluster( hCluster );
  1421. } // if:
  1422. HRETURN( hr );
  1423. } //*** CMajorityNodeSet::GetResourcePrivateData
  1424. //////////////////////////////////////////////////////////////////////////////
  1425. //++
  1426. //
  1427. // CMajorityNodeSet::SetResourcePrivateData
  1428. //
  1429. // Description:
  1430. // Accept the private data for this resource from another hosted instance
  1431. // when this node is being added to the cluster. Note that this is not an
  1432. // additive operation.
  1433. //
  1434. // Arguments:
  1435. // pcbBufferIn
  1436. //
  1437. // cbBufferIn
  1438. //
  1439. // Return Value:
  1440. // S_OK
  1441. // Success
  1442. //
  1443. // Win32 error as HRESULT when an error occurs.
  1444. //
  1445. //--
  1446. //////////////////////////////////////////////////////////////////////////////
  1447. STDMETHODIMP
  1448. CMajorityNodeSet::SetResourcePrivateData(
  1449. const BYTE * pcbBufferIn
  1450. , DWORD cbBufferIn
  1451. )
  1452. {
  1453. TraceFunc( "[IClusCfgManagedResourceData]" );
  1454. HRESULT hr = S_OK;
  1455. DWORD sc;
  1456. //
  1457. // Make sure we have a clean slate to start from.
  1458. //
  1459. m_cplPrivate.DeletePropList();
  1460. //
  1461. // If we didn't get passed anything we can't copy anything.
  1462. //
  1463. if ( ( pcbBufferIn == NULL ) || ( cbBufferIn == 0 ) )
  1464. {
  1465. hr = S_OK;
  1466. goto Cleanup;
  1467. } // if: no data to set
  1468. sc = TW32( m_cplPrivate.ScCopy( (PCLUSPROP_LIST) pcbBufferIn, cbBufferIn ) );
  1469. if ( sc != ERROR_SUCCESS )
  1470. {
  1471. LogMsg( L"[SRV] CMajorityNodeSet::SetResourcePrivateData: ScCopy failed: %d.", sc );
  1472. hr = HRESULT_FROM_WIN32( sc );
  1473. goto Cleanup;
  1474. } // if: ScCopy failed
  1475. Cleanup:
  1476. HRETURN( hr );
  1477. } //*** CMajorityNodeSet::SetResourcePrivateData
  1478. //*************************************************************************//
  1479. /////////////////////////////////////////////////////////////////////////////
  1480. // CMajorityNodeSet class -- IClusCfgVerifyQuorum
  1481. /////////////////////////////////////////////////////////////////////////////
  1482. //////////////////////////////////////////////////////////////////////////////
  1483. //++
  1484. //
  1485. // CMajorityNodeSet::PrepareToHostQuorumResource
  1486. //
  1487. // Description:
  1488. // Do any configuration necessary in preparation for this node hosting
  1489. // the quorum.
  1490. //
  1491. // In this class we need to ensure that we can connect to the proper
  1492. // disk share. The data about what share to connect to should have
  1493. // already been set using SetResourcePrivateData() above.
  1494. //
  1495. // Arguments:
  1496. // None.
  1497. //
  1498. // Return Value:
  1499. // S_OK
  1500. // Success
  1501. //
  1502. // Win32 error as HRESULT when an error occurs.
  1503. //
  1504. //--
  1505. //////////////////////////////////////////////////////////////////////////////
  1506. STDMETHODIMP
  1507. CMajorityNodeSet::PrepareToHostQuorumResource( void )
  1508. {
  1509. TraceFunc( "[IClusCfgVerifyQuorum]" );
  1510. HRESULT hr = S_OK;
  1511. DWORD sc;
  1512. WCHAR * pszResId = NULL;
  1513. CLUSPROP_BUFFER_HELPER cpbh;
  1514. if ( m_cplPrivate.BIsListEmpty() )
  1515. {
  1516. hr = S_OK;
  1517. goto Cleanup;
  1518. } // if:
  1519. //
  1520. // Verify that our resource ID exists. If it doesn't we can't
  1521. // do anything, so return an error.
  1522. //
  1523. sc = TW32( m_cplPrivate.ScMoveToPropertyByName( L"Resource ID" ) );
  1524. if ( sc != ERROR_SUCCESS )
  1525. {
  1526. LogMsg( L"[SRV] CMajorityNodeSet::PrepareToHostQuorum: move to property failed: %d.", sc );
  1527. hr = HRESULT_FROM_WIN32( sc );
  1528. goto Cleanup;
  1529. } // if: ScMoveToPropertyByName failed
  1530. cpbh = m_cplPrivate.CbhCurrentValue();
  1531. Assert( cpbh.pSyntax->dw == CLUSPROP_SYNTAX_LIST_VALUE_SZ );
  1532. pszResId = (WCHAR *) cpbh.pStringValue->sz;
  1533. Assert( pszResId != NULL );
  1534. Assert( wcslen( pszResId ) < MAX_PATH );
  1535. hr = HrSetupShare( pszResId );
  1536. Cleanup:
  1537. HRETURN( hr );
  1538. } //*** CMajorityNodeSet::PrepareToHostQuorumResource
  1539. //////////////////////////////////////////////////////////////////////////////
  1540. //++
  1541. //
  1542. // CMajorityNodeSet::Cleanup
  1543. //
  1544. // Description:
  1545. // Do any necessay cleanup from the PrepareToHostQuorumResource()
  1546. // method.
  1547. //
  1548. // If the cleanup method is anything other than successful completion
  1549. // then the share needs to be torn down.
  1550. //
  1551. // Arguments:
  1552. // cccrReasonIn
  1553. //
  1554. // Return Value:
  1555. // S_OK
  1556. // Success
  1557. //
  1558. // Win32 error as HRESULT when an error occurs.
  1559. //
  1560. //--
  1561. //////////////////////////////////////////////////////////////////////////////
  1562. STDMETHODIMP
  1563. CMajorityNodeSet::Cleanup(
  1564. EClusCfgCleanupReason cccrReasonIn
  1565. )
  1566. {
  1567. TraceFunc( "[IClusCfgVerifyQuorum]" );
  1568. HRESULT hr = S_OK;
  1569. DWORD sc;
  1570. WCHAR * pszResId;
  1571. CLUSPROP_BUFFER_HELPER cpbh;
  1572. if ( cccrReasonIn != crSUCCESS )
  1573. {
  1574. //
  1575. // If the list is empty then we did not participate in the quorum selection
  1576. // process and have nothing to cleanup.
  1577. //
  1578. if ( m_cplPrivate.BIsListEmpty() )
  1579. {
  1580. hr = S_OK;
  1581. goto Cleanup;
  1582. } // if:
  1583. //
  1584. // Have we actually added a share?
  1585. //
  1586. if ( m_fAddedShare == FALSE )
  1587. {
  1588. hr = S_OK;
  1589. goto Cleanup;
  1590. } // if:
  1591. //
  1592. // Verify that our resource ID exists. If it doesn't we can't
  1593. // do anything, so return an error.
  1594. //
  1595. sc = TW32( m_cplPrivate.ScMoveToPropertyByName( L"Resource ID" ) );
  1596. if ( sc != ERROR_SUCCESS )
  1597. {
  1598. LogMsg( L"[SRV] CMajorityNodeSet::PrepareToHostQuorum: move to property failed: %d.", sc );
  1599. hr = HRESULT_FROM_WIN32( sc );
  1600. goto Cleanup;
  1601. }
  1602. cpbh = m_cplPrivate.CbhCurrentValue();
  1603. Assert( cpbh.pSyntax->dw == CLUSPROP_SYNTAX_LIST_VALUE_SZ );
  1604. pszResId = (WCHAR *) cpbh.pStringValue->sz;
  1605. if ( pszResId == NULL || wcslen( pszResId ) > MAX_PATH )
  1606. {
  1607. hr = THR( E_POINTER );
  1608. goto Cleanup;
  1609. } // if: pszResId is NULL or too long
  1610. hr = HrDeleteShare( pszResId );
  1611. } // if: !crSUCCESS
  1612. Cleanup:
  1613. if ( FAILED( hr ) )
  1614. {
  1615. STATUS_REPORT( TASKID_Major_Check_Cluster_Feasibility, TASKID_Minor_MajorityNodeSet_Cleanup, IDS_ERROR_MNS_CLEANUP, hr );
  1616. } // if: we had an error
  1617. HRETURN( hr );
  1618. } //*** CMajorityNodeSet::Cleanup
  1619. //////////////////////////////////////////////////////////////////////////////
  1620. //++
  1621. //
  1622. // CMajorityNodeSet::IsMultiNodeCapable
  1623. //
  1624. // Description:
  1625. // Does this quorum resource support multi node clusters?
  1626. //
  1627. // Arguments:
  1628. // None.
  1629. //
  1630. // Return Value:
  1631. // S_OK
  1632. // The resource allows multi node clusters.
  1633. //
  1634. // S_FALSE
  1635. // The resource does not allow multi node clusters.
  1636. //
  1637. //--
  1638. //////////////////////////////////////////////////////////////////////////////
  1639. STDMETHODIMP
  1640. CMajorityNodeSet::IsMultiNodeCapable( void )
  1641. {
  1642. TraceFunc( "[IClusCfgVerifyQuorum]" );
  1643. HRESULT hr = S_FALSE;
  1644. if ( m_fIsMultiNodeCapable )
  1645. {
  1646. hr = S_OK;
  1647. } // if:
  1648. HRETURN( hr );
  1649. } //*** CMajorityNodeSet::IsMultiNodeCapable
  1650. //////////////////////////////////////////////////////////////////////////////
  1651. //++
  1652. //
  1653. // CMajorityNodeSet::SetMultiNodeCapable
  1654. //
  1655. // Description:
  1656. // Sets the multi node capable flag
  1657. //
  1658. // Arguments:
  1659. // fMultiNodeCapableIn
  1660. // The flag telling this instance whether or not it should support
  1661. // Multi node clusters.
  1662. //
  1663. // Return Value:
  1664. // S_OK
  1665. // Success.
  1666. //
  1667. //--
  1668. //////////////////////////////////////////////////////////////////////////////
  1669. STDMETHODIMP
  1670. CMajorityNodeSet::SetMultiNodeCapable(
  1671. BOOL fMultiNodeCapableIn
  1672. )
  1673. {
  1674. TraceFunc( "[IClusCfgVerifyQuorum]" );
  1675. m_fIsMultiNodeCapable = fMultiNodeCapableIn;
  1676. HRETURN( S_OK );
  1677. } //*** CMajorityNodeSet::IsMultiNodeCapable