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.

898 lines
29 KiB

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