Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

555 lines
17 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CClusDiskJoin.cpp
  7. //
  8. // Description:
  9. // Contains the definition of the CClusDiskJoin class.
  10. //
  11. // Maintained By:
  12. // Vij Vasu (Vvasu) 08-MAR-2000
  13. //
  14. //////////////////////////////////////////////////////////////////////////////
  15. //////////////////////////////////////////////////////////////////////////////
  16. // Include Files
  17. //////////////////////////////////////////////////////////////////////////////
  18. // The precompiled header.
  19. #include "pch.h"
  20. // The header for this file
  21. #include "CClusDiskJoin.h"
  22. // For the CBaseClusterJoin class.
  23. #include "CBaseClusterJoin.h"
  24. // For the CImpersonateUser class.
  25. #include "CImpersonateUser.h"
  26. // For the ResUtil functions
  27. #include "ResAPI.h"
  28. //////////////////////////////////////////////////////////////////////////////
  29. // Macro definitions
  30. //////////////////////////////////////////////////////////////////////////////
  31. // Name of the private property of a physical disk resouce that has its signature.
  32. #define PHYSICAL_DISK_SIGNATURE_PRIVPROP_NAME L"Signature"
  33. //////////////////////////////////////////////////////////////////////////////
  34. //++
  35. //
  36. // CClusDiskJoin::CClusDiskJoin()
  37. //
  38. // Description:
  39. // Constructor of the CClusDiskJoin class
  40. //
  41. // Arguments:
  42. // pbcjParentActionIn
  43. // Pointer to the base cluster action of which this action is a part.
  44. //
  45. // Return Value:
  46. // None.
  47. //
  48. // Exceptions Thrown:
  49. // Any exceptions thrown by underlying functions
  50. //
  51. //--
  52. //////////////////////////////////////////////////////////////////////////////
  53. CClusDiskJoin::CClusDiskJoin(
  54. CBaseClusterJoin * pbcjParentActionIn
  55. )
  56. : BaseClass( pbcjParentActionIn )
  57. , m_nSignatureArraySize( 0 )
  58. , m_nSignatureCount( 0 )
  59. {
  60. BCATraceScope( "" );
  61. SetRollbackPossible( true );
  62. } //*** CClusDiskJoin::CClusDiskJoin()
  63. //////////////////////////////////////////////////////////////////////////////
  64. //++
  65. //
  66. // CClusDiskJoin::~CClusDiskJoin()
  67. //
  68. // Description:
  69. // Destructor of the CClusDiskJoin class.
  70. //
  71. // Arguments:
  72. // None.
  73. //
  74. // Return Value:
  75. // None.
  76. //
  77. // Exceptions Thrown:
  78. // Any exceptions thrown by underlying functions
  79. //
  80. //--
  81. //////////////////////////////////////////////////////////////////////////////
  82. CClusDiskJoin::~CClusDiskJoin( void )
  83. {
  84. BCATraceScope( "" );
  85. } //*** CClusDiskJoin::~CClusDiskJoin()
  86. //////////////////////////////////////////////////////////////////////////////
  87. //++
  88. //
  89. // void
  90. // CClusDiskJoin::Commit()
  91. //
  92. // Description:
  93. // Configure and start the service.
  94. //
  95. // Arguments:
  96. // None.
  97. //
  98. // Return Value:
  99. // None.
  100. //
  101. // Exceptions Thrown:
  102. // Any that are thrown by the contained actions.
  103. //
  104. //--
  105. //////////////////////////////////////////////////////////////////////////////
  106. void
  107. CClusDiskJoin::Commit( void )
  108. {
  109. BCATraceScope( "" );
  110. // Call the base class commit method.
  111. BaseClass::Commit();
  112. try
  113. {
  114. // Create and start the service.
  115. ConfigureService();
  116. // Try and attach to all the disks that the sponsor knows about.
  117. AttachToClusteredDisks();
  118. } // try:
  119. catch( ... )
  120. {
  121. // If we are here, then something went wrong with the create.
  122. BCATraceMsg( "Caught exception during commit." );
  123. //
  124. // Cleanup anything that the failed create might have done.
  125. // Catch any exceptions thrown during Cleanup to make sure that there
  126. // is no collided unwind.
  127. //
  128. try
  129. {
  130. CleanupService();
  131. }
  132. catch( ... )
  133. {
  134. //
  135. // The rollback of the committed action has failed.
  136. // There is nothing that we can do.
  137. // We certainly cannot rethrow this exception, since
  138. // the exception that caused the rollback is more important.
  139. //
  140. THR( E_UNEXPECTED );
  141. BCATraceMsg( "Caught exception during cleanup." );
  142. LogMsg( "THIS COMPUTER MAY BE IN AN INVALID STATE. An error has occurred during cleanup." );
  143. } // catch: all
  144. // Rethrow the exception thrown by commit.
  145. throw;
  146. } // catch: all
  147. // If we are here, then everything went well.
  148. SetCommitCompleted( true );
  149. } //*** CClusDiskJoin::Commit()
  150. //////////////////////////////////////////////////////////////////////////////
  151. //++
  152. //
  153. // void
  154. // CClusDiskJoin::Rollback()
  155. //
  156. // Description:
  157. // Cleanup the service.
  158. //
  159. // Arguments:
  160. // None.
  161. //
  162. // Return Value:
  163. // None.
  164. //
  165. // Exceptions Thrown:
  166. // Any that are thrown by the underlying functions.
  167. //
  168. //--
  169. //////////////////////////////////////////////////////////////////////////////
  170. void
  171. CClusDiskJoin::Rollback( void )
  172. {
  173. BCATraceScope( "" );
  174. // Call the base class rollback method.
  175. BaseClass::Rollback();
  176. // Cleanup the service.
  177. CleanupService();
  178. SetCommitCompleted( false );
  179. } //*** CClusDiskJoin::Rollback()
  180. //////////////////////////////////////////////////////////////////////////////
  181. //++
  182. //
  183. // void
  184. // CClusDiskJoin::AttachToClusteredDisks()
  185. //
  186. // Description:
  187. // Get the signatures of all disks that have been clustered from the sponsor.
  188. // Attach to all these disks.
  189. //
  190. // Arguments:
  191. // None.
  192. //
  193. // Return Value:
  194. // None.
  195. //
  196. // Exceptions Thrown:
  197. // CRuntimeError
  198. // If any of the APIs fail.
  199. //
  200. // Any that are thrown by the underlying functions.
  201. //
  202. //--
  203. //////////////////////////////////////////////////////////////////////////////
  204. void
  205. CClusDiskJoin::AttachToClusteredDisks( void )
  206. {
  207. BCATraceScope( "" );
  208. DWORD dwError = ERROR_SUCCESS;
  209. // Get the parent action pointer.
  210. CBaseClusterJoin * pcjClusterJoin = dynamic_cast< CBaseClusterJoin *>( PbcaGetParent() );
  211. // If the parent action of this action is not CBaseClusterJoin
  212. if ( pcjClusterJoin == NULL )
  213. {
  214. THROW_ASSERT( E_POINTER, "The parent action of this action is not CBaseClusterJoin." );
  215. } // an invalid pointer was passed in.
  216. //
  217. // Connect to the sponsor cluster and get the signatures of all clustered disks.
  218. //
  219. do
  220. {
  221. // Smart handle to sponsor cluster
  222. SmartClusterHandle schSponsorCluster;
  223. BCATraceMsg( "Attempting to impersonate the cluster service account." );
  224. // Impersonate the cluster service account, so that we can contact the sponsor cluster.
  225. // The impersonation is automatically ended when this object is destroyed.
  226. CImpersonateUser ciuImpersonateClusterServiceAccount( pcjClusterJoin->HGetClusterServiceAccountToken() );
  227. {
  228. BCATraceMsg( "Trying to open a handle to the sponsor cluster." );
  229. // Open a handle to the sponsor cluster.
  230. HCLUSTER hSponsorCluster = OpenCluster( pcjClusterJoin->RStrGetClusterBindingString().PszData() );
  231. // Assign it to a smart handle for safe release.
  232. schSponsorCluster.Assign( hSponsorCluster );
  233. }
  234. // Did we succeed in opening a handle to the sponsor cluster?
  235. if ( schSponsorCluster.FIsInvalid() )
  236. {
  237. dwError = TW32( GetLastError() );
  238. BCATraceMsg( "An error occurred trying to open a handle to the sponsor cluster." );
  239. LogMsg( "An error occurred trying to open a handle to the sponsor cluster." );
  240. break;
  241. } // if: OpenCluster() failed
  242. BCATraceMsg1( "Enumerating all '%s' resources in the cluster.", CLUS_RESTYPE_NAME_PHYS_DISK );
  243. // Enumerate all the physical disk resouces in the cluster and get their signatures.
  244. dwError = TW32( ResUtilEnumResourcesEx(
  245. schSponsorCluster.HHandle()
  246. , NULL
  247. , CLUS_RESTYPE_NAME_PHYS_DISK
  248. , S_DwResourceEnumCallback
  249. , this
  250. ) );
  251. if ( dwError != ERROR_SUCCESS )
  252. {
  253. // Free the signature array.
  254. m_rgdwSignatureArray.PRelease();
  255. m_nSignatureArraySize = 0;
  256. m_nSignatureCount = 0;
  257. BCATraceMsg( "An error occurred trying enumerate resources in the sponsor cluster." );
  258. LogMsg( "An error occurred trying enumerate resources in the sponsor cluster." );
  259. break;
  260. } // if: ResUtilEnumResourcesEx() failed
  261. }
  262. while( false ); // dummy do-while loop to avoid gotos.
  263. if ( dwError != ERROR_SUCCESS )
  264. {
  265. LogMsg( "Error %#08x occurred trying to attach to the disks in the sponsor cluster.", dwError );
  266. BCATraceMsg1( "Error %#08x occurred trying to attach to the disks in the sponsor cluster. Throwing exception.", dwError );
  267. THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( dwError ), IDS_ERROR_CLUSDISK_CONFIGURE );
  268. } // if: something has gone wrong
  269. else
  270. {
  271. BCATraceMsg1( "Attaching to the %d disks in the sponsor cluster.", m_nSignatureCount );
  272. AttachToDisks(
  273. m_rgdwSignatureArray.PMem()
  274. , m_nSignatureCount
  275. );
  276. } // else: everything has gone well so far
  277. } //*** CClusDiskJoin::AttachToClusteredDisks()
  278. //////////////////////////////////////////////////////////////////////////////
  279. //++
  280. //
  281. // DWORD
  282. // CClusDiskJoin::DwAddSignature()
  283. //
  284. // Description:
  285. // Add a signature to the array of signatures of disks that ClusDisk should
  286. // attach to. If the array is already full, grow the array.
  287. //
  288. // Arguments:
  289. // dwSignatureIn
  290. // Signature to be added to the array.
  291. //
  292. // Return Value:
  293. // ERROR_SUCCESS
  294. // If everything was ok.
  295. //
  296. // Other Win32 error codes on failure.
  297. //
  298. // Exceptions Thrown:
  299. // None. This function is called from a callback routine and therefore
  300. // cannot throw any exceptions.
  301. //
  302. //--
  303. //////////////////////////////////////////////////////////////////////////////
  304. DWORD
  305. CClusDiskJoin::DwAddSignature( DWORD dwSignatureIn ) throw()
  306. {
  307. BCATraceScope( "" );
  308. DWORD dwError = ERROR_SUCCESS;
  309. do
  310. {
  311. // Is the capacity of the array reached?
  312. if ( m_nSignatureCount == m_nSignatureArraySize )
  313. {
  314. // Increase the array size by a random amount.
  315. const int nGrowSize = 256;
  316. BCATraceMsg2( "Signature count has reached array size ( %d ). Growing array by %d.", m_nSignatureArraySize, nGrowSize );
  317. m_nSignatureArraySize += nGrowSize;
  318. // Grow the array.
  319. DWORD * pdwNewArray = new DWORD[ m_nSignatureArraySize ];
  320. if ( pdwNewArray == NULL )
  321. {
  322. BCATraceMsg1( "Memory allocation failed trying to allocate %d DWORDs.", m_nSignatureArraySize );
  323. dwError = TW32( ERROR_OUTOFMEMORY );
  324. break;
  325. } // if: memory allocation failed
  326. // Copy the old array into the new one.
  327. CopyMemory( pdwNewArray, m_rgdwSignatureArray.PMem(), m_nSignatureCount * sizeof( SmartDwordArray::DataType ) );
  328. // Free the old array and store the new one.
  329. m_rgdwSignatureArray.Assign( pdwNewArray );
  330. } // if: the array capacity has been reached
  331. // Store the new signature in next array location
  332. ( m_rgdwSignatureArray.PMem() )[ m_nSignatureCount ] = dwSignatureIn;
  333. ++m_nSignatureCount;
  334. BCATraceMsg2( "Signature %#08X added to array. There are now %d signature in the array.", dwSignatureIn, m_nSignatureCount );
  335. }
  336. while( false ); // dummy do-while loop to avoid gotos.
  337. BCATraceMsg1( "Return value is %d.", dwError );
  338. return dwError;
  339. } //*** CClusDiskJoin::DwAddSignature()
  340. //////////////////////////////////////////////////////////////////////////////
  341. //++
  342. //
  343. // static DWORD
  344. // CClusDiskJoin::S_DwResourceEnumCallback()
  345. //
  346. // Description:
  347. // This function is called back for every physical disk resouce by
  348. // ResUtilEnumResourcesEx() as a part of enumerating resources.
  349. // This function gets the signature of the current physical disk
  350. // resource and stores it in the object that initiated the enumeration
  351. // ( the pointer to the object is in parameter 4 ).
  352. //
  353. // Arguments:
  354. // HCLUSTER hClusterIn
  355. // Handle to the cluster whose resources are being enumerated.
  356. //
  357. // HRESOURCE hSelfIn
  358. // hSelfIn passed to ResUtilEnumResourcesEx(), if any.
  359. //
  360. // HRESOURCE hCurrentResourceIn
  361. // Handle to the current resource.
  362. //
  363. // PVOID pvParamIn
  364. // Pointer to the object of this class that initiated this enumeration.
  365. //
  366. // Return Value:
  367. // ERROR_SUCCESS
  368. // If everything was ok.
  369. //
  370. // Other Win32 error codes on failure.
  371. // Returning an error code will terminate the enumeration.
  372. //
  373. // Exceptions Thrown:
  374. // None. This function is called from a callback routine and therefore
  375. // cannot throw any exceptions.
  376. //
  377. //--
  378. //////////////////////////////////////////////////////////////////////////////
  379. DWORD
  380. CClusDiskJoin::S_DwResourceEnumCallback(
  381. HCLUSTER hClusterIn
  382. , HRESOURCE hSelfIn
  383. , HRESOURCE hCurrentResourceIn
  384. , PVOID pvParamIn
  385. )
  386. {
  387. BCATraceScope( "" );
  388. DWORD dwError = ERROR_SUCCESS;
  389. CClusDiskJoin * pcdjThisObject = reinterpret_cast< CClusDiskJoin * >( pvParamIn );
  390. // Get the 'Signature' private property of this physical disk.
  391. do
  392. {
  393. SmartByteArray sbaPropertyBuffer;
  394. DWORD dwBytesReturned = 0;
  395. DWORD dwBufferSize;
  396. DWORD dwSignature = 0;
  397. BCATraceMsg1( "Trying to get the signature of the disk resource whose handle is %p.", hCurrentResourceIn );
  398. // Get the size of the buffer required to hold all the private properties of this resource.
  399. dwError = ClusterResourceControl(
  400. hCurrentResourceIn
  401. , NULL
  402. , CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES
  403. , NULL
  404. , 0
  405. , NULL
  406. , 0
  407. , &dwBytesReturned
  408. );
  409. if ( ( dwError != ERROR_MORE_DATA ) && ( dwError != ERROR_SUCCESS ) )
  410. {
  411. // Something went wrong.
  412. TW32( dwError );
  413. BCATraceMsg( "ClusterResourceControl() failed while trying to get the size of the property buffer." );
  414. break;
  415. } // if: the return value of ClusterResourceControl() was not ERROR_MORE_DATA
  416. dwBufferSize = dwBytesReturned;
  417. // Allocate the memory required for the property buffer.
  418. sbaPropertyBuffer.Assign( new BYTE[ dwBufferSize ] );
  419. if ( sbaPropertyBuffer.FIsEmpty() )
  420. {
  421. BCATraceMsg1( "Memory allocation failed trying to allocate %d bytes.", dwBufferSize );
  422. dwError = TW32( ERROR_OUTOFMEMORY );
  423. break;
  424. } // if: memory allocation failed
  425. // Get the all the private properties of this resource.
  426. dwError = TW32( ClusterResourceControl(
  427. hCurrentResourceIn
  428. , NULL
  429. , CLUSCTL_RESOURCE_GET_PRIVATE_PROPERTIES
  430. , NULL
  431. , 0
  432. , sbaPropertyBuffer.PMem()
  433. , dwBufferSize
  434. , &dwBytesReturned
  435. ) );
  436. if ( dwError != ERROR_SUCCESS )
  437. {
  438. BCATraceMsg( "ClusterResourceControl() failed while trying to get the properties of the current resource." );
  439. break;
  440. } // if: an error occurring trying to get the private properties.
  441. // Get the signature of this disk resource.
  442. dwError = TW32( ResUtilFindDwordProperty(
  443. sbaPropertyBuffer.PMem()
  444. , dwBufferSize
  445. , PHYSICAL_DISK_SIGNATURE_PRIVPROP_NAME
  446. , &dwSignature
  447. ) );
  448. if ( dwError != ERROR_SUCCESS )
  449. {
  450. BCATraceMsg( "An error has occurred trying to get the signature from the property buffer." );
  451. break;
  452. } // if: we could not get the signature
  453. dwError = TW32( pcdjThisObject->DwAddSignature( dwSignature ) );
  454. if ( dwError != ERROR_SUCCESS )
  455. {
  456. BCATraceMsg( "An error has occurred trying to add the signature to the signature array." );
  457. break;
  458. } // if: we could not store the signature
  459. }
  460. while( false ); // dummy do-while loop to avoid gotos.
  461. BCATraceMsg1( "Return value is %d.", dwError );
  462. return dwError;
  463. } //*** CClusDiskJoin::S_DwResourceEnumCallback()