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.

649 lines
17 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Module Name:
  4. // CIISClusCfg.cpp
  5. //
  6. // Description:
  7. // Main implementation for the IClusCfgStartupListener sample program.
  8. //
  9. // Maintained By:
  10. // Galen Barbee (GalenB) 24-SEP-2001
  11. //
  12. //////////////////////////////////////////////////////////////////////////////
  13. //////////////////////////////////////////////////////////////////////////////
  14. // Include Files
  15. //////////////////////////////////////////////////////////////////////////////
  16. #include "Pch.h"
  17. #include "IISClusCfg.h"
  18. #include <lm.h> // Required for the references in this module.
  19. //////////////////////////////////////////////////////////////////////////////
  20. // Globals
  21. //////////////////////////////////////////////////////////////////////////////
  22. static PCWSTR g_apszResourceTypesToDelete[] =
  23. {
  24. L"IIS Server Instance",
  25. L"SMTP Server Instance",
  26. L"NNTP Server Instance",
  27. L"IIS Virtual Root",
  28. //
  29. // KB: 18-JUN-2002 GalenB
  30. //
  31. // Since we don't think we are going to be sending this component to
  32. // IIS it is simpler and faster to add this non IIS resource type to this
  33. // component. If this component is ever handed off to IIS then we
  34. // need to remove this resource type from this table.
  35. //
  36. L"Time Service",
  37. NULL
  38. };
  39. //***************************************************************************
  40. //
  41. // CIISClusCfg class
  42. //
  43. //***************************************************************************
  44. //////////////////////////////////////////////////////////////////////////////
  45. //++
  46. //
  47. // static
  48. // CIISClusCfg::S_HrCreateInstance
  49. //
  50. // Description:
  51. // Create a CIISClusCfg instance.
  52. //
  53. // Arguments:
  54. // riidIn - ID of the interface to return.
  55. // ppunkOut - The IUnknown interface of the new object.
  56. //
  57. // Return Values:
  58. // S_OK
  59. // Success.
  60. //
  61. // E_POINTER
  62. // ppunkOut was NULL.
  63. //
  64. // E_OUTOFMEMORY
  65. // Not enough memory to create the object.
  66. //
  67. // other HRESULTs
  68. // Object initialization failed.
  69. //
  70. //--
  71. //////////////////////////////////////////////////////////////////////////////
  72. HRESULT
  73. CIISClusCfg::S_HrCreateInstance(
  74. IUnknown ** ppunkOut
  75. )
  76. {
  77. HRESULT hr = S_OK;
  78. CIISClusCfg * pmsl = NULL;
  79. if ( ppunkOut == NULL )
  80. {
  81. hr = E_POINTER;
  82. goto Cleanup;
  83. } // if:
  84. pmsl = new CIISClusCfg();
  85. if ( pmsl == NULL )
  86. {
  87. hr = E_OUTOFMEMORY;
  88. goto Cleanup;
  89. } // if: error allocating object
  90. hr = pmsl->HrInit();
  91. if ( FAILED( hr ) )
  92. {
  93. goto Cleanup;
  94. } // if: HrInit() failed
  95. hr = pmsl->QueryInterface( IID_IUnknown, reinterpret_cast< void ** >( ppunkOut ) );
  96. if ( FAILED( hr ) )
  97. {
  98. goto Cleanup;
  99. } // if: QI failed
  100. Cleanup:
  101. if ( pmsl != NULL )
  102. {
  103. pmsl->Release();
  104. } // if:
  105. return hr;
  106. } //*** CIISClusCfg::S_HrCreateInstance
  107. //////////////////////////////////////////////////////////////////////////////
  108. //++
  109. //
  110. // CIISClusCfg::S_HrRegisterCatIDSupport
  111. //
  112. // Description:
  113. // Registers/unregisters this class with the categories that it
  114. // belongs to.
  115. //
  116. // Arguments:
  117. // picrIn
  118. // Used to register/unregister our CATID support.
  119. //
  120. // fCreateIn
  121. // When true we are registering the server. When false we are
  122. // un-registering the server.
  123. //
  124. // Return Values:
  125. // S_OK
  126. // Success.
  127. //
  128. // E_INVALIDARG
  129. // The passed in ICatRgister pointer was NULL.
  130. //
  131. // other HRESULTs
  132. // Registration/Unregistration failed.
  133. //
  134. //--
  135. //////////////////////////////////////////////////////////////////////////////
  136. HRESULT
  137. CIISClusCfg::S_HrRegisterCatIDSupport(
  138. ICatRegister * picrIn,
  139. BOOL fCreateIn
  140. )
  141. {
  142. HRESULT hr = S_OK;
  143. CATID rgCatIds[ 2 ];
  144. if ( picrIn == NULL )
  145. {
  146. hr = E_INVALIDARG;
  147. goto Cleanup;
  148. } // if:
  149. rgCatIds[ 0 ] = CATID_ClusCfgStartupListeners;
  150. rgCatIds[ 1 ] = CATID_ClusCfgEvictListeners;
  151. if ( fCreateIn )
  152. {
  153. hr = picrIn->RegisterClassImplCategories( CLSID_IISClusCfg, RTL_NUMBER_OF( rgCatIds ), rgCatIds );
  154. } // if: registering
  155. //
  156. // KB: 24-SEP-2001 GalenB
  157. //
  158. // This code is not needed since this component has been temporarily placed in ClusCfgSrv.dll. Our
  159. // cleanup code does a tree delete the whole registry key and that cleanups up the CATID stuff.
  160. //
  161. /*
  162. else
  163. {
  164. hr = picrIn->UnRegisterClassImplCategories( CLSID_IISClusCfg, ARRAYSIZE( rgCatIds ), rgCatIds );
  165. } // else: unregistering
  166. */
  167. Cleanup:
  168. return hr;
  169. } //*** CIISClusCfg::S_HrRegisterCatIDSupport
  170. //////////////////////////////////////////////////////////////////////////////
  171. //++
  172. //
  173. // CIISClusCfg::CIISClusCfg
  174. //
  175. // Description:
  176. // Constructor of CIISClusCfg. Initializes m_cRef to 1 to avoid
  177. // problems when called from DllGetClassObject. Increments the global
  178. // object count to avoid DLL unload.
  179. //
  180. // Arguments:
  181. // None.
  182. //
  183. // Return Values:
  184. // None.
  185. //
  186. //--
  187. //////////////////////////////////////////////////////////////////////////////
  188. CIISClusCfg::CIISClusCfg( void )
  189. : m_cRef( 1 )
  190. {
  191. //
  192. // Increment the count of components in memory so the DLL hosting this
  193. // object cannot be unloaded.
  194. //
  195. InterlockedIncrement( &g_cObjects );
  196. } //*** CIISClusCfg::CIISClusCfg
  197. /////////////////////////////////////////////////////////////////////////////
  198. //++
  199. //
  200. // CIISClusCfg::~CIISClusCfg
  201. //
  202. // Description:
  203. // Destructor of CIISClusCfg. Decrements the global object count.
  204. //
  205. // Arguments:
  206. // None.
  207. //
  208. // Return Value:
  209. // None.
  210. //
  211. //--
  212. //////////////////////////////////////////////////////////////////////////////
  213. CIISClusCfg::~CIISClusCfg( void )
  214. {
  215. // There's going to be one less component in memory.
  216. // Decrement component count.
  217. InterlockedDecrement( &g_cObjects );
  218. } //*** CIISClusCfg::~CIISClusCfg
  219. //***************************************************************************
  220. //
  221. // IUnknown interface
  222. //
  223. //***************************************************************************
  224. //////////////////////////////////////////////////////////////////////////////
  225. //++
  226. //
  227. // [IUnknown]
  228. // CIISClusCfg::AddRef
  229. //
  230. // Description:
  231. // Increment the reference count of this object by one.
  232. //
  233. // Arguments:
  234. // None.
  235. //
  236. // Return Value:
  237. // The new reference count.
  238. //
  239. //--
  240. //////////////////////////////////////////////////////////////////////////////
  241. STDMETHODIMP_( ULONG )
  242. CIISClusCfg::AddRef( void )
  243. {
  244. return InterlockedIncrement( &m_cRef );
  245. } //*** CIISClusCfg::AddRef
  246. //////////////////////////////////////////////////////////////////////////////
  247. //++
  248. //
  249. // [IUnknown]
  250. // CIISClusCfg::Release
  251. //
  252. // Description:
  253. // Decrement the reference count of this object by one.
  254. // If this reaches 0, the object will be automatically deleted.
  255. //
  256. // Arguments:
  257. // None.
  258. //
  259. // Return Value:
  260. // The new reference count.
  261. //
  262. //--
  263. //////////////////////////////////////////////////////////////////////////////
  264. STDMETHODIMP_( ULONG )
  265. CIISClusCfg::Release( void )
  266. {
  267. LONG cRef;
  268. cRef = InterlockedDecrement( &m_cRef );
  269. if ( cRef == 0 )
  270. {
  271. delete this;
  272. } // if:
  273. return cRef;
  274. } //*** CIISClusCfg::Release
  275. //////////////////////////////////////////////////////////////////////////////
  276. //++
  277. //
  278. // [IUnknown]
  279. // CIISClusCfg::QueryInterface
  280. //
  281. // Description:
  282. // Query this object for the passed in interface.
  283. // This class implements the following interfaces:
  284. //
  285. // IUnknown
  286. // IClusCfgStarutpListener
  287. //
  288. // Arguments:
  289. // riidIn - Id of interface requested.
  290. // ppvOut - Pointer to the requested interface. NULL if unsupported.
  291. //
  292. // Return Value:
  293. // S_OK - If the interface is available on this object.
  294. // E_POINTER - ppvOut was NULL.
  295. // E_NOINTERFACE - If the interface is not available.
  296. //
  297. //--
  298. //////////////////////////////////////////////////////////////////////////////
  299. STDMETHODIMP
  300. CIISClusCfg::QueryInterface(
  301. REFIID riidIn
  302. , void ** ppvOut
  303. )
  304. {
  305. HRESULT hr = S_OK;
  306. //
  307. // Validate arguments.
  308. //
  309. if ( ppvOut == NULL )
  310. {
  311. hr = E_POINTER;
  312. goto Cleanup;
  313. } // if:
  314. //
  315. // Handle known interfaces.
  316. //
  317. if ( IsEqualIID( riidIn, IID_IUnknown ) )
  318. {
  319. //
  320. // We static_cast to IClusCfgStartupListener* to avoid conflicts
  321. // if this class should inherit IUnknown from more than one
  322. // interface.
  323. //
  324. *ppvOut = static_cast< IClusCfgStartupListener * >( this );
  325. } // if:
  326. else if ( IsEqualIID( riidIn, IID_IClusCfgStartupListener ) )
  327. {
  328. *ppvOut = static_cast< IClusCfgStartupListener * >( this );
  329. } // else if:
  330. else if ( IsEqualIID( riidIn, IID_IClusCfgEvictListener ) )
  331. {
  332. *ppvOut = static_cast< IClusCfgEvictListener * >( this );
  333. } // else if:
  334. else
  335. {
  336. *ppvOut = NULL;
  337. hr = E_NOINTERFACE;
  338. } // else:
  339. //
  340. // Add a reference to the interface if successful.
  341. //
  342. if ( SUCCEEDED( hr ) )
  343. {
  344. //
  345. // We will return an interface pointer, so the reference counter needs to
  346. // be incremented.
  347. //
  348. ((IUnknown *) *ppvOut)->AddRef();
  349. } // if:
  350. Cleanup:
  351. return hr;
  352. } //*** CIISClusCfg::QueryInterface
  353. //////////////////////////////////////////////////////////////////////////////
  354. //++
  355. //
  356. // CIISClusCfg::HrCleanupResourceTypes
  357. //
  358. // Description:
  359. // This function will clean up any resource types leftover from a Windows 2000
  360. // cluster installation which are no longer supported.
  361. //
  362. // Arguments:
  363. // none
  364. //
  365. // Return Value:
  366. // S_OK
  367. // Operation completed successfully.
  368. //
  369. //--
  370. //////////////////////////////////////////////////////////////////////////////
  371. HRESULT
  372. CIISClusCfg::HrCleanupResourceTypes( void )
  373. {
  374. HRESULT hr = S_OK;
  375. DWORD sc = ERROR_SUCCESS;
  376. HCLUSTER hCluster = NULL;
  377. WCHAR szClusterName[ MAX_PATH ];
  378. DWORD cchClusterName = RTL_NUMBER_OF( szClusterName );
  379. CLUSTERVERSIONINFO clusterInfo;
  380. PCWSTR * ppszResType;
  381. //
  382. // Open the local cluster service. We can do this since we are running on the
  383. // node that evicted the node, not the node that was evicted...
  384. //
  385. hCluster = OpenCluster( NULL );
  386. if ( hCluster == NULL )
  387. {
  388. sc = GetLastError();
  389. hr = HRESULT_FROM_WIN32( sc );
  390. LogMsg( L"[IISCLUSCFG] Error opening connection to local cluster service. (hr = %#08x)", hr );
  391. goto Cleanup;
  392. } // if:
  393. //
  394. // Check if the entire cluster is running Windows Server 2003 (NT 5.1).
  395. //
  396. sc = GetClusterInformation( hCluster, szClusterName, &cchClusterName, &clusterInfo );
  397. if ( sc != ERROR_SUCCESS )
  398. {
  399. hr = HRESULT_FROM_WIN32( sc );
  400. LogMsg( L"[IISCLUSCFG] Error getting the cluster version information. (hr = %#08x)", hr );
  401. goto Cleanup;
  402. } // if:
  403. //
  404. // If the whole cluster is Windows Server 2003, then the highest version will be NT51, and
  405. // the lowest version will be NT5. This is because ClusterHighestVersion is set to the
  406. // min of the highest version that all nodes can "speak", and ClusterLowestVersion is set to the
  407. // max of the lowest version that all nodes can speak.
  408. //
  409. if ( ( CLUSTER_GET_MAJOR_VERSION( clusterInfo.dwClusterHighestVersion ) == NT51_MAJOR_VERSION )
  410. && ( CLUSTER_GET_MAJOR_VERSION( clusterInfo.dwClusterLowestVersion ) == NT5_MAJOR_VERSION ) )
  411. {
  412. //
  413. // We don't need to enumerate resources to make sure
  414. // that no IIS resources exist before we delete the resource types. The deletion
  415. // of a resource type will fail if resources of that type exist.
  416. //
  417. for ( ppszResType = g_apszResourceTypesToDelete; *ppszResType != NULL; ++ppszResType )
  418. {
  419. //
  420. // ERROR_SUCCESS: successful deletion.
  421. //
  422. // ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND: no problem. The resource type didn't exist,
  423. // so this must be a fresh Windows Server 2003 installation, not an upgrade.
  424. //
  425. // ERROR_DIR_NOT_EMPTY: a resource of that type exists. In this case we require manual
  426. // intervention by an administrator.
  427. sc = DeleteClusterResourceType( hCluster, *ppszResType );
  428. if ( sc == ERROR_SUCCESS )
  429. {
  430. LogMsg( L"[IISCLUSCFG] Successfully deleted resource type \"%ws\". (hr = %#08x)", *ppszResType, HRESULT_FROM_WIN32( sc ) );
  431. continue;
  432. } // if: resource type was deleted.
  433. else if ( sc == ERROR_DIR_NOT_EMPTY )
  434. {
  435. LogMsg( L"[IISCLUSCFG] Could not delete resource type \"%ws\" because there are resources of this type. Trying the next resource type in the table... (hr = %#08x)", *ppszResType, HRESULT_FROM_WIN32( sc ) );
  436. continue;
  437. } // else if: resources of this type exist.
  438. else if ( sc == ERROR_CLUSTER_RESOURCE_TYPE_NOT_FOUND )
  439. {
  440. LogMsg( L"[IISCLUSCFG] Could not delete resource type \"%ws\" because the resource type was not found. Trying the next resource type in the table... (hr = %#08x)", *ppszResType, HRESULT_FROM_WIN32( sc ) );
  441. continue;
  442. } // else if: resource type was not found.
  443. else
  444. {
  445. //
  446. // We failed to delete the resource type.
  447. //
  448. //
  449. // Keep track of the last failure.
  450. // But don't bail out. Keep deleting the other types.
  451. //
  452. hr = HRESULT_FROM_WIN32( sc );
  453. LogMsg( L"[IISCLUSCFG] Unexpected error deleting resource type \"%ws\". Trying the next resource type in the table... (hr = %#08x)", *ppszResType, hr );
  454. } // else: some unknown error.
  455. } // for: each resource type in the table.
  456. } // if: this cluster is 100% Windows Server 2003.
  457. Cleanup:
  458. if ( hCluster != NULL )
  459. {
  460. CloseCluster( hCluster );
  461. } // if:
  462. return hr;
  463. } //*** CIISClusCfg::HrCleanupResourceTypes
  464. //////////////////////////////////////////////////////////////////////////////
  465. //++
  466. //
  467. // [IClusCfgStartupListener]
  468. // CIISClusCfg::Notify
  469. //
  470. // Description:
  471. // This function gets called just after the cluster service has started.
  472. //
  473. // Arguments:
  474. // punkIn
  475. // Pointer to a COM object that implements
  476. // IClusCfgResourceTypeCreate.
  477. //
  478. // Return Value:
  479. // S_OK
  480. // Operation completed successfully.
  481. //
  482. //--
  483. //////////////////////////////////////////////////////////////////////////////
  484. STDMETHODIMP
  485. CIISClusCfg::Notify(
  486. IUnknown * /*unused: punkIn*/ )
  487. {
  488. HRESULT hr = S_OK;
  489. LogMsg( L"[IISCLUSCFG] Entering startup notify... (hr = %#08x)", hr );
  490. hr = HrCleanupResourceTypes();
  491. LogMsg( L"[IISCLUSCFG] Leaving startup notify... (hr = %#08x)", hr );
  492. return hr;
  493. } //*** IISClusCfg::Notify
  494. //////////////////////////////////////////////////////////////////////////////
  495. //++
  496. //
  497. // [IClusCfgEvictListener]
  498. // CIISClusCfg::EvictNotify
  499. //
  500. // Description:
  501. // This function gets called after a node has been evicted.
  502. //
  503. // Arguments:
  504. // pcszNodeNameIn
  505. // The name of the node that has been evicted.
  506. //
  507. // Return Value:
  508. // S_OK
  509. // Operation completed successfully.
  510. //
  511. //--
  512. //////////////////////////////////////////////////////////////////////////////
  513. STDMETHODIMP
  514. CIISClusCfg::EvictNotify(
  515. PCWSTR /* unused: pcszNodeNameIn */ )
  516. {
  517. HRESULT hr = S_OK;
  518. LogMsg( L"[IISCLUSCFG] Entering evict cleanup notify... (hr = %#08x)", hr );
  519. hr = HrCleanupResourceTypes();
  520. LogMsg( L"[IISCLUSCFG] Leaving evict cleanup notify... (hr = %#08x)", hr );
  521. return hr;
  522. } //*** IISClusCfg::EvictNotify
  523. //***************************************************************************
  524. //
  525. // Private methods
  526. //
  527. //***************************************************************************
  528. //////////////////////////////////////////////////////////////////////////////
  529. //++
  530. //
  531. // CIISClusCfg::HrInit
  532. //
  533. // Description:
  534. // Initialize this component.
  535. //
  536. // Arguments:
  537. // None.
  538. //
  539. // Return Value:
  540. // S_OK - Operation completed successfully.
  541. //
  542. // Remarks:
  543. // None.
  544. //
  545. //--
  546. //////////////////////////////////////////////////////////////////////////////
  547. HRESULT
  548. CIISClusCfg::HrInit( void )
  549. {
  550. HRESULT hr = S_OK;
  551. // IUnknown
  552. //Assert( m_cRef == 1 );
  553. return hr;
  554. } //*** CIISClusCfg::HrInit