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.

550 lines
16 KiB

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