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.

904 lines
29 KiB

  1. //////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 1999-2000 Microsoft Corporation
  4. //
  5. // Module Name:
  6. // CClusDisk.cpp
  7. //
  8. // Description:
  9. // Contains the definition of the CClusDisk 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 "CClusDisk.h"
  22. // Required by clusdisk.h
  23. #include <ntddscsi.h>
  24. // For IOCTL_DISK_CLUSTER_ATTACH and IOCTL_DISK_CLUSTER_DETACH
  25. #include <clusdisk.h>
  26. //////////////////////////////////////////////////////////////////////////////
  27. // Macros
  28. //////////////////////////////////////////////////////////////////////////////
  29. // The name of the ClusDisk service
  30. #define CLUSDISK_SERVICE_NAME L"ClusDisk"
  31. //////////////////////////////////////////////////////////////////////////////
  32. //++
  33. //
  34. // CClusDisk::CClusDisk()
  35. //
  36. // Description:
  37. // Constructor of the CClusDisk class. Opens a handle to the service.
  38. //
  39. // Arguments:
  40. // pbcaParentActionIn
  41. // Pointer to the base cluster action of which this action is a part.
  42. //
  43. // Return Value:
  44. // None.
  45. //
  46. // Exceptions Thrown:
  47. // CAssert
  48. // If the parameters are incorrect.
  49. //
  50. // CRuntimeError
  51. // If any of the APIs fail.
  52. //
  53. // Any exceptions thrown by underlying functions
  54. //
  55. //--
  56. //////////////////////////////////////////////////////////////////////////////
  57. CClusDisk::CClusDisk(
  58. CBaseClusterAction * pbcaParentActionIn
  59. )
  60. : m_cservClusDisk( CLUSDISK_SERVICE_NAME )
  61. , m_pbcaParentAction( pbcaParentActionIn )
  62. {
  63. BCATraceScope( "" );
  64. if ( m_pbcaParentAction == NULL)
  65. {
  66. TraceFlow( "Pointers to the parent action is NULL. Throwing exception." );
  67. THROW_ASSERT(
  68. E_INVALIDARG
  69. , "CClusDisk::CClusDisk() => Required input pointer in NULL"
  70. );
  71. } // if: the parent action pointer is NULL
  72. //
  73. // The ClusDisk service has been created at the time the cluster binaries were
  74. // installed. So, get a handle to the ClusDisk service.
  75. //
  76. SmartSCMHandle sscmhTempHandle(
  77. OpenService(
  78. pbcaParentActionIn->HGetSCMHandle()
  79. , CLUSDISK_SERVICE_NAME
  80. , SERVICE_ALL_ACCESS
  81. )
  82. );
  83. // Did we get a handle to the service?
  84. if ( sscmhTempHandle.FIsInvalid() )
  85. {
  86. DWORD dwError = TW32( GetLastError() );
  87. LogMsg( "Error %#08x occurred trying to open a handle to the ClusDisk service.", dwError );
  88. TraceFlow1( "Error %#08x occurred trying to open a handle to the ClusDisk service. Throwing exception.", dwError );
  89. THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( dwError ), IDS_ERROR_CLUSDISK_OPEN );
  90. } // if: OpenService failed
  91. // Initialize the member variable.
  92. m_sscmhServiceHandle = sscmhTempHandle;
  93. } //*** CClusDisk::CClusDisk()
  94. //////////////////////////////////////////////////////////////////////////////
  95. //++
  96. //
  97. // CClusDisk::~CClusDisk()
  98. //
  99. // Description:
  100. // Destructor of the CClusDisk class.
  101. //
  102. // Arguments:
  103. // None.
  104. //
  105. // Return Value:
  106. // None.
  107. //
  108. // Exceptions Thrown:
  109. // Any exceptions thrown by underlying functions
  110. //
  111. //--
  112. //////////////////////////////////////////////////////////////////////////////
  113. CClusDisk::~CClusDisk( void )
  114. {
  115. BCATraceScope( "" );
  116. } //*** CClusDisk::~CClusDisk()
  117. //////////////////////////////////////////////////////////////////////////////
  118. //++
  119. //
  120. // void
  121. // CClusDisk::ConfigureService()
  122. //
  123. // Description:
  124. // This function enables and starts the ClusDisk service.
  125. //
  126. // Arguments:
  127. // None.
  128. //
  129. // Return Value:
  130. // None.
  131. //
  132. // Exceptions Thrown:
  133. // CRuntimeError
  134. // If any of the APIs fail.
  135. //
  136. // Any that are thrown by the underlying functions.
  137. //
  138. //--
  139. //////////////////////////////////////////////////////////////////////////////
  140. void
  141. CClusDisk::ConfigureService( void )
  142. {
  143. BCATraceScope( "" );
  144. LogMsg( "Configuring the ClusDisk service." );
  145. bool fIsRunning;
  146. {
  147. CStatusReport srConfigClusDisk(
  148. PbcaGetParent()->PBcaiGetInterfacePointer()
  149. , TASKID_Major_Configure_Cluster_Services
  150. , TASKID_Minor_Configuring_ClusDisk_Service
  151. , 0, 1
  152. , IDS_TASK_CONFIG_CLUSDISK
  153. );
  154. // Send the next step of this status report.
  155. srConfigClusDisk.SendNextStep( S_OK );
  156. //
  157. // First, initialize the ClusDisk service to make sure that it does not retain
  158. // any state from another cluster that this node may have been a part of.
  159. //
  160. fIsRunning = FInitializeState();
  161. //
  162. // Enable the service.
  163. //
  164. if ( ChangeServiceConfig(
  165. m_sscmhServiceHandle.HHandle() // handle to service
  166. , SERVICE_NO_CHANGE // type of service
  167. , SERVICE_SYSTEM_START // when to start service
  168. , SERVICE_NO_CHANGE // severity of start failure
  169. , NULL // service binary file name
  170. , NULL // load ordering group name
  171. , NULL // tag identifier
  172. , NULL // array of dependency names
  173. , NULL // account name
  174. , NULL // account password
  175. , NULL // display name
  176. )
  177. == FALSE
  178. )
  179. {
  180. DWORD dwError = TW32( GetLastError() );
  181. LogMsg( "Could not enable the ClusDisk service. Error %#08x.", dwError );
  182. TraceFlow1( "ChangeServiceConfig() failed with error %#08x. Throwing exception.", dwError );
  183. THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( dwError ), IDS_ERROR_CLUSDISK_CONFIGURE );
  184. } // if: we could not enable the service.
  185. // Send the last step of this status report.
  186. srConfigClusDisk.SendNextStep( S_OK );
  187. }
  188. LogMsg( "The ClusDisk service has been enabled." );
  189. {
  190. UINT cQueryCount = 10;
  191. CStatusReport srStartClusDisk(
  192. PbcaGetParent()->PBcaiGetInterfacePointer()
  193. , TASKID_Major_Configure_Cluster_Services
  194. , TASKID_Minor_Starting_ClusDisk_Service
  195. , 1, cQueryCount + 2 // we will send at most cQueryCount reports while waiting for the service to start (the two extra sends are below)
  196. , IDS_TASK_STARTING_CLUSDISK
  197. );
  198. // Send the next step of this status report.
  199. srStartClusDisk.SendNextStep( S_OK );
  200. // This call does not actually create the service - it creates the registry entries needed
  201. // by ClusDisk.
  202. m_cservClusDisk.Create( m_pbcaParentAction->HGetMainInfFileHandle() );
  203. // If the service was not already running, start the service.
  204. if ( ! fIsRunning )
  205. {
  206. m_cservClusDisk.Start(
  207. m_pbcaParentAction->HGetSCMHandle()
  208. , true // wait for the service to start
  209. , 500 // wait 500ms between queries for status.
  210. , cQueryCount // query cQueryCount times.
  211. , &srStartClusDisk // status report to be sent while waiting for the service to start
  212. );
  213. } // if: ClusDisk was not already running.
  214. else
  215. {
  216. // Nothing more need be done.
  217. TraceFlow( "ClusDisk is already running." );
  218. } // else: ClusDisk is already running.
  219. LogMsg( "The ClusDisk service has been successfully configured and started." );
  220. // Send the last step of this status report.
  221. srStartClusDisk.SendLastStep( S_OK );
  222. }
  223. } //*** CClusDisk::ConfigureService()
  224. //////////////////////////////////////////////////////////////////////////////
  225. //++
  226. //
  227. // void
  228. // CClusDisk::CleanupService()
  229. //
  230. // Description:
  231. // This function enables and starts the ClusDisk service.
  232. //
  233. // Arguments:
  234. // None.
  235. //
  236. // Return Value:
  237. // None.
  238. //
  239. // Exceptions Thrown:
  240. // CRuntimeError
  241. // If any of the APIs fail.
  242. //
  243. // Any that are thrown by the underlying functions.
  244. //
  245. //--
  246. //////////////////////////////////////////////////////////////////////////////
  247. void
  248. CClusDisk::CleanupService( void )
  249. {
  250. BCATraceScope( "" );
  251. LogMsg( "Cleaning up the ClusDisk service." );
  252. //
  253. // First, initialize the ClusDisk service to make sure that it does not retain
  254. // any state from this cluster.
  255. //
  256. FInitializeState();
  257. //
  258. // Disable the service.
  259. //
  260. if ( ChangeServiceConfig(
  261. m_sscmhServiceHandle.HHandle() // handle to service
  262. , SERVICE_NO_CHANGE // type of service
  263. , SERVICE_DISABLED // when to start service
  264. , SERVICE_NO_CHANGE // severity of start failure
  265. , NULL // service binary file name
  266. , NULL // load ordering group name
  267. , NULL // tag identifier
  268. , NULL // array of dependency names
  269. , NULL // account name
  270. , NULL // account password
  271. , NULL // display name
  272. )
  273. == FALSE
  274. )
  275. {
  276. DWORD dwError = TW32( GetLastError() );
  277. LogMsg( "Could not disable the ClusDisk service. Error %#08x.", dwError );
  278. TraceFlow1( "ChangeServiceConfig() failed with error %#08x. Throwing exception.", dwError );
  279. THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( dwError ), IDS_ERROR_CLUSDISK_CLEANUP );
  280. } // if: we could not enable the service.
  281. LogMsg( "The ClusDisk service has been successfully cleaned up and disabled." );
  282. } //*** CClusDisk::CleanupService()
  283. //////////////////////////////////////////////////////////////////////////////
  284. //++
  285. //
  286. // bool
  287. // CClusDisk::FInitializeState()
  288. //
  289. // Description:
  290. // This function initializes the ClusDisk service and brings it back to
  291. // its ground state.
  292. //
  293. // If the service is running, then ClusDisk is asked to detach
  294. // itself from all the disks that it is currently attached to.
  295. //
  296. // If the service is not running, then its parameters key is deleted
  297. // so as to prevent ClusDisk from reusing any keys leftover from a previous
  298. // cluster.
  299. //
  300. // Arguments:
  301. // None.
  302. //
  303. // Return Value:
  304. // Returns true is the service was running before the initialization began.
  305. // Returns false if it was not.
  306. //
  307. // Exceptions Thrown:
  308. // CRuntimeError
  309. // If any of the APIs fail.
  310. //
  311. // Any that are thrown by the underlying functions.
  312. //
  313. //--
  314. //////////////////////////////////////////////////////////////////////////////
  315. bool
  316. CClusDisk::FInitializeState( void )
  317. {
  318. BCATraceScope( "" );
  319. LogMsg( "Initializing ClusDisk service state.");
  320. bool fIsRunning;
  321. DWORD dwError = ERROR_SUCCESS;
  322. do
  323. {
  324. SERVICE_STATUS ssStatus;
  325. //
  326. // Check if the service is running.
  327. //
  328. ZeroMemory( &ssStatus, sizeof( ssStatus ) );
  329. // Query the service for its status.
  330. if ( QueryServiceStatus(
  331. m_sscmhServiceHandle.HHandle()
  332. , &ssStatus
  333. )
  334. == 0
  335. )
  336. {
  337. dwError = TW32( GetLastError() );
  338. TraceFlow1( "Error %#08x occurred while trying to query ClusDisk status. Throwing exception.", dwError );
  339. break;
  340. } // if: we could not query the service for its status.
  341. if ( ssStatus.dwCurrentState == SERVICE_RUNNING )
  342. {
  343. TraceFlow( "The ClusDisk service is already running. It will be detached from all disks." );
  344. LogMsg( "The ClusDisk service is already running. It will be detached from all disks." );
  345. // ClusDisk is running.
  346. fIsRunning = true;
  347. // Make sure that it is not attached to any disks already.
  348. DetachFromAllDisks();
  349. } // if: the service is running.
  350. else
  351. {
  352. if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
  353. {
  354. TraceFlow( "The ClusDisk service is not running. Its registry will be cleaned up." );
  355. LogMsg( "The ClusDisk service is not running. Its registry will be cleaned up." );
  356. // ClusDisk is not running.
  357. fIsRunning = false;
  358. // Call the cleanup routine of the embedded service object.
  359. m_cservClusDisk.Cleanup( m_pbcaParentAction->HGetMainInfFileHandle() );
  360. } // if: the service is stopped
  361. else
  362. {
  363. dwError = TW32( ERROR_INVALID_HANDLE_STATE );
  364. TraceFlow1( "ClusDisk is in an incorrect state (%#08x).", ssStatus.dwCurrentState );
  365. break;
  366. } // else: the service is in some other state.
  367. } // else: ClusDisk is not running.
  368. }
  369. while( false ); // dummy do-while loop to avoid gotos.
  370. if ( dwError != ERROR_SUCCESS )
  371. {
  372. LogMsg( "Error %#08x occurred trying initialize the ClusDisk service state.", dwError );
  373. TraceFlow1( "Error %#08x occurred trying initialize the ClusDisk service state. Throwing exception.", dwError );
  374. THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( dwError ), IDS_ERROR_CLUSDISK_INITIALIZE );
  375. } // if: something has gone wrong
  376. LogMsg( "The ClusDisk service state has been successfully initialized.");
  377. return fIsRunning;
  378. } //*** CClusDisk::FInitializeState()
  379. //////////////////////////////////////////////////////////////////////////////
  380. //++
  381. //
  382. // void
  383. // CClusDisk::DetachFromAllDisks()
  384. //
  385. // Description:
  386. // This function detaches ClusDisk from all the disks that it is currently
  387. // attached to. A prerequisite for calling this function is that the
  388. // ClusDisk service is running.
  389. //
  390. // Arguments:
  391. // None.
  392. //
  393. // Return Value:
  394. // None.
  395. //
  396. // Exceptions Thrown:
  397. // CRuntimeError
  398. // If any of the APIs fail.
  399. //
  400. // Any that are thrown by the underlying functions.
  401. //
  402. //--
  403. //////////////////////////////////////////////////////////////////////////////
  404. void
  405. CClusDisk::DetachFromAllDisks( void )
  406. {
  407. BCATraceScope( "" );
  408. LONG lError = ERROR_SUCCESS;
  409. LogMsg( "Detaching the ClusDisk service from all disks." );
  410. do
  411. {
  412. CRegistryKey rkSignaturesKey;
  413. DWORD dwSignatureCount = 0;
  414. DWORD dwMaxSignatureNameLen = 0;
  415. DWORD dwSignatureIndex = 0;
  416. // Try and open the ClusDisk signatures key.
  417. try
  418. {
  419. rkSignaturesKey.OpenKey(
  420. HKEY_LOCAL_MACHINE
  421. , L"System\\CurrentControlSet\\Services\\ClusDisk\\Parameters\\Signatures"
  422. , KEY_ALL_ACCESS
  423. );
  424. } // try: to open the ClusDisk signatures key.
  425. catch( CRuntimeError & rteException )
  426. {
  427. //
  428. // If we are here, then OpenKey threw a CRuntimeError.Check if the
  429. // error was ERROR_FILE_NOT_FOUND. This means that the key does
  430. // not exist and we are done.
  431. //
  432. // Otherwise, some other error ocurred, so rethrow the exception.
  433. //
  434. if ( rteException.HrGetErrorCode() == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) )
  435. {
  436. // There is nothing else to do.
  437. break;
  438. } // if: the ClusDisk parameters key does not exist.
  439. // Some other error occurred.
  440. throw;
  441. } // catch( CRuntimeError & )
  442. //
  443. // Find out the number of signatures and the maximum length of the signature
  444. // key names.
  445. //
  446. lError = TW32( RegQueryInfoKey(
  447. rkSignaturesKey.HGetKey() // handle to key
  448. , NULL // class buffer
  449. , NULL // size of class buffer
  450. , NULL // reserved
  451. , &dwSignatureCount // number of subkeys
  452. , &dwMaxSignatureNameLen // longest subkey name
  453. , NULL // longest class string
  454. , NULL // number of value entries
  455. , NULL // longest value name
  456. , NULL // longest value data
  457. , NULL // descriptor length
  458. , NULL // last write time
  459. ) );
  460. if ( lError != ERROR_SUCCESS )
  461. {
  462. TraceFlow( "RegQueryInfoKey() failed." );
  463. break;
  464. } // if: RegQueryInfoKey() failed.
  465. // Account for the terminating '\0'
  466. ++dwMaxSignatureNameLen;
  467. // Allocate the memory required to hold the signatures.
  468. CSmartGenericPtr< CArrayPtrTrait< DWORD > > rgdwSignatureArrayIn( new DWORD[ dwSignatureCount ] );
  469. if ( rgdwSignatureArrayIn.FIsEmpty() )
  470. {
  471. lError = TW32( ERROR_OUTOFMEMORY );
  472. TraceFlow1( "Could not allocate %d bytes required for the signature array.", dwSignatureCount );
  473. break;
  474. } // if:memory allocation failed.
  475. // Allocate the memory required for the signature string.
  476. SmartSz sszSignatureKeyName( new WCHAR[ dwMaxSignatureNameLen ] );
  477. if ( sszSignatureKeyName.FIsEmpty() )
  478. {
  479. lError = TW32( ERROR_OUTOFMEMORY );
  480. TraceFlow1( "Could not allocate %d bytes required for the longest signature key name.", dwMaxSignatureNameLen );
  481. break;
  482. } // if:memory allocation failed.
  483. //
  484. // Iterate through the list of signatures that ClusDisk is currently attached
  485. // to and add each of them to the array of signatures. We cannot detach as
  486. // we enumerate since ClusDisk removes the signature key when it detaches from
  487. // a disk and RegEnumKeyEx requires that the key being enumerated not change
  488. // during an enumeration.
  489. //
  490. do
  491. {
  492. DWORD dwTempSize = dwMaxSignatureNameLen;
  493. WCHAR * pwcCharPtr;
  494. lError = RegEnumKeyEx(
  495. rkSignaturesKey.HGetKey()
  496. , dwSignatureIndex
  497. , sszSignatureKeyName.PMem()
  498. , &dwTempSize
  499. , NULL
  500. , NULL
  501. , NULL
  502. , NULL
  503. );
  504. if ( lError != ERROR_SUCCESS )
  505. {
  506. if ( lError == ERROR_NO_MORE_ITEMS )
  507. {
  508. lError = ERROR_SUCCESS;
  509. } // if: we are at the end of the enumeration
  510. else
  511. {
  512. TW32( lError );
  513. TraceFlow1( "RegEnumKeyEx() has failed. Index = %d.", dwSignatureIndex );
  514. } // else: something else went wrong
  515. break;
  516. } // if: RegEnumKeyEx() did not succeed
  517. TraceFlow2( "Signature %d is '%s'.", dwSignatureIndex + 1, sszSignatureKeyName.PMem() );
  518. // Convert the key name to a hex number.
  519. ( rgdwSignatureArrayIn.PMem() )[ dwSignatureIndex ] =
  520. wcstoul( sszSignatureKeyName.PMem(), &pwcCharPtr, 16 );
  521. // Did the conversion succeed.
  522. if ( sszSignatureKeyName.PMem() == pwcCharPtr )
  523. {
  524. lError = TW32( ERROR_INVALID_PARAMETER );
  525. TraceFlow( "_wcstoul() failed." );
  526. break;
  527. } // if: the conversion of the signature string to a number failed.
  528. // Increment the index.
  529. ++dwSignatureIndex;
  530. }
  531. while( true ); // loop infinitely
  532. if ( lError != ERROR_SUCCESS )
  533. {
  534. break;
  535. } // if: something went wrong
  536. // Detach ClusDisks from all the disks we found it attached to.
  537. DetachFromDisks(
  538. rgdwSignatureArrayIn.PMem()
  539. , dwSignatureCount
  540. );
  541. }
  542. while( false ); // dummy do-while loop to avoid gotos.
  543. if ( lError != ERROR_SUCCESS )
  544. {
  545. LogMsg( "Error %#08x occurred trying detach ClusDisk from all the disks.", lError );
  546. TraceFlow1( "Error %#08x trying detach ClusDisk from all the disks. Throwing exception.", lError );
  547. THROW_RUNTIME_ERROR( HRESULT_FROM_WIN32( lError ), IDS_ERROR_CLUSDISK_INITIALIZE );
  548. } // if: something has gone wrong
  549. LogMsg( "The ClusDisk service has been successfully detached from all disks." );
  550. } //*** CClusDisk::DetachFromAllDisks()
  551. //////////////////////////////////////////////////////////////////////////////
  552. //++
  553. //
  554. // void
  555. // CClusDisk::DetachFromDisks()
  556. //
  557. // Description:
  558. // This function detaches ClusDisk from the disks specified
  559. // by a list of signatures. A prerequisite for calling this function is
  560. // that the ClusDisk service is running.
  561. //
  562. // Arguments:
  563. // rgdwSignatureArrayIn
  564. // Array of signatures of disks to detach from.
  565. //
  566. // uiArraySizeIn
  567. // Number of signatures in above array.
  568. //
  569. // Return Value:
  570. // None.
  571. //
  572. // Exceptions Thrown:
  573. // CRuntimeError
  574. // If any of the APIs fail.
  575. //
  576. // Any that are thrown by the underlying functions.
  577. //
  578. //--
  579. //////////////////////////////////////////////////////////////////////////////
  580. void
  581. CClusDisk::DetachFromDisks(
  582. DWORD rgdwSignatureArrayIn[]
  583. , UINT uiArraySizeIn
  584. )
  585. {
  586. BCATraceScope( "" );
  587. NTSTATUS ntStatus = STATUS_SUCCESS;
  588. UNICODE_STRING ustrClusDiskDeviceName;
  589. OBJECT_ATTRIBUTES oaClusDiskAttrib;
  590. HANDLE hClusDisk;
  591. IO_STATUS_BLOCK iosbIoStatusBlock;
  592. DWORD dwTempSize = 0;
  593. TraceFlow1( "Trying to detach from %d disks.", uiArraySizeIn );
  594. //
  595. // If the list is empty then leave since there are no disks to detach
  596. // from.
  597. //
  598. if ( ( uiArraySizeIn == 0 ) || ( rgdwSignatureArrayIn == NULL ) )
  599. {
  600. goto Cleanup;
  601. } // if:
  602. // Initialize the unicode string with the name of the ClusDisk device.
  603. RtlInitUnicodeString( &ustrClusDiskDeviceName, L"\\Device\\ClusDisk0" );
  604. InitializeObjectAttributes(
  605. &oaClusDiskAttrib
  606. , &ustrClusDiskDeviceName
  607. , OBJ_CASE_INSENSITIVE
  608. , NULL
  609. , NULL
  610. );
  611. TraceFlow( "Trying to get a handle to the ClusDisk device." );
  612. // Get a handle to the ClusDisk device.
  613. ntStatus = THR( NtCreateFile(
  614. &hClusDisk
  615. , SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA
  616. , &oaClusDiskAttrib
  617. , &iosbIoStatusBlock
  618. , NULL
  619. , FILE_ATTRIBUTE_NORMAL
  620. , FILE_SHARE_READ | FILE_SHARE_WRITE
  621. , FILE_OPEN
  622. , 0
  623. , NULL
  624. , 0
  625. ) );
  626. if ( NT_SUCCESS( ntStatus ) == FALSE )
  627. {
  628. TraceFlow( "NtCreateFile has failed." );
  629. goto Cleanup;
  630. } // if: NtCreateFile failed.
  631. { // new block so that that the file handle is closed.
  632. // Assign the opened file handle to a smart handle for safe closing.
  633. CSmartResource<
  634. CHandleTrait<
  635. HANDLE
  636. , NTSTATUS
  637. , NtClose
  638. >
  639. > snthClusDiskHandle( hClusDisk );
  640. // Detach ClusDisk from this disk.
  641. if ( DeviceIoControl(
  642. hClusDisk
  643. , IOCTL_DISK_CLUSTER_DETACH_LIST
  644. , rgdwSignatureArrayIn
  645. , uiArraySizeIn * sizeof( rgdwSignatureArrayIn[ 0 ] )
  646. , NULL
  647. , 0
  648. , &dwTempSize
  649. , FALSE
  650. )
  651. == FALSE
  652. )
  653. {
  654. ntStatus = TW32( GetLastError() );
  655. ntStatus = HRESULT_FROM_WIN32( ntStatus );
  656. TraceFlow( "DeviceIoControl() failed for signature list" );
  657. } // if: DeviceIoControl() failed
  658. }
  659. Cleanup:
  660. if ( ntStatus != STATUS_SUCCESS )
  661. {
  662. LogMsg( "Error %#08x occurred trying detach ClusDisk from a disk.", ntStatus );
  663. TraceFlow1( "Error %#08x trying detach ClusDisk from a disk. Throwing exception.", ntStatus );
  664. THROW_RUNTIME_ERROR( ntStatus, IDS_ERROR_CLUSDISK_INITIALIZE );
  665. } // if: something has gone wrong
  666. } //*** CClusDisk::DetachFromDisks()
  667. //////////////////////////////////////////////////////////////////////////////
  668. //++
  669. //
  670. // void
  671. // CClusDisk::AttachToDisks()
  672. //
  673. // Description:
  674. // This function attaches ClusDisk to the disks specified
  675. // by a list of signatures. A prerequisite for calling this function is
  676. // that the ClusDisk service is running.
  677. //
  678. // Arguments:
  679. // rgdwSignatureArrayIn
  680. // Array of signatures of disks to attach to.
  681. //
  682. // uiArraySizeIn
  683. // Number of signatures in above array.
  684. //
  685. // Return Value:
  686. // None.
  687. //
  688. // Exceptions Thrown:
  689. // CRuntimeError
  690. // If any of the APIs fail.
  691. //
  692. // Any that are thrown by the underlying functions.
  693. //
  694. //--
  695. //////////////////////////////////////////////////////////////////////////////
  696. void
  697. CClusDisk::AttachToDisks(
  698. DWORD rgdwSignatureArrayIn[]
  699. , UINT uiArraySizeIn
  700. )
  701. {
  702. BCATraceScope( "" );
  703. NTSTATUS ntStatus = STATUS_SUCCESS;
  704. UNICODE_STRING ustrClusDiskDeviceName;
  705. OBJECT_ATTRIBUTES oaClusDiskAttrib;
  706. HANDLE hClusDisk;
  707. IO_STATUS_BLOCK iosbIoStatusBlock;
  708. DWORD dwTempSize = 0;
  709. TraceFlow1( "Trying to attach to %d disks.", uiArraySizeIn );
  710. //
  711. // If the list is empty then leave since there are no disks to attach
  712. // to.
  713. //
  714. if ( ( uiArraySizeIn == 0 ) || ( rgdwSignatureArrayIn == NULL ) )
  715. {
  716. goto Cleanup;
  717. } // if:
  718. // Initialize the unicode string with the name of the ClusDisk device.
  719. RtlInitUnicodeString( &ustrClusDiskDeviceName, L"\\Device\\ClusDisk0" );
  720. InitializeObjectAttributes(
  721. &oaClusDiskAttrib
  722. , &ustrClusDiskDeviceName
  723. , OBJ_CASE_INSENSITIVE
  724. , NULL
  725. , NULL
  726. );
  727. TraceFlow( "Trying to get a handle to the ClusDisk device." );
  728. // Get a handle to the ClusDisk device.
  729. ntStatus = THR( NtCreateFile(
  730. &hClusDisk
  731. , SYNCHRONIZE | FILE_READ_DATA | FILE_WRITE_DATA
  732. , &oaClusDiskAttrib
  733. , &iosbIoStatusBlock
  734. , NULL
  735. , FILE_ATTRIBUTE_NORMAL
  736. , FILE_SHARE_READ | FILE_SHARE_WRITE
  737. , FILE_OPEN
  738. , 0
  739. , NULL
  740. , 0
  741. ) );
  742. if ( NT_SUCCESS( ntStatus ) == FALSE )
  743. {
  744. TraceFlow( "NtCreateFile has failed." );
  745. goto Cleanup;
  746. } // if: NtCreateFile failed.
  747. { // new block so that that the file handle is closed.
  748. // Assign the opened file handle to a smart handle for safe closing.
  749. CSmartResource<
  750. CHandleTrait<
  751. HANDLE
  752. , NTSTATUS
  753. , NtClose
  754. >
  755. > snthClusDiskHandle( hClusDisk );
  756. // Attach ClusDisk to this signature list.
  757. if ( DeviceIoControl(
  758. hClusDisk
  759. , IOCTL_DISK_CLUSTER_ATTACH_LIST
  760. , rgdwSignatureArrayIn
  761. , uiArraySizeIn * sizeof( rgdwSignatureArrayIn[0] )
  762. , NULL
  763. , 0
  764. , &dwTempSize
  765. , FALSE
  766. )
  767. == FALSE
  768. )
  769. {
  770. ntStatus = GetLastError();
  771. ntStatus = HRESULT_FROM_WIN32( TW32( ntStatus ) );
  772. TraceFlow( "DeviceIoControl() failed for signature list" );
  773. } // if: DeviceIoControl() failed
  774. }
  775. Cleanup:
  776. if ( ntStatus != STATUS_SUCCESS )
  777. {
  778. LogMsg( "Error %#08x occurred trying attach ClusDisk to a disk.", ntStatus );
  779. TraceFlow1( "Error %#08x trying attach ClusDisk to a disk. Throwing exception.", ntStatus );
  780. THROW_RUNTIME_ERROR( ntStatus, IDS_ERROR_CLUSDISK_INITIALIZE );
  781. } // if: something has gone wrong
  782. } //*** CClusDisk::AttachToDisks()